spinControl.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /********************************************************************************************************************************
  2. * Licensed Materials - Property of IBM *
  3. * *
  4. * IBM Cognos Products: HTS *
  5. * *
  6. * (C) Copyright IBM Corp. 2005, 2010 *
  7. * *
  8. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *
  9. *********************************************************************************************************************************/
  10. function hookEvent(element, eventName, callback)
  11. {
  12. if(typeof(element) == "string")
  13. element = document.getElementById(element);
  14. if(element == null)
  15. return;
  16. if(element.addEventListener)
  17. {
  18. element.addEventListener(eventName, callback, false);
  19. }
  20. else if(element.attachEvent)
  21. element.attachEvent("on" + eventName, callback);
  22. }
  23. function unhookEvent(element, eventName, callback)
  24. {
  25. if(typeof(element) == "string")
  26. element = document.getElementById(element);
  27. if(element == null)
  28. return;
  29. if(element.removeEventListener)
  30. element.removeEventListener(eventName, callback, false);
  31. else if(element.detachEvent)
  32. element.detachEvent("on" + eventName, callback);
  33. }
  34. function getEventTarget(e)
  35. {
  36. e = e ? e : window.event;
  37. return e.target ? e.target : e.srcElement;
  38. }
  39. function cancelEvent(e)
  40. {
  41. e = e ? e : window.event;
  42. if(e.stopPropagation)
  43. e.stopPropagation();
  44. if(e.preventDefault)
  45. e.preventDefault();
  46. e.cancelBubble = true;
  47. e.cancel = true;
  48. e.returnValue = false;
  49. return false;
  50. }
  51. function SpinControlAcceleration(increment, milliseconds)
  52. {
  53. increment = parseFloat(increment);
  54. if(isNaN(increment) || increment < 0)
  55. increment = 0;
  56. milliseconds = parseInt(milliseconds);
  57. if(isNaN(milliseconds) || milliseconds < 0)
  58. milliseconds = 0;
  59. this.GetIncrement = function()
  60. { return increment; }
  61. this.GetMilliseconds = function()
  62. { return milliseconds; }
  63. }
  64. function SpinControlAccelerationCollection()
  65. {
  66. var _array = new Array();
  67. this.GetCount = function()
  68. { return _array.length; }
  69. this.GetIndex = function(index)
  70. {
  71. if(index < 0 || index >= _array.length)
  72. return null;
  73. return _array[index];
  74. }
  75. this.RemoveIndex = function(index)
  76. {
  77. if(index < 0 || index >= _array.length)
  78. return;
  79. newArray = new Array();
  80. for(var i=0; i<_array.length; i++)
  81. {
  82. if(i == index)
  83. continue;
  84. newArray.push(_array[i]);
  85. }
  86. _array = newArray;
  87. }
  88. this.Clear = function()
  89. {
  90. _array = new Array();
  91. }
  92. this.Add = function(spa)
  93. {
  94. if(spa.constructor != SpinControlAcceleration)
  95. return;
  96. if(_array.length == 0)
  97. {
  98. _array.push(spa);
  99. return;
  100. }
  101. var newSec = spa.GetMilliseconds();
  102. if(newSec > _array[_array.length-1].GetMilliseconds())
  103. {
  104. _array.push(spa);
  105. return;
  106. }
  107. var added = false;
  108. var newArray = new Array();
  109. var indexSec;
  110. for(var i=0; i<_array.length; i++)
  111. {
  112. if(added)
  113. {
  114. newArray.push(_array[i]);
  115. }
  116. else
  117. {
  118. indexSec = _array[i].GetMilliseconds();
  119. if(indexSec < newSec)
  120. {
  121. newArray.push(_array[i]);
  122. }
  123. else if(indexSec == newSec)
  124. {
  125. newArray.push(spa);
  126. added = true;
  127. }
  128. else
  129. {
  130. newArray.push(_array[i]);
  131. newArray.push(spa);
  132. added = true;
  133. }
  134. }
  135. }
  136. _array = newArray;
  137. return;
  138. }
  139. }
  140. function SpinControl()
  141. {
  142. var _this = this;
  143. var _accelerationCollection = new SpinControlAccelerationCollection();
  144. var _callbackArray = new Array();
  145. var _currentValue = 1;
  146. var _maximumVal = 100;
  147. var _minimumVal = 0;
  148. var _increment = 1;
  149. var _width = 50;
  150. var _running = 0;
  151. var _interval = -1;
  152. var _timeStart = 0;
  153. var _bodyEventHooked = false;
  154. var _container = document.createElement("DIV");
  155. _container.className = 'spinContainer';
  156. var _leftEdge = document.createElement("DIV");
  157. _leftEdge.className = 'spinLeftRightEdge';
  158. _leftEdge.style.left = '0px';
  159. var _bottomEdge = document.createElement("DIV");
  160. _bottomEdge.className = 'spinTopBottomEdge';
  161. _bottomEdge.style.top = '19px';
  162. var _topEdge = document.createElement("DIV");
  163. _topEdge.className = 'spinTopBottomEdge';
  164. _topEdge.style.top = '0px';
  165. var _rightEdge = document.createElement("DIV");
  166. _rightEdge.className = 'spinLeftRightEdge';
  167. _rightEdge.style.right = '0px';
  168. var _textBox = document.createElement("INPUT");
  169. _textBox.type = 'text';
  170. _textBox.className = 'spinInput';
  171. _textBox.value = _currentValue;
  172. var _upButton = document.createElement("DIV");
  173. _upButton.className = 'spinUpBtn';
  174. var _downButton = document.createElement("DIV");
  175. _downButton.className = 'spinDownBtn';
  176. /*
  177. * Because IE 6 and lower don't support the transparent png background
  178. * mask that we use for the buttons.
  179. * So we use a regular old gif instead.
  180. * This means that, sadly, the button coloring does not work in IE6 and lower.
  181. */
  182. var canChangeBtnColors = true;
  183. if(document.body.filters)
  184. {
  185. var arVersion = navigator.appVersion.split("MSIE");
  186. var version = parseFloat(arVersion[1]);
  187. if(version < 7)
  188. {
  189. canChangeBtnColors = false;
  190. _downButton.style.backgroundImage = 'url(spin_control_buttons.gif)';
  191. _upButton.style.backgroundImage = 'url(spin_control_buttons.gif)';
  192. _downButton.style.backgroundColor = '#FFFFFF';
  193. _upButton.style.backgroundColor = '#FFFFFF';
  194. }
  195. }
  196. _container.appendChild(_leftEdge);
  197. _container.appendChild(_bottomEdge);
  198. _container.appendChild(_topEdge);
  199. _container.appendChild(_rightEdge);
  200. _container.appendChild(_textBox);
  201. _container.appendChild(_upButton);
  202. _container.appendChild(_downButton);
  203. function Run()
  204. {
  205. if(_running == 0)
  206. return;
  207. var elapsed = new Date().getTime() - _timeStart;
  208. var inc = _increment;
  209. if(_accelerationCollection.GetCount() != 0)
  210. {
  211. inc = 0;
  212. for(var i = 0; i<_accelerationCollection.GetCount(); i++)
  213. {
  214. if(elapsed < _accelerationCollection.GetIndex(i).GetMilliseconds())
  215. break;
  216. inc = _accelerationCollection.GetIndex(i).GetIncrement();
  217. }
  218. }
  219. else if(elapsed < 600)
  220. {
  221. return;
  222. }
  223. DoChange(inc);
  224. }
  225. function CancelRunning()
  226. {
  227. _running = 0;
  228. if(_interval != -1)
  229. {
  230. clearInterval(_interval);
  231. _interval = -1;
  232. }
  233. }
  234. function DoChange(inc)
  235. {
  236. var newVal = _currentValue + inc * _running;
  237. UpdateCurrentValue(newVal);
  238. }
  239. function StartRunning(newState)
  240. {
  241. if(_running != 0)
  242. CancelRunning();
  243. _running = newState;
  244. DoChange(_increment);
  245. _timeStart = new Date().getTime();
  246. _interval = setInterval(Run, 150);
  247. }
  248. function UpdateCurrentValue(newVal)
  249. {
  250. if(newVal <_minimumVal)
  251. newVal = _minimumVal;
  252. if(newVal > _maximumVal)
  253. newVal = _maximumVal;
  254. newVal = Math.round(1000*newVal)/1000;
  255. _textBox.value = newVal;
  256. if(newVal == _currentValue)
  257. return;
  258. _currentValue = newVal;
  259. for(var i=0; i<_callbackArray.length; i++)
  260. _callbackArray[i](_this, _currentValue);
  261. }
  262. function UpPress(e)
  263. {
  264. //This is to update to the latest changed
  265. //value when a paste or manual update occurs.
  266. _textBox.blur();
  267. _upButton.className = 'spinUpBtnPress';
  268. _downButton.className = 'spinDownBtn';
  269. StartRunning(1);
  270. _textBox.focus();
  271. return cancelEvent(e);
  272. }
  273. function DownPress(e)
  274. {
  275. //This is to update to the latest changed
  276. //value when a paste or manual update occurs.
  277. _textBox.blur();
  278. _upButton.className = 'spinUpBtn';
  279. _downButton.className = 'spinDownBtnPress';
  280. StartRunning(-1);
  281. _textBox.focus();
  282. return cancelEvent(e);
  283. }
  284. function UpHover(e)
  285. {
  286. if(!_bodyEventHooked)
  287. hookEvent(document.body, 'mouseover', ClearBtns);
  288. _upButton.className = 'spinUpBtnHover';
  289. _downButton.className = 'spinDownBtn';
  290. CancelRunning();
  291. return cancelEvent(e);
  292. }
  293. function DownHover(e)
  294. {
  295. if(!_bodyEventHooked)
  296. hookEvent(document.body, 'mouseover', ClearBtns);
  297. _upButton.className = 'spinUpBtn';
  298. _downButton.className = 'spinDownBtnHover';
  299. CancelRunning();
  300. return cancelEvent(e);
  301. }
  302. function ClearBtns(e)
  303. {
  304. var target = getEventTarget(e);
  305. if(target == _upButton || target == _downButton)
  306. return;
  307. _upButton.className = 'spinUpBtn';
  308. _downButton.className = 'spinDownBtn';
  309. CancelRunning();
  310. if(_bodyEventHooked)
  311. {
  312. unhookEvent(document.body, 'mouseover', ClearBtns);
  313. _bodyEventHooked = false;
  314. }
  315. return cancelEvent(e);
  316. }
  317. function BoxChange()
  318. {
  319. var val = parseFloat(_textBox.value);
  320. if(isNaN(val))
  321. val = _currentValue;
  322. UpdateCurrentValue(val);
  323. }
  324. function MouseWheel(e)
  325. {
  326. //This is to update to the latest changed
  327. //value when a paste is performed
  328. _textBox.blur();
  329. e = e ? e : window.event;
  330. var movement = e.detail ? e.detail / -3 : e.wheelDelta/120;
  331. UpdateCurrentValue(_currentValue + _increment * movement);
  332. _textBox.focus();
  333. return cancelEvent(e);
  334. }
  335. function TextFocused(e)
  336. {
  337. hookEvent(window, 'DOMMouseScroll', MouseWheel);
  338. hookEvent(document, 'mousewheel', MouseWheel);
  339. return cancelEvent(e);
  340. }
  341. function TextBlur(e)
  342. {
  343. unhookEvent(window, 'DOMMouseScroll', MouseWheel);
  344. unhookEvent(document, 'mousewheel', MouseWheel);
  345. return cancelEvent(e);
  346. }
  347. function TextKeyDown(e)
  348. {
  349. switch(e.keyCode) {
  350. case 38://up arrow
  351. UpPress(e);
  352. break;
  353. case 40: //down arrow
  354. DownPress(e);
  355. break;
  356. }
  357. return true;
  358. }
  359. function TextKeyUp(e)
  360. {
  361. switch(e.keyCode) {
  362. case 38://up arrow
  363. UpHover(e);
  364. break;
  365. case 40: //down arrow
  366. DownHover(e);
  367. break;
  368. }
  369. return true;
  370. }
  371. this.StartListening = function()
  372. {
  373. hookEvent(_upButton, 'mousedown', UpPress);
  374. hookEvent(_upButton, 'mouseup', UpHover);
  375. hookEvent(_upButton, 'mouseover', UpHover);
  376. hookEvent(_downButton, 'mousedown', DownPress);
  377. hookEvent(_downButton, 'mouseup', DownHover);
  378. hookEvent(_downButton, 'mouseover', DownHover);
  379. hookEvent(_textBox, 'change', BoxChange);
  380. hookEvent(_textBox, 'focus', TextFocused);
  381. hookEvent(_textBox, 'blur', TextBlur);
  382. hookEvent(_textBox, 'keydown', TextKeyDown);
  383. hookEvent(_textBox, 'keyup', TextKeyUp);
  384. }
  385. this.StopListening = function()
  386. {
  387. unhookEvent(_upButton, 'mousedown', UpPress);
  388. unhookEvent(_upButton, 'mouseup', UpHover);
  389. unhookEvent(_upButton, 'mouseover', UpHover);
  390. unhookEvent(_downButton, 'mousedown', DownPress);
  391. unhookEvent(_downButton, 'mouseup', DownHover);
  392. unhookEvent(_downButton, 'mouseover', DownHover);
  393. unhookEvent(_textBox, 'change', BoxChange);
  394. unhookEvent(_textBox, 'focus', TextFocused);
  395. unhookEvent(_textBox, 'blur', TextBlur);
  396. if(_bodyEventHooked)
  397. {
  398. unhookEvent(document.body, 'mouseover', ClearBtns);
  399. _bodyEventHooked = false;
  400. }
  401. }
  402. this.SetMaxValue = function(value)
  403. {
  404. value = parseFloat(value);
  405. if(isNaN(value))
  406. value = 1;
  407. _maximumVal = value;
  408. UpdateCurrentValue(_currentValue);
  409. }
  410. this.SetMinValue = function(value)
  411. {
  412. value = parseFloat(value);
  413. if(isNaN(value))
  414. value = 0;
  415. _minimumVal = value;
  416. UpdateCurrentValue(_currentValue);
  417. }
  418. this.SetCurrentValue = function(value)
  419. {
  420. value = parseFloat(value);
  421. if(isNaN(value))
  422. value = 0;
  423. UpdateCurrentValue(value);
  424. }
  425. this.SetWidth = function(value)
  426. {
  427. value = parseInt(value);
  428. if(isNaN(value) || value < 25)
  429. value = 25;
  430. _width = value;
  431. _container.style.width = _width + 'px';
  432. _bottomEdge.style.width = (_width - 1) + 'px';
  433. _topEdge.style.width = (_width - 1) + 'px';
  434. _textBox.style.width = (_width - 20) + 'px';
  435. }
  436. this.SetIncrement = function(value)
  437. {
  438. value = parseFloat(value);
  439. if(isNaN(value))
  440. value = 0;
  441. if(value < 0)
  442. value = -value;
  443. _increment = value;
  444. }
  445. this.SetBackgroundColor = function(color)
  446. {
  447. _container.style.backgroundColor = color;
  448. _textBox.style.backgroundColor = color;
  449. }
  450. this.SetButtonColor = function(color)
  451. {
  452. if(!canChangeBtnColors)
  453. return;
  454. _upButton.style.backgroundColor = color;
  455. _downButton.style.backgroundColor = color;
  456. }
  457. this.SetFontColor = function(color)
  458. {
  459. _textBox.style.color = color;
  460. }
  461. this.SetBorderColor = function(color)
  462. {
  463. _topEdge.style.backgroundColor = color;
  464. _bottomEdge.style.backgroundColor = color;
  465. _leftEdge.style.backgroundColor = color;
  466. _rightEdge.style.backgroundColor = color;
  467. }
  468. this.AttachValueChangedListener = function(listener)
  469. {
  470. for(var i=0; i<_callbackArray.length; i++)
  471. if(_callbackArray[i] == listener)
  472. return;
  473. _callbackArray.push(listener);
  474. }
  475. this.DetachValueChangedListener = function(listener)
  476. {
  477. newArray = new Array();
  478. for(var i=0; i<_callbackArray.length; i++)
  479. if(_callbackArray[i] != listener)
  480. newArray.push(_callbackArray[i]);
  481. _callbackArray = newArray;
  482. }
  483. this.GetContainer = function()
  484. { return _container; }
  485. this.GetCurrentValue = function()
  486. { return _currentValue; }
  487. this.GetMaxValue = function()
  488. { return _maximumVal; }
  489. this.GetMinValue = function()
  490. { return _minimumVal; }
  491. this.GetWidth = function()
  492. { return _width; }
  493. this.GetIncrement = function()
  494. { return _increment; }
  495. this.GetAccelerationCollection = function()
  496. { return _accelerationCollection; }
  497. _this.SetWidth(_width);
  498. }