XFormsStyleSheet.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. CSS_NULL = 0;
  2. CSS_FIRST = CSS_NULL;
  3. CSS_USER = 1;
  4. CSS_UNIVERSAL = 2;
  5. CSS_TYPE = 3;
  6. CSS_DYNAMIC_PSEUDO = 4;
  7. CSS_ID = 5;
  8. CSS_DESCENDANT = 6;
  9. CSS_CHILD = 7;
  10. CSS_GROUP = 8;
  11. AS_NULL = 0;
  12. AS_EXIST = 1;
  13. AS_EQUAL = 2;
  14. HAS_NS = 0x00000001;
  15. HAS_ID = 0x00000010;
  16. HAS_CLASS = 0x00000100;
  17. var g_childList = new Array();
  18. var g_objStyleSheet = new XFormsStyleSheet();
  19. /**
  20. * Stylesheet
  21. *
  22. * @author 김지환
  23. */
  24. function XFormsStyleSheet ()
  25. {
  26. this.m_arCSSNode = new Array();
  27. };
  28. XFormsStyleSheet.prototype.push = function (objCSSNode)
  29. {
  30. this.m_arCSSNode.push(objCSSNode);
  31. };
  32. XFormsStyleSheet.prototype.getNode = function (nIndex)
  33. {
  34. return this.m_arCSSNode[nIndex];
  35. };
  36. XFormsStyleSheet.prototype.getLength = function ()
  37. {
  38. return this.m_arCSSNode.length;
  39. };
  40. XFormsStyleSheet.prototype.applyCSS = function (objElement)
  41. {
  42. var htCssData = null;
  43. var strID = objElement.getId();
  44. var nLength = this.getLength();
  45. for (var i=0; i<nLength; i++)
  46. {
  47. var objCSSNode = this.m_arCSSNode[i];
  48. if (objCSSNode.match(objElement))
  49. {
  50. var bMatch = true;
  51. if (null != objCSSNode.getNext())
  52. {
  53. var objCurrent = objCSSNode.getNext();
  54. var objCurrentElement = objElement;
  55. while (null != objCurrent)
  56. {
  57. if (CSS_CHILD == objCurrent.getLink())
  58. {
  59. objCurrentElement = this.matchChild(objCurrent, objCurrentElement);
  60. }
  61. else if (CSS_DESCENDANT == objCurrent.getLink())
  62. {
  63. objCurrentElement = this.matchDescendant(objCurrent, objCurrentElement);
  64. }
  65. if (null == objCurrentElement)
  66. {
  67. bMatch = false;
  68. break;
  69. }
  70. objCurrent = objCurrent.getNext();
  71. }
  72. }
  73. // Stylesheet 적용
  74. if (bMatch)
  75. {
  76. if (null == htCssData)
  77. {
  78. htCssData = new Hashtable();
  79. }
  80. var strPseudo = objCSSNode.getPseudo();
  81. var htAttribute = objCSSNode.getAttribute();
  82. if (null != htAttribute)
  83. {
  84. for (var strKey in htAttribute)
  85. {
  86. var bImportant = false;
  87. var strValue = htAttribute[strKey];
  88. if (null != strKey && 0 < strKey.length && '#' == strKey.charAt(0))
  89. {
  90. bImportant = true;
  91. strKey = strKey.substr(1);
  92. }
  93. // Pseudo
  94. if (null != strPseudo && 0 < strPseudo.length)
  95. {
  96. if ("hover" == strPseudo)
  97. {
  98. objElement.setHoverAttribute(strKey, strValue);
  99. }
  100. else if ("down" == strPseudo)
  101. {
  102. objElement.setDownAttribute(strKey, strValue);
  103. }
  104. else if ("focus" == strPseudo)
  105. {
  106. objElement.setFocusAttribute(strKey, strValue);
  107. }
  108. else if ("disable" == strPseudo)
  109. {
  110. objElement.setDisableAttribute(strKey, strValue);
  111. }
  112. else if ("fixed" == strPseudo)
  113. {
  114. if (objElement instanceof XFormsDataGrid)
  115. {
  116. objElement.setFixedAttribute(strKey, strValue);
  117. }
  118. }
  119. else if ("data" == strPseudo)
  120. {
  121. if (objElement instanceof XFormsDataGrid)
  122. {
  123. objElement.setDataAttribute(strKey, strValue);
  124. }
  125. }
  126. }
  127. else if (0 == strKey.indexOf("select."))
  128. {
  129. objElement.setSelectAttribute(strKey.substr("select.".length), strValue);
  130. }
  131. else
  132. {
  133. if (bImportant)
  134. {
  135. htCssData[strKey] = strValue;
  136. }
  137. else
  138. {
  139. if (objElement.isCSSValid(strKey))
  140. {
  141. htCssData[strKey] = strValue;
  142. }
  143. }
  144. }
  145. }
  146. }
  147. }
  148. }
  149. }
  150. if (null != htCssData)
  151. {
  152. for (var strKey in htCssData)
  153. {
  154. objElement.setAttribute(strKey, htCssData[strKey]);
  155. }
  156. }
  157. };
  158. /**
  159. * 부모가 일치하는지 찾는다.
  160. * @param objCSSNode
  161. * @param objElement
  162. * @return
  163. */
  164. XFormsStyleSheet.prototype.matchChild = function (objCSSNode, objElement)
  165. {
  166. var objParent = objElement.getParent();
  167. if (null != objParent && objCSSNode.match(objParent))
  168. {
  169. return objParent;
  170. }
  171. return null;
  172. };
  173. /**
  174. * 조상중에서 일치하는 조상을 찾는다.
  175. * @param objCSSNode
  176. * @param objElement
  177. * @return
  178. */
  179. XFormsStyleSheet.prototype.matchDescendant = function (objCSSNode, objElement)
  180. {
  181. var objParent = objElement.getParent();
  182. while (null != objParent)
  183. {
  184. if (objCSSNode.match(objParent))
  185. {
  186. return objParent;
  187. }
  188. objParent = objParent.getParent();
  189. }
  190. return null;
  191. };
  192. XFormsStyleSheet.addNode = function (objCSSNode)
  193. {
  194. g_objStyleSheet.push(objCSSNode);
  195. };
  196. XFormsStyleSheet.addNodeForChild = function (objCSSNode)
  197. {
  198. g_childList.push(objCSSNode);
  199. };
  200. XFormsStyleSheet.flushChild = function ()
  201. {
  202. if (0 < g_childList.length)
  203. {
  204. var objCurrent = null;
  205. for (var i=g_childList.length-1; i>=0; i--)
  206. {
  207. var objCSSNode = g_childList[i];
  208. if (null == objCurrent)
  209. {
  210. g_objStyleSheet.push(objCSSNode);
  211. }
  212. else
  213. {
  214. objCurrent.setNext(objCSSNode);
  215. }
  216. objCurrent = objCSSNode;
  217. }
  218. g_childList.removeAll();
  219. }
  220. };
  221. /**
  222. * CSS 의 구문
  223. */
  224. function CSSNode (strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue)
  225. {
  226. if (null == strName)
  227. {
  228. return;
  229. }
  230. // 구문의 이름 id, type, class, universial의 값이 될 수 있다.
  231. this.m_strName = strName;
  232. // CSSNode 연결 타입
  233. this.m_nLink = nLink;
  234. // 의사코드 이벤트 hover, down, focus, disable, fixed, data 등
  235. this.m_strPseudo = strPseudo;
  236. // 스타일 데이터
  237. this.m_htAttribute = htAttribute;
  238. // Attribute Selector 구문의 이름으로 매치가 되더라도 추가적으로 해당 엘리먼트의 어트리부트를 지정해서 해당하는 엘리먼트만 적용할때 쓰인다.
  239. this.m_bHasAs = bHasAs;
  240. this.m_nAsOperator = nAsOperator;
  241. this.m_strAsName = strAsName;
  242. this.m_strAsValue = strAsValue;
  243. // 같은 CSS 구문안에 위치한 다음 노드 (부모 노드에 대한 정보)
  244. this.m_objNext = null;
  245. };
  246. CSSNode.prototype.getPseudo = function ()
  247. {
  248. return this.m_strPseudo;
  249. };
  250. CSSNode.prototype.getLink = function ()
  251. {
  252. return this.m_nLink;
  253. };
  254. CSSNode.prototype.getAttribute = function ()
  255. {
  256. return this.m_htAttribute;
  257. };
  258. CSSNode.prototype.getNext = function ()
  259. {
  260. return this.m_objNext;
  261. };
  262. CSSNode.prototype.setNext = function (objCSSNode)
  263. {
  264. this.m_objNext = objCSSNode;
  265. };
  266. CSSNode.prototype.match = function (objElement)
  267. {
  268. if (!this.onMatch(objElement))
  269. {
  270. return false;
  271. }
  272. // Attribute Selector
  273. if (this.m_bHasAs)
  274. {
  275. if (AS_EQUAL == this.m_nAsOperator)
  276. {
  277. var strAttributeValue = objElement.getAttribute(this.m_strAsName);
  278. if (this.m_strAsValue != strAttributeValue)
  279. {
  280. return false;
  281. }
  282. }
  283. else if (AS_EXIST == this.m_nAsOperator)
  284. {
  285. var strAttributeValue = objElement.getAttribute(this.m_strAsName);
  286. if (null == strAttributeValue)
  287. {
  288. return false;
  289. }
  290. }
  291. }
  292. return true;
  293. };
  294. /**
  295. * CSS의 대상이 class 에 의해 적용되는 CSS 구문
  296. */
  297. CSSNodeUser.prototype = new CSSNode;
  298. function CSSNodeUser (strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue)
  299. {
  300. if (null == strName)
  301. {
  302. return;
  303. }
  304. CSSNode.call(this, strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue);
  305. };
  306. CSSNodeUser.prototype.onMatch = function (objElement)
  307. {
  308. return (null != objElement.getClass && objElement.getClass() == this.m_strName);
  309. };
  310. /**
  311. * CSS의 대상이 id 에 의해 적용되는 CSS 구문
  312. */
  313. CSSNodeID.prototype = new CSSNode;
  314. function CSSNodeID (strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue)
  315. {
  316. if (null == strName)
  317. {
  318. return;
  319. }
  320. CSSNode.call(this, strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue);
  321. };
  322. CSSNodeID.prototype.onMatch = function (objElement)
  323. {
  324. var strId = objElement.getId();
  325. if (CSS_CHILD == this.m_nLink || CSS_DESCENDANT == this.m_nLink)
  326. {
  327. var nIndex = strId.lastIndexOf(".");
  328. if (-1 < nIndex)
  329. {
  330. strId = strId.substr(nIndex + 1);
  331. }
  332. }
  333. return (strId == this.m_strName);
  334. };
  335. /**
  336. * CSS의 대상이 type 에 의해 적용되는 CSS 구문
  337. */
  338. CSSNodeType.prototype = new CSSNode;
  339. function CSSNodeType (strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue)
  340. {
  341. if (null == strName)
  342. {
  343. return;
  344. }
  345. this.m_dwFlag = 0;
  346. this.m_strClass = "";
  347. this.m_strType = "";
  348. this.m_strId = "";
  349. // Class 와 함께인 Type
  350. var nIndex = strName.indexOf(".");
  351. if (-1 != nIndex)
  352. {
  353. this.m_strClass = strName.substr(nIndex + 1);
  354. this.m_dwFlag |= HAS_CLASS;
  355. strName = strName.substring(0, nIndex);
  356. }
  357. // ID 와 함께인 Type
  358. nIndex = strName.indexOf("#");
  359. if (-1 != nIndex)
  360. {
  361. this.m_strId = strName.substr(nIndex + 1);
  362. this.m_dwFlag |= HAS_ID;
  363. strName = strName.substring(0, nIndex);
  364. }
  365. // namespace
  366. this.m_dwFlag |= (strName.indexOf("|") != -1 ? HAS_NS : 0);
  367. strName.replace("|", ":");
  368. this.m_strType = strName;
  369. CSSNode.call(this, strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue);
  370. };
  371. CSSNodeType.prototype.onMatch = function (objElement)
  372. {
  373. if (this.m_dwFlag & HAS_ID)
  374. {
  375. var strId = objElement.getId();
  376. if (CSS_CHILD == this.getLink())
  377. {
  378. var nIndex = strId.lastIndexOf(".");
  379. if (-1 < nIndex)
  380. {
  381. strId = strId.substr(nIndex + 1);
  382. }
  383. }
  384. return (strId == this.m_strName);
  385. }
  386. if (this.m_dwFlag & HAS_CLASS)
  387. {
  388. if ("html" != objElement.id)
  389. {
  390. var strClass = objElement.getClass();
  391. if (this.m_strClass != strClass)
  392. {
  393. return false;
  394. }
  395. }
  396. else
  397. {
  398. return false;
  399. }
  400. }
  401. return (this.m_dwFlag & HAS_NS) ? objElement.getTag() == this.m_strType : objElement.getLocalTag() == this.m_strType;
  402. };
  403. /**
  404. * CSS의 대상이 전체인 CSS 구문 (*)
  405. */
  406. CSSNodeUniversal.prototype = new CSSNodeType;
  407. function CSSNodeUniversal (strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue)
  408. {
  409. if (null == strName)
  410. {
  411. return;
  412. }
  413. CSSNodeType.call(this, strName, nLink, strPseudo, htAttribute, bHasAs, nAsOperator, strAsName, strAsValue);
  414. };
  415. CSSNodeUniversal.prototype.onMatch = function (objElement)
  416. {
  417. if (this.m_dwFlag & HAS_ID)
  418. {
  419. if (this.m_strId != objElement.getId())
  420. {
  421. return false;
  422. }
  423. }
  424. if (this.m_dwFlag & HAS_CLASS)
  425. {
  426. if (this.m_strClass != objElement.getClass())
  427. {
  428. return false;
  429. }
  430. }
  431. return true;
  432. };