laya.html.js 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879
  1. (function(window,document,Laya){
  2. var __un=Laya.un,__uns=Laya.uns,__static=Laya.static,__class=Laya.class,__getset=Laya.getset,__newvec=Laya.__newvec;
  3. var Browser=laya.utils.Browser,ClassUtils=laya.utils.ClassUtils,Context=laya.resource.Context,Event=laya.events.Event;
  4. var Graphics=laya.display.Graphics,HTMLChar=laya.utils.HTMLChar,Handler=laya.utils.Handler,Loader=laya.net.Loader;
  5. var Pool=laya.utils.Pool,Rectangle=laya.maths.Rectangle,Sprite=laya.display.Sprite,Text=laya.display.Text;
  6. var Texture=laya.resource.Texture,URL=laya.net.URL,Utils=laya.utils.Utils;
  7. Laya.interface('laya.html.utils.ILayout');
  8. /**
  9. *@private
  10. */
  11. //class laya.html.dom.HTMLBrElement
  12. var HTMLBrElement=(function(){
  13. function HTMLBrElement(){}
  14. __class(HTMLBrElement,'laya.html.dom.HTMLBrElement');
  15. var __proto=HTMLBrElement.prototype;
  16. /**@private */
  17. __proto._addToLayout=function(out){
  18. out.push(this);
  19. }
  20. //TODO:coverage
  21. __proto.reset=function(){
  22. return this;
  23. }
  24. __proto.destroy=function(){
  25. Pool.recover(HTMLElement.getClassName(this),this.reset());
  26. }
  27. __proto._setParent=function(value){}
  28. //TODO:coverage
  29. __proto._getCSSStyle=function(){
  30. if (!HTMLBrElement.brStyle){
  31. HTMLBrElement.brStyle=new HTMLStyle();
  32. HTMLBrElement.brStyle.setLineElement(true);
  33. HTMLBrElement.brStyle.block=true;
  34. }
  35. return HTMLBrElement.brStyle;
  36. }
  37. __proto.renderSelfToGraphic=function(graphic,gX,gY,recList){}
  38. __getset(0,__proto,'URI',null,function(value){
  39. });
  40. __getset(0,__proto,'parent',null,function(value){
  41. });
  42. __getset(0,__proto,'href',null,function(value){
  43. });
  44. HTMLBrElement.brStyle=null;
  45. return HTMLBrElement;
  46. })()
  47. /**
  48. *@private
  49. */
  50. //class laya.html.utils.LayoutLine
  51. var LayoutLine=(function(){
  52. function LayoutLine(){
  53. this.x=0;
  54. this.y=0;
  55. this.w=0;
  56. this.h=0;
  57. this.wordStartIndex=0;
  58. this.minTextHeight=99999;
  59. this.mWidth=0;
  60. this.elements=new Array;
  61. }
  62. __class(LayoutLine,'laya.html.utils.LayoutLine');
  63. var __proto=LayoutLine.prototype;
  64. /**
  65. *底对齐(默认)
  66. *@param left
  67. *@param width
  68. *@param dy
  69. *@param align 水平
  70. *@param valign 垂直
  71. *@param lineHeight 行高
  72. */
  73. __proto.updatePos=function(left,width,lineNum,dy,align,valign,lineHeight){
  74. var w=0;
  75. var one
  76. if (this.elements.length > 0){
  77. one=this.elements[this.elements.length-1];
  78. w=one.x+one.width-this.elements[0].x;
  79. }
  80. lineHeight=lineHeight || this.h;
  81. var dx=0,ddy=NaN;
  82. if (align===/*laya.html.utils.HTMLStyle.ALIGN_CENTER*/"center")dx=(width-w)/ 2;
  83. if (align===/*laya.html.utils.HTMLStyle.ALIGN_RIGHT*/"right")dx=(width-w);
  84. for (var i=0,n=this.elements.length;i < n;i++){
  85. one=this.elements[i];
  86. var tCSSStyle=one._getCSSStyle();
  87. dx!==0 && (one.x+=dx);
  88. switch (tCSSStyle.valign){
  89. case "top":
  90. one.y=dy;
  91. break ;
  92. case "middle":;
  93. var tMinTextHeight=0;
  94. if (this.minTextHeight !=99999)tMinTextHeight=this.minTextHeight;
  95. var tBottomLineY=(tMinTextHeight+lineHeight)/ 2;
  96. tBottomLineY=Math.max(tBottomLineY,this.h);
  97. if ((one instanceof laya.html.dom.HTMLImageElement ))ddy=dy+tBottomLineY-one.height;
  98. else ddy=dy+tBottomLineY-one.height;
  99. one.y=ddy;
  100. break ;
  101. case "bottom":
  102. one.y=dy+(lineHeight-one.height);
  103. break ;
  104. }
  105. }
  106. }
  107. return LayoutLine;
  108. })()
  109. /**
  110. *@private
  111. */
  112. //class laya.html.utils.HTMLStyle
  113. var HTMLStyle=(function(){
  114. function HTMLStyle(){
  115. /**@private */
  116. //this._type=0;
  117. //this.fontSize=0;
  118. //this.family=null;
  119. //this.color=null;
  120. //this.ower=null;
  121. //this._extendStyle=null;
  122. //this.textDecoration=null;
  123. /**
  124. *文本背景颜色,以字符串表示。
  125. */
  126. //this.bgColor=null;
  127. /**
  128. *文本边框背景颜色,以字符串表示。
  129. */
  130. //this.borderColor=null;
  131. this.padding=HTMLStyle._PADDING;
  132. this.reset();
  133. }
  134. __class(HTMLStyle,'laya.html.utils.HTMLStyle');
  135. var __proto=HTMLStyle.prototype;
  136. //TODO:coverage
  137. __proto._getExtendStyle=function(){
  138. if (this._extendStyle===HTMLExtendStyle.EMPTY)this._extendStyle=HTMLExtendStyle.create();
  139. return this._extendStyle;
  140. }
  141. /**
  142. *重置,方便下次复用
  143. */
  144. __proto.reset=function(){
  145. this.ower=null;
  146. this._type=0;
  147. this.wordWrap=true;
  148. this.fontSize=Text.defaultFontSize;
  149. this.family=Text.defaultFont;
  150. this.color="#000000";
  151. this.valign="top";
  152. this.padding=HTMLStyle._PADDING;
  153. this.bold=false;
  154. this.italic=false;
  155. this.align="left";
  156. this.textDecoration=null;
  157. this.bgColor=null;
  158. this.borderColor=null;
  159. if (this._extendStyle)this._extendStyle.recover();
  160. this._extendStyle=HTMLExtendStyle.EMPTY;
  161. return this;
  162. }
  163. //TODO:coverage
  164. __proto.recover=function(){
  165. Pool.recover("HTMLStyle",this.reset());
  166. }
  167. /**
  168. *复制传入的 CSSStyle 属性值。
  169. *@param src 待复制的 CSSStyle 对象。
  170. */
  171. __proto.inherit=function(src){
  172. var i=0,len=0;
  173. var props;
  174. props=HTMLStyle._inheritProps;
  175. len=props.length;
  176. var key;
  177. for (i=0;i < len;i++){
  178. key=props[i];
  179. this[key]=src[key];
  180. }
  181. }
  182. /**@private */
  183. __proto._widthAuto=function(){
  184. return (this._type & 0x40000)!==0;
  185. }
  186. /**@inheritDoc */
  187. __proto.widthed=function(sprite){
  188. return (this._type & 0x8)!=0;
  189. }
  190. //TODO:coverage
  191. __proto._calculation=function(type,value){
  192. return false;
  193. }
  194. /**
  195. *是否已设置高度。
  196. *@param sprite 显示对象 Sprite。
  197. *@return 一个Boolean 表示是否已设置高度。
  198. */
  199. __proto.heighted=function(sprite){
  200. return (this._type & 0x2000)!=0;
  201. }
  202. /**
  203. *设置宽高。
  204. *@param w 宽度。
  205. *@param h 高度。
  206. */
  207. __proto.size=function(w,h){
  208. var ower=this.ower;
  209. var resize=false;
  210. if (w!==-1 && w !=ower.width){
  211. this._type |=0x8;
  212. ower.width=w;
  213. resize=true;
  214. }
  215. if (h!==-1 && h !=ower.height){
  216. this._type |=0x2000;
  217. ower.height=h;
  218. resize=true;
  219. }
  220. if (resize){
  221. ower._layoutLater();
  222. }
  223. }
  224. /**
  225. *是否是行元素。
  226. */
  227. __proto.getLineElement=function(){
  228. return (this._type & 0x10000)!=0;
  229. }
  230. __proto.setLineElement=function(value){
  231. value ? (this._type |=0x10000):(this._type &=(~0x10000));
  232. }
  233. //TODO:coverage
  234. __proto._enableLayout=function(){
  235. return (this._type & 0x2)===0 && (this._type & 0x4)===0;
  236. }
  237. /**
  238. *设置 CSS 样式字符串。
  239. *@param text CSS样式字符串。
  240. */
  241. __proto.cssText=function(text){
  242. this.attrs(HTMLStyle.parseOneCSS(text,';'));
  243. }
  244. /**
  245. *根据传入的属性名、属性值列表,设置此对象的属性值。
  246. *@param attrs 属性名与属性值列表。
  247. */
  248. __proto.attrs=function(attrs){
  249. if (attrs){
  250. for (var i=0,n=attrs.length;i < n;i++){
  251. var attr=attrs[i];
  252. this[attr[0]]=attr[1];
  253. }
  254. }
  255. }
  256. /**
  257. *字体样式字符串。
  258. */
  259. __getset(0,__proto,'font',function(){
  260. return (this.italic ? "italic " :"")+(this.bold ? "bold " :"")+this.fontSize+"px "+(Browser.onIPhone ? (Text.fontFamilyMap[this.family] || this.family):this.family);
  261. },function(value){
  262. var strs=value.split(' ');
  263. for (var i=0,n=strs.length;i < n;i++){
  264. var str=strs[i];
  265. switch (str){
  266. case 'italic':
  267. this.italic=true;
  268. continue ;
  269. case 'bold':
  270. this.bold=true;
  271. continue ;
  272. }
  273. if (str.indexOf('px')> 0){
  274. this.fontSize=parseInt(str);
  275. this.family=strs[i+1];
  276. i++;
  277. continue ;
  278. }
  279. }
  280. });
  281. __getset(0,__proto,'href',function(){
  282. return this._extendStyle.href;
  283. },function(value){
  284. if (value===this._extendStyle.href)return;
  285. this._getExtendStyle().href=value;
  286. });
  287. /**行高。 */
  288. __getset(0,__proto,'lineHeight',function(){
  289. return this._extendStyle.lineHeight;
  290. },function(value){
  291. if (this._extendStyle.lineHeight===value)return;
  292. this._getExtendStyle().lineHeight=value;
  293. });
  294. /**
  295. *<p>描边颜色,以字符串表示。</p>
  296. *@default "#000000";
  297. */
  298. __getset(0,__proto,'strokeColor',function(){
  299. return this._extendStyle.strokeColor;
  300. },function(value){
  301. if (this._extendStyle.strokeColor===value)return;
  302. this._getExtendStyle().strokeColor=value;
  303. });
  304. /**
  305. *<p>描边宽度(以像素为单位)。</p>
  306. *默认值0,表示不描边。
  307. *@default 0
  308. */
  309. __getset(0,__proto,'stroke',function(){
  310. return this._extendStyle.stroke;
  311. },function(value){
  312. if (this._extendStyle.stroke===value)return;
  313. this._getExtendStyle().stroke=value;
  314. });
  315. /**
  316. *<p>垂直行间距(以像素为单位)</p>
  317. */
  318. __getset(0,__proto,'leading',function(){
  319. return this._extendStyle.leading;
  320. },function(value){
  321. if (this._extendStyle.leading===value)return;
  322. this._getExtendStyle().leading=value;
  323. });
  324. /**
  325. *<p>表示使用此文本格式的文本段落的水平对齐方式。</p>
  326. *@default "left"
  327. */
  328. __getset(0,__proto,'align',function(){
  329. var v=this._type & 0x30;
  330. return HTMLStyle.align_Value[v];
  331. },function(v){
  332. if (!(v in HTMLStyle.alignVDic))return;
  333. this._type &=(~0x30);
  334. this._type |=HTMLStyle.alignVDic[v];
  335. });
  336. /**
  337. *<p>表示使用此文本格式的文本段落的水平对齐方式。</p>
  338. *@default "left"
  339. */
  340. __getset(0,__proto,'valign',function(){
  341. var v=this._type & 0xc0;
  342. return HTMLStyle.vAlign_Value[v];
  343. },function(v){
  344. if (!(v in HTMLStyle.alignVDic))return;
  345. this._type &=(~0xc0);
  346. this._type |=HTMLStyle.alignVDic[v];
  347. });
  348. /**
  349. *是否显示为块级元素。
  350. */
  351. /**表示元素是否显示为块级元素。*/
  352. __getset(0,__proto,'block',function(){
  353. return (this._type & 0x1)!=0;
  354. },function(value){
  355. value ? (this._type |=0x1):(this._type &=(~0x1));
  356. });
  357. /**
  358. *表示是否换行。
  359. */
  360. __getset(0,__proto,'wordWrap',function(){
  361. return (this._type & 0x20000)===0;
  362. },function(value){
  363. value ? (this._type &=~0x20000):(this._type |=0x20000);
  364. });
  365. /**是否为粗体*/
  366. __getset(0,__proto,'bold',function(){
  367. return (this._type & 0x400)!=0;
  368. },function(value){
  369. value ? (this._type |=0x400):(this._type &=~0x400);
  370. });
  371. /**
  372. *表示使用此文本格式的文本是否为斜体。
  373. *@default false
  374. */
  375. __getset(0,__proto,'italic',function(){
  376. return (this._type & 0x800)!=0;
  377. },function(value){
  378. value ? (this._type |=0x800):(this._type &=~0x800);
  379. });
  380. /**
  381. *设置如何处理元素内的空白。
  382. */
  383. __getset(0,__proto,'whiteSpace',function(){
  384. return (this._type & 0x20000)? "nowrap" :"";
  385. },function(type){
  386. type==="nowrap" && (this._type |=0x20000);
  387. type==="none" && (this._type &=~0x20000);
  388. });
  389. /**
  390. *宽度。
  391. */
  392. __getset(0,__proto,'width',null,function(w){
  393. this._type |=0x8;
  394. if ((typeof w=='string')){
  395. var offset=w.indexOf('auto');
  396. if (offset >=0){
  397. this._type |=0x40000;
  398. w=w.substr(0,offset);
  399. }
  400. if (this._calculation("width",w))return;
  401. w=parseInt(w);
  402. }
  403. this.size(w,-1);
  404. });
  405. /**
  406. *高度。
  407. */
  408. __getset(0,__proto,'height',null,function(h){
  409. this._type |=0x2000;
  410. if ((typeof h=='string')){
  411. if (this._calculation("height",h))return;
  412. h=parseInt(h);
  413. }
  414. this.size(-1,h);
  415. });
  416. /**
  417. *间距。
  418. */
  419. __getset(0,__proto,'letterSpacing',function(){
  420. return this._extendStyle.letterSpacing;
  421. },function(d){
  422. ((typeof d=='string'))&& (d=parseInt(d+""));
  423. if (d==this._extendStyle.letterSpacing)return;
  424. this._getExtendStyle().letterSpacing=d;
  425. });
  426. /**
  427. *元素的定位类型。
  428. */
  429. __getset(0,__proto,'position',function(){
  430. return (this._type & 0x4)? "absolute" :"";
  431. },function(value){
  432. value==="absolute" ? (this._type |=0x4):(this._type &=~0x4);
  433. });
  434. /**@inheritDoc */
  435. __getset(0,__proto,'absolute',function(){
  436. return (this._type & 0x4)!==0;
  437. });
  438. /**@inheritDoc */
  439. __getset(0,__proto,'paddingLeft',function(){
  440. return this.padding[3];
  441. });
  442. /**@inheritDoc */
  443. __getset(0,__proto,'paddingTop',function(){
  444. return this.padding[0];
  445. });
  446. HTMLStyle.create=function(){
  447. return Pool.getItemByClass("HTMLStyle",HTMLStyle);
  448. }
  449. HTMLStyle.parseOneCSS=function(text,clipWord){
  450. var out=[];
  451. var attrs=text.split(clipWord);
  452. var valueArray;
  453. for (var i=0,n=attrs.length;i < n;i++){
  454. var attr=attrs[i];
  455. var ofs=attr.indexOf(':');
  456. var name=attr.substr(0,ofs).replace(/^\s+|\s+$/g,'');
  457. if (name.length===0)continue ;
  458. var value=attr.substr(ofs+1).replace(/^\s+|\s+$/g,'');
  459. var one=[name,value];
  460. switch (name){
  461. case 'italic':
  462. case 'bold':
  463. one[1]=value=="true";
  464. break ;
  465. case "font-weight":
  466. if (value=="bold"){
  467. one[1]=true;
  468. one[0]="bold";
  469. }
  470. break ;
  471. case 'line-height':
  472. one[0]='lineHeight';
  473. one[1]=parseInt(value);
  474. break ;
  475. case 'font-size':
  476. one[0]='fontSize';
  477. one[1]=parseInt(value);
  478. break ;
  479. case 'stroke':
  480. one[0]='stroke';
  481. one[1]=parseInt(value);
  482. break ;
  483. case 'padding':
  484. valueArray=value.split(' ');
  485. valueArray.length > 1 || (valueArray[1]=valueArray[2]=valueArray[3]=valueArray[0]);
  486. one[1]=[parseInt(valueArray[0]),parseInt(valueArray[1]),parseInt(valueArray[2]),parseInt(valueArray[3])];
  487. break ;
  488. default :
  489. (one[0]=HTMLStyle._CSSTOVALUE[name])|| (one[0]=name);
  490. }
  491. out.push(one);
  492. }
  493. return out;
  494. }
  495. HTMLStyle.parseCSS=function(text,uri){
  496. var one;
  497. while ((one=HTMLStyle._parseCSSRegExp.exec(text))!=null){
  498. HTMLStyle.styleSheets[one[1]]=HTMLStyle.parseOneCSS(one[2],';');
  499. }
  500. }
  501. HTMLStyle._CSSTOVALUE={'letter-spacing':'letterSpacing','white-space':'whiteSpace','line-height':'lineHeight','font-family':'family','vertical-align':'valign','text-decoration':'textDecoration','background-color':'bgColor','border-color':'borderColor'};
  502. HTMLStyle._parseCSSRegExp=new RegExp("([\.\#]\\w+)\\s*{([\\s\\S]*?)}","g");
  503. HTMLStyle.ALIGN_LEFT="left";
  504. HTMLStyle.ALIGN_CENTER="center";
  505. HTMLStyle.ALIGN_RIGHT="right";
  506. HTMLStyle.VALIGN_TOP="top";
  507. HTMLStyle.VALIGN_MIDDLE="middle";
  508. HTMLStyle.VALIGN_BOTTOM="bottom";
  509. HTMLStyle.styleSheets={};
  510. HTMLStyle.ADDLAYOUTED=0x200;
  511. HTMLStyle._PADDING=[0,0,0,0];
  512. HTMLStyle._HEIGHT_SET=0x2000;
  513. HTMLStyle._LINE_ELEMENT=0x10000;
  514. HTMLStyle._NOWARP=0x20000;
  515. HTMLStyle._WIDTHAUTO=0x40000;
  516. HTMLStyle._BOLD=0x400;
  517. HTMLStyle._ITALIC=0x800;
  518. HTMLStyle._CSS_BLOCK=0x1;
  519. HTMLStyle._DISPLAY_NONE=0x2;
  520. HTMLStyle._ABSOLUTE=0x4;
  521. HTMLStyle._WIDTH_SET=0x8;
  522. HTMLStyle._ALIGN=0x30;
  523. HTMLStyle._VALIGN=0xc0;
  524. __static(HTMLStyle,
  525. ['_inheritProps',function(){return this._inheritProps=["italic","align","valign","leading","stroke","strokeColor","bold","fontSize","lineHeight","wordWrap","color"];},'alignVDic',function(){return this.alignVDic={"left":0,"center":0x10,"right":0x20,"top":0,"middle":0x40,"bottom":0x80};},'align_Value',function(){return this.align_Value={0:"left",0x10:"center",0x20:"right"};},'vAlign_Value',function(){return this.vAlign_Value={0:"top",0x40:"middle",0x80:"bottom"};}
  526. ]);
  527. return HTMLStyle;
  528. })()
  529. /**
  530. *@private
  531. */
  532. //class laya.html.dom.HTMLDocument
  533. var HTMLDocument=(function(){
  534. function HTMLDocument(){
  535. this.all=new Array;
  536. this.styleSheets=HTMLStyle.styleSheets;
  537. }
  538. __class(HTMLDocument,'laya.html.dom.HTMLDocument');
  539. var __proto=HTMLDocument.prototype;
  540. //TODO:coverage
  541. __proto.getElementById=function(id){
  542. return this.all[id];
  543. }
  544. //TODO:coverage
  545. __proto.setElementById=function(id,e){
  546. this.all[id]=e;
  547. }
  548. __static(HTMLDocument,
  549. ['document',function(){return this.document=new HTMLDocument();}
  550. ]);
  551. return HTMLDocument;
  552. })()
  553. /**
  554. *@private
  555. */
  556. //class laya.html.dom.HTMLElement
  557. var HTMLElement=(function(){
  558. function HTMLElement(){
  559. //this.URI=null;
  560. //this.parent=null;
  561. //this._style=null;
  562. //this._text=null;
  563. //this._children=null;
  564. //this._x=NaN;
  565. //this._y=NaN;
  566. //this._width=NaN;
  567. //this._height=NaN;
  568. this._creates();
  569. this.reset();
  570. }
  571. __class(HTMLElement,'laya.html.dom.HTMLElement');
  572. var __proto=HTMLElement.prototype;
  573. __proto._creates=function(){
  574. this._style=HTMLStyle.create();
  575. }
  576. /**
  577. *重置
  578. */
  579. __proto.reset=function(){
  580. this.URI=null;
  581. this.parent=null;
  582. this._style.reset();
  583. this._style.ower=this;
  584. this._style.valign="middle";
  585. if (this._text && this._text.words){
  586. var words=this._text.words;
  587. var i=0,len=0;
  588. len=words.length;
  589. var tChar;
  590. for (i=0;i < len;i++){
  591. tChar=words[i];
  592. if (tChar)tChar.recover();
  593. }
  594. }
  595. this._text=HTMLElement._EMPTYTEXT;
  596. if (this._children)this._children.length=0;
  597. this._x=this._y=this._width=this._height=0;
  598. return this;
  599. }
  600. /**@private */
  601. __proto._getCSSStyle=function(){
  602. return this._style;
  603. }
  604. /**@private */
  605. __proto._addChildsToLayout=function(out){
  606. var words=this._getWords();
  607. if (words==null && (!this._children || this._children.length==0))
  608. return false;
  609. if (words){
  610. for (var i=0,n=words.length;i < n;i++){
  611. out.push(words[i]);
  612. }
  613. }
  614. if (this._children)
  615. this._children.forEach(function(o,index,array){
  616. var _style=o._style;
  617. _style._enableLayout && _style._enableLayout()&& o._addToLayout(out);
  618. });
  619. return true;
  620. }
  621. /**@private */
  622. __proto._addToLayout=function(out){
  623. if (!this._style)return;
  624. var style=this._style;
  625. if (style.absolute)return;
  626. style.block ? out.push(this):(this._addChildsToLayout(out)&& (this.x=this.y=0));
  627. }
  628. __proto.repaint=function(recreate){
  629. (recreate===void 0)&& (recreate=false);
  630. this.parentRepaint(recreate);
  631. }
  632. __proto.parentRepaint=function(recreate){
  633. (recreate===void 0)&& (recreate=false);
  634. if (this.parent)this.parent.repaint(recreate);
  635. }
  636. __proto._setParent=function(value){
  637. if ((value instanceof laya.html.dom.HTMLElement )){
  638. var p=value;
  639. this.URI || (this.URI=p.URI);
  640. if (this.style)
  641. this.style.inherit(p.style);
  642. }
  643. }
  644. __proto.appendChild=function(c){
  645. return this.addChild(c);
  646. }
  647. __proto.addChild=function(c){
  648. if (c.parent)c.parent.removeChild(c);
  649. if (!this._children)this._children=[];
  650. this._children.push(c);
  651. c.parent=this;
  652. c._setParent(this);
  653. this.repaint();
  654. return c;
  655. }
  656. __proto.removeChild=function(c){
  657. if (!this._children)return null;
  658. var i=0,len=0;
  659. len=this._children.length;
  660. for (i=0;i < len;i++){
  661. if (this._children[i]==c){
  662. this._children.splice(i,1);
  663. return c;
  664. }
  665. }
  666. return null;
  667. }
  668. /**
  669. *<p>销毁此对象。destroy对象默认会把自己从父节点移除,并且清理自身引用关系,等待js自动垃圾回收机制回收。destroy后不能再使用。</p>
  670. *<p>destroy时会移除自身的事情监听,自身的timer监听,移除子对象及从父节点移除自己。</p>
  671. *@param destroyChild (可选)是否同时销毁子节点,若值为true,则销毁子节点,否则不销毁子节点。
  672. */
  673. __proto.destroy=function(){
  674. if (this._children){
  675. this.destroyChildren();
  676. this._children.length=0;
  677. }
  678. Pool.recover(HTMLElement.getClassName(this),this.reset());
  679. }
  680. /**
  681. *销毁所有子对象,不销毁自己本身。
  682. */
  683. __proto.destroyChildren=function(){
  684. if (this._children){
  685. for (var i=this._children.length-1;i >-1;i--){
  686. this._children[i].destroy();
  687. }
  688. this._children.length=0;
  689. }
  690. }
  691. __proto._getWords=function(){
  692. if (!this._text)return null;
  693. var txt=this._text.text;
  694. if (!txt || txt.length===0)
  695. return null;
  696. var words=this._text.words;
  697. if (words && words.length===txt.length)
  698. return words;
  699. words===null && (this._text.words=words=[]);
  700. words.length=txt.length;
  701. var size;
  702. var style=this.style;
  703. var fontStr=style.font;
  704. for (var i=0,n=txt.length;i < n;i++){
  705. size=Utils.measureText(txt.charAt(i),fontStr);
  706. words[i]=HTMLChar.create().setData(txt.charAt(i),size.width,size.height || style.fontSize,style);
  707. }
  708. return words;
  709. }
  710. //TODO:coverage
  711. __proto._isChar=function(){
  712. return false;
  713. }
  714. __proto._layoutLater=function(){
  715. var style=this.style;
  716. if ((style._type & /*laya.html.utils.HTMLStyle.ADDLAYOUTED*/0x200))
  717. return;
  718. if (style.widthed(this)&& ((this._children && this._children.length > 0)|| this._getWords()!=null)&& style.block){
  719. Layout.later(this);
  720. style._type |=/*laya.html.utils.HTMLStyle.ADDLAYOUTED*/0x200;
  721. }else {
  722. this.parent && this.parent._layoutLater();
  723. }
  724. }
  725. __proto._setAttributes=function(name,value){
  726. switch (name){
  727. case 'style':
  728. this.style.cssText(value);
  729. break ;
  730. case 'class':
  731. this.className=value;
  732. break ;
  733. case 'x':
  734. this.x=parseFloat(value);
  735. break ;
  736. case 'y':
  737. this.y=parseFloat(value);
  738. break ;
  739. case 'width':
  740. this.width=parseFloat(value);
  741. break ;
  742. case 'height':
  743. this.height=parseFloat(value);
  744. break ;
  745. default :
  746. this[name]=value;
  747. }
  748. }
  749. __proto.formatURL=function(url){
  750. if (!this.URI)return url;
  751. return HTMLElement.formatURL1(url,this.URI ? this.URI.path :null);
  752. }
  753. __proto.drawToGraphic=function(graphic,gX,gY,recList){
  754. gX+=this.x;
  755. gY+=this.y;
  756. var cssStyle=this.style;
  757. if (cssStyle.paddingLeft){
  758. gX+=cssStyle.paddingLeft;
  759. }
  760. if (cssStyle.paddingTop){
  761. gY+=cssStyle.paddingTop;
  762. }
  763. if (cssStyle.bgColor !=null || cssStyle.borderColor){
  764. graphic.drawRect(gX,gY,this.width,this.height,cssStyle.bgColor,cssStyle.borderColor,1);
  765. }
  766. this.renderSelfToGraphic(graphic,gX,gY,recList);
  767. var i=0,len=0;
  768. var tChild;
  769. if (this._children && this._children.length > 0){
  770. len=this._children.length;
  771. for (i=0;i < len;i++){
  772. tChild=this._children[i];
  773. if (tChild.drawToGraphic !=null)
  774. tChild.drawToGraphic(graphic,gX,gY,recList);
  775. }
  776. }
  777. }
  778. __proto.renderSelfToGraphic=function(graphic,gX,gY,recList){
  779. var cssStyle=this.style;
  780. var words=this._getWords();
  781. var i=0,len=0;
  782. if (words){
  783. len=words.length;
  784. var a;
  785. if (cssStyle){
  786. var font=cssStyle.font;
  787. var color=cssStyle.color;
  788. if (cssStyle.stroke){
  789. var stroke=cssStyle.stroke;
  790. stroke=parseInt(stroke);
  791. var strokeColor=cssStyle.strokeColor;
  792. graphic.fillBorderWords(words,gX,gY,font,color,strokeColor,stroke);
  793. }else {
  794. graphic.fillWords(words,gX,gY,font,color);
  795. }
  796. if (this.href){
  797. var lastIndex=words.length-1;
  798. var lastWords=words[lastIndex];
  799. var lineY=lastWords.y+lastWords.height;
  800. if (lastWords.y==words[0].y){
  801. if(cssStyle.textDecoration!="none")
  802. graphic.drawLine(words[0].x,lineY,lastWords.x+lastWords.width,lineY,color,1);
  803. var hitRec=HTMLHitRect.create();
  804. hitRec.rec.setTo(words[0].x,lastWords.y,lastWords.x+lastWords.width-words[0].x,lastWords.height);
  805. hitRec.href=this.href;
  806. recList.push(hitRec);
  807. }else{
  808. this.workLines(words,graphic,recList);
  809. }
  810. }
  811. }
  812. }
  813. }
  814. __proto.workLines=function(wordList,g,recList){
  815. var cssStyle=this.style;
  816. var hasLine=false;
  817. hasLine=cssStyle.textDecoration !="none";
  818. var i=0,len=0;
  819. len=wordList.length;
  820. var tStartWord;
  821. tStartWord=wordList[i];
  822. var tEndWord;
  823. tEndWord=tStartWord;
  824. if (!tStartWord)return;
  825. var tword;
  826. for (i=1;i < len;i++){
  827. tword=wordList[i];
  828. if (tword.y !=tStartWord.y){
  829. this.createOneLine(tStartWord,tEndWord,hasLine,g,recList);
  830. tStartWord=tword;
  831. tEndWord=tword;
  832. }else{
  833. tEndWord=tword;
  834. }
  835. }
  836. this.createOneLine(tStartWord,tEndWord,hasLine,g,recList);
  837. }
  838. __proto.createOneLine=function(startWord,lastWords,hasLine,graphic,recList){
  839. var lineY=lastWords.y+lastWords.height;
  840. if(hasLine)
  841. graphic.drawLine(startWord.x,lineY,lastWords.x+lastWords.width,lineY,this.color,1);
  842. var hitRec=HTMLHitRect.create();
  843. hitRec.rec.setTo(startWord.x,lastWords.y,lastWords.x+lastWords.width-startWord.x,lastWords.height);
  844. hitRec.href=this.href;
  845. recList.push(hitRec);
  846. }
  847. __getset(0,__proto,'href',function(){
  848. if (!this._style)return null;
  849. return this._style.href;
  850. },function(url){
  851. if (!this._style)return;
  852. if (url !=this._style.href){
  853. this._style.href=url;
  854. this.repaint();
  855. }
  856. });
  857. __getset(0,__proto,'color',null,function(value){
  858. this.style.color=value;
  859. });
  860. __getset(0,__proto,'id',null,function(value){
  861. HTMLDocument.document.setElementById(value,this);
  862. });
  863. __getset(0,__proto,'innerTEXT',function(){
  864. return this._text.text;
  865. },function(value){
  866. if (this._text===HTMLElement._EMPTYTEXT){
  867. this._text={text:value,words:null};
  868. }else {
  869. this._text.text=value;
  870. this._text.words && (this._text.words.length=0);
  871. }
  872. this.repaint();
  873. });
  874. __getset(0,__proto,'style',function(){
  875. return this._style;
  876. });
  877. __getset(0,__proto,'width',function(){
  878. return this._width;
  879. },function(value){
  880. if (this._width!==value){
  881. this._width=value;
  882. this.repaint();
  883. }
  884. });
  885. __getset(0,__proto,'x',function(){
  886. return this._x;
  887. },function(v){
  888. if (this._x !=v){
  889. this._x=v;
  890. this.parentRepaint();
  891. }
  892. });
  893. __getset(0,__proto,'y',function(){
  894. return this._y;
  895. },function(v){
  896. if (this._y !=v){
  897. this._y=v;
  898. this.parentRepaint();
  899. }
  900. });
  901. __getset(0,__proto,'height',function(){
  902. return this._height;
  903. },function(value){
  904. if (this._height!==value){
  905. this._height=value;
  906. this.repaint();
  907. }
  908. });
  909. __getset(0,__proto,'className',null,function(value){
  910. this.style.attrs(HTMLDocument.document.styleSheets['.'+value]);
  911. });
  912. HTMLElement.formatURL1=function(url,basePath){
  913. if (!url)return "null path";
  914. if (!basePath)basePath=URL.basePath;
  915. if (url.indexOf(":")> 0)return url;
  916. if (URL.customFormat !=null)url=URL.customFormat(url);
  917. if (url.indexOf(":")> 0)return url;
  918. var char1=url.charAt(0);
  919. if (char1==="."){
  920. return URL._formatRelativePath (basePath+url);
  921. }else if (char1==='~'){
  922. return URL.rootPath+url.substring(1);
  923. }else if (char1==="d"){
  924. if (url.indexOf("data:image")===0)return url;
  925. }else if (char1==="/"){
  926. return url;
  927. }
  928. return basePath+url;
  929. }
  930. HTMLElement.getClassName=function(tar){
  931. if ((typeof tar=='function'))return tar.name;
  932. return tar["constructor"].name;
  933. }
  934. HTMLElement._EMPTYTEXT={text:null,words:null};
  935. return HTMLElement;
  936. })()
  937. /**
  938. *@private
  939. */
  940. //class laya.html.utils.HTMLParse
  941. var HTMLParse=(function(){
  942. function HTMLParse(){}
  943. __class(HTMLParse,'laya.html.utils.HTMLParse');
  944. HTMLParse.getInstance=function(type){
  945. var rst=Pool.getItem(HTMLParse._htmlClassMapShort[type]);
  946. if (!rst){
  947. rst=ClassUtils.getInstance(type);
  948. }
  949. return rst;
  950. }
  951. HTMLParse.parse=function(ower,xmlString,url){
  952. xmlString=xmlString.replace(/<br>/g,"<br/>");
  953. xmlString="<root>"+xmlString+"</root>";
  954. xmlString=xmlString.replace(HTMLParse.spacePattern,HTMLParse.char255);
  955. var xml=Utils.parseXMLFromString(xmlString);
  956. HTMLParse._parseXML(ower,xml.childNodes[0].childNodes,url);
  957. }
  958. HTMLParse._parseXML=function(parent,xml,url,href){
  959. var i=0,n=0;
  960. if (xml.join || xml.item){
  961. for (i=0,n=xml.length;i < n;++i){
  962. HTMLParse._parseXML(parent,xml[i],url,href);
  963. }
  964. }else {
  965. var node;
  966. var nodeName;
  967. if (xml.nodeType==3){
  968. var txt;
  969. if ((parent instanceof laya.html.dom.HTMLDivParser )){
  970. if (xml.nodeName==null){
  971. xml.nodeName="#text";
  972. }
  973. nodeName=xml.nodeName.toLowerCase();
  974. txt=xml.textContent.replace(/^\s+|\s+$/g,'');
  975. if (txt.length > 0){
  976. node=HTMLParse.getInstance(nodeName);
  977. if (node){
  978. parent.addChild(node);
  979. ((node).innerTEXT=txt.replace(HTMLParse.char255AndOneSpacePattern," "));
  980. }
  981. }
  982. }else {
  983. txt=xml.textContent.replace(/^\s+|\s+$/g,'');
  984. if (txt.length > 0){
  985. ((parent).innerTEXT=txt.replace(HTMLParse.char255AndOneSpacePattern," "));
  986. }
  987. }
  988. return;
  989. }else {
  990. nodeName=xml.nodeName.toLowerCase();
  991. if (nodeName=="#comment")return;
  992. node=HTMLParse.getInstance(nodeName);
  993. if (node){
  994. if (nodeName=="p"){
  995. parent.addChild(HTMLParse.getInstance("br"));
  996. node=parent.addChild(node);
  997. parent.addChild(HTMLParse.getInstance("br"));
  998. }else{
  999. node=parent.addChild(node);
  1000. }
  1001. (node).URI=url;
  1002. (node).href=href;
  1003. var attributes=xml.attributes;
  1004. if (attributes && attributes.length > 0){
  1005. for (i=0,n=attributes.length;i < n;++i){
  1006. var attribute=attributes[i];
  1007. var attrName=attribute.nodeName;
  1008. var value=attribute.value;
  1009. node._setAttributes(attrName,value);
  1010. }
  1011. }
  1012. HTMLParse._parseXML(node,xml.childNodes,url,(node).href);
  1013. }else {
  1014. HTMLParse._parseXML(parent,xml.childNodes,url,href);
  1015. }
  1016. }
  1017. }
  1018. }
  1019. HTMLParse.char255=String.fromCharCode(255);
  1020. HTMLParse.spacePattern=/&nbsp;|&#160;/g;
  1021. HTMLParse.char255AndOneSpacePattern=new RegExp(String.fromCharCode(255)+"|(\\s+)","g");
  1022. HTMLParse._htmlClassMapShort={'div':'HTMLDivParser','p':'HTMLElement','img':'HTMLImageElement','span':'HTMLElement','br':'HTMLBrElement','style':'HTMLStyleElement','font':'HTMLElement','a':'HTMLElement','#text':'HTMLElement','link':'HTMLLinkElement'};
  1023. return HTMLParse;
  1024. })()
  1025. /**
  1026. *@private
  1027. */
  1028. //class laya.html.utils.HTMLExtendStyle
  1029. var HTMLExtendStyle=(function(){
  1030. function HTMLExtendStyle(){
  1031. /**
  1032. *<p>描边宽度(以像素为单位)。</p>
  1033. *默认值0,表示不描边。
  1034. *@default 0
  1035. */
  1036. //this.stroke=NaN;
  1037. /**
  1038. *<p>描边颜色,以字符串表示。</p>
  1039. *@default "#000000";
  1040. */
  1041. //this.strokeColor=null;
  1042. /**
  1043. *<p>垂直行间距(以像素为单位)</p>
  1044. */
  1045. //this.leading=NaN;
  1046. /**行高。 */
  1047. //this.lineHeight=NaN;
  1048. //this.letterSpacing=0;
  1049. //this.href=null;
  1050. this.reset();
  1051. }
  1052. __class(HTMLExtendStyle,'laya.html.utils.HTMLExtendStyle');
  1053. var __proto=HTMLExtendStyle.prototype;
  1054. __proto.reset=function(){
  1055. this.stroke=0;
  1056. this.strokeColor="#000000";
  1057. this.leading=0;
  1058. this.lineHeight=0;
  1059. this.letterSpacing=0;
  1060. this.href=null;
  1061. return this;
  1062. }
  1063. __proto.recover=function(){
  1064. if (this==HTMLExtendStyle.EMPTY)return;
  1065. Pool.recover("HTMLExtendStyle",this.reset());
  1066. }
  1067. HTMLExtendStyle.create=function(){
  1068. return Pool.getItemByClass("HTMLExtendStyle",HTMLExtendStyle);
  1069. }
  1070. HTMLExtendStyle.EMPTY=new HTMLExtendStyle();
  1071. return HTMLExtendStyle;
  1072. })()
  1073. /**
  1074. *@private
  1075. *HTML的布局类
  1076. *对HTML的显示对象进行排版
  1077. */
  1078. //class laya.html.utils.Layout
  1079. var Layout=(function(){
  1080. function Layout(){}
  1081. __class(Layout,'laya.html.utils.Layout');
  1082. Layout.later=function(element){
  1083. if (Layout._will==null){
  1084. Layout._will=[];
  1085. Laya.stage.frameLoop(1,null,function(){
  1086. if (Layout._will.length < 1)
  1087. return;
  1088. for (var i=0;i < Layout._will.length;i++){
  1089. laya.html.utils.Layout.layout(Layout._will[i]);
  1090. }
  1091. Layout._will.length=0;
  1092. });
  1093. }
  1094. Layout._will.push(element);
  1095. }
  1096. Layout.layout=function(element){
  1097. if (!element || !element._style)return null;
  1098. var style=element._style;
  1099. if ((style._type & /*laya.html.utils.HTMLStyle.ADDLAYOUTED*/0x200)===0)
  1100. return null;
  1101. element.style._type &=~ /*laya.html.utils.HTMLStyle.ADDLAYOUTED*/0x200;
  1102. var arr=Layout._multiLineLayout(element);
  1103. return arr;
  1104. }
  1105. Layout._multiLineLayout=function(element){
  1106. var elements=new Array;
  1107. element._addChildsToLayout(elements);
  1108. var i=0,n=elements.length,j=0;
  1109. var style=element._getCSSStyle();
  1110. var letterSpacing=style.letterSpacing;
  1111. var leading=style.leading;
  1112. var lineHeight=style.lineHeight;
  1113. var widthAuto=style._widthAuto()|| !style.wordWrap;
  1114. var width=widthAuto ? 999999 :element.width;
  1115. var height=element.height;
  1116. var maxWidth=0;
  1117. var exWidth=style.italic ? style.fontSize / 3 :0;
  1118. var align=style.align;
  1119. var valign=style.valign;
  1120. var endAdjust=valign!==/*laya.html.utils.HTMLStyle.VALIGN_TOP*/"top" || align!==/*laya.html.utils.HTMLStyle.ALIGN_LEFT*/"left" || lineHeight !=0;
  1121. var oneLayout;
  1122. var x=0;
  1123. var y=0;
  1124. var w=0;
  1125. var h=0;
  1126. var tBottom=0;
  1127. var lines=new Array;
  1128. var curStyle;
  1129. var curPadding;
  1130. var curLine=lines[0]=new LayoutLine();
  1131. var newLine=false,nextNewline=false;
  1132. var htmlWord;
  1133. var sprite;
  1134. curLine.h=0;
  1135. if (style.italic)
  1136. width-=style.fontSize / 3;
  1137. var tWordWidth=0;
  1138. var tLineFirstKey=true;
  1139. function addLine (){
  1140. curLine.y=y;
  1141. y+=curLine.h+leading;
  1142. curLine.mWidth=tWordWidth;
  1143. tWordWidth=0;
  1144. curLine=new LayoutLine();
  1145. lines.push(curLine);
  1146. curLine.h=0;
  1147. x=0;
  1148. tLineFirstKey=true;
  1149. newLine=false;
  1150. }
  1151. for (i=0;i < n;i++){
  1152. oneLayout=elements[i];
  1153. if (oneLayout==null){
  1154. if (!tLineFirstKey){
  1155. x+=Layout.DIV_ELEMENT_PADDING;
  1156. }
  1157. curLine.wordStartIndex=curLine.elements.length;
  1158. continue ;
  1159. }
  1160. tLineFirstKey=false;
  1161. if ((oneLayout instanceof laya.html.dom.HTMLBrElement )){
  1162. addLine();
  1163. curLine.y=y;
  1164. curLine.h=lineHeight;
  1165. continue ;
  1166. }else if (oneLayout._isChar()){
  1167. htmlWord=oneLayout;
  1168. if (!htmlWord.isWord){
  1169. if (lines.length > 0 && (x+w)> width && curLine.wordStartIndex > 0){
  1170. var tLineWord=0;
  1171. tLineWord=curLine.elements.length-curLine.wordStartIndex+1;
  1172. curLine.elements.length=curLine.wordStartIndex;
  1173. i-=tLineWord;
  1174. addLine();
  1175. continue ;
  1176. }
  1177. newLine=false;
  1178. tWordWidth+=htmlWord.width;
  1179. }else {
  1180. newLine=nextNewline || (htmlWord.char==='\n');
  1181. curLine.wordStartIndex=curLine.elements.length;
  1182. }
  1183. w=htmlWord.width+htmlWord.style.letterSpacing;
  1184. h=htmlWord.height;
  1185. nextNewline=false;
  1186. newLine=newLine || ((x+w)> width);
  1187. newLine && addLine();
  1188. curLine.minTextHeight=Math.min(curLine.minTextHeight,oneLayout.height);
  1189. }else {
  1190. curStyle=oneLayout._getCSSStyle();
  1191. sprite=oneLayout;
  1192. curPadding=curStyle.padding;
  1193. newLine=nextNewline || curStyle.getLineElement();
  1194. w=sprite.width+curPadding[1]+curPadding[3]+curStyle.letterSpacing;
  1195. h=sprite.height+curPadding[0]+curPadding[2];
  1196. nextNewline=curStyle.getLineElement();
  1197. newLine=newLine || ((x+w)> width && curStyle.wordWrap);
  1198. newLine && addLine();
  1199. }
  1200. curLine.elements.push(oneLayout);
  1201. curLine.h=Math.max(curLine.h,h);
  1202. oneLayout.x=x;
  1203. oneLayout.y=y;
  1204. x+=w;
  1205. curLine.w=x-letterSpacing;
  1206. curLine.y=y;
  1207. maxWidth=Math.max(x+exWidth,maxWidth);
  1208. }
  1209. y=curLine.y+curLine.h;
  1210. if (endAdjust){
  1211. var tY=0;
  1212. var tWidth=width;
  1213. if (widthAuto && element.width > 0){
  1214. tWidth=element.width;
  1215. }
  1216. for (i=0,n=lines.length;i < n;i++){
  1217. lines[i].updatePos(0,tWidth,i,tY,align,valign,lineHeight);
  1218. tY+=Math.max(lineHeight,lines[i].h+leading);
  1219. }
  1220. y=tY;
  1221. }
  1222. widthAuto && (element.width=maxWidth);
  1223. (y > element.height)&& (element.height=y);
  1224. return [maxWidth,y];
  1225. }
  1226. Layout.DIV_ELEMENT_PADDING=0;
  1227. Layout._will=null;
  1228. return Layout;
  1229. })()
  1230. /**
  1231. *@private
  1232. */
  1233. //class laya.html.dom.HTMLHitRect
  1234. var HTMLHitRect=(function(){
  1235. function HTMLHitRect(){
  1236. //this.rec=null;
  1237. //this.href=null;
  1238. this.rec=new Rectangle();
  1239. this.reset();
  1240. }
  1241. __class(HTMLHitRect,'laya.html.dom.HTMLHitRect');
  1242. var __proto=HTMLHitRect.prototype;
  1243. __proto.reset=function(){
  1244. this.rec.reset();
  1245. this.href=null;
  1246. return this;
  1247. }
  1248. __proto.recover=function(){
  1249. Pool.recover("HTMLHitRect",this.reset());
  1250. }
  1251. HTMLHitRect.create=function(){
  1252. return Pool.getItemByClass("HTMLHitRect",HTMLHitRect);
  1253. }
  1254. return HTMLHitRect;
  1255. })()
  1256. /**
  1257. *@private
  1258. */
  1259. //class laya.html.dom.HTMLDivParser extends laya.html.dom.HTMLElement
  1260. var HTMLDivParser=(function(_super){
  1261. function HTMLDivParser(){
  1262. /**实际内容的高 */
  1263. this.contextHeight=NaN;
  1264. /**实际内容的宽 */
  1265. this.contextWidth=NaN;
  1266. /**@private */
  1267. this._htmlBounds=null;
  1268. /**@private */
  1269. this._boundsRec=null;
  1270. /**重绘回调 */
  1271. this.repaintHandler=null;
  1272. HTMLDivParser.__super.call(this);
  1273. }
  1274. __class(HTMLDivParser,'laya.html.dom.HTMLDivParser',_super);
  1275. var __proto=HTMLDivParser.prototype;
  1276. __proto.reset=function(){
  1277. HTMLStyleElement;
  1278. HTMLLinkElement;
  1279. _super.prototype.reset.call(this);
  1280. this._style.block=true;
  1281. this._style.setLineElement(true);
  1282. this._style.width=200;
  1283. this._style.height=200;
  1284. this.repaintHandler=null;
  1285. this.contextHeight=0;
  1286. this.contextWidth=0;
  1287. return this;
  1288. }
  1289. /**
  1290. *追加内容,解析并对显示对象排版
  1291. *@param text
  1292. */
  1293. __proto.appendHTML=function(text){
  1294. HTMLParse.parse(this,text,this.URI);
  1295. this.layout();
  1296. }
  1297. /**
  1298. *@private
  1299. *@param out
  1300. *@return
  1301. */
  1302. __proto._addChildsToLayout=function(out){
  1303. var words=this._getWords();
  1304. if (words==null && (!this._children||this._children.length==0))return false;
  1305. words && words.forEach(function(o){
  1306. out.push(o);
  1307. });
  1308. var tFirstKey=true;
  1309. for (var i=0,len=this._children.length;i < len;i++){
  1310. var o=this._children[i];
  1311. if (tFirstKey){
  1312. tFirstKey=false;
  1313. }else {
  1314. out.push(null);
  1315. }
  1316. o._addToLayout(out)
  1317. }
  1318. return true;
  1319. }
  1320. //TODO:coverage
  1321. __proto._addToLayout=function(out){
  1322. this.layout();
  1323. !this.style.absolute && out.push(this);
  1324. }
  1325. /**
  1326. *获取bounds
  1327. *@return
  1328. */
  1329. __proto.getBounds=function(){
  1330. if (!this._htmlBounds)return null;
  1331. if (!this._boundsRec)this._boundsRec=Rectangle.create();
  1332. return this._boundsRec.copyFrom(this._htmlBounds);
  1333. }
  1334. __proto.parentRepaint=function(recreate){
  1335. (recreate===void 0)&& (recreate=false);
  1336. _super.prototype.parentRepaint.call(this);
  1337. if (this.repaintHandler)this.repaintHandler.runWith(recreate);
  1338. }
  1339. /**
  1340. *@private
  1341. *对显示内容进行排版
  1342. */
  1343. __proto.layout=function(){
  1344. this.style._type |=/*laya.html.utils.HTMLStyle.ADDLAYOUTED*/0x200;
  1345. var tArray=Layout.layout(this);
  1346. if (tArray){
  1347. if (!this._htmlBounds)this._htmlBounds=Rectangle.create();
  1348. var tRectangle=this._htmlBounds;
  1349. tRectangle.x=tRectangle.y=0;
  1350. tRectangle.width=this.contextWidth=tArray[0];
  1351. tRectangle.height=this.contextHeight=tArray[1];
  1352. }
  1353. }
  1354. /**
  1355. *获取对象的高
  1356. */
  1357. __getset(0,__proto,'height',function(){
  1358. if (this._height)return this._height;
  1359. return this.contextHeight;
  1360. },_super.prototype._$set_height);
  1361. /**
  1362. *设置标签内容
  1363. */
  1364. __getset(0,__proto,'innerHTML',null,function(text){
  1365. this.destroyChildren();
  1366. this.appendHTML(text);
  1367. });
  1368. /**
  1369. *获取对象的宽
  1370. */
  1371. __getset(0,__proto,'width',function(){
  1372. if (this._width)return this._width;
  1373. return this.contextWidth;
  1374. },function(value){
  1375. var changed=false;
  1376. if (value===0){
  1377. changed=value !=this._width;
  1378. }else {
  1379. changed=value !=this.width;
  1380. }
  1381. Laya.superSet(HTMLElement,this,'width',value);
  1382. if (changed)this.layout();
  1383. });
  1384. return HTMLDivParser;
  1385. })(HTMLElement)
  1386. /**
  1387. *@private
  1388. */
  1389. //class laya.html.dom.HTMLImageElement extends laya.html.dom.HTMLElement
  1390. var HTMLImageElement=(function(_super){
  1391. function HTMLImageElement(){
  1392. //this._tex=null;
  1393. //this._url=null;
  1394. HTMLImageElement.__super.call(this);
  1395. }
  1396. __class(HTMLImageElement,'laya.html.dom.HTMLImageElement',_super);
  1397. var __proto=HTMLImageElement.prototype;
  1398. __proto.reset=function(){
  1399. _super.prototype.reset.call(this);
  1400. if (this._tex){
  1401. this._tex.off(/*laya.events.Event.LOADED*/"loaded",this,this.onloaded);
  1402. }
  1403. this._tex=null;
  1404. this._url=null;
  1405. return this;
  1406. }
  1407. //TODO:coverage
  1408. __proto.onloaded=function(){
  1409. if (!this._style)return;
  1410. var style=this._style;
  1411. var w=style.widthed(this)?-1 :this._tex.width;
  1412. var h=style.heighted(this)?-1 :this._tex.height;
  1413. if (!style.widthed(this)&& this._width !=this._tex.width){
  1414. this.width=this._tex.width;
  1415. this.parent && this.parent._layoutLater();
  1416. }
  1417. if (!style.heighted(this)&& this._height !=this._tex.height){
  1418. this.height=this._tex.height;
  1419. this.parent && this.parent._layoutLater();
  1420. }
  1421. this.repaint();
  1422. }
  1423. //TODO:coverage
  1424. __proto._addToLayout=function(out){
  1425. var style=this._style;
  1426. !style.absolute && out.push(this);
  1427. }
  1428. //TODO:coverage
  1429. __proto.renderSelfToGraphic=function(graphic,gX,gY,recList){
  1430. if (!this._tex)return;
  1431. graphic.drawImage(this._tex,gX,gY,this.width || this._tex.width,this.height || this._tex.height);
  1432. }
  1433. __getset(0,__proto,'src',null,function(url){
  1434. url=this.formatURL(url);
  1435. if (this._url===url)return;
  1436. this._url=url;
  1437. var tex=this._tex=Loader.getRes(url);
  1438. if (!tex){
  1439. this._tex=tex=new Texture();
  1440. tex.load(url);
  1441. Loader.cacheRes(url,tex);
  1442. }
  1443. tex.getIsReady()? this.onloaded():tex.once(/*laya.events.Event.READY*/"ready",this,this.onloaded);
  1444. });
  1445. return HTMLImageElement;
  1446. })(HTMLElement)
  1447. /**
  1448. *@private
  1449. */
  1450. //class laya.html.dom.HTMLStyleElement extends laya.html.dom.HTMLElement
  1451. var HTMLStyleElement=(function(_super){
  1452. function HTMLStyleElement(){
  1453. HTMLStyleElement.__super.call(this);;
  1454. }
  1455. __class(HTMLStyleElement,'laya.html.dom.HTMLStyleElement',_super);
  1456. var __proto=HTMLStyleElement.prototype;
  1457. __proto._creates=function(){}
  1458. __proto.drawToGraphic=function(graphic,gX,gY,recList){}
  1459. //TODO:coverage
  1460. __proto.reset=function(){
  1461. return this;
  1462. }
  1463. /**
  1464. *解析样式
  1465. */
  1466. __getset(0,__proto,'innerTEXT',_super.prototype._$get_innerTEXT,function(value){
  1467. HTMLStyle.parseCSS(value,null);
  1468. });
  1469. return HTMLStyleElement;
  1470. })(HTMLElement)
  1471. /**
  1472. *@private
  1473. */
  1474. //class laya.html.dom.HTMLLinkElement extends laya.html.dom.HTMLElement
  1475. var HTMLLinkElement=(function(_super){
  1476. function HTMLLinkElement(){
  1477. //this.type=null;
  1478. //this._loader=null;
  1479. HTMLLinkElement.__super.call(this);
  1480. }
  1481. __class(HTMLLinkElement,'laya.html.dom.HTMLLinkElement',_super);
  1482. var __proto=HTMLLinkElement.prototype;
  1483. __proto._creates=function(){}
  1484. __proto.drawToGraphic=function(graphic,gX,gY,recList){}
  1485. __proto.reset=function(){
  1486. if (this._loader)this._loader.off(/*laya.events.Event.COMPLETE*/"complete",this,this._onload);
  1487. this._loader=null;
  1488. return this;
  1489. }
  1490. __proto._onload=function(data){
  1491. if (this._loader)this._loader=null;
  1492. switch (this.type){
  1493. case 'text/css':
  1494. HTMLStyle.parseCSS(data,this.URI);
  1495. break ;
  1496. }
  1497. this.repaint(true);
  1498. }
  1499. __getset(0,__proto,'href',_super.prototype._$get_href,function(url){
  1500. if (!url)return;
  1501. url=this.formatURL(url);
  1502. this.URI=new URL(url);
  1503. if (this._loader)this._loader.off(/*laya.events.Event.COMPLETE*/"complete",this,this._onload);
  1504. if (Loader.getRes(url)){
  1505. if (this.type=="text/css"){
  1506. HTMLStyle.parseCSS(Loader.getRes(url),this.URI);
  1507. }
  1508. return;
  1509. }
  1510. this._loader=new Loader();
  1511. this._loader.once(/*laya.events.Event.COMPLETE*/"complete",this,this._onload);
  1512. this._loader.load(url,/*laya.net.Loader.TEXT*/"text");
  1513. });
  1514. HTMLLinkElement._cuttingStyle=new RegExp("((@keyframes[\\s\\t]+|)(.+))[\\t\\n\\r\\\s]*{","g");
  1515. return HTMLLinkElement;
  1516. })(HTMLElement)
  1517. /**
  1518. *HTML图文类,用于显示html内容
  1519. *
  1520. *支持的标签如下:
  1521. *a:链接标签,点击后会派发"link"事件 比如:<a href='alink'>a</a>
  1522. *div:div容器标签,比如:<div>abc</div>
  1523. *span:行内元素标签,比如:<span style='color:#ff0000'>abc</span>
  1524. *p:行元素标签,p标签会自动换行,div不会,比如:<p>abc</p>
  1525. *img:图片标签,比如:<img src='res/boy.png'></img>
  1526. *br:换行标签,比如:<div>abc<br/>def</div>
  1527. *style:样式标签,比如:<div style='width:130px;height:50px;color:#ff0000'>abc</div>
  1528. *link:外链样式标签,可以加载一个css文件来当style使用,比如:<link type='text/css' href='html/test.css'/>
  1529. *
  1530. *style支持的属性如下:
  1531. *italic:true|false;是否是斜体
  1532. *bold:true|false;是否是粗体
  1533. *letter-spacing:10px;字间距
  1534. *font-family:宋体;字体
  1535. *font-size:20px;字体大小
  1536. *font-weight:bold:none;字体是否是粗体,功能同bold
  1537. *color:#ff0000;字体颜色
  1538. *stroke:2px;字体描边宽度
  1539. *strokeColor:#ff0000;字体描边颜色
  1540. *padding:10px 10px 20px 20px;边缘的距离
  1541. *vertical-align:top|bottom|middle;垂直对齐方式
  1542. *align:left|right|center;水平对齐方式
  1543. *line-height:20px;行高
  1544. *background-color:#ff0000;背景颜色
  1545. *border-color:#ff0000;边框颜色
  1546. *width:100px;对象宽度
  1547. *height:100px;对象高度
  1548. *
  1549. *示例用法:
  1550. *var div:HTMLDivElement=new HTMLDivElement();
  1551. *div.innerHTML="<link type='text/css' href='html/test.css'/><a href='alink'>a</a><div style='width:130px;height:50px;color:#ff0000'>div</div><br/><span style='font-weight:bold;color:#ffffff;font-size:30px;stroke:2px;italic:true;'>span</span><span style='letter-spacing:5px'>span2</span><p>p</p><img src='res/boy.png'></img>";
  1552. */
  1553. //class laya.html.dom.HTMLDivElement extends laya.display.Sprite
  1554. var HTMLDivElement=(function(_super){
  1555. function HTMLDivElement(){
  1556. /**@private */
  1557. this._element=null;
  1558. /**@private */
  1559. this._recList=[];
  1560. /**@private */
  1561. this._innerHTML=null;
  1562. /**@private */
  1563. this._repaintState=0;
  1564. HTMLDivElement.__super.call(this);
  1565. this._element=new HTMLDivParser();
  1566. this._element.repaintHandler=new Handler(this,this._htmlDivRepaint);
  1567. this.mouseEnabled=true;
  1568. this.on(/*laya.events.Event.CLICK*/"click",this,this._onMouseClick);
  1569. }
  1570. __class(HTMLDivElement,'laya.html.dom.HTMLDivElement',_super);
  1571. var __proto=HTMLDivElement.prototype;
  1572. /**@private */
  1573. __proto.destroy=function(destroyChild){
  1574. (destroyChild===void 0)&& (destroyChild=true);
  1575. if (this._element)this._element.reset();
  1576. this._element=null;
  1577. this._doClears();
  1578. _super.prototype.destroy.call(this,destroyChild);
  1579. }
  1580. /**@private */
  1581. __proto._htmlDivRepaint=function(recreate){
  1582. (recreate===void 0)&& (recreate=false);
  1583. if (recreate){
  1584. if (this._repaintState < 2)this._repaintState=2;
  1585. }else {
  1586. if (this._repaintState < 1)this._repaintState=1;
  1587. }
  1588. if (this._repaintState > 0)this._setGraphicDirty();
  1589. }
  1590. __proto._updateGraphicWork=function(){
  1591. switch(this._repaintState){
  1592. case 1:
  1593. this._updateGraphic();
  1594. break ;
  1595. case 2:
  1596. this._refresh();
  1597. break ;
  1598. }
  1599. }
  1600. __proto._setGraphicDirty=function(){
  1601. this.callLater(this._updateGraphicWork);
  1602. }
  1603. /**@private */
  1604. __proto._doClears=function(){
  1605. if (!this._recList)return;
  1606. var i=0,len=this._recList.length;
  1607. var tRec;
  1608. for (i=0;i < len;i++){
  1609. tRec=this._recList[i];
  1610. tRec.recover();
  1611. }
  1612. this._recList.length=0;
  1613. }
  1614. /**@private */
  1615. __proto._updateGraphic=function(){
  1616. this._doClears();
  1617. this.graphics.clear(true);
  1618. this._repaintState=0;
  1619. this._element.drawToGraphic(this.graphics,-this._element.x,-this._element.y,this._recList);
  1620. var bounds=this._element.getBounds();
  1621. if (bounds)this.setSelfBounds(bounds);
  1622. this.size(bounds.width,bounds.height);
  1623. }
  1624. __proto._refresh=function(){
  1625. this._repaintState=1;
  1626. if (this._innerHTML)this._element.innerHTML=this._innerHTML;
  1627. this._setGraphicDirty();
  1628. }
  1629. /**@private */
  1630. __proto._onMouseClick=function(){
  1631. var tX=this.mouseX;
  1632. var tY=this.mouseY;
  1633. var i=0,len=0;
  1634. var tHit;
  1635. len=this._recList.length;
  1636. for (i=0;i < len;i++){
  1637. tHit=this._recList[i];
  1638. if (tHit.rec.contains(tX,tY)){
  1639. this._eventLink(tHit.href);
  1640. }
  1641. }
  1642. }
  1643. /**@private */
  1644. __proto._eventLink=function(href){
  1645. this.event(/*laya.events.Event.LINK*/"link",[href]);
  1646. }
  1647. /**
  1648. *获取HTML样式
  1649. */
  1650. __getset(0,__proto,'style',function(){
  1651. return this._element.style;
  1652. });
  1653. /**
  1654. *设置标签内容
  1655. */
  1656. __getset(0,__proto,'innerHTML',null,function(text){
  1657. if (this._innerHTML==text)return;
  1658. this._repaintState=1;
  1659. this._innerHTML=text;
  1660. this._element.innerHTML=text;
  1661. this._setGraphicDirty();
  1662. });
  1663. /**
  1664. *获取內容宽度
  1665. */
  1666. __getset(0,__proto,'contextWidth',function(){
  1667. return this._element.contextWidth;
  1668. });
  1669. /**
  1670. *获取內容高度
  1671. */
  1672. __getset(0,__proto,'contextHeight',function(){
  1673. return this._element.contextHeight;
  1674. });
  1675. return HTMLDivElement;
  1676. })(Sprite)
  1677. /**
  1678. *iframe标签类,目前用于加载外并解析数据
  1679. */
  1680. //class laya.html.dom.HTMLIframeElement extends laya.html.dom.HTMLDivElement
  1681. var HTMLIframeElement=(function(_super){
  1682. function HTMLIframeElement(){
  1683. HTMLIframeElement.__super.call(this);
  1684. this._element._getCSSStyle().valign="middle";
  1685. }
  1686. __class(HTMLIframeElement,'laya.html.dom.HTMLIframeElement',_super);
  1687. var __proto=HTMLIframeElement.prototype;
  1688. /**
  1689. *加载html文件,并解析数据
  1690. *@param url
  1691. */
  1692. __getset(0,__proto,'href',null,function(url){
  1693. var _$this=this;
  1694. url=this._element.formatURL(url);
  1695. var l=new Loader();
  1696. l.once(/*laya.events.Event.COMPLETE*/"complete",null,function(data){
  1697. var pre=_$this._element.URI;
  1698. _$this._element.URI=new URL(url);
  1699. _$this.innerHTML=data;
  1700. !pre || (_$this._element.URI=pre);
  1701. });
  1702. l.load(url,/*laya.net.Loader.TEXT*/"text");
  1703. });
  1704. return HTMLIframeElement;
  1705. })(HTMLDivElement)
  1706. })(window,document,Laya);