1 Ext.define('Ext.navigation.View', {
2 extend: 'Ext.Container',
3 alternateClassName: 'Ext.NavigationView',
4 xtype: 'navigationview',
5 requires: ['Ext.navigation.Bar'],
6 config: {
7 /**
8 * @cfg
9 * @inheritdoc
10 */
11 baseCls: Ext.baseCSSPrefix + 'navigationview',
12 /**
13 * @cfg {Boolean/Object} navigationBar
14 * 用以配置导航栏
15 */
16 navigationBar: {
17 docked: 'top'
18 },
19 /**
20 * @cfg {String} defaultBackButtonText
21 * 返回按钮默认显示值
22 */
23 defaultBackButtonText: 'Back',
24 /**
25 * @cfg {Boolean} useTitleForBackButtonText
26 * 当此值为false时,返回按钮显示值为defaultBackButtonText中设置的值
27 * 当此值为true时,返回按钮显示值为上个项的title值
28 * @accessor
29 */
30 useTitleForBackButtonText: false,
31 /**
32 * @cfg
33 * @hide
34 */
35 layout: {
36 type: 'card',
37 animation: {
38 duration: 300,
39 easing: 'ease-out',
40 type: 'slide',
41 direction: 'left'
42 }
43 }
44 },
45 // @private
46 initialize: function () {
47 var me = this,
48 navBar = me.getNavigationBar();
49
50 //为导航栏上的后退按钮,添加监听
51 navBar.on({
52 back: me.onBackButtonTap,
53 scope: me
54 });
55
56 me.relayEvents(navBar, 'rightbuttontap');
57
58 me.relayEvents(me, {
59 add: 'push',
60 remove: 'pop'
61 });
62
63 //<debug>
64 var layout = me.getLayout();
65 if (layout && !layout.isCard) {
66 Ext.Logger.error('The base layout for a NavigationView must always be a Card Layout');
67 }
68 //</debug>
69 },
70 /**
71 * @private
72 */
73 applyLayout: function (config) {
74 config = config || {};
75
76 return config;
77 },
78 /**
79 * @private
80 * 用户点击返回按钮
81 */
82 onBackButtonTap: function () {
83 this.pop();
84 this.fireEvent('back', this);
85 },
86 /**
87 * 添加并且显示一个新项
88 * @return {Ext.Component}
89 */
90 push: function (view) {
91 return this.add(view);
92 },
93 /**
94 * 不填写参数时,移除当前项,返回到上一项
95 * 如果参数是数字,则从最后一项开始移除指定数目的项
96 * 如果参数是string,则移除指定类型的项
97 * 如果参数是项,则移除传入的项
98 * 不论参数如何,都会保留一个活动项
99 * @return {Ext.Component} 当前活动项
100 */
101 pop: function (count) {
102 if (this.beforePop(count)) {
103 return this.doPop();
104 }
105 },
106 /**
107 * @private
108 *删除指定项
109 */
110 beforePop: function (count) {
111 var me = this,
112 innerItems = me.getInnerItems();
113
114 if (Ext.isString(count) || Ext.isObject(count)) {
115 var last = innerItems.length - 1,
116 i;
117 for (i = last; i >= 0; i--) {
118 if ((Ext.isString(count) && Ext.ComponentQuery.is(innerItems[i], count)) || (Ext.isObject(count) && count == innerItems[i])) {
119 //获得移除项序号
120 count = last - i;
121 break;
122 }
123 }
124
125 if (!Ext.isNumber(count)) {
126 return false;
127 }
128 }
129
130 var ln = innerItems.length,
131 toRemove;
132
133 //默认移除一项
134 if (!Ext.isNumber(count) || count < 1) {
135 count = 1;
136 }
137
138 //当我们试图移除更多视图时
139 count = Math.min(count, ln - 1);
140
141 if (count) {
142 //更新导航栏
143 me.getNavigationBar().beforePop(count);
144
145 //开始移除视图
146 toRemove = innerItems.splice(-count, count - 1);
147 for (i = 0; i < toRemove.length; i++) {
148 this.remove(toRemove[i]);
149 }
150
151 return true;
152 }
153
154 return false;
155 },
156 /**
157 * @private
158 *移除最后一项
159 */
160 doPop: function () {
161 var me = this,
162 innerItems = this.getInnerItems();
163 me.remove(innerItems[innerItems.length - 1]);
164 return this.getActiveItem();
165 },
166 /**
167 * 获取上一项
168 * @return {Mixed} 上一项
169 */
170 getPreviousItem: function () {
171 var innerItems = this.getInnerItems();
172 return innerItems[innerItems.length - 2];
173 },
174 /**
175 * 更新导航栏标题栏 {@link #navigationBar}
176 * @private
177 */
178 updateUseTitleForBackButtonText: function (useTitleForBackButtonText) {
179 var navigationBar = this.getNavigationBar();
180 if (navigationBar) {
181 navigationBar.setUseTitleForBackButtonText(useTitleForBackButtonText);
182 }
183 },
184 /**
185 * 更新后退按钮显示值 {@link #navigationBar}
186 * @private
187 */
188 updateDefaultBackButtonText: function (defaultBackButtonText) {
189 var navigationBar = this.getNavigationBar();
190 if (navigationBar) {
191 navigationBar.setDefaultBackButtonText(defaultBackButtonText);
192 }
193 },
194 // @private 初始化时添加导航栏
195 applyNavigationBar: function (config) {
196 if (!config) {
197 config = {
198 hidden: true,
199 docked: 'top'
200 };
201 }
202
203 if (config.title) {
204 delete config.title;
205 //<debug>
206 Ext.Logger.warn("Ext.navigation.View: The 'navigationBar' configuration does not accept a 'title' property. You " +
207 "set the title of the navigationBar by giving this navigation view's children a 'title' property.");
208 //</debug>
209 }
210
211 config.view = this;
212 config.useTitleForBackButtonText = this.getUseTitleForBackButtonText();
213
214 return Ext.factory(config, Ext.navigation.Bar, this.getNavigationBar());
215 },
216 // @private 更新导航栏
217 updateNavigationBar: function (newNavigationBar, oldNavigationBar) {
218 if (oldNavigationBar) {
219 this.remove(oldNavigationBar, true);
220 }
221
222 if (newNavigationBar) {
223 this.add(newNavigationBar);
224 }
225 },
226 /**
227 * @private
228 */
229 applyActiveItem: function (activeItem, currentActiveItem) {
230 var me = this,
231 innerItems = me.getInnerItems();
232
233 // 确保已经初始化
234 me.getItems();
235
236 // 如果没有初始化,将堆栈中最后一项设置为活动
237 if (!me.initialized) {
238 activeItem = innerItems.length - 1;
239 }
240
241 return this.callParent([activeItem, currentActiveItem]);
242 },
243 doResetActiveItem: function (innerIndex) {
244 var me = this,
245 innerItems = me.getInnerItems(),
246 animation = me.getLayout().getAnimation();
247
248 if (innerIndex > 0) {
249 if (animation && animation.isAnimation) {
250 animation.setReverse(true);
251 }
252 me.setActiveItem(innerIndex - 1);
253 me.getNavigationBar().onViewRemove(me, innerItems[innerIndex], innerIndex);
254 }
255 },
256 /**
257 * @private
258 *执行移除项,调用remove方法后自动执行
259 */
260 doRemove: function () {
261 var animation = this.getLayout().getAnimation();
262
263 if (animation && animation.isAnimation) {
264 animation.setReverse(false);
265 }
266
267 this.callParent(arguments);
268 },
269 /**
270 * @private
271 *执行添加项,调用add方法后自动执行
272 */
273 onItemAdd: function (item, index) {
274 this.doItemLayoutAdd(item, index);
275
276 if (!this.isItemsInitializing && item.isInnerItem()) {
277 this.setActiveItem(item);
278 this.getNavigationBar().onViewAdd(this, item, index);
279 }
280
281 if (this.initialized) {
282 this.fireEvent('add', this, item, index);
283 }
284 },
285 /**
286 * 移除第一项和最后项之间的所有项(包括最后项)
287 * @return {Ext.Component} 当前活动视图
288 */
289 reset: function () {
290 return this.pop(this.getInnerItems().length);
291 }
292 });