1 // ==========================================================================
  2 // Project:   SproutCore - JavaScript Application Framework
  3 // Copyright: ©2006-2011 Strobe Inc. and contributors.
  4 //            Portions ©2008-2011 Apple Inc. All rights reserved.
  5 // License:   Licensed under MIT license (see license.js)
  6 // ==========================================================================
  7 
  8 
  9 /** @class
 10 
 11   A modal pane is used to capture mouse events inside a pane that is modal.
 12   You normally will not work with modal panes directly, though you may set
 13   the modalPane property to a subclass of this pane when designing custom
 14   panes.
 15 
 16   A modal pane is automatically appended when a pane with isModal set to
 17   `YES` is made visible and removed when the same pane is hidden.  The only
 18   purpose of the `ModalPane` is to absorb mouse events so that they cannot
 19   filter through to the underlying content.
 20 
 21   @extends SC.Pane
 22   @since SproutCore 1.0
 23 */
 24 SC.ModalPane = SC.Pane.extend(
 25 /** @scope SC.ModalPane.prototype */{
 26 
 27   /**
 28     @type Array
 29     @default ['sc-modal']
 30     @see SC.View#classNames
 31   */
 32   classNames: 'sc-modal',
 33 
 34   /** @private */
 35   _openPaneCount: 0,
 36 
 37   /** @private
 38     Called by a pane just before it appends itself.   The modal pane can
 39     make itself visible first if needed.
 40 
 41     @param {SC.Pane} pane the pane
 42     @returns {SC.ModalPane} receiver
 43   */
 44   paneWillAppend: function(pane) {
 45     var _tmpPane;
 46     this._openPaneCount++;
 47     if (!this.get('isVisibleInWindow')) this.append();
 48     var panes = SC.RootResponder.responder.panes;
 49     for(var i=0, iLen=panes.length; i<iLen; i++ ){
 50       _tmpPane = panes[i];
 51       if(_tmpPane!==pane) {
 52         //_tmpPane.set('ariaHidden', YES);
 53         this._hideShowTextfields(_tmpPane, NO);
 54       }
 55     }
 56     return this ;
 57   },
 58 
 59   /** @private
 60     Called by a pane just after it removes itself.  The modal pane can remove
 61     itself if needed.   Modal panes only remove themselves when an equal
 62     number of `paneWillAppend()` and `paneDidRemove()` calls are received.
 63 
 64     @param {SC.Pane} pane the pane
 65     @returns {SC.ModalPane} receiver
 66   */
 67   paneDidRemove: function(pane) {
 68     var _tmpPane;
 69     this._openPaneCount--;
 70     var panes = SC.RootResponder.responder.panes;
 71     for(var i=0, iLen=panes.length; i<iLen; i++ ){
 72       _tmpPane = panes[i];
 73       if(_tmpPane!==pane) {
 74         //_tmpPane.set('ariaHidden', NO);
 75         this._hideShowTextfields(_tmpPane, YES);
 76       }
 77     }
 78     if (this._openPaneCount <= 0) {
 79       this._openPaneCount = 0 ;
 80       if (this.get('isVisibleInWindow')) this.remove();
 81     }
 82   },
 83 
 84   /** @private
 85     If `focusable` is NO all SC.TextFieldViews not belonging to the given
 86     pane will have isBrowserFocusable set to NO.  If `focusable` is YES, then
 87     all SC.TextFieldViews not belonging to the given pane will have
 88     isBrowserFocusable set to YES, unless they previously had it set explictly
 89     to NO.
 90   */
 91   _hideShowTextfields: function(pane, focusable){
 92     var view;
 93 
 94     for (view in SC.View.views) {
 95       view = SC.View.views[view];
 96       if (view.get('isTextField') && view !== pane && view.get('pane') === pane) {
 97         if (focusable) {
 98           // Setting isBrowserFocusable back to YES. If we cached the previous
 99           // value, use that instead.
100           if (view._scmp_isBrowserFocusable !== undefined) {
101             focusable = view._scmp_isBrowserFocusable;
102 
103             // Clean up entirely.
104             delete view._scmp_isBrowserFocusable;
105           }
106         } else {
107           // Cache the value of isBrowserFocusable. If the text field
108           // already had isBrowserFocusable: NO, we don't want to
109           // set it back to YES.
110           view._scmp_isBrowserFocusable = view.get('isBrowserFocusable');
111         }
112         view.set('isBrowserFocusable', focusable);
113       }
114     }
115   },
116 
117   /** @private */
118   mouseDown: function(evt) {
119     var owner = this.get('owner');
120     if (owner && owner.modalPaneDidClick) owner.modalPaneDidClick(evt);
121   },
122 
123   /** @private */
124   touchStart: function(evt) {
125     this.mouseDown(evt);
126   }
127 });
128