attachbox_ui.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. TrexMessage.addMsg({
  2. '@attacher.ins': "삽입",
  3. '@attacher.del': "삭제",
  4. '@attacher.preview.image': "#iconpath/pn_preview.gif",
  5. '@attacher.delete.confirm': "삭제하시면 본문에서도 삭제됩니다. 계속하시겠습니까?",
  6. '@attacher.delete.all.confirm': "모든 첨부 파일을 삭제하시겠습니까? 삭제하시면 본문에서도 삭제됩니다.",
  7. '@attacher.exist.alert': "이미 본문에 삽입되어 있습니다."
  8. });
  9. Trex.install("attachbox.onAttachBoxInitialized @if config.sidebar.attachbox.show = true", function(editor, toolbar, sidebar, canvas, config) {
  10. var attachbox = editor.getAttachBox();
  11. if (config.sidebar.attachbox.show == _TRUE) {
  12. Object.extend(attachbox, Trex.I.AttachBox);
  13. attachbox.onAttachBoxInitialized(config, canvas, editor);
  14. }
  15. });
  16. Trex.I.AttachBox = {
  17. useBox: _TRUE,
  18. isDisplay: _FALSE,
  19. lastSelectedEntry: _NULL,
  20. onAttachBoxInitialized: function(config, canvas) {
  21. var _entryBox = this;
  22. this.canvas = canvas;
  23. var _initializedId = ((config.initializedId) ? config.initializedId : "");
  24. this.elBox = $must("tx_attach_div" + _initializedId, "Trex.I.AttachBox");
  25. this.elList = $must("tx_attach_list" + _initializedId, "Trex.I.AttachBox");
  26. var _elPreview = $must('tx_attach_preview' + _initializedId, "Trex.I.AttachBox");
  27. this.elPreviewKind = $tom.collect(_elPreview, "p");
  28. var _elPreviewImg = $tom.collect(_elPreview, "img");
  29. this.elPreviewImg = _elPreviewImg;
  30. this.imageResizer = new Trex.ImageResizer(_elPreviewImg, {
  31. maxWidth: 147,
  32. maxHeight: 108,
  33. defImgUrl: TXMSG("@attacher.preview.image"),
  34. onComplete: function(width, height) { //vertical positioning
  35. _elPreviewImg.style.marginTop = Math.floor((108 - height) / 2).toPx();
  36. }
  37. });
  38. this.elDelete = $tom.collect("#tx_attach_delete" + _initializedId + " a");
  39. $tx.observe(this.elDelete, 'click', function() {
  40. if (config.sidebar.attachbox.confirmForDeleteAll) {
  41. _entryBox.onDeleteAll(false);
  42. } else {
  43. _entryBox.onDeleteAll(true);
  44. }
  45. });
  46. if (typeof showAttachBox == "function") { //NOTE: 첨부박스가 보여질 때 실행할 서비스 콜백
  47. this.observeJob(Trex.Ev.__ATTACHBOX_SHOW, function() {
  48. showAttachBox();
  49. });
  50. }
  51. if (typeof hideAttachBox == "function") { //NOTE: 첨부박스가 감춰질 때 실행할 서비스 콜백
  52. this.observeJob(Trex.Ev.__ATTACHBOX_HIDE, function() {
  53. hideAttachBox();
  54. });
  55. }
  56. var _elProgress = $must('tx_upload_progress' + _initializedId, 'Trex.I.AttachBox');
  57. this.elProgress = _elProgress;
  58. this.elProgressPercent = $tom.collect(_elProgress, "div");
  59. this.elProgressTicker = $tom.collect(_elProgress, "p");
  60. this.observeJob(Trex.Ev.__ENTRYBOX_ENTRY_ADDED, function(entry) {
  61. _entryBox.registerEntryNode(entry);
  62. _entryBox.displayBox();
  63. });
  64. this.observeJob(Trex.Ev.__ENTRYBOX_ENTRY_MODIFIED, function(entry) {
  65. _entryBox.modifyEntryNode(entry);
  66. _entryBox.refreshPreview();
  67. });
  68. this.observeJob(Trex.Ev.__ENTRYBOX_ENTRY_REMOVED, function(entry) {
  69. _entryBox.removeEntryNode(entry);
  70. _entryBox.displayBox();
  71. if (_entryBox.lastSelectedEntry && _entryBox.lastSelectedEntry.key == entry.key) {
  72. _entryBox.refreshPreview();
  73. }
  74. });
  75. this.observeJob(Trex.Ev.__ENTRYBOX_ALL_ENTRY_REMOVED, function() {
  76. _entryBox.datalist.each(function(entry) {
  77. _entryBox.removeEntryNode(entry, _TRUE);
  78. });
  79. _entryBox.displayBox();
  80. if (_entryBox.lastSelectedEntry) {
  81. _entryBox.refreshPreview();
  82. }
  83. });
  84. this.observeJob(Trex.Ev.__ENTRYBOX_ENTRY_REFRESH, function(entry) {
  85. _entryBox.displayBox();
  86. _entryBox.refreshEntryNode(entry);
  87. });
  88. var _elUploadedSize = $tx('tx_attach_up_size' + _initializedId), _elMaximumSize = $tx('tx_attach_max_size' + _initializedId), _elGroupUsedSize = $tx('tx_attach_group_used_size' + _initializedId), _elGroupMaximumSize = $tx('tx_attach_group_max_size' + _initializedId);
  89. this.observeJob(Trex.Ev.__ENTRYBOX_CAPACITY_UPDATE, function() {
  90. var capacity = config.sidebar.capacity;
  91. if (capacity.show == _FALSE) {
  92. return;
  93. }
  94. if (_elUploadedSize) {
  95. _elUploadedSize.innerText = capacity.uploaded.toByteUnit();
  96. }
  97. if (_elMaximumSize) {
  98. // maximum을 안쓰고 available을 사용하는 이유는 group 값 이용시 group.used의 사용여하에 따라 최대치가 달라지기 때문
  99. _elMaximumSize.innerText = capacity.available.toByteUnit();
  100. }
  101. if (capacity.group) {
  102. if (_elGroupUsedSize) {
  103. _elGroupUsedSize.innerText = (capacity.group.used + capacity.uploaded).toByteUnit();
  104. }
  105. if (_elGroupMaximumSize) {
  106. _elGroupMaximumSize.innerText = capacity.group.maximum.toByteUnit();
  107. }
  108. }
  109. });
  110. // canvas에서 제거된 첨부파일은 첨부박스에는 1차로는 남아있기 때문에 아래와 같은 삭제 과정이 필요하지 않다
  111. // canvas.observeJob(Trex.Ev.__CANVAS_PANEL_DELETE_SOMETHING, function(ev){
  112. // // 데이터중에 존재하지 stage에 존재하지 않는 entry는 박스에서 바로 제거
  113. // _entryBox.datalist.each(function (entry) {
  114. // if (entry.type =='image' && entry.actor.name == 'image' && entry.existStage == false) {
  115. // entry.execRemove();
  116. // }
  117. // });
  118. // _entryBox.refreshPreview();
  119. // });
  120. },
  121. onDeleteAll: function(force) {
  122. if (this.datalist.length === 0) {
  123. return;
  124. }
  125. if (!force && !confirm(TXMSG("@attacher.delete.all.confirm"))) {
  126. return;
  127. }
  128. this.datalist.each(function(entry) {
  129. if (entry.deletedMark == _FALSE) {
  130. entry.execRemove();
  131. }
  132. });
  133. // this.imageResizer.execResize(TXMSG("@attacher.preview.image"));
  134. this.initPreviewImage();
  135. },
  136. checkDisplay: function() {
  137. return this.isDisplay;
  138. },
  139. setDisplay: function(isDisplay) {
  140. this.isDisplay = isDisplay;
  141. },
  142. displayBox: function() {
  143. var isDisplay = _FALSE;
  144. for (var i = 0; i < this.datalist.length; i++) {
  145. if (this.datalist[i].deletedMark == _FALSE) {
  146. isDisplay = _TRUE;
  147. }
  148. }
  149. //var isDisplay = (this.datalist.length > 0);
  150. if (this.isDisplay == isDisplay) {
  151. return;
  152. }
  153. if (isDisplay) {
  154. $tx.show(this.elBox);
  155. this.fireJobs(Trex.Ev.__ATTACHBOX_SHOW, _TRUE);
  156. } else {
  157. $tx.hide(this.elBox);
  158. this.fireJobs(Trex.Ev.__ATTACHBOX_HIDE, _FALSE);
  159. }
  160. this.isDisplay = isDisplay;
  161. },
  162. registerEntryNode: function(entry) {
  163. var _elData = tx.li({
  164. className: "type-" + entry.type
  165. });
  166. if (entry.actor.boxonly) {
  167. $tx.addClassName(_elData, "tx-boxonly");
  168. }
  169. this.elList.appendChild(_elData);
  170. entry.elData = _elData;
  171. entry.makeSelection = function(isPreviewed) {
  172. if (isPreviewed) {
  173. this.showEntryThumb(entry);
  174. } else {
  175. this.hideEntryThumb(entry);
  176. }
  177. }
  178. .bind(this);
  179. //NOTE: only blog cuz iframe area
  180. $tx.observe(_elData, 'mouseover', this.onEntryMouseOver.bind(this, entry));
  181. $tx.observe(_elData, 'mouseout', this.onEntryMouseOut.bind(this, entry));
  182. var _elRow = tx.dl();
  183. _elData.appendChild(_elRow);
  184. var _elName = tx.dt({
  185. className: "tx-name",
  186. unselectable: "on"
  187. }, entry.boxAttr.name); //파일명
  188. entry.elName = _elName;
  189. _elRow.appendChild(_elName);
  190. $tx.observe(_elData, 'click', function(e) {
  191. var _el = $tx.element(e);
  192. if (_el.className == "tx-delete" || _el.className == "tx-insert") {
  193. return;
  194. }
  195. if (e.ctrlKey) {
  196. this.clickEntryWithCtrl(entry);
  197. } else if (e.shiftKey) {
  198. this.clickEntryWithShift(entry);
  199. } else {
  200. this.clickEntry(entry);
  201. }
  202. if (entry.actor.name == 'image') { //NOTE: get image scale
  203. if (!entry.data.width || !entry.data.height) {
  204. new Trex.ImageScale(entry.data);
  205. }
  206. }
  207. }
  208. .bind(this), _FALSE);
  209. var _elButton = tx.dd({
  210. className: "tx-button"
  211. }); //버튼
  212. _elRow.appendChild(_elButton);
  213. var _elDelete = tx.a({
  214. className: "tx-delete"
  215. }, TXMSG("@attacher.del")); //삭제
  216. _elButton.appendChild(_elDelete);
  217. $tx.observe(_elDelete, 'click', function() {
  218. if (!confirm(TXMSG("@attacher.delete.confirm"))) {
  219. return;
  220. }
  221. entry.execRemove();
  222. }, _FALSE);
  223. var _elInsert = tx.a({
  224. className: "tx-insert"
  225. }, TXMSG("@attacher.ins")); //삽입
  226. entry.elInsert = _elInsert;
  227. _elButton.appendChild(_elInsert);
  228. $tx.observe(_elInsert, 'click', function() {
  229. if (entry.existStage && !entry.actor.config.multipleuse) {
  230. alert(TXMSG("@attacher.exist.alert"));
  231. } else {
  232. entry.execAppend();
  233. }
  234. }, _FALSE);
  235. },
  236. changeState: function(entry) {
  237. var _existStage = entry.existStage;
  238. if (_existStage && !entry.actor.config.multipleuse) {
  239. $tx.addClassName(entry.elData, "tx-existed");
  240. } else {
  241. $tx.removeClassName(entry.elData, "tx-existed");
  242. }
  243. },
  244. modifyEntryNode: function(entry) {
  245. entry.elName.innerText = entry.boxAttr.name;
  246. },
  247. removeEntryNode: function(entry, force) {
  248. if (force) {
  249. entry.elData.parentNode.removeChild(entry.elData);
  250. } else if (entry.deletedMark) {
  251. $tx.hide(entry.elData);
  252. }
  253. },
  254. refreshEntryNode: function(entry) {
  255. if (entry.deletedMark) {
  256. $tx.hide(entry.elData);
  257. } else {
  258. $tx.show(entry.elData);
  259. }
  260. },
  261. refreshPreview: function() {
  262. // reload last selected entry
  263. for (var i = 0, l = this.datalist.length - 1; i < l; ++i) {
  264. var entry = this.datalist[i];
  265. if (this.lastSelectedEntry && this.lastSelectedEntry.key == entry.key && entry.deleteMark == false) {
  266. this.setPreivewImage(entry);
  267. return _TRUE;
  268. }
  269. }
  270. // reselect
  271. for (var i = 0, l = this.datalist.length - 1; i < l; ++i) {
  272. var entry = this.datalist[i];
  273. if (entry.deletedMark == false && $tx.hasClassName(entry.elData, "tx-clicked")) {
  274. this.setPreivewImage(entry);
  275. return _TRUE;
  276. }
  277. }
  278. // init
  279. this.initPreviewImage();
  280. return _FALSE;
  281. },
  282. setPreivewImage: function(entry) {
  283. this.imageResizer.execResize(entry.boxAttr.image);
  284. this.lastSelectedEntry = entry;
  285. },
  286. initPreviewImage: function() {
  287. this.imageResizer.execResize(TXMSG("@attacher.preview.image"));
  288. this.lastSelectedEntry = _NULL;
  289. },
  290. showEntryThumb: function(entry) {
  291. $tx.addClassName(entry.elData, "tx-clicked");
  292. $tx.removeClassName(entry.elData, "tx-hovered");
  293. },
  294. hideEntryThumb: function(entry) {
  295. $tx.removeClassName(entry.elData, "tx-clicked");
  296. },
  297. onEntryMouseOver: function(entry) {
  298. $tx.addClassName(entry.elData, "tx-hovered");
  299. },
  300. onEntryMouseOut: function(entry) {
  301. $tx.removeClassName(entry.elData, "tx-hovered");
  302. },
  303. startUpload: function() {
  304. this.elProgressPercent.style.width = "0".toPx();
  305. $tx.setStyle(this.elList, {
  306. opacity: 0.3
  307. });
  308. $tx.show(this.elProgress);
  309. },
  310. doUpload: function(percent) {
  311. var progressWidth = 300;
  312. this.elProgressPercent.style.width = Math.floor(progressWidth * (isNaN(percent) ? 0 : parseFloat(percent) * 0.01)).toPx();
  313. this.elProgressTicker.innerText = Math.floor((isNaN(percent) ? 0 : parseFloat(percent))) + "%";
  314. },
  315. endUpload: function() {
  316. $tx.hide(this.elProgress);
  317. $tx.setStyle(this.elList, {
  318. opacity: 1
  319. });
  320. },
  321. clickEntry: function(entry) {
  322. if (this.lastSelectedEntry) {
  323. if (this.lastSelectedEntry.key == entry.key) {
  324. return;
  325. }
  326. this.datalist.each(function(entry) {
  327. entry.makeSelection(_FALSE);
  328. });
  329. }
  330. this.elPreviewKind.className = ((entry.boxAttr.className) ? entry.boxAttr.className : "");
  331. entry.makeSelection(_TRUE);
  332. this.setPreivewImage(entry);
  333. },
  334. clickEntryWithCtrl: function(entry) {
  335. if ($tx.hasClassName(entry.elData, 'tx-clicked')) {
  336. entry.makeSelection(_FALSE);
  337. this.refreshPreview();
  338. } else {
  339. this.elPreviewKind.className = ((entry.boxAttr.className) ? entry.boxAttr.className : "");
  340. entry.makeSelection(_TRUE);
  341. this.setPreivewImage(entry);
  342. }
  343. },
  344. clickEntryWithShift: function(entry) {
  345. if ($tx.hasClassName(entry.elData, 'tx-clicked')) {
  346. entry.makeSelection(_FALSE);
  347. this.lastSelectedEntry = _NULL;
  348. } else {
  349. var idx = this.getIndexOf(entry);
  350. var targetIdx;
  351. if (this.lastSelectedEntry) {
  352. targetIdx = this.getIndexOf(this.lastSelectedEntry);
  353. }
  354. var from = targetIdx, to = idx;
  355. if (idx == targetIdx) {
  356. from = to = idx;
  357. } else if (idx < targetIdx) {
  358. from = idx;
  359. to = targetIdx;
  360. }
  361. this.elPreviewKind.className = ((entry.boxAttr.className) ? entry.boxAttr.className : "");
  362. for (var i = from; i < to + 1; i++) {
  363. this.datalist[i].makeSelection(_TRUE);
  364. }
  365. this.setPreivewImage(entry);
  366. }
  367. },
  368. getIndexOf: function(entry) {
  369. var i, matched;
  370. for (i = 0; i < this.datalist.length; i++) {
  371. if (this.datalist[i] === entry) {
  372. matched = _TRUE;
  373. break;
  374. }
  375. }
  376. return matched ? i : -1;
  377. },
  378. getSelectedList: function(attachType) {
  379. var _list = [];
  380. var _source;
  381. if (attachType) {
  382. _source = this.getAttachments(attachType);
  383. } else {
  384. _source = this.datalist;
  385. }
  386. _source.each(function(entry) {
  387. if ($tx.hasClassName(entry.elData, "tx-clicked")) {
  388. _list.push(entry);
  389. }
  390. });
  391. return _list;
  392. },
  393. removeSelection: function(datalist) {
  394. datalist.each(function(data) {
  395. $tx.removeClassName(data.elData, "tx-clicked");
  396. })
  397. }
  398. };