ValidationStatus.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /**
  2. * A {@link Ext.ux.statusbar.StatusBar} plugin that provides automatic error
  3. * notification when the associated form contains validation errors.
  4. */
  5. Ext.define('Ext.ux.statusbar.ValidationStatus', {
  6. extend: 'Ext.Component',
  7. requires: ['Ext.util.MixedCollection'],
  8. /**
  9. * @cfg {String} errorIconCls
  10. * The {@link Ext.ux.statusbar.StatusBar#iconCls iconCls} value to be applied
  11. * to the status message when there is a validation error.
  12. */
  13. errorIconCls : 'x-status-error',
  14. /**
  15. * @cfg {String} errorListCls
  16. * The css class to be used for the error list when there are validation errors.
  17. */
  18. errorListCls : 'x-status-error-list',
  19. /**
  20. * @cfg {String} validIconCls
  21. * The {@link Ext.ux.statusbar.StatusBar#iconCls iconCls} value to be applied
  22. * to the status message when the form validates.
  23. */
  24. validIconCls : 'x-status-valid',
  25. /**
  26. * @cfg {String} showText
  27. * The {@link Ext.ux.statusbar.StatusBar#text text} value to be applied when
  28. * there is a form validation error.
  29. */
  30. showText : 'The form has errors (click for details...)',
  31. /**
  32. * @cfg {String} hideText
  33. * The {@link Ext.ux.statusbar.StatusBar#text text} value to display when
  34. * the error list is displayed.
  35. */
  36. hideText : 'Click again to hide the error list',
  37. /**
  38. * @cfg {String} submitText
  39. * The {@link Ext.ux.statusbar.StatusBar#text text} value to be applied when
  40. * the form is being submitted.
  41. */
  42. submitText : 'Saving...',
  43. // private
  44. init : function(sb){
  45. sb.on('render', function(){
  46. this.statusBar = sb;
  47. this.monitor = true;
  48. this.errors = Ext.create('Ext.util.MixedCollection');
  49. this.listAlign = (sb.statusAlign === 'right' ? 'br-tr?' : 'bl-tl?');
  50. if (this.form) {
  51. this.formPanel = Ext.getCmp(this.form);
  52. this.basicForm = this.formPanel.getForm();
  53. this.startMonitoring();
  54. this.basicForm.on('beforeaction', function(f, action){
  55. if(action.type === 'submit'){
  56. // Ignore monitoring while submitting otherwise the field validation
  57. // events cause the status message to reset too early
  58. this.monitor = false;
  59. }
  60. }, this);
  61. var startMonitor = function(){
  62. this.monitor = true;
  63. };
  64. this.basicForm.on('actioncomplete', startMonitor, this);
  65. this.basicForm.on('actionfailed', startMonitor, this);
  66. }
  67. }, this, {single:true});
  68. sb.on({
  69. scope: this,
  70. afterlayout:{
  71. single: true,
  72. fn: function(){
  73. // Grab the statusEl after the first layout.
  74. sb.statusEl.getEl().on('click', this.onStatusClick, this, {buffer:200});
  75. }
  76. },
  77. beforedestroy:{
  78. single: true,
  79. fn: this.onDestroy
  80. }
  81. });
  82. },
  83. // private
  84. startMonitoring : function() {
  85. this.basicForm.getFields().each(function(f){
  86. f.on('validitychange', this.onFieldValidation, this);
  87. }, this);
  88. },
  89. // private
  90. stopMonitoring : function(){
  91. this.basicForm.getFields().each(function(f){
  92. f.un('validitychange', this.onFieldValidation, this);
  93. }, this);
  94. },
  95. // private
  96. onDestroy : function(){
  97. this.stopMonitoring();
  98. this.statusBar.statusEl.un('click', this.onStatusClick, this);
  99. this.callParent(arguments);
  100. },
  101. // private
  102. onFieldValidation : function(f, isValid){
  103. if (!this.monitor) {
  104. return false;
  105. }
  106. var msg = f.getErrors()[0];
  107. if (msg) {
  108. this.errors.add(f.id, {field:f, msg:msg});
  109. } else {
  110. this.errors.removeAtKey(f.id);
  111. }
  112. this.updateErrorList();
  113. if(this.errors.getCount() > 0) {
  114. if(this.statusBar.getText() !== this.showText){
  115. this.statusBar.setStatus({text:this.showText, iconCls:this.errorIconCls});
  116. }
  117. }else{
  118. this.statusBar.clearStatus().setIcon(this.validIconCls);
  119. }
  120. },
  121. // private
  122. updateErrorList : function(){
  123. if(this.errors.getCount() > 0){
  124. var msg = '<ul>';
  125. this.errors.each(function(err){
  126. msg += ('<li id="x-err-'+ err.field.id +'"><a href="#">' + err.msg + '</a></li>');
  127. }, this);
  128. this.getMsgEl().update(msg+'</ul>');
  129. }else{
  130. this.getMsgEl().update('');
  131. }
  132. // reset msgEl size
  133. this.getMsgEl().setSize('auto', 'auto');
  134. },
  135. // private
  136. getMsgEl : function(){
  137. if(!this.msgEl){
  138. this.msgEl = Ext.DomHelper.append(Ext.getBody(), {
  139. cls: this.errorListCls
  140. }, true);
  141. this.msgEl.hide();
  142. this.msgEl.on('click', function(e){
  143. var t = e.getTarget('li', 10, true);
  144. if(t){
  145. Ext.getCmp(t.id.split('x-err-')[1]).focus();
  146. this.hideErrors();
  147. }
  148. }, this, {stopEvent:true}); // prevent anchor click navigation
  149. }
  150. return this.msgEl;
  151. },
  152. // private
  153. showErrors : function(){
  154. this.updateErrorList();
  155. this.getMsgEl().alignTo(this.statusBar.getEl(), this.listAlign).slideIn('b', {duration: 300, easing:'easeOut'});
  156. this.statusBar.setText(this.hideText);
  157. this.formPanel.el.on('click', this.hideErrors, this, {single:true}); // hide if the user clicks directly into the form
  158. },
  159. // private
  160. hideErrors : function(){
  161. var el = this.getMsgEl();
  162. if(el.isVisible()){
  163. el.slideOut('b', {duration: 300, easing:'easeIn'});
  164. this.statusBar.setText(this.showText);
  165. }
  166. this.formPanel.el.un('click', this.hideErrors, this);
  167. },
  168. // private
  169. onStatusClick : function(){
  170. if(this.getMsgEl().isVisible()){
  171. this.hideErrors();
  172. }else if(this.errors.getCount() > 0){
  173. this.showErrors();
  174. }
  175. }
  176. });