Resizeable Text Fields

Based on Resizeable Textarea 0.1 (https://addons.mozilla.org/de/firefox/addon/3818), original coding by Raik Jürgens. Added support for select lists and horizontal resizing of input fields by Florian Höch. Should now work on all page types (XML/XHTML/you-name-it).

当前为 2014-09-04 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Resizeable Text Fields
  3. // @namespace http://userscripts.org/scripts/show/42433
  4. // @description Based on Resizeable Textarea 0.1 (https://addons.mozilla.org/de/firefox/addon/3818), original coding by Raik Jürgens. Added support for select lists and horizontal resizing of input fields by Florian Höch. Should now work on all page types (XML/XHTML/you-name-it).
  5. // @include *
  6. // @version 0.0.1.20140904104754
  7. // ==/UserScript==
  8.  
  9. window.resizeableTF =
  10. {
  11. loaded: false,
  12. TF: [],
  13. TF_names: [],
  14. TF_lineheights: [],
  15. TF_tags: {
  16. /*
  17. directions:
  18. 0 = determine on runtime by looking at size attribute
  19. 1 = only horizontal
  20. 2 = horizontal & vertical
  21. */
  22. 'input': {
  23. directions: 1,
  24. types: ['text', 'password']
  25. },
  26. 'pre': {
  27. directions: 2
  28. },
  29. 'select': {
  30. directions: 0
  31. },
  32. 'textarea': {
  33. directions: 2
  34. }
  35. },
  36.  
  37. pageload: function (e) {
  38. if (!resizeableTF.loaded) {
  39. resizeableTF.doc = document;
  40. resizeableTF.rootElem = resizeableTF.doc.getElementsByTagName('body')[0] || resizeableTF.doc.documentElement;
  41. }
  42. var TF = []
  43. for (var tagName in resizeableTF.TF_tags) {
  44. TF = TF.concat(Array.prototype.slice.call(resizeableTF.doc.getElementsByTagName(tagName)));
  45. }
  46. if (TF.length) {
  47. var i = TF.length, k = resizeableTF.TF.length, curTF_Nr;
  48. while (i--) {
  49. var TF_tag = resizeableTF.TF_tags[TF[i].tagName.toLowerCase()]
  50. if ((TF_tag && (!TF_tag.types || TF_tag.types.indexOf(TF[i].type) > -1)) && (!resizeableTF.loaded || resizeableTF.TF_names.indexOf(TF[i].name) < 0)) {
  51. resizeableTF.TF[k] = TF[i];
  52. resizeableTF.TF_names[k] = TF[i].name;
  53. resizeableTF.TF_lineheights[k] = resizeableTF.getlineheight(TF[i]);
  54. resizeableTF.newdiv('5' , '1' , 'resizeableTFgripH_', k, 'w' ).addEventListener('mouseout', resizeableTF.hidediv, false);
  55. if (TF_tag.directions == 2 || (TF_tag.directions == 0 && TF[i].size > 1)) {
  56. resizeableTF.newdiv('1' , '5' , 'resizeableTFgripV_', k, 'n' ).addEventListener('mouseout', resizeableTF.hidediv, false);
  57. resizeableTF.newdiv('10', '5', 'resizeableTFgripX_', k, 'se').addEventListener('mouseout', resizeableTF.hidediv, false);
  58. }
  59. resizeableTF.TF[k].addEventListener('mousemove', new Function('if (!resizeableTF.isresizing && resizeableTF.curTF_Nr !== ' + k + ') { resizeableTF.curTF_Nr = ' + k + '; resizeableTF.posdiv() }'), false);
  60. resizeableTF.TF[k].addEventListener('mouseout', resizeableTF.hidediv, false);
  61. k++;
  62. }
  63. }
  64. if (!resizeableTF.loaded) {
  65. resizeableTF.newdiv('0', '0', 'resizeableTFshowCursor', '', 'w');
  66. resizeableTF.CursorDiv = resizeableTF.doc.getElementById('resizeableTFshowCursor');
  67. resizeableTF.CursorDiv.removeEventListener('mousedown', resizeableTF.activate, true);
  68. window.addEventListener('resize', resizeableTF.hidedivs, true);
  69. window.addEventListener('scroll', resizeableTF.hidedivs, true);
  70. }
  71. }
  72. resizeableTF.loaded = true;
  73. },
  74.  
  75. newdiv: function (w, h, id, nr, cu) {
  76. var grip = this.rootElem.namespaceURI ? this.doc.createElementNS(this.rootElem.namespaceURI, 'div') : this.doc.createElement('div');
  77. grip.setAttribute('id', id + nr);
  78. grip.setAttribute('style', 'display: none; border: none; font-size: 1px; line-height: 1px; margin: 0; padding: 0; position: fixed; width: ' + w + 'px; height: ' + h + 'px; cursor: ' + cu + '-resize; left: 0; top: 0; z-index: 2147483647;'); // max possible z-index value 2^32/2-1
  79. grip.addEventListener('mousedown', this.activate, true);
  80. this.rootElem.appendChild(grip);
  81. return grip;
  82. },
  83.  
  84. getpositionabs: function (k, elem) {
  85. var curElem = elem || this.TF[k];
  86. var curX = curElem.offsetLeft;
  87. while (curElem.offsetParent) {
  88. curX += Math.abs(curElem.offsetParent.offsetLeft) + (curElem.offsetParent.tagName.toLowerCase() != 'table' ? curElem.offsetParent.clientLeft : 0) - curElem.offsetParent.scrollLeft;
  89. // Math.abs needed for <body> which returns negative offset if it has a border (NOT ok - should be positive)
  90. // curElem.offsetParent.clientLeft not needed for tables (cell offsetLeft already contains table clientLeft)
  91. curElem = curElem.offsetParent;
  92. }
  93. if (curElem != document.documentElement) curX += document.documentElement.offsetLeft; // <html> returns negative offset if it has a border (OK)
  94. curElem = elem || this.TF[k];
  95. var curY = curElem.offsetTop;
  96. while (curElem.offsetParent) {
  97. curY += Math.abs(curElem.offsetParent.offsetTop) + (curElem.offsetParent.tagName.toLowerCase() != 'table' ? curElem.offsetParent.clientTop : 0) - curElem.offsetParent.scrollTop;
  98. // Math.abs needed for <body> which returns negative offset if it has a border (NOT ok - should be positive)
  99. // curElem.offsetParent.clientTop not needed for tables (cell offsetTop already contains table clientTop)
  100. curElem = curElem.offsetParent;
  101. }
  102. if (curElem != document.documentElement) curY += document.documentElement.offsetTop; // <html> returns negative offset if it has a border (OK)
  103. return [curX, curY];
  104. },
  105.  
  106. getposition: function (k, elem) {
  107. var curElem = elem || this.TF[k];
  108. var curX = curElem.offsetLeft;
  109. while (curElem.offsetParent) {
  110. curX += Math.abs(curElem.offsetParent.offsetLeft) + (curElem.offsetParent.tagName.toLowerCase() != 'table' ? curElem.offsetParent.clientLeft : 0) - curElem.offsetParent.scrollLeft;
  111. // Math.abs needed for <body> which returns negative offset if it has a border (NOT ok - should be positive)
  112. // curElem.offsetParent.clientLeft not needed for tables (cell offsetLeft already contains table clientLeft)
  113. curElem = curElem.offsetParent;
  114. }
  115. if (curElem != document.documentElement) curX -= document.documentElement.scrollLeft;
  116. curElem = elem || this.TF[k];
  117. var curY = curElem.offsetTop;
  118. while (curElem.offsetParent) {
  119. curY += Math.abs(curElem.offsetParent.offsetTop) + (curElem.offsetParent.tagName.toLowerCase() != 'table' ? curElem.offsetParent.clientTop : 0) - curElem.offsetParent.scrollTop;
  120. // Math.abs needed for <body> which returns negative offset if it has a border (NOT ok - should be positive)
  121. // curElem.offsetParent.clientTop not needed for tables (cell offsetTop already contains table clientTop)
  122. curElem = curElem.offsetParent;
  123. }
  124. if (curElem != document.documentElement) curY -= document.documentElement.scrollTop;
  125. return [curX, curY];
  126. },
  127.  
  128. getdimensions: function (elem) {
  129. if (document.compatMode == 'BackCompat' || elem.tagName.toLowerCase() == 'select') {
  130. var w = elem.offsetWidth;
  131. var h = elem.offsetHeight;
  132. }
  133. else {
  134. var style = document.defaultView.getComputedStyle(elem, null);
  135. var w = parseFloat(style.width);
  136. var h = parseFloat(style.height);
  137. if (elem.tagName.toLowerCase() == 'td' || elem.tagName.toLowerCase() == 'th') {
  138. // w += parseFloat(style.paddingLeft);
  139. // w += parseFloat(style.paddingRight);
  140. h += parseFloat(style.paddingTop);
  141. h += parseFloat(style.paddingBottom);
  142. }
  143. }
  144. return [w, h];
  145. },
  146.  
  147. getlineheight: function (elem) {
  148. var style = document.defaultView.getComputedStyle(elem, null);
  149. return parseFloat(style.lineHeight);
  150. },
  151.  
  152. posdiv: function (e) {
  153. resizeableTF.isshown = true;
  154. var k = resizeableTF.curTF_Nr, hx, hy, hh, vx, vy, vw, xx, xy;
  155. var curPos = resizeableTF.getposition(k);
  156. resizeableTF.doc.getElementById('resizeableTFgripH_' + k).style.left = hx = (curPos[0] + resizeableTF.TF[k].offsetWidth - 5) + 'px';
  157. resizeableTF.doc.getElementById('resizeableTFgripH_' + k).style.top = hy = (curPos[1] ) + 'px';
  158. var TF_tag = resizeableTF.TF_tags[resizeableTF.TF[k].tagName.toLowerCase()];
  159. if (TF_tag.directions == 2 || (TF_tag.directions == 0 && resizeableTF.TF[k].size > 1)) {
  160. resizeableTF.doc.getElementById('resizeableTFgripH_' + k).style.height = hh = ( resizeableTF.TF[k].offsetHeight - 5) + 'px';
  161. resizeableTF.doc.getElementById('resizeableTFgripV_' + k).style.left = vx = (curPos[0] ) + 'px';
  162. resizeableTF.doc.getElementById('resizeableTFgripV_' + k).style.top = vy = (curPos[1] + resizeableTF.TF[k].offsetHeight - 5) + 'px';
  163. resizeableTF.doc.getElementById('resizeableTFgripV_' + k).style.width = vw = ( resizeableTF.TF[k].offsetWidth - 10) + 'px';
  164. resizeableTF.doc.getElementById('resizeableTFgripV_' + k).style.display = 'block';
  165. resizeableTF.doc.getElementById('resizeableTFgripX_' + k).style.left = xx = (curPos[0] + resizeableTF.TF[k].offsetWidth - 10) + 'px';
  166. resizeableTF.doc.getElementById('resizeableTFgripX_' + k).style.top = xy = (curPos[1] + resizeableTF.TF[k].offsetHeight - 5) + 'px';
  167. resizeableTF.doc.getElementById('resizeableTFgripX_' + k).style.display = 'block';
  168. }
  169. else {
  170. resizeableTF.doc.getElementById('resizeableTFgripH_' + k).style.height = hh = resizeableTF.TF[k].offsetHeight + 'px';
  171. }
  172. resizeableTF.doc.getElementById('resizeableTFgripH_' + k).style.display = 'block';
  173. },
  174.  
  175. activate: function (e) {
  176. resizeableTF.isresizing = true;
  177. var curTargetId = e.target.getAttribute('id').split('_');
  178. resizeableTF.curTarget = curTargetId[0];
  179. resizeableTF.curTF_Nr = parseInt(curTargetId[1]);
  180. resizeableTF.curTF = resizeableTF.TF[resizeableTF.curTF_Nr];
  181. var curPos = resizeableTF.getposition(resizeableTF.curTF_Nr),
  182. curDim = resizeableTF.getdimensions(resizeableTF.curTF);
  183. resizeableTF.offset = [
  184. e.pageX - curPos[0] - curDim[0],
  185. e.pageY - curPos[1] - curDim[1]
  186. ];
  187. var elem = resizeableTF.curTF.parentNode;
  188. // if (elem.tagName.toLowerCase() == 'td' || elem.tagName.toLowerCase() == 'th') {
  189. // while (elem.tagName.toLowerCase() != 'table') elem = elem.parentNode;
  190. // }
  191. with (elem.style)
  192. resizeableTF.storedDim = [minWidth, minHeight, width, height];
  193. var parDim = resizeableTF.getdimensions(elem)
  194. elem.style.minWidth = parDim[0] + 'px';
  195. elem.style.minHeight = parDim[1] + 'px';
  196. resizeableTF.doc.addEventListener('mouseup', resizeableTF.deactivate, true);
  197. switch(resizeableTF.curTarget){
  198. case 'resizeableTFgripH':
  199. resizeableTF.doc.addEventListener('mousemove', resizeableTF.resizeta_h, true);
  200. resizeableTF.doc.addEventListener('draggesture', resizeableTF.cancelEvent, true);
  201. resizeableTF.doc.addEventListener('dragstart', resizeableTF.cancelEvent, true);
  202. break;
  203. case 'resizeableTFgripV':
  204. resizeableTF.doc.addEventListener('mousemove', resizeableTF.resizeta_v, true);
  205. resizeableTF.doc.addEventListener('draggesture', resizeableTF.cancelEvent, true);
  206. resizeableTF.doc.addEventListener('dragstart', resizeableTF.cancelEvent, true);
  207. break;
  208. case 'resizeableTFgripX':
  209. resizeableTF.doc.addEventListener('mousemove', resizeableTF.resizeta_x, true);
  210. resizeableTF.doc.addEventListener('draggesture', resizeableTF.cancelEvent, true);
  211. resizeableTF.doc.addEventListener('dragstart', resizeableTF.cancelEvent, true);
  212. break;
  213. }
  214. resizeableTF.CursorDiv.style.width = resizeableTF.rootElem.offsetWidth + 'px';
  215. resizeableTF.CursorDiv.style.height = resizeableTF.rootElem.offsetHeight + 'px';
  216. resizeableTF.CursorDiv.style.cursor = e.target.style.cursor;
  217. resizeableTF.CursorDiv.style.display = 'block';
  218. resizeableTF.cancelEvent(e);
  219. },
  220.  
  221. deactivate: function () {
  222. resizeableTF.isresizing = false;
  223. var elem = resizeableTF.curTF.parentNode;
  224. // if (elem.tagName.toLowerCase() == 'td' || elem.tagName.toLowerCase() == 'th') {
  225. // while (elem.tagName.toLowerCase() != 'table') elem = elem.parentNode;
  226. // }
  227. elem.style.minWidth = resizeableTF.storedDim[0];
  228. elem.style.minHeight = resizeableTF.storedDim[1];
  229. // elem.style.width = resizeableTF.storedDim[2];
  230. // elem.style.height = resizeableTF.storedDim[3];
  231. resizeableTF.doc.removeEventListener('mouseup', resizeableTF.deactivate, true);
  232. resizeableTF.posdiv();
  233. switch(resizeableTF.curTarget){
  234. case 'resizeableTFgripH':
  235. resizeableTF.doc.removeEventListener('mousemove', resizeableTF.resizeta_h, true);
  236. resizeableTF.doc.removeEventListener('draggesture', resizeableTF.cancelEvent, true);
  237. resizeableTF.doc.removeEventListener('dragstart', resizeableTF.cancelEvent, true);
  238. resizeableTF.doc.removeEventListener('select', resizeableTF.cancelEvent, true);
  239. break;
  240. case 'resizeableTFgripV':
  241. resizeableTF.doc.removeEventListener('mousemove', resizeableTF.resizeta_v, true);
  242. resizeableTF.doc.removeEventListener('draggesture', resizeableTF.cancelEvent, true);
  243. resizeableTF.doc.removeEventListener('dragstart', resizeableTF.cancelEvent, true);
  244. resizeableTF.doc.removeEventListener('select', resizeableTF.cancelEvent, true);
  245. break;
  246. case 'resizeableTFgripX':
  247. resizeableTF.doc.removeEventListener('mousemove', resizeableTF.resizeta_x, true);
  248. resizeableTF.doc.removeEventListener('draggesture', resizeableTF.cancelEvent, true);
  249. resizeableTF.doc.removeEventListener('dragstart', resizeableTF.cancelEvent, true);
  250. resizeableTF.doc.removeEventListener('select', resizeableTF.cancelEvent, true);
  251. break;
  252. }
  253. resizeableTF.CursorDiv.style.width = '0';
  254. resizeableTF.CursorDiv.style.height = '0';
  255. resizeableTF.CursorDiv.style.display = 'none';
  256. },
  257.  
  258. hidedivs: function () {
  259. if (resizeableTF.isshown && !resizeableTF.isresizing) {
  260. var k = resizeableTF.TF.length;
  261. while (k--) {
  262. resizeableTF.curTF_Nr = k;
  263. resizeableTF.hidediv();
  264. }
  265. resizeableTF.isshown = false;
  266. }
  267. },
  268.  
  269. hidediv: function (e) {
  270. if (resizeableTF.isshown && !resizeableTF.isresizing) {
  271. try {
  272. if (e && e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id.indexOf('resizeableTFgrip') == 0) return;
  273. }
  274. catch (exception) {
  275. };
  276. var k = resizeableTF.curTF_Nr;
  277. if (k != undefined && !resizeableTF.isresizing) {
  278. var grip = resizeableTF.doc.getElementById('resizeableTFgripH_' + k);
  279. grip.style.display = 'none';
  280. if (grip = resizeableTF.doc.getElementById('resizeableTFgripV_' + k))
  281. grip.style.display = 'none';
  282. if (grip = resizeableTF.doc.getElementById('resizeableTFgripX_' + k))
  283. grip.style.display = 'none';
  284. resizeableTF.curTF_Nr = undefined;
  285. }
  286. }
  287. },
  288.  
  289. cancelEvent: function (e) {
  290. e.preventDefault();
  291. e.stopPropagation();
  292. },
  293.  
  294. resizeta_h: function (e) {
  295. var curPos = resizeableTF.getposition(resizeableTF.curTF_Nr);
  296. resizeableTF.curTF.style.minWidth = Math.max(25, e.pageX - resizeableTF.offset[0] - curPos[0]) + 'px';
  297. resizeableTF.curTF.style.width = Math.max(25, e.pageX - resizeableTF.offset[0] - curPos[0]) + 'px';
  298. resizeableTF.cancelEvent(e);
  299. },
  300.  
  301. resizeta_v: function (e) {
  302. var curPos = resizeableTF.getposition(resizeableTF.curTF_Nr);
  303. resizeableTF.curTF.style.minHeight = Math.max(resizeableTF.TF_lineheights[resizeableTF.curTF_Nr], e.pageY - resizeableTF.offset[1] - curPos[1]) + 'px';
  304. resizeableTF.curTF.style.height = Math.max(resizeableTF.TF_lineheights[resizeableTF.curTF_Nr], e.pageY - resizeableTF.offset[1] - curPos[1]) + 'px';
  305. resizeableTF.cancelEvent(e);
  306. },
  307.  
  308. resizeta_x: function (e) {
  309. var curPos = resizeableTF.getposition(resizeableTF.curTF_Nr);
  310. resizeableTF.curTF.style.minWidth = Math.max(25, e.pageX - resizeableTF.offset[0] - curPos[0]) + 'px';
  311. resizeableTF.curTF.style.width = Math.max(25, e.pageX - resizeableTF.offset[0] - curPos[0]) + 'px';
  312. resizeableTF.curTF.style.minHeight = Math.max(resizeableTF.TF_lineheights[resizeableTF.curTF_Nr], e.pageY - resizeableTF.offset[1] - curPos[1]) + 'px';
  313. resizeableTF.curTF.style.height = Math.max(resizeableTF.TF_lineheights[resizeableTF.curTF_Nr], e.pageY - resizeableTF.offset[1] - curPos[1]) + 'px';
  314. resizeableTF.cancelEvent(e);
  315. }
  316. };
  317.  
  318. window.addEventListener('load', resizeableTF.pageload, true);
  319. resizeableTF.pageload();