ResizeTableColumn.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // wrapped by build app
  2. define("dojox/editor/plugins/ResizeTableColumn", ["dijit","dojo","dojox","dojo/require!dojox/editor/plugins/TablePlugins"], function(dijit,dojo,dojox){
  3. dojo.provide("dojox.editor.plugins.ResizeTableColumn");
  4. dojo.require("dojox.editor.plugins.TablePlugins");
  5. dojo.declare("dojox.editor.plugins.ResizeTableColumn", dojox.editor.plugins.TablePlugins, {
  6. constructor: function(){
  7. // summary:
  8. // Because IE will ignore the cursor style when the editMode of the document is on,
  9. // we need to create a div within the outer document to mimic the behavior of drag&drop
  10. this.isLtr = this.dir ? (this.dir == "ltr") : dojo._isBodyLtr();
  11. this.ruleDiv = dojo.create("div",
  12. {style: "top: -10000px; z-index: 10001"},
  13. dojo.body(), "last");
  14. },
  15. setEditor: function(editor){
  16. // summary:
  17. // Handle the drag&drop events
  18. // editor:
  19. // The editor which this plugin belongs to
  20. // tags:
  21. // protected
  22. var ruleDiv = this.ruleDiv;
  23. this.editor = editor;
  24. this.editor.customUndo = true;
  25. this.onEditorLoaded();
  26. // The content of the editor is loaded asynchronously, so the function
  27. // should be called when it is loaded.
  28. editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
  29. this.connect(this.editor.editNode, "onmousemove", function(evt){
  30. var editorCoords = dojo.coords(editor.iframe, true),
  31. ex = editorCoords.x, cx = evt.clientX;
  32. if(!this.isDragging){
  33. // If it is just a movement, put the div at the edge of the
  34. // target cell so that when the cursor hover on it, it will
  35. // change to the col-resize style.
  36. var obj = evt.target;
  37. if(obj.tagName && obj.tagName.toLowerCase() == "td"){
  38. var objCoords = dojo.coords(obj), ox = objCoords.x, ow = objCoords.w,
  39. pos = ex + objCoords.x - 2;
  40. if(this.isLtr){
  41. ruleDiv.headerColumn = true;
  42. if(!isBoundary(obj, "first") || cx > ox + ow / 2){
  43. pos += ow;
  44. ruleDiv.headerColumn = false;
  45. }
  46. }else{
  47. ruleDiv.headerColumn = false;
  48. if(isBoundary(obj, "first") && cx > ox + ow / 2){
  49. pos += ow;
  50. ruleDiv.headerColumn = true;
  51. }
  52. }
  53. dojo.style(ruleDiv, {
  54. position: "absolute",
  55. cursor: "col-resize",
  56. display: "block",
  57. width: "4px",
  58. backgroundColor: "transparent",
  59. top: editorCoords.y + objCoords.y + "px",
  60. left: pos + "px",
  61. height: objCoords.h + "px"
  62. });
  63. this.activeCell = obj;
  64. }else{
  65. dojo.style(ruleDiv, {display: "none", top: "-10000px"});
  66. }
  67. }else{
  68. // Begin to drag&drop
  69. var activeCell = this.activeCell,
  70. activeCoords = dojo.coords(activeCell), ax = activeCoords.x, aw = activeCoords.w,
  71. sibling = nextSibling(activeCell), siblingCoords, sx, sw,
  72. containerCoords = dojo.coords(getTable(activeCell).parentNode),
  73. ctx = containerCoords.x, ctw = containerCoords.w;
  74. if(sibling){
  75. siblingCoords = dojo.coords(sibling);
  76. sx = siblingCoords.x;
  77. sw = siblingCoords.w;
  78. }
  79. // The leading and trailing columns can only be sized to the extent of the containing div.
  80. if(this.isLtr &&
  81. ((ruleDiv.headerColumn && sibling && ctx < cx && cx < ax + aw) ||
  82. ((!sibling && ax < cx && cx < ctx + ctw) || (sibling && ax < cx && cx < sx + sw))) ||
  83. !this.isLtr &&
  84. ((ruleDiv.headerColumn && sibling && ctx > cx && cx > ax) ||
  85. ((!sibling && ax + aw > cx && cx > ctx) || (sibling && ax + aw > cx && cx > sx)))){
  86. dojo.style(ruleDiv, {left: ex + cx + "px"});
  87. }
  88. }
  89. });
  90. this.connect(ruleDiv, "onmousedown", function(evt){
  91. var editorCoords = dojo.coords(editor.iframe, true),
  92. tableCoords = dojo.coords(getTable(this.activeCell));
  93. this.isDragging = true;
  94. dojo.style(editor.editNode, {cursor: "col-resize"});
  95. dojo.style(ruleDiv, {
  96. width: "1px",
  97. left: evt.clientX + "px",
  98. top: editorCoords.y + tableCoords.y + "px",
  99. height: tableCoords.h + "px",
  100. backgroundColor: "#777"
  101. });
  102. });
  103. this.connect(ruleDiv, "onmouseup", function(evt){
  104. var activeCell = this.activeCell,
  105. activeCoords = dojo.coords(activeCell), aw = activeCoords.w, ax = activeCoords.x,
  106. sibling = nextSibling(activeCell), siblingCoords, sx, sw,
  107. editorCoords = dojo.coords(editor.iframe), ex = editorCoords.x,
  108. table = getTable(activeCell), tableCoords = dojo.coords(table),
  109. cs = table.getAttribute("cellspacing"),
  110. cx = evt.clientX,
  111. headerCell = getHeaderCell(activeCell), headerSibling,
  112. newWidth, newSiblingWidth;
  113. if(!cs || (cs = parseInt(cs, 10)) < 0){ cs = 2; }
  114. if(sibling){
  115. siblingCoords = dojo.coords(sibling);
  116. sx = siblingCoords.x;
  117. sw = siblingCoords.w;
  118. headerSibling = getHeaderCell(sibling);
  119. }
  120. // The delta width is either taken from or added to the adjacent column on the trailing edge.
  121. // Sizing the rightmost or leftmost columns affects only those columns.
  122. if(this.isLtr){
  123. if(ruleDiv.headerColumn){
  124. newWidth = ex + ax + aw - cx;
  125. }else{
  126. newWidth = cx - ex - ax;
  127. if(sibling) { newSiblingWidth = ex + sx + sw - cx - cs; }
  128. }
  129. }else{
  130. if(ruleDiv.headerColumn){
  131. newWidth = cx - ex - ax;
  132. }else{
  133. newWidth = ex + ax + aw - cx;
  134. if(sibling) { newSiblingWidth = cx - ex - sx - cs; }
  135. }
  136. }
  137. this.isDragging = false;
  138. marginBox(headerCell, newWidth);
  139. if(sibling){
  140. if(!ruleDiv.headerColumn){
  141. marginBox(headerSibling, newSiblingWidth);
  142. }
  143. }
  144. if(ruleDiv.headerColumn && isBoundary(activeCell, "first") || isBoundary(activeCell, "last")){
  145. dojo.marginBox(table, {w: tableCoords.w + newWidth - aw});
  146. }
  147. // Do it again to consolidate the result,
  148. // because maybe the cell cannot be so narrow as you specified.
  149. marginBox(headerCell, dojo.coords(activeCell).w);
  150. if(sibling){
  151. marginBox(headerSibling, dojo.coords(sibling).w);
  152. }
  153. dojo.style(editor.editNode, {cursor: "auto"});
  154. dojo.style(ruleDiv, {display: "none", top: "-10000px"});
  155. this.activeCell = null;
  156. });
  157. }));
  158. function isBoundary(/*DomNode*/ n, /*String*/ b){
  159. // summary:
  160. // Check if the current cell is in the first column or
  161. // in the last column.
  162. // n:
  163. // The node of a table cell
  164. // b:
  165. // Indicate if the cell node is compared with the first coluln
  166. // or the last column
  167. var nodes = dojo.withGlobal(editor.window, "query", dojo, ["> td", n.parentNode]);
  168. switch(b){
  169. case "first":
  170. return nodes[0] == n;
  171. case "last":
  172. return nodes[nodes.length - 1] == n;
  173. default:
  174. return false;
  175. }
  176. }
  177. function nextSibling(/*DomNode*/ node){
  178. // summary:
  179. // Get the next cell in row
  180. // node:
  181. // The table cell
  182. node = node.nextSibling
  183. while(node){
  184. if(node.tagName && node.tagName.toLowerCase() == "td"){
  185. break;
  186. }
  187. node = node.nextSibling
  188. }
  189. return node;
  190. }
  191. function getTable(/*DomNode*/ t){
  192. // summary:
  193. // Get the table that this cell belongs to.
  194. // t:
  195. // The table cell
  196. while((t = t.parentNode) && t.tagName.toLowerCase() != "table"){}
  197. return t;
  198. }
  199. function getHeaderCell(/*DomNode*/ t){
  200. // summary:
  201. // Get the table cell in the first row that shares the same
  202. // column with the node t.
  203. // t:
  204. // The node of the table cell
  205. var tds = dojo.withGlobal(editor.window, "query", dojo, ["td", getTable(t)]),
  206. len = tds.length;
  207. for(var i = 0; i < len; i++){
  208. if(dojo.coords(tds[i]).x == dojo.coords(t).x){
  209. return tds[i];
  210. }
  211. }
  212. return null;
  213. }
  214. function marginBox(/*DomNode*/ node, /*Number*/ width){
  215. // summary:
  216. // In IE, if the border width of the td is not specified in table, the default value is 1px,
  217. // though it is marked "medium".
  218. // node:
  219. // The node to be set width
  220. // width:
  221. // The new width of the node
  222. if(dojo.isIE){
  223. var s = node.currentStyle,
  224. bl = px(node, s.borderLeftWidth), br = px(node, s.borderRightWidth),
  225. pl = px(node, s.paddingLeft), pr = px(node, s.paddingRight);
  226. node.style.width = width - bl - br - pl - pr;
  227. }else{
  228. dojo.marginBox(node, {w: width});
  229. }
  230. function px(element, avalue){
  231. if(!avalue){ return 0; }
  232. if(avalue == "medium"){ return 1; }
  233. // style values can be floats, client code may
  234. // want to round this value for integer pixels.
  235. if(avalue.slice && avalue.slice(-2) == 'px'){ return parseFloat(avalue); }
  236. with(element){
  237. var sLeft = style.left;
  238. var rsLeft = runtimeStyle.left;
  239. runtimeStyle.left = currentStyle.left;
  240. try{
  241. // 'avalue' may be incompatible with style.left, which can cause IE to throw
  242. // this has been observed for border widths using "thin", "medium", "thick" constants
  243. // those particular constants could be trapped by a lookup
  244. // but perhaps there are more
  245. style.left = avalue;
  246. avalue = style.pixelLeft;
  247. }catch(e){
  248. avalue = 0;
  249. }
  250. style.left = sLeft;
  251. runtimeStyle.left = rsLeft;
  252. }
  253. return avalue;
  254. }
  255. }
  256. }
  257. });
  258. dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
  259. if(o.plugin){ return; }
  260. // make first character lower case
  261. if(o.args && o.args.command){
  262. var cmd = o.args.command.charAt(0).toLowerCase() + o.args.command.substring(1, o.args.command.length);
  263. if(cmd == "resizeTableColumn"){
  264. o.plugin = new dojox.editor.plugins.ResizeTableColumn({commandName: cmd});
  265. }
  266. }
  267. });
  268. });