/** @namespace */ var $tom = {}; (function() { var __TRANSLATIONS = { '%body': ['body'], '%text': ['#text', 'br'], '%element': ['#element'], '%control': ['img','object','hr','table','button','iframe'], //['input','select','textarea','label','br'], '%inline': ['span','font','u','i','b','em','strong','big','small','a','sub','sup','span'],//['tt','dfn','code','samp','kbd','var','cite','abbr','acronym','img','object','br','script','map','q','bdo','input','select','textarea','label','button'], '%block': ['p','div','ul','ol','h1','h2','h3','h4','h5','h6','pre','dl','hr','table','button'], //['noscript','blockquote','form','fieldset','address'], !button '%paragraph': ['p','li','dd','dt','h1','h2','h3','h4','h5','h6','td','th','div','caption'], //!button '%wrapper': ['div','ul','ol','dl','pre','xmp','table','button','blockquote'],// FTDUEDTR-1412 '%innergroup': ['li','dd','dt','td', 'th'], '%outergroup': ['ul','ol','dl','tr','tbody','thead','tfoot','table'], '%tablegroup': ['td', 'th','tr','tbody','thead','tfoot','table'], '%listgroup': ['li','ul','ol'], '%datagroup': ['dd','dt','dl'], '%listhead': ['ul','ol'] }; var __TRANSLATIONS_MAP = {}; //for caching for(var _ptrn in __TRANSLATIONS) { __TRANSLATIONS_MAP[_ptrn] = {}; if (__TRANSLATIONS[_ptrn]) { $A(__TRANSLATIONS[_ptrn]).each(function(tag){ __TRANSLATIONS_MAP[_ptrn][tag] = _TRUE; }); } } function createMap(patterns) { var _map = {}; var _patterns = patterns.split(","); _patterns.each(function(pattern) { if(__TRANSLATIONS_MAP[pattern]) { for(var _part in __TRANSLATIONS_MAP[pattern]) { _map[_part] = _TRUE; } } else { _map[pattern] = _TRUE; } }); return _map; } var Translator = Trex.Class.create({ initialize: function(patterns) { this.patterns = patterns; this.map = createMap(patterns); }, hasParts: function() { return (this.patterns.length > 0); }, include: function(partPtrn) { var _partMap = createMap(partPtrn); for(var _part in _partMap) { if(this.map[_part]) { return _TRUE; } } return _FALSE; }, memberOf: function(wholePtrn) { var _wholeMap = createMap(wholePtrn); for(var _part in this.map) { if(_wholeMap[_part]) { return _TRUE; } } return _FALSE; }, extract: function(wholePtrn) { var _wholeMap = createMap(wholePtrn); var _matches = []; for(var _part in this.map) { if(_wholeMap[_part]) { _matches.push(_part); } } return $tom.translate(_matches.join(",")); }, getExpression: function() { if(!this.exprs) { var _exprs = []; for(var _part in this.map) { _exprs.push(_part); } this.exprs = _exprs.join(","); } return this.exprs; } }); var __TRANSLATOR_CACHES = {}; //for caching Object.extend($tom, { translate: function(pattern) { if(!__TRANSLATOR_CACHES[pattern]) { __TRANSLATOR_CACHES[pattern] = new Translator(pattern); } return __TRANSLATOR_CACHES[pattern]; } }); })(); Object.extend($tom, { __POSITION: { __START_OF_TEXT: -1, __MIDDLE_OF_TEXT: 0, __END_OF_TEXT: 1, __EMPTY_TEXT: -2 } }); Object.extend($tom, /** @lends $tom */{ /** * node가 HTMLElement이면 true를 아니면 false를 반환한다. * @function */ isElement: function(node) { return node && node.nodeType == 1; }, /** * node가 요소이면 true를 반환한다. * @function */ isBody: function(node) { return $tom.isElement(node) && node.tagName == "BODY"; }, /** * node가 아래에 나열된 block 요소이면 true 를 반환한다. * 'p','div','ul','ol','h1','h2','h3','h4','h5','h6','pre','dl','hr','table','button' * @function */ isBlock: function(node) { return $tom.kindOf(node, '%block'); }, /** * node가 아래에 나열된 요소이면 true 를 반환한다. * 'p','li','dd','dt','h1','h2','h3','h4','h5','h6','td','th','div','caption' * @function */ isParagraph: function(node) { return $tom.kindOf(node, '%paragraph'); }, /** * node가 텍스트이거나
요소이면 true 를 반환한다. * @function */ isText: function(node) { return $tom.kindOf(node, '%text'); }, /** * node가 아래에 나열된 요소이면 true를 반환한다. * 'img','object','hr','table','button' * @function */ isControl: function(node) { return $tom.kindOf(node, '%control'); }, /** * element가 tagName면 true를 반환한다. * @function */ isTagName: function(element, tagName){ tagName = tagName.toUpperCase(); return element && element.tagName === tagName; }, getOwnerDocument: function(node) { return node.ownerDocument || node.document; }, /** * node의 이름을 반환한다. * @function */ getName: function(node) { return ((node && node.nodeType == 1)? node.nodeName.toLowerCase(): ""); }, /** * node의 text content 를 반환한다. * @function */ getText: function(node) { return node.textContent || node.text || node.innerText || ""; }, /** * 요소의 nodeType 1이면 child 노드의 길이를, nodeType 3이면 nodeValue의 길이를 반환한다. * @function */ getLength: function(node) { if(!node) { return 0; } if(node.nodeType == 1) { return node.childNodes.length; } else if(node.nodeType == 3) { return node.nodeValue.length; } return 0; }, /** * node가 같은 레벨의 요소 중 몇 번째인지 인덱스값을 반환한다. * @function */ indexOf: function(node){ if(!node) { return -1; } var _pNode = node.parentNode; for (var i = 0, len = _pNode.childNodes.length, childNodes = _pNode.childNodes; i < len; i++) { if (childNodes[i] == node) { return i; } } return -1; }, /** * node가 textNode이면 공백을 제거한 nodeValue의 내용이 존재하면 true를 반환한다. * @function */ hasContent: function(node, ignoreZWNBS) { if(!node || node.nodeType != 3) { return _TRUE; } var _text = $tom.removeMeaninglessSpace( node.nodeValue ); if(ignoreZWNBS) { _text = _text.replace(Trex.__WORD_JOINER_REGEXP, ""); } return (_text != ""); }, removeEmptyTextNode: function(textNode) { if (textNode && textNode.nodeType == 3 && !textNode.nodeValue) { $tom.remove(textNode); } }, hasUsefulChildren: function(node, ignoreZWNBS) { if(!node) { return _FALSE; } var _inner = $tom.removeMeaninglessSpace( node.innerHTML ); if(ignoreZWNBS) { _inner = _inner.replace(Trex.__WORD_JOINER_REGEXP, ""); } if(!_inner) { return _FALSE; } if(_inner.stripTags()) { return _TRUE; } if(_inner.search(/<(img|br|hr)\s?[^>]*>/i) > -1) { return _TRUE; } if(_inner.search(/<\/span>/i) > -1) { return _TRUE; } return _FALSE; }, /** * node에 의미있는 데이터가 있는지 확인한다. * @function */ hasData: function(node, ignoreStuff) { if(!node) { return _FALSE; } var _inner = ''; if(node.nodeType == 1) { _inner = node.innerHTML; } else { _inner = node.nodeValue; } _inner = $tom.removeMeaninglessSpace( _inner ); if(_inner.trim() == '') {// #PCCAFEQA-11 return _FALSE; } if(_inner.stripTags() != '') { return _TRUE; } if(ignoreStuff) { return _FALSE; } if(_inner.search(//i) > -1) { return _TRUE; } return _FALSE; }, /** * 주어진 스트링에서 의미없는 스페이스를 제거하는 함수. * @function */ removeMeaninglessSpace: function(str){ /* /\s/ == /[\f\n\r\t\v\u2028\u2029\u00a0]/ */ return str.replace(/(^[\f\n\r\t\v\u2028\u2029]*)|([\f\n\r\t\v\u2028\u2029]*$)/g, ""); } }); Object.extend($tom, /** @lends $tom */{ /** * $tom.find, $tom.collect, $tom.collectAll 에서 공통적으로 호출되는 함수. * @function * @example * var result1 = $tom.search(["td,th"], dFindy, _NULL); * var result2 = $tom.search([context, "td,th"], dFindy, _NULL); * var results = $tom.search([context, "td,th"], dGetties, []); */ search: function(args, searchFunction, defaultValue) { var context = (args.length == 1) ? _DOC : args[0]; var pattern = args[args.length - 1]; var invalidArgument = (!pattern || !context || !context.nodeType || typeof pattern != "string"); if (invalidArgument) { return defaultValue; } var translator = $tom.translate(pattern); return searchFunction(context, translator.getExpression()); }, /** * css selector 로 요소를 찾아서 반환하는데 인자 node의 상위에 있는 요소를 찾는다. * @function * @example * var _elNode = $tom.find(node, "table.txc-layout-wz"); */ find: function() { return this.search(arguments, dFindy, _NULL); }, /** * css selector 로 요소를 찾아서 반환하는데 인자 node의 하위에 있는 요소를 찾는다. * @function * @example * var _elInput = $tom.collect(this.elMenu, 'textarea'); */ collect: function() { return this.search(arguments, dGetty, _NULL); }, /** * css selector로 요소를 찾아서 반환하는데 인자 node의 하위에 있는 요소를 찾고 모든 요소를 배열에 담아서 반환한다. * @function * @example * var _elItemList = $tom.collectAll(this.elMenu, "li a"); */ collectAll: function() { return this.search(arguments, dGetties, []); } }); (function() { function makeFilter(pattern) { if(pattern) { if(typeof(pattern) === 'function') { return pattern; } else { var _translator = $tom.translate(pattern); return function(node) { if(node.nodeType == 1) { if (_translator.include('#element')) { return _TRUE; } else { return dChecky(node, _translator.getExpression()); } } else { return _translator.include('#text'); } }; } } else { return _NULL; } } var nodePatternCache = {}; function findNodePattern(pattern) { pattern = pattern || "#element,#text"; if (nodePatternCache[pattern]) { return nodePatternCache[pattern]; } var filter = new NodePattern(pattern); nodePatternCache[pattern] = filter; return filter; } var NodePattern = Trex.Class.create({ initialize: function(pattern) { this.pattern = pattern; this.translator = $tom.translate(pattern); // for better performance this.hasClassPattern = pattern.indexOf(".") >= 0; this.hasIdPattern = pattern.indexOf("#") >= 0; this.matchesText = this.translator.include("#text"); this.matchesElement = this.translator.include("#element"); }, test: function(node) { var nodeType = node.nodeType; var translatorMap = this.translator.map; if (nodeType == 1) { if (this.matchesElement) { return _TRUE; } var tagName = node.tagName.toLowerCase(); // early matching for performance if (translatorMap[tagName]) { return _TRUE; } var checkPattern = []; if (this.hasClassPattern && node.className) { node.className.split(/\s/).each(function(className) { checkPattern.push("." + className); checkPattern.push(tagName + "." + className); }); } if (this.hasIdPattern && node.id) { var id = node.id; checkPattern.push("#" + id); checkPattern.push(tagName + "#" + id); } for (var i = 0; i < checkPattern.length; i++) { if (translatorMap[checkPattern[i]]) { return _TRUE; } } return _FALSE; } else if (nodeType == 3) { return this.matchesText; } } }); Object.extend($tom, /** @lends $tom */{ tagName: function(node, tagName) { if (!node) { return _NULL; } return node.tagName; }, /** * node가 pattern에 맞는 요소이면 true를 반환한다. * @function * @param node * @param pattern css selector rule * @example * $tom.kindOf(node, "img.txc-image") // node가 txc-image라는 이름의 class속성을 가진 img 요소이면 true */ // 더 이상 사용하지 않는 dChecky를 없애자. kindOf: function(node, pattern) { if (!node || !pattern) { return _FALSE; } var filter = findNodePattern(pattern); return filter.test(node); }, kindOf_old: function(node, pattern) { if(!node || !pattern) { return _FALSE; } return makeFilter(pattern)(node); }, /* has filter */ /** * pattern에 맞는 descendant의 상위요소를 찾아서 반환한다. * @function */ ancestor: function(descendant, pattern) { if(!descendant || !descendant.parentNode) { return _NULL; } var filter = findNodePattern(pattern); var _node = descendant.parentNode; while(_node) { if($tom.isBody(_node)) { return _NULL; } if (filter.test(_node)) { break; } _node = _node.parentNode; } return _node; }, findAncestor: function(node, matched, mustStop) { while (!mustStop(node)) { if (matched(node)) { return node; } node = node.parentNode; } return _NULL; }, /** * pattern에 맞는 descendant의 하위요소를 찾아서 반환한다. * @function */ descendant: function(ancestor, pattern) { var _nodes = $tom.descendants(ancestor, pattern, _TRUE); if(_nodes.length == 0) { return _NULL; } return _nodes[0]; }, /** * pattern에 맞는 descendant의 모든 하위요소를 찾아서 반환한다. * @function */ descendants: function(ancestor, pattern, single) { single = single || _FALSE; if(!ancestor || !ancestor.firstChild) { return []; } var _found = _FALSE; var filter = findNodePattern(pattern); var _nodes = []; var _gets = function(parent) { if(single && _found) { return; } if(!$tom.first(parent)) { return; } var _chilren = $tom.children(parent); for(var i=0,len=_chilren.length;i= eInx) { return; } var _inx = sInx; while (_inx++ < eInx && sInx < sNode.childNodes.length) { dNode.appendChild(sNode.childNodes[sInx]); } }, /** * node의 자식노드를 node의 부모노드에 붙인다. * @function */ moveChildToParent: function(node) { if(!node) { return; } while (node.firstChild) { node.parentNode.insertBefore(node.firstChild, node); } } }); /* * Create, Destroy, Change */ Object.extend($tom, /** @lends $tom */{ /** * source를 target로 교체하고 target를 반환한다. * @function */ replace: function(source, target) { if (!source || !target) { return _NULL; } if ($tom.getName(source) == $tom.getName(target)) { $tom.remove(target); return source; } else { // FTDUEDTR-1248 var children = [], childNodes = source.childNodes, len = childNodes.length; for (var i = 0; i < len; i++) { children.push(childNodes[i]); } for (i = 0; i < len; i++) { var child = children[i]; if (child.lastChild === source) { var cloneChild = $tom.clone(child); $tom.moveChild(child, cloneChild); child.innerHTML = ""; target.appendChild(cloneChild); } else { target.appendChild(child); } } $tom.insertAt(target, source); $tom.remove(source); return target; } }, /** * node를 복사 후 반환한다. * @function */ clone: function(node, deep) { var cloneNode = node.cloneNode(!!deep); if (node.nodeType == 1) { cloneNode.removeAttribute("id"); } return cloneNode; } }); /* * Wrap, Unwrap */ Object.extend($tom, /** @lends $tom */{ /** * wNode 아래에 pNodes를 붙여서 pNodes를 wNode로 감싼다. * @function * @return wNode */ wrap: function(wNode, pNodes) { //NOTE: quote, quotenodesign, textbox 등에서 사용됨, actually using 'div', 'blockquote' if (!wNode || !pNodes) { return _NULL; } if (pNodes instanceof Array == _FALSE) { pNodes = [].concat(pNodes); } $tom.insertAt(wNode, pNodes[0]); pNodes.each((function(pNode){ $tom.append(wNode, pNode); })); return wNode; }, /** * node를 제거하고 node의 자식노드는 node의 상위에 붙인다. * @function */ unwrap: function(node) { if (!node) { return _NULL; } var _nNode = $tom.first(node); if ($tx.msie_nonstd) { node.removeNode(); // IE에서는 이게 더 빠름 } else { $tom.moveChildToParent(node); $tom.remove(node); } return _nNode; } }); Object.extend($tom, /** @lends $tom */{ /** * @private * @function */ divideText: function(node, offset) { if(!$tom.isText(node)) { return node; } if(offset <= 0 || offset >= node.length) { //나눌필요가 있을까? return node; } var _newNode = node.cloneNode(_FALSE); node.deleteData(offset, node.length - offset); _newNode.deleteData(0, offset); $tom.insertNext(_newNode, node); return _newNode; }, /** * node의 offset번째 child를 기준으로 두 개로 분리한다. */ divideNode: function(node, offset) { if(!$tom.isElement(node)) { return _NULL; } /*if(offset <= 0 || offset >= node.childNodes.length) { //나눌필요가 있을까? return node; }*/ var _lastOffset = node.childNodes.length - offset; var _newNode = node.cloneNode(_FALSE); for(var i=0;i<_lastOffset;i++) { $tom.insertFirst(_newNode, node.lastChild); } $tom.insertNext(_newNode, node); return _newNode; }, /** * divideNode와 비슷한데, node를 clone할 때에 style, attribute를 모두 복사하게 된다. * divideNode 사용에 대한 legacy 때문에 따로 만들었으며, 사용법이 확인된 이후에는 두 개가 합쳐질 필요가 있다. * 예를 들어 style을 복사하는 책임을 caller에게 넘기는 방식이나, 파라미터로 선택할 수 있도록 해서... */ splitAt: function(node, index) { if (!$tom.isElement(node)) { return; } var clonedNode = $tom.clone(node); $tom.moveChild(node, clonedNode, index + 1, node.childNodes.length); $tom.insertNext(clonedNode, node); return clonedNode; }, /** * stopAncestor은 dividedPoint의 ancestor 이어야 함 * stopAncestor와 dividedPoint 사이에 table이 없어야 함 */ divideTree: function(stopAncestor, dividedPoint) { var currentNode = dividedPoint, offset, parent; do { parent = currentNode.parentNode; offset = $tom.indexOf(currentNode); currentNode = $tom.divideNode(parent, offset); } while (currentNode.previousSibling != stopAncestor); return currentNode; }, /** * @private * @function */ divideParagraph: function(node) { var _node = node; var _offset = $tom.indexOf(node); var _divided = _node; while (_node) { if ($tom.isBody(_node)) { break; } else if ($tom.kindOf(_node, 'td,th,%wrapper,%outergroup')) { break; } else if ($tom.kindOf(_node, "#tx_start_marker,#tx_end_marker")) { _offset = $tom.indexOf(_node); } else if($tom.isControl(_node)) { _offset = $tom.indexOf(_node); } else if ($tom.isText(_node)) { //text _node = $tom.divideText(_node, _offset); _offset = $tom.indexOf(_node); } else { //%inline, %paragraph _node = $tom.divideNode(_node, _offset); _offset = $tom.indexOf(_node); _divided = _node; if ($tom.kindOf(_node, 'p,li,dd,dt,h1,h2,h3,h4,h5,h6')) { break; } } _node = _node.parentNode; } return _divided; }, wrapInlinesWithP: function(inline, ancestorBlock) { var ownerDocument = $tom.getOwnerDocument(inline); var inlineNodes = $tom.extract(ancestorBlock || ownerDocument.body, inline, '%text,%inline,%control'); // caret은 곧 사라지기 때문에P로 감쌀 필요가 없다 if (this.hasOnlySavedCaret(inlineNodes, inline)) { return _NULL; } var newParagraph = ownerDocument.createElement("p"); $tom.wrap(newParagraph, inlineNodes); return newParagraph; }, hasOnlySavedCaret: function(inlines, inline) { var validInlines = inlines.findAll(function(node) { return node.nodeType != 3 || node.nodeValue.trim() != ""; }); return this.isGoogRangeCaret(inline) && validInlines.length == 1 && validInlines[0] == inline; }, isGoogRangeCaret: function(node) { return node && /goog_[0-9]+/.test(node.id); } }); Object.extend($tom, /** @lends $tom */{ /** * name의 하위요소로 들어올 요소이름 반환 * @function * @example * $tom.paragraphOf("table") // 'td'를 반환한다. */ paragraphOf: function(name) { if(!name) { return 'p'; } var _translator = $tom.translate(name); if (_translator.memberOf('ul,ol')) { return 'li'; } else if (_translator.memberOf('dl')) { return 'dd'; } else if (_translator.memberOf('tr,tbody,thead,tfoot,table')) { return 'td'; } else { return 'p'; } }, /** * 'span' 을 반환한다. * @function */ inlineOf: function() { return 'span'; }, /** * 요소의 name을 받아서 상위요소가 되는 요소이름을 반환한다. * @function * @example * $tom.outerOf("td") // "table"을 반환한다. */ outerOf: function(name) { if(!name) { return 'span'; } var _translator = $tom.translate(name); if (_translator.memberOf('li')) { return 'ol'; } else if (_translator.memberOf('dd,dt')) { return 'dl'; } else if (_translator.memberOf('td,th,tr')) { return 'table'; } else { return 'p'; } } }); (function() { var __IGNORE_NAME_FLAG = 0; var UnitCalculate = Trex.Class.create({ $const: { __FONT_SIZE_BASIS: 9, __REG_EXT_NUMBER: new RegExp("[0-9\.]+"), __REG_EXT_UNIT: new RegExp("px|pt|em") }, initialize: function() { this.unitConverter = { //1em = 9pt "px2em": 1 / 12, "px2pt": 9 / 12, "em2px": 12, // 12 : 1 "em2pt": 9, // 9 : 1 "pt2px": 12 / 9, "pt2em": 1 / 9 }; }, calculate: function(strA, strB) { if (strA == _NULL || strA.length == 0) { strA = "0em"; } if (strB == _NULL || strB.length == 0) { strB = "0em"; } var _sign = this.extractSign(strB); var _unitA = this.extractUnit(strA); var _unitB = this.extractUnit(strB); //basis unit var _numA = this.extractNumber(strA).toNumber(); var _numB = this.extractNumber(strB).toNumber(); if(_unitA != _unitB) { //different unit if(this.unitConverter[_unitA+"2"+_unitB]) { _numA *= this.unitConverter[_unitA+"2"+_unitB]; } } var _result = 0; if(_sign == "-") { _result = Math.max(_numA - _numB, 0); } else { _result = (_numA + _numB); } _result = (Math.round(_result*10)/10); if (_result == 0) { return _NULL; } else { return _result + _unitB; } }, needCalculation: function(str) { if(str == _NULL || typeof str != "string") { return _FALSE; } else { return (str.charAt(0) == '+' || str.charAt(0) == '-'); } }, extractSign: function(str) { var _sign = "+"; if(str.charAt(0) == '+' || str.charAt(0) == '-') { _sign = str.charAt(0); } return _sign; }, extractNumber: function(str) { var _num = 0; var _match; if((_match = str.match(UnitCalculate.__REG_EXT_NUMBER)) != _NULL) { _num = _match[0]; } if(str.indexOf("%") > -1) { //% _num = _num / 100; } return _num; }, extractUnit: function(str) { var _unit = "em"; var _match; if((_match = str.match(UnitCalculate.__REG_EXT_UNIT)) != _NULL) { _unit = _match[0]; } return _unit; } }); var _unitCalculator = new UnitCalculate(); var __ATTRIBUTE_TRANSLATIONS = { colspan: "colSpan", rowspan: "rowSpan", valign: "vAlign", datetime: "dateTime", accesskey: "accessKey", tabindex: "tabIndex", enctype: "encType", maxlength: "maxLength", readonly: "readOnly", longdesc: "longDesc", cellPadding: "cellPadding", cellSpacing: "cellSpacing", more: "more", less: "less", style: "style" }; Object.extend($tom, /** @lends $tom */{ /** * node에 인자로 받은 attributes 속성을 세팅한다. * @function * @param {Element} node * @param {JSON} attributes * @example * $tom.applyAttributes(inNode, { * 'style': { 'fontSize': null }, * 'size': null * }); */ applyAttributes: function(node, attributes) { if(!$tom.isElement(node)) { return; } for(var _name in attributes) { if(_name == "style") { $tom.applyStyles(node, attributes[_name]); } else { $tom.setAttribute(node, _name, attributes[_name]); } } }, /** * node에 인자로 받은 attributes 속성을 제거한다. * @function */ removeAttributes: function(node, attributes) { if(!$tom.isElement(node)) { return; } for(var _name in attributes) { if(_name == "style") { $tom.removeStyles(attributes[_name]) } else { node.removeAttribute(_name, __IGNORE_NAME_FLAG); } } }, /** * node에서 attrName을 이름으로 갖는 속성의 값을 반환 * @function * @example * $tx("tx_image").getAttribute("class") // class속성의 값 반환 */ getAttribute: function(node, attrName) { if(!$tom.isElement(node)) { return _NULL; } if(node && node.getAttribute) { return node.getAttribute(__ATTRIBUTE_TRANSLATIONS[attrName] || attrName); } else { return _NULL; } }, /** * node에 attrName를 이름으로, attrValue를 값으로 갖는 속성을 세팅한다. * @function */ setAttribute: function(node, attrName, attrValue) { if(!$tom.isElement(node)) { return; } if(attrValue == _NULL || attrValue.length == 0 || attrValue == 0) { node.removeAttribute(attrName, __IGNORE_NAME_FLAG); } else { if(__ATTRIBUTE_TRANSLATIONS[attrName]) { node.setAttribute(__ATTRIBUTE_TRANSLATIONS[attrName], attrValue); } else { try { node[attrName] = attrValue; } catch(e) { console.log(e); node.setAttribute(__ATTRIBUTE_TRANSLATIONS[attrName] || attrName, attrValue); } } } }, // TODO : refactoring 뭔가 복잡하다. setStyles: function(node, styles, overwrite) { var nodeCssText = node.style.cssText; var canSetStyle; var styleToSet = Object.extend({}, styles); if (styleToSet.font) { if (overwrite) { node.style.font = styleToSet.font; // 이 부분에서 chrome, opera는 font의 css 속성이 분해된 형태로 적용된다. } else if (node.style.cssText.indexOf("font:") == -1) { node.style.cssText = 'font: ' + styleToSet.font + '; ' + node.style.cssText; } delete styleToSet.font; } for (var styleName in styleToSet) { var styleValue; if (_unitCalculator.needCalculation(styleToSet[styleName])) { styleValue = _unitCalculator.calculate(node.style[styleName], styleToSet[styleName]); } else { styleValue = styleToSet[styleName]; } if (styleValue == _NULL) { styleValue = ""; } if (styleName == 'float') { styleName = $tx.msie ? 'styleFloat' : 'cssFloat'; } canSetStyle = (!node.style[styleName] && (styleName.indexOf("font") != 0 || nodeCssText.indexOf("font:") == -1)) || overwrite; var newTextDecoration = (styleName == "textDecoration") && !node.style[styleName].include(styleValue); if (canSetStyle) { node.style[styleName] = styleValue; } else if (newTextDecoration) { node.style[styleName] += " " + styleValue; } } $tom._clearUselessStyle(node); }, /** * node에 styles에서 지정한 스타일을 적용한다. * @function * @example * $tom.applyStyles(node, { * 'width': width * }); */ applyStyles: function(node, styles) { this.setStyles(node, styles, _TRUE); }, /** * node의 style 속성값을 적용하되, 이미 존재하는 속성은 유지된다. * @param node * @param styles */ addStyles: function(node, styles) { this.setStyles(node, styles, _FALSE); }, /** * node에서 styles인자에서 지정한 스타일 속성값을 제거한다. * @function */ removeStyles: function(node, styles) { // FTDUEDTR-1166 var cssText = node.style.cssText; var orignalCssText = cssText; for(var _name in styles) { _name = _name.replace(/([A-Z])/g, "-$1"); cssText = cssText.replace(new RegExp("(^| )" + _name + "\\s*:[^;]+;? ?", "ig"), ""); } if (orignalCssText != cssText) { node.style.cssText = cssText; $tom._clearUselessStyle(node); } }, _clearUselessStyle: function(node) { var _attrValue = $tom.getAttribute(node, "style"); if (!_attrValue) { //remove needless style node.removeAttribute("style", __IGNORE_NAME_FLAG); } }, /** * node에서 style 속성값 텍스트를 모두 반환한다. * @function */ getStyleText: function(node) { return node.style.cssText; }, /** * node의 style 속성값을 value로 넣는다. 기존에 있는 값은 덮어쓰여진다. * @function * @param {Element} node * @param {String} value style 속성에 바로 세팅할 텍스트 값을 넣어야 함 * @example * $tom.setStyleText($tx("tx_article_category"), "width:50px;height:10px") */ setStyleText: function(node, value) { node.style.cssText = value; !value && $tom._clearUselessStyle(node); } }); })(); Object.extend($tom, /** @lends $tom */{ /** * @private * @function */ goInto: function(node, toTop) { if(!node || !node.scrollIntoView) { return; } node.scrollIntoView(toTop); }, /** * 수직 스크롤 위치값을 반환한다. * @function * @example * $tom.getScrollTop(document) */ getScrollTop: function(doc) { if(!doc) { return 0; } return doc.documentElement.scrollTop >= 0 ? doc.documentElement.scrollTop : doc.body.scrollTop; }, /** * 수직 스크롤 값을 셋팅한다. * @function * @param {Element} doc * @param {Number} scrollTop 수직 스크롤 값 */ setScrollTop: function(doc, scrollTop) { if(!doc) { return; } if(doc.documentElement.scrollTop) { doc.documentElement.scrollTop = scrollTop; } else { doc.body.scrollTop = scrollTop; } }, /** * 수평 스크롤 위치값을 반환한다. * @function */ getScrollLeft: function(doc) { if(!doc) { return 0; } return (doc.documentElement.scrollLeft || doc.body.scrollLeft); }, /** * 수평 스크롤 값을 셋팅한다. * @function * @param {Element} doc * @param {Number} scrollLeft 수평 스크롤 값 */ setScrollLeft: function(doc, scrollLeft) { if(!doc) { return; } if(doc.documentElement.scrollLeft) { doc.documentElement.scrollLeft = scrollLeft; } else { doc.body.scrollLeft = scrollLeft; } }, /** * element요소의 left, top, width, height 값을 계산하여 반환한다. * @function * @return { * x: 0, * y: 0, * width: 0, * height: 0 * } */ getPosition: function(element, cumulative) { if(!element) { return { x: 0, y: 0, width: 0, height: 0 }; } cumulative = !!cumulative; element = $tx(element); var pos = (cumulative)? $tx.cumulativeOffset(element): $tx.positionedOffset(element); var dim; var display = element.style.display; if (display != 'none' && display != _NULL) { //Safari bug dim = { width: element.offsetWidth, height: element.offsetHeight }; } else { var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; var originalDisplay = els.display; els.visibility = 'hidden'; els.position = 'absolute'; els.display = 'block'; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; els.display = originalDisplay; els.position = originalPosition; els.visibility = originalVisibility; dim = { width: originalWidth, height: originalHeight }; } return { x: pos[0], y: pos[1], width: dim.width, height: dim.height }; }, /** * node 요소의 width값을 반환한다. * inline style이 px값으로 유효하지 않으면 offset으로 대체한다. * @function */ getWidth: function(node) { var width = node.style["width"]; if( width.isPx() ){ return width.parsePx(); } return node.offsetWidth; }, /** * node 요소 스타일속성의 width 값을 세팅한다. * @function */ setWidth: function(node, width) { $tom.applyStyles(node, { 'width': width }); }, /** * node 요소의 height값을 반환한다. * inline style이 px값으로 유효하지 않으면 offset으로 대체한다. * @function */ getHeight: function(node) { var height = node.style["height"]; if( height.isPx() ){ return height.parsePx(); } return node.offsetHeight; }, /** * node 요소 스타일속성의 height 값을 세팅한다. * @function */ setHeight: function(node, height) { $tom.applyStyles(node, { 'height': height }); }, /** * @private * @function */ replacePngPath: function(node) { if ($tx.msie6) { if(_DOC.location.href.indexOf("http://") > -1) { return; } try { var _orgFilter = $tx.getStyle(node, 'filter'); var _orgSrc = /src='([^']+)'/.exec(_orgFilter)[1]; if(!_orgSrc || _orgSrc == 'none') { return; } else if(_orgSrc.indexOf("http://") > -1) { return; } var _docPathSlices = _DOC.location.href.split("/"); _docPathSlices.push("css"); _docPathSlices.pop(); _orgSrc = _orgSrc.replace(/\.\.\//g, function() { _docPathSlices.pop(); return ""; }); var _newSrc = _docPathSlices.join("/") + "/" + _orgSrc; node.style.filter = _orgFilter.replace(/src='([^']+)'/, "src='" + _newSrc + "'"); } catch(e) {alert(e)} } } }); Object.extend($tom, /** @lends $tom */{ /** * 편집영역에서 기본 빈 문단에 해당하는 content * @constant */ EMPTY_BOGUS: ($tx.msie_quirks || $tx.msie && $tx.msie_ver < 11 ? " " : "
") }); Object.extend($tom, /** @lends $tom */{ /** * 편집영역에서 기본 빈 문단에 해당하는 HTML * @constant */ EMPTY_PARAGRAPH_HTML: "

" + $tom.EMPTY_BOGUS + "

" }); _WIN.$tom = $tom;