ExtJs4.2 Web DeskTop 改进
ExtJs 自带示例确实很好,从中也学到了很多东西,个人感觉为适合我们在真正项目中的使用,还有几个地方需修改的
1、Js文件较多,写的很复杂,对于不是很熟悉Extjs的人员,修改很麻烦,如果代码看不明白,我是不敢轻易用在项目里,万一出问题,老板让修改就麻烦了
2、一次把所有不是WebDesktop需要的Js也加载进来了
3、没有动态生成桌面图标,菜单功能
4、桌面图标不能换行
根据以上问题,基于示例,我重写了WebDesktop,所有参数、动态生成项目都集中在了Desktop.js文件,项目其他调用的Js文件 后期动态加载,提高了访问速度;
文件结构

只用了7个Js,代码按我们习惯的方式编写,大家更容易明白和修改
desktop.html 文件,只加载桌面Js,所有快捷方式调用的功能Js后期按需加载
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml" > 3 <head> 4 <title></title> 5 <link rel="stylesheet" type="text/css" href="css/desktop.css" /> 6 <link href="../Resources/ext-4.2.1.883/resources/css/ext-all.css" rel="Stylesheet" /> 7 <script type="text/javascript" src="../Resources/ext-4.2.1.883/bootstrap.js"></script> 8 <script type="text/javascript" src="../Resources/ext-4.2.1.883/locale/ext-lang-zh_CN.js"></script> 9 <script type="text/javascript" src="StartMenu.js"></script> 10 <script type="text/javascript" src="TaskBar.js"></script> 11 <script type="text/javascript" src="Wallpaper.js"></script> 12 <script type="text/javascript" src="Desktop.js"></script> 13 <script type="text/javascript" src="ShortcutModel.js"></script> 14 <script type="text/javascript" src="Settings.js"></script> 15 <script type="text/javascript" src="WallpaperModel.js"></script> 16 <script type="text/javascript"> 17 Ext.Loader.setPath('MyDesktop',''); 18 Ext.onReady(function() { 19 var Menu = Ext.create('Ext.ux.desktop.Desktop'); 20 viewport = new Ext.container.Viewport({ 21 layout: 'fit', 22 items: [Menu] 23 }); 24 }); 25 </script> 26 </head> 27 <body> 28 </body> 29 </html>
desktop.js 主文件 需动态生成的桌面快捷方式和菜单 只要修改initComponent函数就可以了
1 Ext.define('Ext.ux.desktop.Desktop', { 2 extend: 'Ext.panel.Panel', 3 alias: 'widget.desktop', 4 uses: [ 5 'Ext.util.MixedCollection', 6 'Ext.menu.Menu', 7 'Ext.view.View', // dataview 8 'Ext.window.Window', 9 'Ext.ux.desktop.TaskBar', 10 'Ext.ux.desktop.Wallpaper', 11 'Ext.ux.desktop.ShortcutModel' 12 ], 13 activeWindowCls: 'ux-desktop-active-win', 14 inactiveWindowCls: 'ux-desktop-inactive-win', 15 lastActiveWindow: null, 16 border: false, 17 html: ' ', 18 layout: 'fit', 19 xTickSize: 1, 20 yTickSize: 1, 21 shortcuts: null, //桌面快捷方式Store 22 shortcutItemSelector: 'div.ux-desktop-shortcut', 23 menupnlItemSelector: 'div.ux-menupnl-shortcut', 24 shortcutTpl: [ 25 '<tpl for=".">', 26 '<div class="ux-desktop-shortcut" id="{name}-shortcut">', 27 '<div class="ux-desktop-shortcut-icon {iconCls}">', 28 '<img src="', Ext.BLANK_IMAGE_URL, '" title="{name}">', 29 '</div>', 30 '<span class="ux-desktop-shortcut-text">{name}</span>', 31 '</div>', 32 '</tpl>', 33 '<div class="x-clear"></div>' 34 ], 35 windowMenu: null, //任务栏右键菜单 36 initComponent: function() { 37 var me = this; 38 me.bbar = me.taskbar = new Ext.ux.desktop.TaskBar(); 39 me.taskbar.startMenu.menu.on('mouseover', function(menu, item, e, eOpts) { 40 if (item == null) return; 41 me.showMenuChildItem(item.text); 42 }); 43 me.taskbar.quickStart.add([{ name: 'Accordion Window', iconCls: 'accordion', handler: Ext.bind(me.tileWindows, me) }, 44 { name: 'Cascade Window', iconCls: 'icon-grid', handler: Ext.bind(me.cascadeWindows, me) }, 45 { name: 'Show Desktop', iconCls: 'showdesktop', handler: Ext.bind(me.showDesktop, me) } 46 ]); 47 48 me.windowMenu = Ext.create('Ext.menu.Menu', { 49 defaultAlign: 'br-tr', 50 items: [ 51 { text: '还原', handler: me.onWindowMenuRestore, scope: me }, 52 { text: '最小化', handler: me.onWindowMenuMinimize, scope: me }, 53 { text: '最大化', handler: me.onWindowMenuMaximize, scope: me }, 54 '-', 55 { text: 'Close', handler: me.onWindowMenuClose, scope: me } 56 ], 57 listeners: { 58 beforeshow: me.onWindowMenuBeforeShow, 59 hide: me.onWindowMenuHide, 60 scope: me 61 } 62 }); 63 me.taskbar.windowMenu = me.windowMenu; 64 me.windows = new Ext.util.MixedCollection(); //所有显示窗体列表 65 me.contextMenu = Ext.create('Ext.menu.Menu', { //桌面右键菜单 66 items: [ 67 { text: '桌面设置', iconCls: 'showdesktop', handler: me.onSettings, scope: me }, 68 '-', 69 { text: '平铺', iconCls: 'accordion', handler: me.tileWindows, scope: me, minWindows: 1 }, 70 { text: '层叠', iconCls: 'icon-grid', handler: me.cascadeWindows, scope: me, minWindows: 1 } 71 ] 72 }); 73 me.shortcuts = Ext.create('Ext.data.Store', { //桌面图标初始化(在这里后台动态生成) 74 model: 'Ext.ux.desktop.ShortcutModel', 75 data: [ 76 { name: 'Grid Window', iconCls: 'grid-shortcut', module: 'MyDesktop.GridWindow' }, 77 { name: 'Accordion Window', iconCls: 'accordion-shortcut', module: 'MyDesktop.TabWindow' }, 78 { name: 'Notepad', iconCls: 'notepad-shortcut', module: 'MyDesktop.GridWindow' }, 79 { name: 'System Status', iconCls: 'cpu-shortcut', module: 'MyDesktop.TabWindow' } 80 ] 81 }) 82 83 84 me.menus = Ext.create('Ext.data.Store', { //菜单结构初始化(在这里后台动态生成) 85 model: 'Ext.ux.desktop.MenuModel', 86 data: [ 87 { name: 'Grid Window', iconCls: 'grid-shortcut', getChildMenu: [{ name: '表格表格', iconCls: 'accordion-shortcut', module: 'MyDesktop.TabWindow' }, { name: 'Accordion Window', iconCls: 'grid-shortcut', module: 'MyDesktop.TabWindow' }, { name: 'Accordion Window1', iconCls: 'grid-shortcut', module: 'MyDesktop.GridWindow'}] }, 88 { name: 'Accordion Window', iconCls: 'accordion-shortcut', getChildMenu: [{ name: 'Accordion Window', iconCls: 'grid-shortcut', module: 'MyDesktop.GridWindow'}] }, 89 { name: 'Notepad', iconCls: 'notepad-shortcut', getChildMenu: [{ name: 'Notepad', iconCls: 'notepad-shortcut', module: 'MyDesktop.TabWindow'}] }, 90 { name: 'System Status', iconCls: 'cpu-shortcut', getChildMenu: [{ name: 'System Status', iconCls: 'cpu-shortcut', module: 'MyDesktop.GridWindow'}] } 91 ] 92 }) 93 me.insertStartMenu(); 94 me.insertStartPnlTool(); 95 me.items = [ 96 { xtype: 'wallpaper', id: me.id + '_wallpaper' }, 97 me.createDataView() 98 ]; 99 me.callParent(); 100 me.shortcutsView = me.items.getAt(1); 101 me.shortcutsView.on('itemclick', me.onShortcutItemClick, me); 102 103 var wallpaper = 'wallpapers/Blue-Sencha.jpg'; // me.wallpaper; 104 me.wallpaper = me.items.getAt(0); 105 if (wallpaper) { 106 me.setWallpaper(wallpaper, me.wallpaperStretch); 107 } 108 }, 109 110 afterRender: function() { 111 var me = this; 112 me.callParent(); 113 me.el.on('contextmenu', me.onDesktopMenu, me); 114 Ext.Function.defer(me.initShortcut, 1); 115 }, 116 117 //------------------------------------------------------ 118 // Overrideable configuration creation methods 119 120 createDataView: function() { 121 var me = this; 122 return { 123 xtype: 'dataview', 124 overItemCls: 'x-view-over', 125 trackOver: true, 126 itemSelector: me.shortcutItemSelector, 127 store: me.shortcuts, 128 style: { 129 position: 'absolute' 130 }, 131 x: 0, y: 0, 132 listeners: { 133 resize: me.initShortcut 134 }, 135 tpl: new Ext.XTemplate(me.shortcutTpl) 136 }; 137 }, 138 //处理桌面图标自动换行问题 139 initShortcut: function() { 140 var btnHeight = 64; 141 var btnWidth = 64; 142 var btnPadding = 30; 143 var col = { index: 1, x: btnPadding }; 144 var row = { index: 1, y: btnPadding }; 145 var bottom; 146 var numberOfItems = 0; 147 var taskBarHeight = Ext.query(".ux-taskbar")[0].clientHeight + 40; 148 var bodyHeight = Ext.getBody().getHeight() - taskBarHeight; 149 var items = Ext.query(".ux-desktop-shortcut"); 150 151 for (var i = 0, len = items.length; i < len; i++) { 152 numberOfItems += 1; 153 bottom = row.y + btnHeight; 154 if (((bodyHeight < bottom) ? true : false) && bottom > (btnHeight + btnPadding)) { 155 numberOfItems = 0; 156 col = { index: col.index++, x: col.x + btnWidth + btnPadding }; 157 row = { index: 1, y: btnPadding }; 158 } 159 Ext.fly(items[i]).setXY([col.x, row.y]); 160 row.index++; 161 row.y = row.y + btnHeight + btnPadding; 162 } 163 }, 164 //------------------------------------------------------ 165 // Event handler methods 166 //桌面右键事件 167 onDesktopMenu: function(e) { 168 var me = this, menu = me.contextMenu; 169 e.stopEvent(); 170 if (!menu.rendered) { 171 menu.on('beforeshow', me.onDesktopMenuBeforeShow, me); 172 } 173 menu.showAt(e.getXY()); 174 menu.doConstrain(); 175 }, 176 //桌面右键菜单显示前事件 177 onDesktopMenuBeforeShow: function(menu) { 178 var me = this, count = me.windows.getCount(); 179 180 menu.items.each(function(item) { 181 var min = item.minWindows || 0; 182 item.setDisabled(count < min); 183 }); 184 }, 185 //点击桌面快捷方式事件 186 onShortcutItemClick: function(dataView, record) { 187 var me = this; 188 me.ShowWindow(record.data.module); 189 }, 190 ShowWindow: function(wincls) { 191 var me = this; 192 var windowid = 'windows-' + wincls; 193 var win = me.getWindow(windowid); 194 if (!win) { //不存在 195 Ext.require(wincls, function() { 196 var mw = Ext.create(wincls); 197 win = mw.createWindow(); 198 stateful: false; 199 me.add(win); 200 win.isWindow = true; 201 win.constrainHeader = true; 202 win.minimizable = true; 203 win.maximizable = true; 204 win.id = windowid; 205 me.windows.add(win); 206 win.taskButton = me.taskbar.addTaskButton(win); 207 win.animateTarget = win.taskButton.el; 208 win.on({ 209 activate: me.updateActiveWindow, 210 beforeshow: me.updateActiveWindow, 211 deactivate: me.updateActiveWindow, 212 minimize: me.minimizeWindow, 213 destroy: me.onWindowClose, 214 scope: me 215 }); 216 217 win.on({ 218 boxready: function() { 219 win.dd.xTickSize = me.xTickSize; 220 win.dd.yTickSize = me.yTickSize; 221 if (win.resizer) { 222 win.resizer.widthIncrement = me.xTickSize; 223 win.resizer.heightIncrement = me.yTickSize; 224 } 225 }, 226 single: true 227 }); 228 229 // replace normal window close w/fadeOut animation: 230 win.doClose = function() { 231 win.doClose = Ext.emptyFn; // dblclick can call again... 232 win.el.disableShadow(); 233 win.el.fadeOut({ 234 listeners: { 235 afteranimate: function() { 236 win.destroy(); 237 } 238 } 239 }); 240 }; 241 me.restoreWindow(win); 242 }); 243 } 244 else { 245 me.restoreWindow(win); 246 } 247 }, 248 insertStartPnlTool: function() { 249 var me = this; 250 me.StartPnlTool = Ext.create('Ext.toolbar.Toolbar', { 251 dock: 'bottom', 252 items: ['->', { text: '修改密码', iconCls: 'accordion', handler: Ext.bind(me.onSystemFunClick, me, ['修改密码']) }, 253 { text: '帮助', iconCls: 'settings', handler: Ext.bind(me.onSystemFunClick, me, ['帮助']) }, 254 { text: '退出', iconCls: 'logout', handler: Ext.bind(me.onSystemFunClick, me, ['退出']) } 255 ] 256 }); 257 me.taskbar.startMenu.rightpnl.addDocked(me.StartPnlTool, 'bottom'); 258 }, 259 insertStartMenu: function() { 260 var me = this; 261 me.menus.each(function(record) { 262 me.taskbar.startMenu.menu.add([{ text: record.get('name'), iconCls: record.get('iconCls')}]); 263 }); 264 }, 265 showMenuChildItem: function(menu) { 266 var me = this; 267 var iIndex = me.menus.find('name', menu); 268 if (iIndex < 0) return; 269 me.taskbar.startMenu.rightpnl.removeAll(true); 270 var datamodel = me.menus.getAt(iIndex); 271 for (var i = 0; i < datamodel.raw.getChildMenu.length; i++) { 272 var btnhtml = '<div id="' + datamodel.raw.getChildMenu[i].name + '-menupnl">' + 273 '<div class="ux-start-pnl-icon ' + datamodel.raw.getChildMenu[i].iconCls + '">' + 274 '<img src="' + Ext.BLANK_IMAGE_URL + '" title="' + datamodel.raw.getChildMenu[i].name + '">' + 275 '</div>' + 276 '<span class="ux-start-pnl-text">' + datamodel.raw.getChildMenu[i].name + '</span>' + 277 '</div>' + 278 '<div class="x-clear"></div>'; 279 me.taskbar.startMenu.rightpnl.add({ xtype: 'button', style: { margin: '10px', padding: '4px' }, title: datamodel.raw.getChildMenu[i].name, html: btnhtml, width: 72, height: 72, handler: Ext.bind(me.ShowWindow, me, [datamodel.raw.getChildMenu[i].module]) 280 }); 281 } 282 }, 283 onSystemFunClick: function(fun) { 284 alert(fun); 285 }, 286 onWindowClose: function(win) { 287 var me = this; 288 me.windows.remove(win); 289 me.taskbar.removeTaskButton(win.taskButton); 290 me.updateActiveWindow(); 291 }, 292 293 //------------------------------------------------------ 294 // Window context menu handlers 295 296 onWindowMenuBeforeShow: function(menu) { 297 var items = menu.items.items, win = menu.theWin; 298 items[0].setDisabled(win.maximized !== true && win.hidden !== true); // Restore 299 items[1].setDisabled(win.minimized === true); // Minimize 300 items[2].setDisabled(win.maximized === true || win.hidden === true); // Maximize 301 }, 302 303 onWindowMenuClose: function() { 304 var me = this, win = me.windowMenu.theWin; 305 win.close(); 306 }, 307 308 onWindowMenuHide: function(menu) { 309 Ext.defer(function() { 310 menu.theWin = null; 311 }, 1); 312 }, 313 314 onWindowMenuMaximize: function() { 315 var me = this, win = me.windowMenu.theWin; 316 win.maximize(); 317 win.toFront(); 318 }, 319 320 onWindowMenuMinimize: function() { 321 var me = this, win = me.windowMenu.theWin; 322 win.minimize(); 323 }, 324 325 onWindowMenuRestore: function() { 326 var me = this, win = me.windowMenu.theWin; 327 me.restoreWindow(win); 328 }, 329 onSettings: function() { 330 var dlg = new MyDesktop.Settings({ 331 desktop: this 332 }); 333 dlg.show(); 334 }, 335 //------------------------------------------------------ 336 // Dynamic (re)configuration methods 337 338 getWallpaper: function() { 339 return this.wallpaper.wallpaper; 340 }, 341 342 setTickSize: function(xTickSize, yTickSize) { 343 var me = this, 344 xt = me.xTickSize = xTickSize, 345 yt = me.yTickSize = (arguments.length > 1) ? yTickSize : xt; 346 347 me.windows.each(function(win) { 348 var dd = win.dd, resizer = win.resizer; 349 dd.xTickSize = xt; 350 dd.yTickSize = yt; 351 resizer.widthIncrement = xt; 352 resizer.heightIncrement = yt; 353 }); 354 }, 355 356 setWallpaper: function(wallpaper, stretch) { 357 this.wallpaper.setWallpaper(wallpaper, stretch); 358 return this; 359 }, 360 361 //------------------------------------------------------ 362 // Window management methods 363 364 cascadeWindows: function() { 365 if (this.windows.getCount() <= 0) return; 366 var x = 0, y = 0, 367 zmgr = this.getDesktopZIndexManager(); 368 369 zmgr.eachBottomUp(function(win) { 370 if (win.isWindow && win.isVisible() && !win.maximized) { 371 win.setPosition(x, y); 372 x += 20; 373 y += 20; 374 } 375 }); 376 }, 377 getActiveWindow: function() { 378 var win = null, 379 zmgr = this.getDesktopZIndexManager(); 380 381 if (zmgr) { 382 // We cannot rely on activate/deactive because that fires against non-Window 383 // components in the stack. 384 385 zmgr.eachTopDown(function(comp) { 386 if (comp.isWindow && !comp.hidden) { 387 win = comp; 388 return false; 389 } 390 return true; 391 }); 392 } 393 394 return win; 395 }, 396 397 getDesktopZIndexManager: function() { 398 var windows = this.windows; 399 // TODO - there has to be a better way to get this... 400 return (windows.getCount() && windows.getAt(0).zIndexManager) || null; 401 }, 402 403 getWindow: function(id) { 404 return this.windows.get(id); 405 }, 406 407 minimizeWindow: function(win) { 408 win.minimized = true; 409 win.hide(); 410 }, 411 412 restoreWindow: function(win) { 413 if (win.isVisible()) { 414 win.restore(); 415 win.toFront(); 416 } else { 417 win.show(); 418 } 419 return win; 420 }, 421 422 tileWindows: function() { 423 var me = this, availWidth = me.body.getWidth(true); 424 var x = me.xTickSize, y = me.yTickSize, nextY = y; 425 426 me.windows.each(function(win) { 427 if (win.isVisible() && !win.maximized) { 428 var w = win.el.getWidth(); 429 430 // Wrap to next row if we are not at the line start and this Window will 431 // go off the end 432 if (x > me.xTickSize && x + w > availWidth) { 433 x = me.xTickSize; 434 y = nextY; 435 } 436 437 win.setPosition(x, y); 438 x += w + me.xTickSize; 439 nextY = Math.max(nextY, y + win.el.getHeight() + me.yTickSize); 440 } 441 }); 442 }, 443 showDesktop: function() { 444 var me = this; 445 me.windows.each(function(win) { 446 if (win.isVisible()) { 447 win.minimize(); 448 } 449 }); 450 }, 451 updateActiveWindow: function() { 452 var me = this, activeWindow = me.getActiveWindow(), last = me.lastActiveWindow; 453 if (activeWindow === last) { 454 return; 455 } 456 457 if (last) { 458 if (last.el.dom) { 459 last.addCls(me.inactiveWindowCls); 460 last.removeCls(me.activeWindowCls); 461 } 462 last.active = false; 463 } 464 465 me.lastActiveWindow = activeWindow; 466 467 if (activeWindow) { 468 activeWindow.addCls(me.activeWindowCls); 469 activeWindow.removeCls(me.inactiveWindowCls); 470 activeWindow.minimized = false; 471 activeWindow.active = true; 472 } 473 me.taskbar.setActiveButton(activeWindow && activeWindow.taskButton); 474 } 475 });
ShortcutModel.js 数据模型增加二级菜单Model 使用了一对多关系
1 Ext.define('Ext.ux.desktop.ShortcutModel', { 2 extend: 'Ext.data.Model', 3 fields: [ 4 { name: 'name' }, 5 { name: 'iconCls' }, 6 { name: 'module' } 7 ] 8 }); 9 Ext.define('Ext.ux.desktop.MenuModel', { 10 extend: 'Ext.data.Model', 11 fields: [ 12 { name: 'name' }, 13 { name: 'iconCls' } 14 ], 15 hasMany: { model: 'Ext.ux.desktop.MenuChildModel', name: 'getChildMenu', autoLoad: false } 16 }); 17 Ext.define('Ext.ux.desktop.MenuChildModel', { 18 extend: 'Ext.data.Model', 19 fields: [ 20 { name: 'name' }, 21 { name: 'iconCls' }, 22 { name: 'module' } 23 ], 24 belongsTo: 'Ext.ux.desktop.ShortcutModel' 25 });
TaskBar.js 文件
1 Ext.define('Ext.ux.desktop.TaskBar', { 2 extend: 'Ext.toolbar.Toolbar', 3 requires: [ 4 'Ext.button.Button', 5 'Ext.resizer.Splitter', 6 'Ext.menu.Menu', 7 'Ext.ux.desktop.StartMenu' 8 ], 9 alias: 'widget.taskbar', 10 cls: 'ux-taskbar', 11 startBtnText: 'Start', 12 startMenu:null, 13 initComponent: function() { 14 var me = this; 15 me.startMenu = new Ext.ux.desktop.StartMenu(); 16 17 me.quickStart = Ext.create('Ext.toolbar.Toolbar'); 18 19 me.windowBar = Ext.create('Ext.toolbar.Toolbar', { 20 flex: 1, 21 cls: 'ux-desktop-windowbar', 22 items: [' '], 23 layout: { overflowHandler: 'Scroller' } 24 }); 25 26 me.tray = Ext.create('Ext.toolbar.Toolbar', { 27 items: [{ xtype: 'trayclock', flex: 1}] 28 }); 29 30 me.items = [ 31 { 32 xtype: 'button', 33 cls: 'ux-start-button', 34 iconCls: 'ux-start-button-icon', 35 menu: me.startMenu, 36 menuAlign: 'bl-tl', 37 text: me.startBtnText 38 }, 39 me.quickStart, 40 { 41 xtype: 'splitter', html: ' ', 42 height: 14, width: 2, // TODO - there should be a CSS way here 43 cls: 'x-toolbar-separator x-toolbar-separator-horizontal' 44 }, 45 me.windowBar, 46 '-', 47 me.tray 48 ]; 49 50 me.callParent(); 51 }, 52 53 afterLayout: function() { 54 var me = this; 55 me.callParent(); 56 me.windowBar.el.on('contextmenu', me.onButtonContextMenu, me); 57 }, 58 getWindowBtnFromEl: function(el) { 59 var c = this.windowBar.getChildByElement(el); 60 return c || null; 61 }, 62 onQuickStartClick: function(btn) { 63 var module = this.app.getModule(btn.module), 64 window; 65 66 if (module) { 67 window = module.createWindow(); 68 window.show(); 69 } 70 }, 71 72 onButtonContextMenu: function(e) { 73 var me = this; 74 var t = e.getTarget(); 75 var btn = me.getWindowBtnFromEl(t); 76 if (btn) { 77 e.stopEvent(); 78 me.windowMenu.theWin = btn.win; 79 me.windowMenu.showBy(t); 80 } 81 }, 82 83 onWindowBtnClick: function(btn) { 84 var win = btn.win; 85 86 if (win.minimized || win.hidden) { 87 btn.disable(); 88 win.show(null, function() { 89 btn.enable(); 90 }); 91 } else if (win.active) { 92 btn.disable(); 93 win.on('hide', function() { 94 btn.enable(); 95 }, null, { single: true }); 96 win.minimize(); 97 } else { 98 win.toFront(); 99 } 100 }, 101 102 addTaskButton: function(win) { 103 var config = { 104 iconCls: win.iconCls, 105 enableToggle: true, 106 toggleGroup: 'all', 107 width: 140, 108 margins: '0 2 0 3', 109 text: Ext.util.Format.ellipsis(win.title, 20), 110 listeners: { 111 click: this.onWindowBtnClick, 112 scope: this 113 }, 114 win: win 115 }; 116 117 var cmp = this.windowBar.add(config); 118 cmp.toggle(true); 119 return cmp; 120 }, 121 122 removeTaskButton: function(btn) { 123 var found, me = this; 124 me.windowBar.items.each(function(item) { 125 if (item === btn) { 126 found = item; 127 } 128 return !found; 129 }); 130 if (found) { 131 me.windowBar.remove(found); 132 } 133 return found; 134 }, 135 136 setActiveButton: function(btn) { 137 if (btn) { 138 btn.toggle(true); 139 } else { 140 this.windowBar.items.each(function(item) { 141 if (item.isButton) { 142 item.toggle(false); 143 } 144 }); 145 } 146 } 147 }); 148 149 /** 150 * @class Ext.ux.desktop.TrayClock 151 * @extends Ext.toolbar.TextItem 152 * This class displays a clock on the toolbar. 153 */ 154 Ext.define('Ext.ux.desktop.TrayClock', { 155 extend: 'Ext.toolbar.TextItem', 156 157 alias: 'widget.trayclock', 158 159 cls: 'ux-desktop-trayclock', 160 161 html: ' ', 162 163 timeFormat: 'g:i A', 164 165 tpl: '{time}', 166 167 initComponent: function() { 168 var me = this; 169 170 me.callParent(); 171 172 if (typeof (me.tpl) == 'string') { 173 me.tpl = new Ext.XTemplate(me.tpl); 174 } 175 }, 176 177 afterRender: function() { 178 var me = this; 179 Ext.Function.defer(me.updateTime, 100, me); 180 me.callParent(); 181 }, 182 183 onDestroy: function() { 184 var me = this; 185 186 if (me.timer) { 187 window.clearTimeout(me.timer); 188 me.timer = null; 189 } 190 191 me.callParent(); 192 }, 193 194 updateTime: function() { 195 var me = this, time = Ext.Date.format(new Date(), me.timeFormat), 196 text = me.tpl.apply({ time: time }); 197 if (me.lastText != text) { 198 me.setText(text); 199 me.lastText = text; 200 } 201 me.timer = Ext.Function.defer(me.updateTime, 10000, me); 202 } 203 });
StartMenu.js 文件 增加了动态显示子菜单Panel的功能
1 Ext.define('Ext.ux.desktop.StartMenu', { 2 extend: 'Ext.panel.Panel', 3 requires: [ 4 'Ext.menu.Menu', 5 'Ext.toolbar.Toolbar' 6 ], 7 ariaRole: 'menu', 8 cls: 'x-menu ux-start-menu', 9 defaultAlign: 'bl-tl', 10 iconCls: 'ux-start-button-icon', 11 title:'菜单', 12 floating: true, 13 shadow: true, 14 width: 500, 15 height: 300, 16 initComponent: function() { 17 var me = this; 18 menu = me.menu; 19 me.menu = new Ext.menu.Menu({ 20 cls: 'ux-start-menu-body', 21 border: false, 22 floating: false 23 }); 24 me.items = [me.menu]; 25 me.menu.layout.align = 'stretch'; 26 me.layout = 'fit'; 27 28 Ext.menu.Manager.register(me); 29 me.callParent(); 30 me.rightpnl = Ext.create('Ext.panel.Panel', { 31 dock: 'right', 32 width: 400 33 }); 34 me.rightpnl.layout.align = 'stretch'; 35 me.addDocked(me.rightpnl); 36 } 37 });
看下最终效果图吧

鼠标移动的那个菜单,动态显示该菜单下的二级功能

点击菜单或桌面快捷方式 弹出的windows 都是后期按需自动加载,解决了原示例的一次加载所有js的问题
演示地址:http://223.82.210.220:1980/WebDesktop/DesktopEx/desktop.html
通过调试器,可以看到TabWindow.js 和GridWindow.js 都是在需要时动态加载的
浙公网安备 33010602011771号