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:      02.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('core/foundation/view.js');
 13 
 14 /**
 15  * @class
 16  *
 17  * The ViewManager manages and knows all views that are used in the application. The ViewManager is part of M.Application.
 18  *
 19  * It is used by various other components (e.g. controller: switchToPage) to connect from javascript objects to their
 20  * HTML representation. 
 21  *
 22  * @extends M.Object
 23  */
 24 M.ViewManager = M.Object.extend(
 25 /** @scope M.ViewManager.prototype */ {
 26 
 27     /**
 28      * The type of this object.
 29      *
 30      * @type String
 31      */
 32     type: 'M.ViewManager',
 33 
 34     /**
 35      * The nextId delivered to a view (used as html id attribute value) with prefix m_.
 36      * Initial state is 0, will be incremeneted by 1 on each call.
 37      *
 38      * @type Number
 39      */
 40     nextId: 0,
 41 
 42     /**
 43      * Prefix for Id.
 44      *
 45      * @type String
 46      */
 47     idPrefix: 'm_',
 48 
 49     /**
 50      * An associative array containing all views used in the application. The key for a view is
 51      * its id.
 52      *
 53      * @type Object
 54      */
 55     viewList: {},
 56 
 57     /**
 58      * An associative array containing all pages used in the application. The key for a page is
 59      * its id.
 60      *
 61      * @type Object
 62      */
 63     pageList: {},
 64 
 65     /**
 66      * A reference to the currently displayed page.
 67      *
 68      * @type Object
 69      */
 70     currentPage: null,
 71 
 72     /**
 73      * A reference to the currently rendered page.
 74      *
 75      * @type Object
 76      */
 77     currentlyRenderedPage: null,
 78 
 79     /**
 80      * A reference to the latest found view which is necessary for the findView() method.
 81      *
 82      * @type Object
 83      */
 84     foundView: null,
 85 
 86     /**
 87      * Returns the next Id build from nextId property incremented by 1 and the prefix.
 88      * The id is used as the value for the HTML attribute id.
 89      * 
 90      * @returns {String} The next id for a view, e.g. 'm_123' (if last id was 'm_122').
 91      */
 92     getNextId: function() {
 93         this.nextId = this.nextId + 1;
 94         return this.idPrefix + this.nextId;
 95     },
 96 
 97     /**
 98      * Adds the view to the viewlist array.
 99      *
100      * @param {Object} view The view to be registered in the viewlist.
101      */
102     register: function(view) {
103         this.viewList[view.id] = view;
104 
105         if(view.type === 'M.PageView') {
106             this.pageList[view.id] = view;
107         }
108     },
109 
110     /**
111      * Unregisters the view from the viewlist array.
112      *
113      * @param {Object} view The view to be unregistered from the viewlist.
114      */
115     unregister: function(view) {
116         delete this.viewList[view.id];
117     },
118 
119     /**
120      * Returns the view object from the view list array identified
121      * by the value of its id attribute.
122      *
123      * @param {String} id The DOM id of the corresponding view object.
124      * @returns {Object} The view object from the view list identified by id.
125      */
126     getViewById: function(id) {
127         return this.viewList[id];
128     },
129 
130 	/**
131      * another naming for getViewById - same same as getViewById
132      *
133      * @param {String} id The DOM id of the corresponding view object.
134      * @returns {Object} The view object from the view list identified by id.
135      */
136 
137     findViewById: function(id) {
138         return this.getViewById(id);
139     },
140 
141     /**
142      * Returns the id for a given view.
143      *
144      * @param {Object} view The view for which the id value is wanted.
145      * @returns {String} The id of a view object.
146      */
147     getIdByView: function(view) {
148         return view.id;
149     },
150 
151     /**
152      * Returns the view object from the view list array identified by the view's
153      * name and its surrounding view. If there are multiple views with the same
154      * name on the same surrounding view, the first result is returned.
155      *
156      * Note: Try to use unique names for your views within the same surrounding view!
157      *
158      * @param {String|Object} parentView The name of the parent view (if it is a page) or the parent view itself.
159      * @param {String} targetView The name of the view to be returned.
160      * @returns {Object} The view object from the view list identified by the view's name and the page where it's on.
161      */
162     getView: function(parentView, targetView) {
163         if(typeof(parentView) !== 'object') {
164             parentView = M.Application.pages[parentView] ? M.Application.pages[parentView] : (M.ViewManager.getViewById(parentView) ? M.ViewManager.getViewById(parentView) : null);
165         }
166         var view = null;
167 
168         /* reset previously found views before searching again */
169         this.foundView = null;
170         if(parentView) {
171             view = this.findView(parentView, targetView);
172         }
173 
174         if(!view) {
175             M.Logger.log('view \'' + targetView + '\' not found.', M.WARN);
176         }
177         return view;
178     },
179 
180     /**
181      * Searches for a certain view within a given parent view. If it is found, the result
182      * is returned. Otherwise the search algorithm checks for possible child views and then
183      * recursively searches within these child views for the target view.
184      *
185      * This method is mainly used by the getView() method to find a view within a page.
186      *
187      * @param {Object} parentView The parent view to search in.
188      * @param {String} targetView The name of the view to be returned.
189      * @returns {Object} The last found view.
190      */
191     findView: function(parentView, targetView) {
192         if(parentView.childViews) {
193             var childViews = parentView.getChildViewsAsArray();
194             for(var i in childViews) {
195                 if(targetView === childViews[i]) {
196                     this.foundView =  parentView[targetView];
197                     return this.foundView;
198                 } else {
199                     this.findView(parentView[childViews[i]], targetView);
200                 }
201             }
202         }
203         return this.foundView;
204     },
205 
206     /**
207      * Returns the page object from the view list array identified by its name. If
208      * there are multiple pages with the same name, the first result is returned.
209      *
210      * Note: Try to use unique names for your pages!
211      *
212      * @param {String} pageName The name of the page to be returned.
213      * @returns {Object} M.Page object identified by its name.
214      */
215     getPage: function(pageName) {
216         var page = M.Application.pages[pageName];
217 
218         if(!page) {
219             M.Logger.log('page \'' + pageName + '\' not found.', M.WARN);
220         }
221         return page;
222     },
223 
224     /**
225      * Returns the currently displayed page.
226      * @returns {Object} The currently displayed page.
227      */
228     getCurrentPage: function() {
229         return this.currentPage;
230     },
231 
232     /**
233      * Sets the currently displayed page.
234      * @param {Object} page The page to be set as current page.
235      */
236     setCurrentPage: function(page) {
237         this.currentPage = page;
238     },
239 
240     /**
241      * Debug method to print out all content from the viewlist array to the console.
242      * @private
243      */
244     dumpViewList: function() {
245       _.each(this.viewList, function(view){
246         console.log(view.id + ': '+ view.type);
247       });  
248     }
249 
250 });