| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- Trex.I.FontTool = Trex.Mixin.create({
- initialize: function(editor, toolbar, config) {
- this.$super.initialize(editor, toolbar, config);
- },
- handler: function(data) {
- this.onBeforeHandler(data);
- this.doHandle(data);
- this.onAfterHandler(data);
- },
- onBeforeHandler: function() {
- },
- doHandle: function(data) {
- var self = this,
- range, newStyle = self.computeNewStyle(data);
- self.canvas.execute(function(processor) {
- var selectedCells = (processor.table) ? processor.table.getTdArr() : [];
- if (selectedCells.length > 0) {
- range = goog.dom.Range.createFromNodeContents(selectedCells[0]);
- processor.executeUsingCaret(function() {
- self.tableCellsExecutor(processor, newStyle, selectedCells);
- });
- } else {
- range = processor.createGoogRange();
- if (range) {
- self.rangeExecutor(processor, newStyle, range);
- }
- }
- });
- },
- onAfterHandler: function() {
- },
- tableCellsExecutor: function(processor, newStyle, cells) {
- var self = this;
- cells.each(function(cell) {
- var range = goog.dom.Range.createFromNodeContents(cell);
- range.select();
- self.rangeExecutor(processor, newStyle, range);
- });
- },
- findQueryingNode: function(goog_range) {
- if (goog_range) {
- var textNode;
- try {
- textNode = this.findFirst(goog_range.__iterator__(), function(node) {
- return node.nodeType == 3 && node.nodeValue.trim();
- });
- } catch (ignore4ie678) {}
- if (textNode) {
- return textNode.parentNode;
- } else { // fallback condition
- var startNode = goog_range.getStartNode();
- if (startNode && startNode.nodeType == 3) {
- return startNode.parentNode;
- }
- return startNode;
- }
- }
- },
- findFirst: function(iterator, condition) {
- try {
- return goog.iter.filter(iterator, condition).next();
- } catch(e) {
- return null;
- }
- }
- });
- Trex.I.WrappingSpanFontTool = Trex.Mixin.create({
- wrapTextAsStyledSpan: function(processor, newStyle, range) {
- var affectedNodes;
- if (processor.isCollapsed()) {
- var startNode = range.getStartNode();
- if (startNode.nodeType == 3) {
- startNode = startNode.parentNode;
- }
- var targetNode = this.findOrCreateDummySpan(startNode, processor, range);
- var wordJoiner = targetNode.firstChild;
- processor.createGoogRangeFromNodes(wordJoiner, wordJoiner.length, wordJoiner, wordJoiner.length).select();
- affectedNodes = [ targetNode ];
- } else {
- processor.executeUsingCaret(function(range, savedCaret) {
- var iterator = createTextRangeIterator(savedCaret);
- var textNodes = collectTextNodes(iterator);
- affectedNodes = collectTextOnlySpans(textNodes);
- });
- }
- processor.apply(affectedNodes, {
- style: newStyle
- });
- function createTextRangeIterator(savedCaret) {
- var startCaret = savedCaret.getCaret(_TRUE),
- endCaret = savedCaret.getCaret(_FALSE);
- return new goog.dom.TextRangeIterator(startCaret, 0, endCaret, 0);
- }
- // Known Issue : <p> </p>에 대해 p의 childNodes.length === 0 이라 적용이 안된다.
- function collectTextNodes(iterator) {
- var result = [];
- goog.iter.forEach(iterator, function(node) {
- // 잘못된 위치의 TextNode는 제외
- if (node.nodeType == 3 && !$tom.kindOf(node.parentNode, "table,thead,tbody,tr,ul,ol")) {
- result.push(node);
- }
- });
- return result;
- }
- function collectTextOnlySpans(textNodes) {
- var result = [];
- textNodes.each(function(node) {
- var parentNode = node.parentNode;
- if (parentNode.nodeName == "SPAN" && hasOnlyOneChild(parentNode)) {
- result.push(parentNode);
- } else {
- var newSpan = processor.create("span");
- $tom.wrap(newSpan, node);
- result.push(newSpan);
- }
- });
- return result;
- }
- function hasOnlyOneChild(node) {
- var childNodes = node.childNodes;
- var childCount = childNodes.length;
- if (childCount > 3) { // early return
- return _FALSE;
- }
- for (var i = 0, len = childCount; i < len; i++) {
- if ($tom.isGoogRangeCaret(childNodes[i])) {
- childCount = childCount - 1;
- }
- }
- return childCount == 1;
- }
- },
- /**
- * collapsed 일 때에 style을 적용할 수 있는 span을 찾거나, 새로 span을 만든다.
- */
- findOrCreateDummySpan: function(node, processor, goog_range) {
- var reuseExistNode = (node.tagName == "SPAN" && node.childNodes.length == 1 && node.firstChild.nodeType == 3 && node.firstChild.nodeValue == Trex.__WORD_JOINER);
- if (reuseExistNode) {
- return node;
- } else {
- return this.createDummySpan(node, processor, goog_range);
- }
- },
- createDummySpan: function (parentNode, processor, goog_range) {
- var newNode = null;
- if (parentNode.tagName == "SPAN") {
- newNode = $tom.clone(parentNode);
- } else {
- newNode = processor.create('span');
- }
- newNode.appendChild(processor.newDummy());
- newNode = goog_range.insertNode(newNode); // NOTE: IE에서는 return된 value를 사용해야 한다.
- // insertNode로 인해 빈 TextNode가 생긴 경우, 바로 삭제해준다.
- $tom.removeEmptyTextNode(newNode.previousSibling);
- $tom.removeEmptyTextNode(newNode.nextSibling);
- return newNode;
- }
- });
- Trex.I.WrappingDummyFontTool = Trex.Mixin.create({
- wrapDummy: function(processor, range) {
- var targetNode = this.createDummySpan(processor, range);
- var wordJoiner = targetNode.firstChild;
- $tom.unwrap(targetNode);
- processor.createGoogRangeFromNodes(wordJoiner, 0, wordJoiner, wordJoiner.length).select();
- return wordJoiner;
- },
- createDummySpan: function (processor, goog_range) {
- var newNode = null;
- newNode = processor.create('span');
- newNode.appendChild(processor.newDummy());
- newNode = goog_range.insertNode(newNode); // NOTE: IE에서는 return된 value를 사용해야 한다.
- // insertNode로 인해 빈 TextNode가 생긴 경우, 바로 삭제해준다.
- $tom.removeEmptyTextNode(newNode.previousSibling);
- $tom.removeEmptyTextNode(newNode.nextSibling);
- return newNode;
- }
- });
|