insertlink.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /**
  2. * @fileoverview
  3. * '링크삽입' Icon Source,
  4. * Class Trex.Tool.Link과 configuration을 포함
  5. *
  6. */
  7. TrexConfig.addTool(
  8. "link",
  9. {
  10. wysiwygonly: _TRUE,
  11. sync: _FALSE,
  12. status: _TRUE
  13. }
  14. );
  15. TrexMessage.addMsg({
  16. '@insertlink.cancel.image': "#iconpath/btn_cancel.gif?v=2",
  17. '@insertlink.confirm.image': "#iconpath/btn_confirm.gif?v=2",
  18. '@insertlink.invalid.url': "URL을 입력해주세요.",
  19. '@insertlink.link.alt': "[#{title}]로 이동합니다.",
  20. '@insertlink.remove.image': "#iconpath/btn_remove.gif?v=2",
  21. '@insertlink.title': "선택된 부분에 걸릴 URL주소를 넣어주세요.",
  22. '@insertlink.onclick.target': "클릭 시",
  23. '@insertlink.target.blank': "새 창",
  24. '@insertlink.target.self': "현재창",
  25. '@insertlink.class.name': "tx-link"
  26. });
  27. Trex.Tool.Link = Trex.Class.create({
  28. $const: {
  29. __Identity: 'link'
  30. },
  31. $extend: Trex.Tool,
  32. oninitialized: function() {
  33. var _tool = this;
  34. var _canvas = this.canvas;
  35. var _toolHandler = function(data) {
  36. if (_canvas.isWYSIWYG()) {
  37. if (data) {
  38. _canvas.execute(function(processor) {
  39. var _attributes = {
  40. 'href': data.link,
  41. 'target': data.target ? data.target : '_blank',
  42. 'className': data.className
  43. };
  44. var _aNode, _nodes;
  45. if(processor.findNode('a')) {
  46. _aNode = processor.findNode('a');
  47. $tom.applyAttributes(_aNode, _attributes);
  48. } else if (processor.hasControl()) {
  49. _nodes = processor.controls(function() {
  50. return 'img';
  51. });
  52. $tom.wrap(processor.create('a', _attributes), _nodes);
  53. } else if(processor.isCollapsed()) {
  54. _aNode = processor.create('a', _attributes);
  55. var text = processor.doc.createTextNode(data.link);
  56. _aNode.appendChild(text);
  57. processor.pasteNode(_aNode, _FALSE);
  58. } else {
  59. _nodes = processor.inlines(function() {
  60. return '%text,img,a,%inline';
  61. });
  62. _nodes.each(function(node) {
  63. if ($tom.hasUsefulChildren(node, _TRUE)) {
  64. if ($tom.kindOf(node, 'a')) {
  65. $tom.applyAttributes(node, _attributes);
  66. } else if ($tom.kindOf(node, 'img')) {
  67. $tom.wrap(processor.create('a', _attributes), [node]);
  68. } else {
  69. var _styleValue = $tom.getStyleText(node);
  70. var _oldNodes = $tom.collectAll(node, 'a');
  71. _oldNodes.each(function(oldNode){
  72. $tom.moveChildToParent(oldNode);
  73. $tom.remove(oldNode);
  74. });
  75. var _aNode = processor.create('a', _attributes);
  76. $tom.setStyleText(_aNode, _styleValue);
  77. $tom.replace(node, _aNode);
  78. }
  79. } else {
  80. $tom.remove(node);
  81. }
  82. });
  83. }
  84. });
  85. } else {
  86. _canvas.execute(function(processor) {
  87. var _node = processor.findNode('a');
  88. if (_node) {
  89. processor.unwrap(_node);
  90. }
  91. });
  92. }
  93. }else{
  94. _canvas.execute(function(processor) {
  95. processor.insertTag('<a href="' + data.link + '" target="' +data.target+ '" >','</a>');
  96. });
  97. }
  98. };
  99. var __DefaultValue = "";
  100. var _initHandler = function() {
  101. if (_canvas.isWYSIWYG()) {
  102. return _canvas.query(function(processor){
  103. var node, value, target, text;
  104. node = processor.findNode('a');
  105. if (node) {
  106. value = $tom.getAttribute(node, "href");
  107. if (value) {
  108. target = $tom.getAttribute(node, "target");
  109. return {
  110. exist: _TRUE,
  111. value: value,
  112. target: target
  113. };
  114. }
  115. } else {
  116. text = processor.getText();
  117. if (/^\w+\:\/\/\S+/.test(text)) { // only for url with protocol.
  118. return {
  119. exist: _FALSE,
  120. value: text
  121. }
  122. }
  123. }
  124. return {
  125. exist: _FALSE,
  126. value: __DefaultValue
  127. };
  128. });
  129. }else{
  130. return {
  131. exist: _FALSE,
  132. value: __DefaultValue
  133. };
  134. }
  135. };
  136. /* button & menu weave */
  137. this.weave.bind(this)(
  138. /* button */
  139. new Trex.Button(this.buttonCfg),
  140. /* menu */
  141. new Trex.Menu.Link(this.menuCfg),
  142. /* handler */
  143. _toolHandler,
  144. /* handler for menu initial value */
  145. _initHandler
  146. );
  147. var _popdownHandler = function(ev) {
  148. _tool.button.onMouseDown(ev);
  149. };
  150. this.bindKeyboard({ // ctrl + k - 링크
  151. ctrlKey: _TRUE,
  152. keyCode: 75
  153. }, _popdownHandler);
  154. }
  155. });
  156. /* Trex.Menu.Link ************************************************************************************/
  157. Trex.MarkupTemplate.add(
  158. 'menu.insertlink', [
  159. '<div class="tx-menu-inner">',
  160. ' <dl>',
  161. ' <dt>',
  162. ' @insertlink.title',
  163. ' </dt>',
  164. ' <dd>',
  165. ' <input type="text" class="tx-text-input"/>',
  166. ' </dd>',
  167. ' <dd class="tx-rp">',
  168. ' <span class="tx-text tx-first">@insertlink.onclick.target</span>',
  169. ' <span><input type="radio" name="tx-insertlink-win" value="_blank"/><span class="tx-text">@insertlink.target.blank</span></span>',
  170. ' <span><input type="radio" name="tx-insertlink-win" value="_top"/><span class="tx-text">@insertlink.target.self</span></span>',
  171. ' </dd>',
  172. ' <dd class="tx-hr">',
  173. ' <hr/>',
  174. ' </dd>',
  175. ' <dd>',
  176. ' <img width="32" height="21" src="@insertlink.confirm.image"/>',
  177. ' <img width="32" height="21" src="@insertlink.cancel.image"/>',
  178. ' <img width="51" height="21" src="@insertlink.remove.image" style="display: none;"/>',
  179. ' </dd>',
  180. ' </dl>',
  181. '</div>'
  182. ].join("")
  183. );
  184. Trex.Menu.Link = Trex.Class.create({
  185. $extend: Trex.Menu,
  186. ongenerated: function() {
  187. var _elMenu = this.elMenu;
  188. Trex.MarkupTemplate.get('menu.insertlink').evaluateToDom({}, _elMenu);
  189. var _elTargets = $tom.collectAll(_elMenu, ".tx-rp input");
  190. var _newInput = this.newInput = _elTargets[0];
  191. $tx.observe(_newInput, "click", function(){
  192. _newInput.checked = "checked";
  193. _currInput.checked = "";
  194. });
  195. var _currInput = this.currInput = _elTargets[1];
  196. $tx.observe(_currInput, "click", function(){
  197. _currInput.checked = "checked";
  198. _newInput.checked = "";
  199. });
  200. var _checkValidation = this.urlValidator;
  201. var _elInput = this.elInput = $tom.collect(_elMenu, 'input.tx-text-input');
  202. $tx.observe(_elInput, "keydown", function(ev) {
  203. if(ev.keyCode == 13) { //Enter
  204. var _val = _checkValidation(_elInput.value);
  205. if (!_val) {
  206. alert( TXMSG("@insertlink.invalid.url") );
  207. $tx.stop(ev);
  208. return;
  209. }
  210. var _target = _newInput.checked ? _newInput.value : _currInput.value;
  211. this.onSelect(ev, {
  212. link: _val,
  213. target: _target,
  214. className: TXMSG("@insertlink.class.name")
  215. });
  216. $tx.stop(ev);
  217. }
  218. }.bindAsEventListener(this));
  219. var _elImgs = $tom.collectAll(_elMenu, 'img');
  220. $tx.observe(_elImgs[0], "click", function(ev) {
  221. var _val = _checkValidation(_elInput.value);
  222. if (!_val) {
  223. alert( TXMSG("@insertlink.invalid.url") );
  224. $tx.stop(ev);
  225. return;
  226. }
  227. var _target = _newInput.checked ? _newInput.value : _currInput.value;
  228. this.onSelect(ev, {
  229. link: _val,
  230. target: _target,
  231. className: TXMSG("@insertlink.class.name")
  232. });
  233. $tx.stop(ev);
  234. }.bind(this));
  235. $tx.observe(_elImgs[1], "click", function() {
  236. this.onCancel();
  237. }.bindAsEventListener(this));
  238. var _elRemoveBtn = $tx(_elImgs[2]);
  239. $tx.observe(_elRemoveBtn, "click", function(ev) {
  240. this.onSelect(ev, _NULL);
  241. }.bindAsEventListener(this));
  242. this.toggleRemoveBtn = function(exist) {
  243. _elRemoveBtn.style.display = ((exist)? '': 'none');
  244. };
  245. },
  246. onregenerated: function() {
  247. var _elInput = this.elInput;
  248. var _initData = this.initHandler();
  249. _elInput.value = _initData.value;
  250. if(_initData.target == "_self" || _initData.target == "_top"){
  251. this.currInput.checked = "checked";
  252. this.newInput.checked = "";
  253. }else{
  254. this.newInput.checked = "checked";
  255. this.currInput.checked = "";
  256. }
  257. this.toggleRemoveBtn(_initData.exist);
  258. _elInput.focus();
  259. // Set focus to end of input box. ( For IE );
  260. if ($tx.msie_nonstd) {
  261. setTimeout(function() {
  262. try {
  263. _elInput.focus();
  264. var _sel = _DOC.selection.createRange();
  265. _sel.move("character", _elInput.value.length);
  266. _sel.select();
  267. }
  268. catch (ignore) {}
  269. }, 100);
  270. }
  271. },
  272. urlValidator: function(value) {
  273. if (!value) {
  274. return _FALSE;
  275. }
  276. value = value.trim();
  277. if (value.length == 0) {
  278. return _FALSE;
  279. }
  280. var pattern = /^[a-z0-9+.-]+:|^\/\//i;// FTDUEDTR-1330 && MAILCS-24754
  281. if ( pattern.test(value) ) {
  282. return value;
  283. } else {
  284. return "http://" + value;
  285. }
  286. }
  287. });