/hippo/src/main/webapp/ext/pkgs/pkg-tips-debug.js

http://hdbc.googlecode.com/ · JavaScript · 994 lines · 612 code · 65 blank · 317 comment · 124 complexity · 9f7536015e0b7e1b0df51ac1131e53c0 MD5 · raw file

  1. /*!
  2. * Ext JS Library 3.0.0
  3. * Copyright(c) 2006-2009 Ext JS, LLC
  4. * licensing@extjs.com
  5. * http://www.extjs.com/license
  6. */
  7. /**
  8. * @class Ext.Tip
  9. * @extends Ext.Panel
  10. * This is the base class for {@link Ext.QuickTip} and {@link Ext.Tooltip} that provides the basic layout and
  11. * positioning that all tip-based classes require. This class can be used directly for simple, statically-positioned
  12. * tips that are displayed programmatically, or it can be extended to provide custom tip implementations.
  13. * @constructor
  14. * Create a new Tip
  15. * @param {Object} config The configuration options
  16. */
  17. Ext.Tip = Ext.extend(Ext.Panel, {
  18. /**
  19. * @cfg {Boolean} closable True to render a close tool button into the tooltip header (defaults to false).
  20. */
  21. /**
  22. * @cfg {Number} width
  23. * Width in pixels of the tip (defaults to auto). Width will be ignored if it exceeds the bounds of
  24. * {@link #minWidth} or {@link #maxWidth}. The maximum supported value is 500.
  25. */
  26. /**
  27. * @cfg {Number} minWidth The minimum width of the tip in pixels (defaults to 40).
  28. */
  29. minWidth : 40,
  30. /**
  31. * @cfg {Number} maxWidth The maximum width of the tip in pixels (defaults to 300). The maximum supported value is 500.
  32. */
  33. maxWidth : 300,
  34. /**
  35. * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop"
  36. * for bottom-right shadow (defaults to "sides").
  37. */
  38. shadow : "sides",
  39. /**
  40. * @cfg {String} defaultAlign <b>Experimental</b>. The default {@link Ext.Element#alignTo} anchor position value
  41. * for this tip relative to its element of origin (defaults to "tl-bl?").
  42. */
  43. defaultAlign : "tl-bl?",
  44. autoRender: true,
  45. quickShowInterval : 250,
  46. // private panel overrides
  47. frame:true,
  48. hidden:true,
  49. baseCls: 'x-tip',
  50. floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
  51. autoHeight:true,
  52. closeAction: 'hide',
  53. // private
  54. initComponent : function(){
  55. Ext.Tip.superclass.initComponent.call(this);
  56. if(this.closable && !this.title){
  57. this.elements += ',header';
  58. }
  59. },
  60. // private
  61. afterRender : function(){
  62. Ext.Tip.superclass.afterRender.call(this);
  63. if(this.closable){
  64. this.addTool({
  65. id: 'close',
  66. handler: this[this.closeAction],
  67. scope: this
  68. });
  69. }
  70. },
  71. /**
  72. * Shows this tip at the specified XY position. Example usage:
  73. * <pre><code>
  74. // Show the tip at x:50 and y:100
  75. tip.showAt([50,100]);
  76. </code></pre>
  77. * @param {Array} xy An array containing the x and y coordinates
  78. */
  79. showAt : function(xy){
  80. Ext.Tip.superclass.show.call(this);
  81. if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
  82. this.doAutoWidth();
  83. }
  84. if(this.constrainPosition){
  85. xy = this.el.adjustForConstraints(xy);
  86. }
  87. this.setPagePosition(xy[0], xy[1]);
  88. },
  89. // protected
  90. doAutoWidth : function(){
  91. var bw = this.body.getTextWidth();
  92. if(this.title){
  93. bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
  94. }
  95. bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr");
  96. this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
  97. // IE7 repaint bug on initial show
  98. if(Ext.isIE7 && !this.repainted){
  99. this.el.repaint();
  100. this.repainted = true;
  101. }
  102. },
  103. /**
  104. * <b>Experimental</b>. Shows this tip at a position relative to another element using a standard {@link Ext.Element#alignTo}
  105. * anchor position value. Example usage:
  106. * <pre><code>
  107. // Show the tip at the default position ('tl-br?')
  108. tip.showBy('my-el');
  109. // Show the tip's top-left corner anchored to the element's top-right corner
  110. tip.showBy('my-el', 'tl-tr');
  111. </code></pre>
  112. * @param {Mixed} el An HTMLElement, Ext.Element or string id of the target element to align to
  113. * @param {String} position (optional) A valid {@link Ext.Element#alignTo} anchor position (defaults to 'tl-br?' or
  114. * {@link #defaultAlign} if specified).
  115. */
  116. showBy : function(el, pos){
  117. if(!this.rendered){
  118. this.render(Ext.getBody());
  119. }
  120. this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
  121. },
  122. initDraggable : function(){
  123. this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
  124. this.header.addClass('x-tip-draggable');
  125. }
  126. });
  127. // private - custom Tip DD implementation
  128. Ext.Tip.DD = function(tip, config){
  129. Ext.apply(this, config);
  130. this.tip = tip;
  131. Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
  132. this.setHandleElId(tip.header.id);
  133. this.scroll = false;
  134. };
  135. Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
  136. moveOnly:true,
  137. scroll:false,
  138. headerOffsets:[100, 25],
  139. startDrag : function(){
  140. this.tip.el.disableShadow();
  141. },
  142. endDrag : function(e){
  143. this.tip.el.enableShadow(true);
  144. }
  145. });/**
  146. * @class Ext.ToolTip
  147. * @extends Ext.Tip
  148. * A standard tooltip implementation for providing additional information when hovering over a target element.
  149. * @constructor
  150. * Create a new Tooltip
  151. * @param {Object} config The configuration options
  152. */
  153. Ext.ToolTip = Ext.extend(Ext.Tip, {
  154. /**
  155. * When a Tooltip is configured with the {@link #delegate} option to cause selected child elements of the {@link #target}
  156. * Element to each trigger a seperate show event, this property is set to the DOM element which triggered the show.
  157. * @type DOMElement
  158. * @property triggerElement
  159. */
  160. /**
  161. * @cfg {Mixed} target The target HTMLElement, Ext.Element or id to monitor for mouseover events to trigger
  162. * showing this ToolTip.
  163. */
  164. /**
  165. * @cfg {Boolean} autoHide True to automatically hide the tooltip after the mouse exits the target element
  166. * or after the {@link #dismissDelay} has expired if set (defaults to true). If {@link closable} = true a close
  167. * tool button will be rendered into the tooltip header.
  168. */
  169. /**
  170. * @cfg {Number} showDelay Delay in milliseconds before the tooltip displays after the mouse enters the
  171. * target element (defaults to 500)
  172. */
  173. showDelay: 500,
  174. /**
  175. * @cfg {Number} hideDelay Delay in milliseconds after the mouse exits the target element but before the
  176. * tooltip actually hides (defaults to 200). Set to 0 for the tooltip to hide immediately.
  177. */
  178. hideDelay: 200,
  179. /**
  180. * @cfg {Number} dismissDelay Delay in milliseconds before the tooltip automatically hides (defaults to 5000).
  181. * To disable automatic hiding, set dismissDelay = 0.
  182. */
  183. dismissDelay: 5000,
  184. /**
  185. * @cfg {Array} mouseOffset An XY offset from the mouse position where the tooltip should be shown (defaults to [15,18]).
  186. */
  187. /**
  188. * @cfg {Boolean} trackMouse True to have the tooltip follow the mouse as it moves over the target element (defaults to false).
  189. */
  190. trackMouse : false,
  191. /**
  192. * @cfg {Boolean} anchorToTarget True to anchor the tooltip to the target element, false to
  193. * anchor it relative to the mouse coordinates (defaults to true). When anchorToTarget is
  194. * true, use {@link #defaultAlign} to control tooltip alignment to the target element. When
  195. * anchorToTarget is false, use {@link #anchorPosition} instead to control alignment.
  196. */
  197. anchorToTarget: true,
  198. /**
  199. * @cfg {Number} anchorOffset A numeric pixel value used to offset the default position of the
  200. * anchor arrow (defaults to 0). When the anchor position is on the top or bottom of the tooltip,
  201. * anchorOffset will be used as a horizontal offset. Likewise, when the anchor position is on the
  202. * left or right side, anchorOffset will be used as a vertical offset.
  203. */
  204. anchorOffset: 0,
  205. /**
  206. * @cfg {String} delegate <p>Optional. A {@link Ext.DomQuery DomQuery} selector which allows selection of individual elements
  207. * within the {@link #target} element to trigger showing and hiding the ToolTip as the mouse moves within the target.</p>
  208. * <p>When specified, the child element of the target which caused a show event is placed into the {@link #triggerElement} property
  209. * before the ToolTip is shown.</p>
  210. * <p>This may be useful when a Component has regular, repeating elements in it, each of which need a Tooltip which contains
  211. * information specific to that element. For example:</p><pre><code>
  212. var myGrid = new Ext.grid.gridPanel(gridConfig);
  213. myGrid.on('render', function(grid) {
  214. var store = grid.getStore(); // Capture the Store.
  215. var view = grid.getView(); // Capture the GridView.
  216. myGrid.tip = new Ext.ToolTip({
  217. target: view.mainBody, // The overall target element.
  218. delegate: '.x-grid3-row', // Each grid row causes its own seperate show and hide.
  219. trackMouse: true, // Moving within the row should not hide the tip.
  220. renderTo: document.body, // Render immediately so that tip.body can be referenced prior to the first show.
  221. listeners: { // Change content dynamically depending on which element triggered the show.
  222. beforeshow: function updateTipBody(tip) {
  223. var rowIndex = view.findRowIndex(tip.triggerElement);
  224. tip.body.dom.innerHTML = "Over Record ID " + store.getAt(rowIndex).id;
  225. }
  226. }
  227. });
  228. });</code></pre>
  229. */
  230. // private
  231. targetCounter: 0,
  232. constrainPosition: false,
  233. // private
  234. initComponent: function(){
  235. Ext.ToolTip.superclass.initComponent.call(this);
  236. this.lastActive = new Date();
  237. this.initTarget(this.target);
  238. this.origAnchor = this.anchor;
  239. },
  240. // private
  241. onRender : function(ct, position){
  242. Ext.ToolTip.superclass.onRender.call(this, ct, position);
  243. this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
  244. this.anchorEl = this.el.createChild({
  245. cls: 'x-tip-anchor ' + this.anchorCls
  246. });
  247. },
  248. // private
  249. afterRender : function(){
  250. Ext.ToolTip.superclass.afterRender.call(this);
  251. this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1);
  252. },
  253. /**
  254. * Binds this ToolTip to the specified element. The tooltip will be displayed when the mouse moves over the element.
  255. * @param {Mixed} t The Element, HtmlElement, or ID of an element to bind to
  256. */
  257. initTarget : function(target){
  258. var t;
  259. if((t = Ext.get(target))){
  260. if(this.target){
  261. this.target = Ext.get(this.target);
  262. this.target.un('mouseover', this.onTargetOver, this);
  263. this.target.un('mouseout', this.onTargetOut, this);
  264. this.target.un('mousemove', this.onMouseMove, this);
  265. }
  266. this.mon(t, {
  267. mouseover: this.onTargetOver,
  268. mouseout: this.onTargetOut,
  269. mousemove: this.onMouseMove,
  270. scope: this
  271. });
  272. this.target = t;
  273. }
  274. if(this.anchor){
  275. this.anchorTarget = this.target;
  276. }
  277. },
  278. // private
  279. onMouseMove : function(e){
  280. var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
  281. if (t) {
  282. this.targetXY = e.getXY();
  283. if (t === this.triggerElement) {
  284. if(!this.hidden && this.trackMouse){
  285. this.setPagePosition(this.getTargetXY());
  286. }
  287. } else {
  288. this.hide();
  289. this.lastActive = new Date(0);
  290. this.onTargetOver(e);
  291. }
  292. } else if (!this.closable && this.isVisible()) {
  293. this.hide();
  294. }
  295. },
  296. // private
  297. getTargetXY : function(){
  298. if(this.anchor){
  299. this.targetCounter++;
  300. var offsets = this.getOffsets();
  301. var xy = (this.anchorToTarget && !this.trackMouse) ?
  302. this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) :
  303. this.targetXY;
  304. var dw = Ext.lib.Dom.getViewWidth()-5;
  305. var dh = Ext.lib.Dom.getViewHeight()-5;
  306. var scrollX = (document.documentElement.scrollLeft || document.body.scrollLeft || 0)+5;
  307. var scrollY = (document.documentElement.scrollTop || document.body.scrollTop || 0)+5;
  308. var axy = [xy[0] + offsets[0], xy[1] + offsets[1]];
  309. var sz = this.getSize();
  310. this.anchorEl.removeClass(this.anchorCls);
  311. if(this.targetCounter < 2){
  312. if(axy[0] < scrollX){
  313. if(this.anchorToTarget){
  314. this.defaultAlign = 'l-r';
  315. if(this.mouseOffset){this.mouseOffset[0] *= -1;}
  316. }
  317. this.anchor = 'left';
  318. return this.getTargetXY();
  319. }
  320. if(axy[0]+sz.width > dw){
  321. if(this.anchorToTarget){
  322. this.defaultAlign = 'r-l';
  323. if(this.mouseOffset){this.mouseOffset[0] *= -1;}
  324. }
  325. this.anchor = 'right';
  326. return this.getTargetXY();
  327. }
  328. if(axy[1] < scrollY){
  329. if(this.anchorToTarget){
  330. this.defaultAlign = 't-b';
  331. if(this.mouseOffset){this.mouseOffset[1] *= -1;}
  332. }
  333. this.anchor = 'top';
  334. return this.getTargetXY();
  335. }
  336. if(axy[1]+sz.height > dh){
  337. if(this.anchorToTarget){
  338. this.defaultAlign = 'b-t';
  339. if(this.mouseOffset){this.mouseOffset[1] *= -1;}
  340. }
  341. this.anchor = 'bottom';
  342. return this.getTargetXY();
  343. }
  344. }
  345. this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
  346. this.anchorEl.addClass(this.anchorCls);
  347. this.targetCounter = 0;
  348. return axy;
  349. }else{
  350. var mouseOffset = this.getMouseOffset();
  351. return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
  352. }
  353. },
  354. getMouseOffset : function(){
  355. var offset = this.anchor ? [0,0] : [15,18];
  356. if(this.mouseOffset){
  357. offset[0] += this.mouseOffset[0];
  358. offset[1] += this.mouseOffset[1];
  359. }
  360. return offset;
  361. },
  362. // private
  363. getAnchorPosition : function(){
  364. if(this.anchor){
  365. this.tipAnchor = this.anchor.charAt(0);
  366. }else{
  367. var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
  368. if(!m){
  369. throw "AnchorTip.defaultAlign is invalid";
  370. }
  371. this.tipAnchor = m[1].charAt(0);
  372. }
  373. switch(this.tipAnchor){
  374. case 't': return 'top';
  375. case 'b': return 'bottom';
  376. case 'r': return 'right';
  377. }
  378. return 'left';
  379. },
  380. // private
  381. getAnchorAlign : function(){
  382. switch(this.anchor){
  383. case 'top' : return 'tl-bl';
  384. case 'left' : return 'tl-tr';
  385. case 'right': return 'tr-tl';
  386. default : return 'bl-tl';
  387. }
  388. },
  389. // private
  390. getOffsets: function(){
  391. var offsets, ap = this.getAnchorPosition().charAt(0);
  392. if(this.anchorToTarget && !this.trackMouse){
  393. switch(ap){
  394. case 't':
  395. offsets = [0, 9];
  396. break;
  397. case 'b':
  398. offsets = [0, -13];
  399. break;
  400. case 'r':
  401. offsets = [-13, 0];
  402. break;
  403. default:
  404. offsets = [9, 0];
  405. break;
  406. }
  407. }else{
  408. switch(ap){
  409. case 't':
  410. offsets = [-15-this.anchorOffset, 30];
  411. break;
  412. case 'b':
  413. offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
  414. break;
  415. case 'r':
  416. offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
  417. break;
  418. default:
  419. offsets = [25, -13-this.anchorOffset];
  420. break;
  421. }
  422. }
  423. var mouseOffset = this.getMouseOffset();
  424. offsets[0] += mouseOffset[0];
  425. offsets[1] += mouseOffset[1];
  426. return offsets;
  427. },
  428. // private
  429. onTargetOver : function(e){
  430. if(this.disabled || e.within(this.target.dom, true)){
  431. return;
  432. }
  433. var t = e.getTarget(this.delegate);
  434. if (t) {
  435. this.triggerElement = t;
  436. this.clearTimer('hide');
  437. this.targetXY = e.getXY();
  438. this.delayShow();
  439. }
  440. },
  441. // private
  442. delayShow : function(){
  443. if(this.hidden && !this.showTimer){
  444. if(this.lastActive.getElapsed() < this.quickShowInterval){
  445. this.show();
  446. }else{
  447. this.showTimer = this.show.defer(this.showDelay, this);
  448. }
  449. }else if(!this.hidden && this.autoHide !== false){
  450. this.show();
  451. }
  452. },
  453. // private
  454. onTargetOut : function(e){
  455. if(this.disabled || e.within(this.target.dom, true)){
  456. return;
  457. }
  458. this.clearTimer('show');
  459. if(this.autoHide !== false){
  460. this.delayHide();
  461. }
  462. },
  463. // private
  464. delayHide : function(){
  465. if(!this.hidden && !this.hideTimer){
  466. this.hideTimer = this.hide.defer(this.hideDelay, this);
  467. }
  468. },
  469. /**
  470. * Hides this tooltip if visible.
  471. */
  472. hide: function(){
  473. this.clearTimer('dismiss');
  474. this.lastActive = new Date();
  475. if(this.anchorEl){
  476. this.anchorEl.hide();
  477. }
  478. Ext.ToolTip.superclass.hide.call(this);
  479. delete this.triggerElement;
  480. },
  481. /**
  482. * Shows this tooltip at the current event target XY position.
  483. */
  484. show : function(){
  485. if(this.anchor){
  486. // pre-show it off screen so that the el will have dimensions
  487. // for positioning calcs when getting xy next
  488. this.showAt([-1000,-1000]);
  489. this.origConstrainPosition = this.constrainPosition;
  490. this.constrainPosition = false;
  491. this.anchor = this.origAnchor;
  492. }
  493. this.showAt(this.getTargetXY());
  494. if(this.anchor){
  495. this.syncAnchor();
  496. this.anchorEl.show();
  497. this.constrainPosition = this.origConstrainPosition;
  498. }else{
  499. this.anchorEl.hide();
  500. }
  501. },
  502. // inherit docs
  503. showAt : function(xy){
  504. this.lastActive = new Date();
  505. this.clearTimers();
  506. Ext.ToolTip.superclass.showAt.call(this, xy);
  507. if(this.dismissDelay && this.autoHide !== false){
  508. this.dismissTimer = this.hide.defer(this.dismissDelay, this);
  509. }
  510. },
  511. // private
  512. syncAnchor : function(){
  513. var anchorPos, targetPos, offset;
  514. switch(this.tipAnchor.charAt(0)){
  515. case 't':
  516. anchorPos = 'b';
  517. targetPos = 'tl';
  518. offset = [20+this.anchorOffset, 2];
  519. break;
  520. case 'r':
  521. anchorPos = 'l';
  522. targetPos = 'tr';
  523. offset = [-2, 11+this.anchorOffset];
  524. break;
  525. case 'b':
  526. anchorPos = 't';
  527. targetPos = 'bl';
  528. offset = [20+this.anchorOffset, -2];
  529. break;
  530. default:
  531. anchorPos = 'r';
  532. targetPos = 'tl';
  533. offset = [2, 11+this.anchorOffset];
  534. break;
  535. }
  536. this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
  537. },
  538. // private
  539. setPagePosition : function(x, y){
  540. Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
  541. if(this.anchor){
  542. this.syncAnchor();
  543. }
  544. },
  545. // private
  546. clearTimer : function(name){
  547. name = name + 'Timer';
  548. clearTimeout(this[name]);
  549. delete this[name];
  550. },
  551. // private
  552. clearTimers : function(){
  553. this.clearTimer('show');
  554. this.clearTimer('dismiss');
  555. this.clearTimer('hide');
  556. },
  557. // private
  558. onShow : function(){
  559. Ext.ToolTip.superclass.onShow.call(this);
  560. Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
  561. },
  562. // private
  563. onHide : function(){
  564. Ext.ToolTip.superclass.onHide.call(this);
  565. Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
  566. },
  567. // private
  568. onDocMouseDown : function(e){
  569. if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
  570. this.disable();
  571. this.enable.defer(100, this);
  572. }
  573. },
  574. // private
  575. onDisable : function(){
  576. this.clearTimers();
  577. this.hide();
  578. },
  579. // private
  580. adjustPosition : function(x, y){
  581. if(this.contstrainPosition){
  582. var ay = this.targetXY[1], h = this.getSize().height;
  583. if(y <= ay && (y+h) >= ay){
  584. y = ay-h-5;
  585. }
  586. }
  587. return {x : x, y: y};
  588. },
  589. // private
  590. onDestroy : function(){
  591. Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
  592. Ext.ToolTip.superclass.onDestroy.call(this);
  593. }
  594. });/**
  595. * @class Ext.QuickTip
  596. * @extends Ext.ToolTip
  597. * A specialized tooltip class for tooltips that can be specified in markup and automatically managed by the global
  598. * {@link Ext.QuickTips} instance. See the QuickTips class header for additional usage details and examples.
  599. * @constructor
  600. * Create a new Tip
  601. * @param {Object} config The configuration options
  602. */
  603. Ext.QuickTip = Ext.extend(Ext.ToolTip, {
  604. /**
  605. * @cfg {Mixed} target The target HTMLElement, Ext.Element or id to associate with this quicktip (defaults to the document).
  606. */
  607. /**
  608. * @cfg {Boolean} interceptTitles True to automatically use the element's DOM title value if available (defaults to false).
  609. */
  610. interceptTitles : false,
  611. // private
  612. tagConfig : {
  613. namespace : "ext",
  614. attribute : "qtip",
  615. width : "qwidth",
  616. target : "target",
  617. title : "qtitle",
  618. hide : "hide",
  619. cls : "qclass",
  620. align : "qalign",
  621. anchor : "anchor"
  622. },
  623. // private
  624. initComponent : function(){
  625. this.target = this.target || Ext.getDoc();
  626. this.targets = this.targets || {};
  627. Ext.QuickTip.superclass.initComponent.call(this);
  628. },
  629. /**
  630. * Configures a new quick tip instance and assigns it to a target element. The following config values are
  631. * supported (for example usage, see the {@link Ext.QuickTips} class header):
  632. * <div class="mdetail-params"><ul>
  633. * <li>autoHide</li>
  634. * <li>cls</li>
  635. * <li>dismissDelay (overrides the singleton value)</li>
  636. * <li>target (required)</li>
  637. * <li>text (required)</li>
  638. * <li>title</li>
  639. * <li>width</li></ul></div>
  640. * @param {Object} config The config object
  641. */
  642. register : function(config){
  643. var cs = Ext.isArray(config) ? config : arguments;
  644. for(var i = 0, len = cs.length; i < len; i++){
  645. var c = cs[i];
  646. var target = c.target;
  647. if(target){
  648. if(Ext.isArray(target)){
  649. for(var j = 0, jlen = target.length; j < jlen; j++){
  650. this.targets[Ext.id(target[j])] = c;
  651. }
  652. } else{
  653. this.targets[Ext.id(target)] = c;
  654. }
  655. }
  656. }
  657. },
  658. /**
  659. * Removes this quick tip from its element and destroys it.
  660. * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed.
  661. */
  662. unregister : function(el){
  663. delete this.targets[Ext.id(el)];
  664. },
  665. /**
  666. * Hides a visible tip or cancels an impending show for a particular element.
  667. * @param {String/HTMLElement/Element} el The element that is the target of the tip.
  668. */
  669. cancelShow: function(el){
  670. var at = this.activeTarget;
  671. el = Ext.get(el).dom;
  672. if(this.isVisible()){
  673. if(at && at.el == el){
  674. this.hide();
  675. }
  676. }else if(at && at.el == el){
  677. this.clearTimer('show');
  678. }
  679. },
  680. // private
  681. onTargetOver : function(e){
  682. if(this.disabled){
  683. return;
  684. }
  685. this.targetXY = e.getXY();
  686. var t = e.getTarget();
  687. if(!t || t.nodeType !== 1 || t == document || t == document.body){
  688. return;
  689. }
  690. if(this.activeTarget && t == this.activeTarget.el){
  691. this.clearTimer('hide');
  692. this.show();
  693. return;
  694. }
  695. if(t && this.targets[t.id]){
  696. this.activeTarget = this.targets[t.id];
  697. this.activeTarget.el = t;
  698. this.anchor = this.activeTarget.anchor;
  699. if(this.anchor){
  700. this.anchorTarget = t;
  701. }
  702. this.delayShow();
  703. return;
  704. }
  705. var ttp, et = Ext.fly(t), cfg = this.tagConfig;
  706. var ns = cfg.namespace;
  707. if(this.interceptTitles && t.title){
  708. ttp = t.title;
  709. t.qtip = ttp;
  710. t.removeAttribute("title");
  711. e.preventDefault();
  712. } else{
  713. ttp = t.qtip || et.getAttribute(cfg.attribute, ns);
  714. }
  715. if(ttp){
  716. var autoHide = et.getAttribute(cfg.hide, ns);
  717. this.activeTarget = {
  718. el: t,
  719. text: ttp,
  720. width: et.getAttribute(cfg.width, ns),
  721. autoHide: autoHide != "user" && autoHide !== 'false',
  722. title: et.getAttribute(cfg.title, ns),
  723. cls: et.getAttribute(cfg.cls, ns),
  724. align: et.getAttribute(cfg.align, ns)
  725. };
  726. this.anchor = et.getAttribute(cfg.anchor, ns);
  727. if(this.anchor){
  728. this.anchorTarget = t;
  729. }
  730. this.delayShow();
  731. }
  732. },
  733. // private
  734. onTargetOut : function(e){
  735. this.clearTimer('show');
  736. if(this.autoHide !== false){
  737. this.delayHide();
  738. }
  739. },
  740. // inherit docs
  741. showAt : function(xy){
  742. var t = this.activeTarget;
  743. if(t){
  744. if(!this.rendered){
  745. this.render(Ext.getBody());
  746. this.activeTarget = t;
  747. }
  748. if(t.width){
  749. this.setWidth(t.width);
  750. this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
  751. this.measureWidth = false;
  752. } else{
  753. this.measureWidth = true;
  754. }
  755. this.setTitle(t.title || '');
  756. this.body.update(t.text);
  757. this.autoHide = t.autoHide;
  758. this.dismissDelay = t.dismissDelay || this.dismissDelay;
  759. if(this.lastCls){
  760. this.el.removeClass(this.lastCls);
  761. delete this.lastCls;
  762. }
  763. if(t.cls){
  764. this.el.addClass(t.cls);
  765. this.lastCls = t.cls;
  766. }
  767. if(this.anchor){
  768. this.constrainPosition = false;
  769. }else if(t.align){ // TODO: this doesn't seem to work consistently
  770. xy = this.el.getAlignToXY(t.el, t.align);
  771. this.constrainPosition = false;
  772. }else{
  773. this.constrainPosition = true;
  774. }
  775. }
  776. Ext.QuickTip.superclass.showAt.call(this, xy);
  777. },
  778. // inherit docs
  779. hide: function(){
  780. delete this.activeTarget;
  781. Ext.QuickTip.superclass.hide.call(this);
  782. }
  783. });/**
  784. * @class Ext.QuickTips
  785. * <p>Provides attractive and customizable tooltips for any element. The QuickTips
  786. * singleton is used to configure and manage tooltips globally for multiple elements
  787. * in a generic manner. To create individual tooltips with maximum customizability,
  788. * you should consider either {@link Ext.Tip} or {@link Ext.ToolTip}.</p>
  789. * <p>Quicktips can be configured via tag attributes directly in markup, or by
  790. * registering quick tips programmatically via the {@link #register} method.</p>
  791. * <p>The singleton's instance of {@link Ext.QuickTip} is available via
  792. * {@link #getQuickTip}, and supports all the methods, and all the all the
  793. * configuration properties of Ext.QuickTip. These settings will apply to all
  794. * tooltips shown by the singleton.</p>
  795. * <p>Below is the summary of the configuration properties which can be used.
  796. * For detailed descriptions see {@link #getQuickTip}</p>
  797. * <p><b>QuickTips singleton configs (all are optional)</b></p>
  798. * <div class="mdetail-params"><ul><li>dismissDelay</li>
  799. * <li>hideDelay</li>
  800. * <li>maxWidth</li>
  801. * <li>minWidth</li>
  802. * <li>showDelay</li>
  803. * <li>trackMouse</li></ul></div>
  804. * <p><b>Target element configs (optional unless otherwise noted)</b></p>
  805. * <div class="mdetail-params"><ul><li>autoHide</li>
  806. * <li>cls</li>
  807. * <li>dismissDelay (overrides singleton value)</li>
  808. * <li>target (required)</li>
  809. * <li>text (required)</li>
  810. * <li>title</li>
  811. * <li>width</li></ul></div>
  812. * <p>Here is an example showing how some of these config options could be used:</p>
  813. * <pre><code>
  814. // Init the singleton. Any tag-based quick tips will start working.
  815. Ext.QuickTips.init();
  816. // Apply a set of config properties to the singleton
  817. Ext.apply(Ext.QuickTips.getQuickTip(), {
  818. maxWidth: 200,
  819. minWidth: 100,
  820. showDelay: 50,
  821. trackMouse: true
  822. });
  823. // Manually register a quick tip for a specific element
  824. Ext.QuickTips.register({
  825. target: 'my-div',
  826. title: 'My Tooltip',
  827. text: 'This tooltip was added in code',
  828. width: 100,
  829. dismissDelay: 20
  830. });
  831. </code></pre>
  832. * <p>To register a quick tip in markup, you simply add one or more of the valid QuickTip attributes prefixed with
  833. * the <b>ext:</b> namespace. The HTML element itself is automatically set as the quick tip target. Here is the summary
  834. * of supported attributes (optional unless otherwise noted):</p>
  835. * <ul><li><b>hide</b>: Specifying "user" is equivalent to setting autoHide = false. Any other value will be the
  836. * same as autoHide = true.</li>
  837. * <li><b>qclass</b>: A CSS class to be applied to the quick tip (equivalent to the 'cls' target element config).</li>
  838. * <li><b>qtip (required)</b>: The quick tip text (equivalent to the 'text' target element config).</li>
  839. * <li><b>qtitle</b>: The quick tip title (equivalent to the 'title' target element config).</li>
  840. * <li><b>qwidth</b>: The quick tip width (equivalent to the 'width' target element config).</li></ul>
  841. * <p>Here is an example of configuring an HTML element to display a tooltip from markup:</p>
  842. * <pre><code>
  843. // Add a quick tip to an HTML button
  844. &lt;input type="button" value="OK" ext:qtitle="OK Button" ext:qwidth="100"
  845. ext:qtip="This is a quick tip from markup!">&lt;/input>
  846. </code></pre>
  847. * @singleton
  848. */
  849. Ext.QuickTips = function(){
  850. var tip, locks = [];
  851. return {
  852. /**
  853. * Initialize the global QuickTips instance and prepare any quick tips.
  854. * @param {Boolean} autoRender True to render the QuickTips container immediately to preload images. (Defaults to true)
  855. */
  856. init : function(autoRender){
  857. if(!tip){
  858. if(!Ext.isReady){
  859. Ext.onReady(function(){
  860. Ext.QuickTips.init(autoRender);
  861. });
  862. return;
  863. }
  864. tip = new Ext.QuickTip({elements:'header,body'});
  865. if(autoRender !== false){
  866. tip.render(Ext.getBody());
  867. }
  868. }
  869. },
  870. /**
  871. * Enable quick tips globally.
  872. */
  873. enable : function(){
  874. if(tip){
  875. locks.pop();
  876. if(locks.length < 1){
  877. tip.enable();
  878. }
  879. }
  880. },
  881. /**
  882. * Disable quick tips globally.
  883. */
  884. disable : function(){
  885. if(tip){
  886. tip.disable();
  887. }
  888. locks.push(1);
  889. },
  890. /**
  891. * Returns true if quick tips are enabled, else false.
  892. * @return {Boolean}
  893. */
  894. isEnabled : function(){
  895. return tip !== undefined && !tip.disabled;
  896. },
  897. /**
  898. * Gets the global QuickTips instance.
  899. */
  900. getQuickTip : function(){
  901. return tip;
  902. },
  903. /**
  904. * Configures a new quick tip instance and assigns it to a target element. See
  905. * {@link Ext.QuickTip#register} for details.
  906. * @param {Object} config The config object
  907. */
  908. register : function(){
  909. tip.register.apply(tip, arguments);
  910. },
  911. /**
  912. * Removes any registered quick tip from the target element and destroys it.
  913. * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed.
  914. */
  915. unregister : function(){
  916. tip.unregister.apply(tip, arguments);
  917. },
  918. /**
  919. * Alias of {@link #register}.
  920. * @param {Object} config The config object
  921. */
  922. tips :function(){
  923. tip.register.apply(tip, arguments);
  924. }
  925. }
  926. }();