1 // ==========================================================================
  2 // Project:   The M-Project - Mobile HTML5 Application Framework
  3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved.
  4 //            (c) 2011 panacoda GmbH. All rights reserved.
  5 // Creator:   Dominik
  6 // Date:      23.11.2010
  7 // License:   Dual licensed under the MIT or GPL Version 2 licenses.
  8 //            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
  9 //            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
 10 // ==========================================================================
 11 
 12 m_require('ui/dialog.js');
 13 
 14 /**
 15  * @class
 16  *
 17  * This is the prototype for any action sheet dialog view. It is derived from M.DialogView
 18  * and mainly used for implementing a action sheet dialog view specific render method.
 19  *
 20  * @extends M.DialogView 
 21  */
 22 M.ActionSheetDialogView = M.DialogView.extend(
 23 /** @scope M.ActionSheetDialogView.prototype */ {
 24 
 25     /**
 26      * The type of this object.
 27      *
 28      * @type String
 29      */
 30     type: 'M.ActionSheetDialogView',
 31 
 32     /**
 33      * The default title of an action sheet dialog.
 34      *
 35      * @type String
 36      */
 37     title: 'ActionSheet',
 38 
 39     /**
 40      * Defines the value of the destructive button (the one button that is showed in red)
 41      *
 42      * @type String
 43      */
 44     destructiveButtonValue: null,
 45 
 46     /**
 47      * Defines the value of the cancel button
 48      *
 49      * @type String
 50      */
 51     cancelButtonValue: null,
 52 
 53     /**
 54      * Contains the values of all other buttons as strings
 55      *
 56      * @type Array
 57      */
 58     otherButtonValues: null,
 59 
 60     /**
 61      * Contains the tags of all other buttons as strings
 62      *
 63      * @type Array
 64      */
 65     otherButtonTags: null,
 66 
 67     /**
 68      * Delay between action sheet slide out animation finished and deleting it from DOM and deleting the object
 69      */
 70     deletionDelay: 1000,
 71 
 72     /**
 73      * If set, contains the dialog's callbacks in sub objects named 'destruction', 'cancel' and 'other' or as  functions named confirm, cancel and other.
 74      *
 75      * @type Object
 76      */
 77     callbacks: null,
 78 
 79     /**
 80      * Renders an action sheet dialog as a slide-up.
 81      *
 82      * @private
 83      * @returns {String} The action sheet dialog view's html representation.
 84      */
 85 
 86     render: function() {
 87         /* render half transparent grey background */
 88         this.html = '<div class="tmp-dialog-background"></div>';
 89 
 90         /* render title */
 91         this.html += '<div id="' + this.id + '" class="tmp-actionsheet">';
 92         this.html += '<div class="tmp-dialog-header">';
 93         this.html += this.title ? this.title : '';
 94         this.html +='</div>';
 95 
 96         /* render footer that contains all buttons */
 97         this.html += '<div class="tmp-dialog-footer">';
 98 
 99         var that = this;
100 
101         var buttons = [];
102         if(this.destructiveButtonValue) {
103             buttons.push(M.ButtonView.design({
104                 value: this.destructiveButtonValue,
105                 tag: 'destruction',
106                 cssClass: 'a tmp-actionsheet-destructive-button',
107                 events: {
108                     tap: {
109                         target: that,
110                         action: 'handleCallback'
111                     }
112                 }
113             }));
114         }
115         if(this.otherButtonValues) {
116             if(this.otherButtonTags && !(_.isArray(this.otherButtonTags)) && !(_.isArray(this.otherButtonValues))) {
117                 M.Logger.log('Error in Action Sheet: Values and (optional) tags must be passed as string in an array! Rendering will not proceed.', M.WARN);
118                 return '';
119             }
120             /* First check if passed number of values matches number of labels passed */
121             /* If not, do not use values, but use incremented buttonNr as value */
122             if(this.otherButtonTags && this.otherButtonTags.length !== this.otherButtonValues.length) {
123                 M.Logger.log('Mismatch in Action Sheet: Number of other button\'s tags doesn\'t match number of values. Will not use given values, but use generated numbers as values.', M.WARN);
124                 this.otherButtonTags = null;
125             }
126 
127             var buttonNr = 0;
128 
129             _.each(this.otherButtonValues, function(btn) {
130                 buttons.push(M.ButtonView.design({
131                     value: btn,
132                     tag: that.otherButtonTags ? that.otherButtonTags[buttonNr++] : buttonNr++,
133                     events: {
134                         tap: {
135                             target: that,
136                             action: 'handleCallback'
137                         }
138                     }
139                 }));
140             });
141         }
142         
143         if(this.cancelButtonValue) {
144             buttons.push(M.ButtonView.design({
145                 value: this.cancelButtonValue,
146                 tag: 'cancel',
147                 cssClass: 'a',
148                 events: {
149                     tap: {
150                         target: that,
151                         action: 'handleCallback'
152                     }
153                 }
154             }));
155         }
156 
157 
158         /* render each button saved in the buttons array */
159         for(var i in buttons) {
160             this.html += buttons[i].render();
161         };
162 
163         this.html += '</div>';
164         this.html += '</div>';
165 
166         $('body').append(this.html);
167 
168         /* register events for each designed and rendered button and theme it afterwards
169          * must be performed AFTER button has been inserted to DOM
170          */
171         for(var i in buttons) {
172             buttons[i].registerEvents();
173             buttons[i].theme();
174         };
175     },
176 
177     show: function() {
178         this.render();
179         var dialog = $('#' + this.id);
180         dialog.removeClass('slideup out reverse');
181         dialog.addClass('slideup in');
182     },
183 
184     hide: function() {
185         var dialog = $('#' + this.id);
186         dialog.removeClass('slideup in');
187         dialog.addClass('slideup out reverse');
188         $('.tmp-dialog-background').remove();
189 
190         /* destroying the view object and its DOM representation must be performed after the slide animation is finished. */
191         var that = this;
192         window.setTimeout(that.bindToCaller(that, that.destroy), this.deletionDelay);
193 
194         /* now wait 100ms (plus the default delay) and then call the next in the queue */
195         var that = this;
196         window.setTimeout(function() {
197             M.DialogView.isActive = NO;
198             that.dequeue();
199         }, this.deletionDelay + 100);
200     },
201 
202     handleCallback: function(viewId, event) {
203         this.hide();
204         var button = M.ViewManager.getViewById(viewId);
205         var buttonType = (button.tag === 'destruction' || button.tag === 'cancel') ? button.tag : 'other';
206 
207         if(this.callbacks && buttonType && M.EventDispatcher.checkHandler(this.callbacks[buttonType])){
208             this.bindToCaller(this.callbacks[buttonType].target, this.callbacks[buttonType].action, button.tag)();
209         }
210     }
211 
212 
213 
214 });