svn: /web/doc-editor/trunk/js/ux/ extjsPowered/.directory extjsPowered/RowEditor.css extjsPowered/RowEditor.js extjsPowered/StatusBar.css extjsPowered/StatusBar.js extjsPowered/TabCloseMenu.js
[email protected] (Yannick Torres)
| Newsgroups | php.doc.web |
|---|---|
| Message-ID | <[email protected]> |
yannick Sat, 19 Dec 2009 09:39:39 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=292318
Log:
Migration ExtJs 3.0 : Reorder Ux powered by ExtJs team
Changed paths:
A web/doc-editor/trunk/js/ux/extjsPowered/
A web/doc-editor/trunk/js/ux/extjsPowered/.directory
A web/doc-editor/trunk/js/ux/extjsPowered/RowEditor.css
A web/doc-editor/trunk/js/ux/extjsPowered/RowEditor.js
A web/doc-editor/trunk/js/ux/extjsPowered/StatusBar.css
A web/doc-editor/trunk/js/ux/extjsPowered/StatusBar.js
A web/doc-editor/trunk/js/ux/extjsPowered/TabCloseMenu.js
svn-diffs-292318.txt
(text/x-diff, 39.7 KB)
Added: web/doc-editor/trunk/js/ux/extjsPowered/.directory =================================================================== --- web/doc-editor/trunk/js/ux/extjsPowered/.directory (rev 0) +++ web/doc-editor/trunk/js/ux/extjsPowered/.directory 2009-12-19 09:39:39 UTC (rev 292318) @@ -0,0 +1,6 @@ +[Dolphin] +Timestamp=2009,12,19,9,5,49 +ViewMode=1 + +[Settings] +ShowDotFiles=true Added: web/doc-editor/trunk/js/ux/extjsPowered/RowEditor.css =================================================================== --- web/doc-editor/trunk/js/ux/extjsPowered/RowEditor.css (rev 0) +++ web/doc-editor/trunk/js/ux/extjsPowered/RowEditor.css 2009-12-19 09:39:39 UTC (rev 292318) @@ -0,0 +1,52 @@ +/*! + * Ext JS Library 3.0.0 + * Copyright(c) 2006-2009 Ext JS, LLC + * [email protected] + * http://www.extjs.com/license + */ +.ext-ie .x-row-editor .x-form-text { + margin:0 !important; +} +.x-row-editor-header { + height:2px; + overflow:hidden; + background: transparent url(../images/row-editor-bg.gif) repeat-x 0 0; +} +.x-row-editor-footer { + height:2px; + overflow:hidden; + background: transparent url(../images/row-editor-bg.gif) repeat-x 0 -2px; +} +.ext-ie .x-row-editor-footer { + margin-top:-1px; +} + +.x-row-editor-body { + overflow:hidden; + zoom:1; + background: #ebf2fb; + padding-top:2px; +} +.x-row-editor .x-btns { + position:absolute; + top:28px; + left:20px; + padding-left:5px; + background: transparent url(../images/row-editor-btns.gif) no-repeat 0 0; +} +.x-row-editor .x-btns .x-plain-bwrap { + padding-right:5px; + background: transparent url(../images/row-editor-btns.gif) no-repeat right -31px; +} +.x-row-editor .x-btns .x-plain-body { + background: transparent url(../images/row-editor-btns.gif) repeat-x 0 -62px; + height:31px; +} +.x-row-editor .x-btns .x-table-layout-cell { + padding:3px; +} + +.errorTip .x-tip-body ul{ + list-style-type:disc; + margin-left:15px; +} Added: web/doc-editor/trunk/js/ux/extjsPowered/RowEditor.js =================================================================== --- web/doc-editor/trunk/js/ux/extjsPowered/RowEditor.js (rev 0) +++ web/doc-editor/trunk/js/ux/extjsPowered/RowEditor.js 2009-12-19 09:39:39 UTC (rev 292318) @@ -0,0 +1,521 @@ +/*! + * Ext JS Library 3.0.0 + * Copyright(c) 2006-2009 Ext JS, LLC + * [email protected] + * http://www.extjs.com/license + */ +Ext.ns('Ext.ux.grid'); + +/** + * @class Ext.ux.grid.RowEditor + * @extends Ext.Panel + * Plugin (ptype = 'roweditor') that adds the ability to rapidly edit full rows in a grid. + * A validation mode may be enabled which uses AnchorTips to notify the user of all + * validation errors at once. + * + * @ptype roweditor + */ +Ext.ux.grid.RowEditor = Ext.extend(Ext.Panel, { + floating: true, + shadow: false, + layout: 'hbox', + cls: 'x-small-editor', + buttonAlign: 'center', + baseCls: 'x-row-editor', + elements: 'header,footer,body', + frameWidth: 5, + buttonPad: 3, + clicksToEdit: 'auto', + monitorValid: true, + focusDelay: 250, + errorSummary: true, + + defaults: { + normalWidth: true + }, + + initComponent: function(){ + Ext.ux.grid.RowEditor.superclass.initComponent.call(this); + this.addEvents( + /** + * @event beforeedit + * Fired before the row editor is activated. + * If the listener returns <tt>false</tt> the editor will not be activated. + * @param {Ext.ux.grid.RowEditor} roweditor This object + * @param {Number} rowIndex The rowIndex of the row just edited + */ + 'beforeedit', + /** + * @event validateedit + * Fired after a row is edited and passes validation. + * If the listener returns <tt>false</tt> changes to the record will not be set. + * @param {Ext.ux.grid.RowEditor} roweditor This object + * @param {Object} changes Object with changes made to the record. + * @param {Ext.data.Record} r The Record that was edited. + * @param {Number} rowIndex The rowIndex of the row just edited + */ + 'validateedit', + /** + * @event afteredit + * Fired after a row is edited and passes validation. This event is fired + * after the store's update event is fired with this edit. + * @param {Ext.ux.grid.RowEditor} roweditor This object + * @param {Object} changes Object with changes made to the record. + * @param {Ext.data.Record} r The Record that was edited. + * @param {Number} rowIndex The rowIndex of the row just edited + */ + 'afteredit' + ); + }, + + init: function(grid){ + this.grid = grid; + this.ownerCt = grid; + if(this.clicksToEdit === 2){ + grid.on('rowdblclick', this.onRowDblClick, this); + }else{ + grid.on('rowclick', this.onRowClick, this); + if(Ext.isIE){ + grid.on('rowdblclick', this.onRowDblClick, this); + } + } + + // stopEditing without saving when a record is removed from Store. + grid.getStore().on('remove', function() { + this.stopEditing(false); + },this); + + grid.on({ + scope: this, + keydown: this.onGridKey, + columnresize: this.verifyLayout, + columnmove: this.refreshFields, + reconfigure: this.refreshFields, + destroy : this.destroy, + bodyscroll: { + buffer: 250, + fn: this.positionButtons + } + }); + grid.getColumnModel().on('hiddenchange', this.verifyLayout, this, {delay:1}); + grid.getView().on('refresh', this.stopEditing.createDelegate(this, [])); + }, + + refreshFields: function(){ + this.initFields(); + this.verifyLayout(); + }, + + isDirty: function(){ + var dirty; + this.items.each(function(f){ + if(String(this.values[f.id]) !== String(f.getValue())){ + dirty = true; + return false; + } + }, this); + return dirty; + }, + + startEditing: function(rowIndex, doFocus){ + if(this.editing && this.isDirty()){ + this.showTooltip('You need to commit or cancel your changes'); + return; + } + this.editing = true; + if(typeof rowIndex == 'object'){ + rowIndex = this.grid.getStore().indexOf(rowIndex); + } + if(this.fireEvent('beforeedit', this, rowIndex) !== false){ + var g = this.grid, view = g.getView(); + var row = view.getRow(rowIndex); + var record = g.store.getAt(rowIndex); + this.record = record; + this.rowIndex = rowIndex; + this.values = {}; + if(!this.rendered){ + this.render(view.getEditorParent()); + } + var w = Ext.fly(row).getWidth(); + this.setSize(w); + if(!this.initialized){ + this.initFields(); + } + var cm = g.getColumnModel(), fields = this.items.items, f, val; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + val = this.preEditValue(record, cm.getDataIndex(i)); + f = fields[i]; + f.setValue(val); + this.values[f.id] = val || ''; + } + this.verifyLayout(true); + if(!this.isVisible()){ + this.setPagePosition(Ext.fly(row).getXY()); + } else{ + this.el.setXY(Ext.fly(row).getXY(), {duration:0.15}); + } + if(!this.isVisible()){ + this.show().doLayout(); + } + if(doFocus !== false){ + this.doFocus.defer(this.focusDelay, this); + } + } + }, + + stopEditing : function(saveChanges){ + this.editing = false; + if(!this.isVisible()){ + return; + } + if(saveChanges === false || !this.isValid()){ + this.hide(); + return; + } + var changes = {}, r = this.record, hasChange = false; + var cm = this.grid.colModel, fields = this.items.items; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + if(!cm.isHidden(i)){ + var dindex = cm.getDataIndex(i); + if(!Ext.isEmpty(dindex)){ + var oldValue = r.data[dindex]; + var value = this.postEditValue(fields[i].getValue(), oldValue, r, dindex); + if(String(oldValue) !== String(value)){ + changes[dindex] = value; + hasChange = true; + } + } + } + } + if(hasChange && this.fireEvent('validateedit', this, changes, r, this.rowIndex) !== false){ + r.beginEdit(); + for(var k in changes){ + if(changes.hasOwnProperty(k)){ + r.set(k, changes[k]); + } + } + r.endEdit(); + this.fireEvent('afteredit', this, changes, r, this.rowIndex); + } + this.hide(); + }, + + verifyLayout: function(force){ + if(this.el && (this.isVisible() || force === true)){ + var row = this.grid.getView().getRow(this.rowIndex); + this.setSize(Ext.fly(row).getWidth(), Ext.isIE ? Ext.fly(row).getHeight() + (Ext.isBorderBox ? 9 : 0) : undefined); + var cm = this.grid.colModel, fields = this.items.items; + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + if(!cm.isHidden(i)){ + var adjust = 0; + if(i === 0){ + adjust += 0; // outer padding + } + if(i === (len - 1)){ + adjust += 3; // outer padding + } else{ + adjust += 1; + } + fields[i].show(); + fields[i].setWidth(cm.getColumnWidth(i) - adjust); + } else{ + fields[i].hide(); + } + } + this.doLayout(); + this.positionButtons(); + } + }, + + slideHide : function(){ + this.hide(); + }, + + initFields: function(){ + var cm = this.grid.getColumnModel(), pm = Ext.layout.ContainerLayout.prototype.parseMargins; + this.removeAll(false); + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + var c = cm.getColumnAt(i); + var ed = c.getEditor(); + if(!ed){ + ed = c.displayEditor || new Ext.form.DisplayField(); + } + if(i == 0){ + ed.margins = pm('0 1 2 1'); + } else if(i == len - 1){ + ed.margins = pm('0 0 2 1'); + } else{ + ed.margins = pm('0 1 2'); + } + ed.setWidth(cm.getColumnWidth(i)); + ed.column = c; + if(ed.ownerCt !== this){ + ed.on('focus', this.ensureVisible, this); + ed.on('specialkey', this.onKey, this); + } + this.insert(i, ed); + } + this.initialized = true; + }, + + onKey: function(f, e){ + if(e.getKey() === e.ENTER){ + this.stopEditing(true); + e.stopPropagation(); + } + }, + + onGridKey: function(e){ + if(e.getKey() === e.ENTER && !this.isVisible()){ + var r = this.grid.getSelectionModel().getSelected(); + if(r){ + var index = this.grid.store.indexOf(r); + this.startEditing(index); + e.stopPropagation(); + } + } + }, + + ensureVisible: function(editor){ + if(this.isVisible()){ + this.grid.getView().ensureVisible(this.rowIndex, this.grid.colModel.getIndexById(editor.column.id), true); + } + }, + + onRowClick: function(g, rowIndex, e){ + if(this.clicksToEdit == 'auto'){ + var li = this.lastClickIndex; + this.lastClickIndex = rowIndex; + if(li != rowIndex && !this.isVisible()){ + return; + } + } + this.startEditing(rowIndex, false); + this.doFocus.defer(this.focusDelay, this, [e.getPoint()]); + }, + + onRowDblClick: function(g, rowIndex, e){ + this.startEditing(rowIndex, false); + this.doFocus.defer(this.focusDelay, this, [e.getPoint()]); + }, + + onRender: function(){ + Ext.ux.grid.RowEditor.superclass.onRender.apply(this, arguments); + this.el.swallowEvent(['keydown', 'keyup', 'keypress']); + this.btns = new Ext.Panel({ + baseCls: 'x-plain', + cls: 'x-btns', + elements:'body', + layout: 'table', + width: (this.minButtonWidth * 2) + (this.frameWidth * 2) + (this.buttonPad * 4), // width must be specified for IE + items: [{ + ref: 'saveBtn', + itemId: 'saveBtn', + xtype: 'button', + text: this.saveText || 'Save', + width: this.minButtonWidth, + handler: this.stopEditing.createDelegate(this, [true]) + }, { + xtype: 'button', + text: this.cancelText || 'Cancel', + width: this.minButtonWidth, + handler: this.stopEditing.createDelegate(this, [false]) + }] + }); + this.btns.render(this.bwrap); + }, + + afterRender: function(){ + Ext.ux.grid.RowEditor.superclass.afterRender.apply(this, arguments); + this.positionButtons(); + if(this.monitorValid){ + this.startMonitoring(); + } + }, + + onShow: function(){ + if(this.monitorValid){ + this.startMonitoring(); + } + Ext.ux.grid.RowEditor.superclass.onShow.apply(this, arguments); + }, + + onHide: function(){ + Ext.ux.grid.RowEditor.superclass.onHide.apply(this, arguments); + this.stopMonitoring(); + this.grid.getView().focusRow(this.rowIndex); + }, + + positionButtons: function(){ + if(this.btns){ + var h = this.el.dom.clientHeight; + var view = this.grid.getView(); + var scroll = view.scroller.dom.scrollLeft; + var width = view.mainBody.getWidth(); + var bw = this.btns.getWidth(); + this.btns.el.shift({left: (width/2)-(bw/2)+scroll, top: h - 2, stopFx: true, duration:0.2}); + } + }, + + // private + preEditValue : function(r, field){ + var value = r.data[field]; + return this.autoEncode && typeof value === 'string' ? Ext.util.Format.htmlDecode(value) : value; + }, + + // private + postEditValue : function(value, originalValue, r, field){ + return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value; + }, + + doFocus: function(pt){ + if(this.isVisible()){ + var index = 0; + if(pt){ + index = this.getTargetColumnIndex(pt); + } + var cm = this.grid.getColumnModel(); + for(var i = index||0, len = cm.getColumnCount(); i < len; i++){ + var c = cm.getColumnAt(i); + if(!c.hidden && c.getEditor()){ + c.getEditor().focus(); + break; + } + } + } + }, + + getTargetColumnIndex: function(pt){ + var grid = this.grid, v = grid.view; + var x = pt.left; + var cms = grid.colModel.config; + var i = 0, match = false; + for(var len = cms.length, c; c = cms[i]; i++){ + if(!c.hidden){ + if(Ext.fly(v.getHeaderCell(i)).getRegion().right >= x){ + match = i; + break; + } + } + } + return match; + }, + + startMonitoring : function(){ + if(!this.bound && this.monitorValid){ + this.bound = true; + Ext.TaskMgr.start({ + run : this.bindHandler, + interval : this.monitorPoll || 200, + scope: this + }); + } + }, + + stopMonitoring : function(){ + this.bound = false; + if(this.tooltip){ + this.tooltip.hide(); + } + }, + + isValid: function(){ + var valid = true; + this.items.each(function(f){ + if(!f.isValid(true)){ + valid = false; + return false; + } + }); + return valid; + }, + + // private + bindHandler : function(){ + if(!this.bound){ + return false; // stops binding + } + var valid = this.isValid(); + if(!valid && this.errorSummary){ + this.showTooltip(this.getErrorText().join('')); + } + this.btns.saveBtn.setDisabled(!valid); + this.fireEvent('validation', this, valid); + }, + + showTooltip: function(msg){ + var t = this.tooltip; + if(!t){ + t = this.tooltip = new Ext.ToolTip({ + maxWidth: 600, + cls: 'errorTip', + width: 300, + title: 'Errors', + autoHide: false, + anchor: 'left', + anchorToTarget: true, + mouseOffset: [40,0] + }); + } + t.initTarget(this.items.last().getEl()); + if(!t.rendered){ + t.show(); + t.hide(); + } + t.body.update(msg); + t.doAutoWidth(); + t.show(); + }, + + getErrorText: function(){ + var data = ['<ul>']; + this.items.each(function(f){ + if(!f.isValid(true)){ + data.push('<li>', f.activeError, '</li>'); + } + }); + data.push('</ul>'); + return data; + } +}); +Ext.preg('roweditor', Ext.ux.grid.RowEditor); + +Ext.override(Ext.form.Field, { + markInvalid : function(msg){ + if(!this.rendered || this.preventMark){ // not rendered + return; + } + msg = msg || this.invalidText; + + var mt = this.getMessageHandler(); + if(mt){ + mt.mark(this, msg); + }else if(this.msgTarget){ + this.el.addClass(this.invalidClass); + var t = Ext.getDom(this.msgTarget); + if(t){ + t.innerHTML = msg; + t.style.display = this.msgDisplay; + } + } + this.activeError = msg; + this.fireEvent('invalid', this, msg); + } +}); + +Ext.override(Ext.ToolTip, { + doAutoWidth : function(){ + var bw = this.body.getTextWidth(); + if(this.title){ + bw = Math.max(bw, this.header.child('span').getTextWidth(this.title)); + } + bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + 20; + this.setWidth(bw.constrain(this.minWidth, this.maxWidth)); + + // IE7 repaint bug on initial show + if(Ext.isIE7 && !this.repainted){ + this.el.repaint(); + this.repainted = true; + } + } +}); Added: web/doc-editor/trunk/js/ux/extjsPowered/StatusBar.css =================================================================== --- web/doc-editor/trunk/js/ux/extjsPowered/StatusBar.css (rev 0) +++ web/doc-editor/trunk/js/ux/extjsPowered/StatusBar.css 2009-12-19 09:39:39 UTC (rev 292318) @@ -0,0 +1,86 @@ +/*! + * Ext JS Library 3.0.0 + * Copyright(c) 2006-2009 Ext JS, LLC + * [email protected] + * http://www.extjs.com/license + */ +/* + * Ext JS Library 2.2 + * Copyright(c) 2006-2008, Ext JS, LLC. + * [email protected] + * + * http://extjs.com/license + */ + +/* StatusBar */ + +.x-statusbar .x-status-text { + height: 21px; + line-height: 21px; + padding: 0 4px; + cursor: default; +} +.x-statusbar .x-status-busy { + padding-left: 25px !important; + background: transparent url(../images/loading.gif) no-repeat 3px 3px; +} +.x-statusbar .x-status-text-panel { + border-top: 1px solid #99BBE8; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #99BBE8; + padding: 2px 8px 2px 5px; +} + +/* StatusBar word processor example styles */ + +#word-status .x-status-text { + color: #777; +} +#word-status .x-status-text-panel .spacer { + width: 60px; + font-size:0; + line-height:0; +} +#word-status .x-status-busy { + padding-left: 25px !important; + background: transparent url(../images/saving.gif) no-repeat 3px 3px; +} +#word-status .x-status-saved { + padding-left: 25px !important; + background: transparent url(../images/saved.png) no-repeat 3px 3px; +} + +/* StatusBar form validation example styles */ + +.x-statusbar .x-status-error { + color: #C33; + cursor: pointer; + padding-left: 25px !important; + background: transparent url(../images/exclamation.gif) no-repeat 3px 3px; +} +.x-statusbar .x-status-valid { + padding-left: 25px !important; + background: transparent url(../images/accept.png) no-repeat 3px 3px; +} +.x-status-error-list { + font: 11px tahoma,arial,verdana,sans-serif; + position: absolute; + z-index: 9999; + border: 1px solid #C33; + background: #ffa; + padding: 5px 10px; + color: #999; +} +.x-status-error-list li { + cursor: pointer; + list-style: disc; + margin-left: 10px; +} +.x-status-error-list li a { + color: #15428B; + text-decoration: none; +} +.x-status-error-list li a:hover { + text-decoration: underline; +} Added: web/doc-editor/trunk/js/ux/extjsPowered/StatusBar.js =================================================================== --- web/doc-editor/trunk/js/ux/extjsPowered/StatusBar.js (rev 0) +++ web/doc-editor/trunk/js/ux/extjsPowered/StatusBar.js 2009-12-19 09:39:39 UTC (rev 292318) @@ -0,0 +1,409 @@ +/*! + * Ext JS Library 3.0.0 + * Copyright(c) 2006-2009 Ext JS, LLC + * [email protected] + * http://www.extjs.com/license + */ +/** + * @class Ext.ux.StatusBar + * <p>Basic status bar component that can be used as the bottom toolbar of any {@link Ext.Panel}. In addition to + * supporting the standard {@link Ext.Toolbar} interface for adding buttons, menus and other items, the StatusBar + * provides a greedy status element that can be aligned to either side and has convenient methods for setting the + * status text and icon. You can also indicate that something is processing using the {@link #showBusy} method.</p> + * <p><b>Note:</b> Although StatusBar supports xtype:'statusbar', at this time Ext.Toolbar (the base class) does + * not support xtype. For this reason, if you are adding Toolbar items into the StatusBar you must declare it + * using the "new StatusBar()" syntax for the items to render correctly.</p> + * <pre><code> +new Ext.Panel({ + title: 'StatusBar', + // etc. + bbar: new Ext.ux.StatusBar({ + id: 'my-status', + + // defaults to use when the status is cleared: + defaultText: 'Default status text', + defaultIconCls: 'default-icon', + + // values to set initially: + text: 'Ready', + iconCls: 'ready-icon', + + // any standard Toolbar items: + items: [{ + text: 'A Button' + }, '-', 'Plain Text'] + }) +}); + +// Update the status bar later in code: +var sb = Ext.getCmp('my-status'); +sb.setStatus({ + text: 'OK', + iconCls: 'ok-icon', + clear: true // auto-clear after a set interval +}); + +// Set the status bar to show that something is processing: +sb.showBusy(); + +// processing.... + +sb.clearStatus(); // once completeed +</code></pre> + * @extends Ext.Toolbar + * @constructor + * Creates a new StatusBar + * @param {Object/Array} config A config object + */ +Ext.ux.StatusBar = Ext.extend(Ext.Toolbar, { + /** + * @cfg {String} statusAlign + * The alignment of the status element within the overall StatusBar layout. When the StatusBar is rendered, + * it creates an internal div containing the status text and icon. Any additional Toolbar items added in the + * StatusBar's {@link #items} config, or added via {@link #add} or any of the supported add* methods, will be + * rendered, in added order, to the opposite side. The status element is greedy, so it will automatically + * expand to take up all sapce left over by any other items. Example usage: + * <pre><code> +// Create a left-aligned status bar containing a button, +// separator and text item that will be right-aligned (default): +new Ext.Panel({ + title: 'StatusBar', + // etc. + bbar: new Ext.ux.StatusBar({ + defaultText: 'Default status text', + id: 'status-id', + items: [{ + text: 'A Button' + }, '-', 'Plain Text'] + }) +}); + +// By adding the statusAlign config, this will create the +// exact same toolbar, except the status and toolbar item +// layout will be reversed from the previous example: +new Ext.Panel({ + title: 'StatusBar', + // etc. + bbar: new Ext.ux.StatusBar({ + defaultText: 'Default status text', + id: 'status-id', + statusAlign: 'right', + items: [{ + text: 'A Button' + }, '-', 'Plain Text'] + }) +}); +</code></pre> + */ + /** + * @cfg {String} defaultText + * The default {@link #text} value. This will be used anytime the status bar is cleared with the + * <tt>useDefaults:true</tt> option (defaults to ''). + */ + /** + * @cfg {String} defaultIconCls + * The default {@link #iconCls} value (see the iconCls docs for additional details about customizing the icon). + * This will be used anytime the status bar is cleared with the <tt>useDefaults:true</tt> option (defaults to ''). + */ + /** + * @cfg {String} text + * A string that will be rendered into the status element as the status message (defaults to ''); + */ + /** + * @cfg {String} iconCls + * A CSS class that will be applied to the status element and is expected to provide a background image that will + * serve as the status bar icon (defaults to ''). The class is applied directly to the div that also contains the + * status text, so the rule should provide the appropriate padding on the div to make room for the image. + * Example usage:<pre><code> +// Example CSS rule: +.x-statusbar .x-status-custom { + padding-left: 25px; + background: transparent url(images/custom-icon.gif) no-repeat 3px 3px; +} + +// Initializing the status bar: +var sb = new Ext.ux.StatusBar({ + defaultIconCls: 'x-status-custom' +}); + +// Setting it in code: +sb.setStatus({ + text: 'New status', + iconCls: 'x-status-custom' +}); +</code></pre> + */ + + /** + * @cfg {String} cls + * The base class applied to the containing element for this component on render (defaults to 'x-statusbar') + */ + cls : 'x-statusbar', + /** + * @cfg {String} busyIconCls + * The default {@link #iconCls} applied when calling {@link #showBusy} (defaults to 'x-status-busy'). It can be + * overridden at any time by passing the <tt>iconCls</tt> argument into <tt>showBusy</tt>. See the + * iconCls docs for additional details about customizing the icon. + */ + busyIconCls : 'x-status-busy', + /** + * @cfg {String} busyText + * The default {@link #text} applied when calling {@link #showBusy} (defaults to 'Loading...'). It can be + * overridden at any time by passing the <tt>text</tt> argument into <tt>showBusy</tt>. + */ + busyText : 'Loading...', + /** + * @cfg {Number} autoClear + * The number of milliseconds to wait after setting the status via {@link #setStatus} before automatically + * clearing the status text and icon (defaults to 5000). Note that this only applies when passing the + * <tt>clear</tt> argument to setStatus since that is the only way to defer clearing the status. This can + * be overridden by specifying a different <tt>wait</tt> value in setStatus. Calls to {@link #clearStatus} + * always clear the status bar immediately and ignore this value. + */ + autoClear : 5000, + + // private + activeThreadId : 0, + + // private + initComponent : function(){ + if(this.statusAlign=='right'){ + this.cls += ' x-status-right'; + } + Ext.ux.StatusBar.superclass.initComponent.call(this); + }, + + // private + afterRender : function(){ + Ext.ux.StatusBar.superclass.afterRender.call(this); + + var right = this.statusAlign == 'right'; + this.statusEl = new Ext.Toolbar.TextItem({ + cls: 'x-status-text ' + (this.iconCls || this.defaultIconCls || ''), + text: this.text || this.defaultText || '' + }); + + if(right){ + this.add('->'); + this.add(this.statusEl); + }else{ + this.insert(0, this.statusEl); + this.insert(1, '->'); + } + +// this.statusEl = td.createChild({ +// cls: 'x-status-text ' + (this.iconCls || this.defaultIconCls || ''), +// html: this.text || this.defaultText || '' +// }); +// this.statusEl.unselectable(); + +// this.spacerEl = td.insertSibling({ +// tag: 'td', +// style: 'width:100%', +// cn: [{cls:'ytb-spacer'}] +// }, right ? 'before' : 'after'); + }, + + /** + * Sets the status {@link #text} and/or {@link #iconCls}. Also supports automatically clearing the + * status that was set after a specified interval. + * @param {Object/String} config A config object specifying what status to set, or a string assumed + * to be the status text (and all other options are defaulted as explained below). A config + * object containing any or all of the following properties can be passed:<ul> + * <li><tt>text</tt> {String} : (optional) The status text to display. If not specified, any current + * status text will remain unchanged.</li> + * <li><tt>iconCls</tt> {String} : (optional) The CSS class used to customize the status icon (see + * {@link #iconCls} for details). If not specified, any current iconCls will remain unchanged.</li> + * <li><tt>clear</tt> {Boolean/Number/Object} : (optional) Allows you to set an internal callback that will + * automatically clear the status text and iconCls after a specified amount of time has passed. If clear is not + * specified, the new status will not be auto-cleared and will stay until updated again or cleared using + * {@link #clearStatus}. If <tt>true</tt> is passed, the status will be cleared using {@link #autoClear}, + * {@link #defaultText} and {@link #defaultIconCls} via a fade out animation. If a numeric value is passed, + * it will be used as the callback interval (in milliseconds), overriding the {@link #autoClear} value. + * All other options will be defaulted as with the boolean option. To customize any other options, + * you can pass an object in the format:<ul> + * <li><tt>wait</tt> {Number} : (optional) The number of milliseconds to wait before clearing + * (defaults to {@link #autoClear}).</li> + * <li><tt>anim</tt> {Number} : (optional) False to clear the status immediately once the callback + * executes (defaults to true which fades the status out).</li> + * <li><tt>useDefaults</tt> {Number} : (optional) False to completely clear the status text and iconCls + * (defaults to true which uses {@link #defaultText} and {@link #defaultIconCls}).</li> + * </ul></li></ul> + * Example usage:<pre><code> +// Simple call to update the text +statusBar.setStatus('New status'); + +// Set the status and icon, auto-clearing with default options: +statusBar.setStatus({ + text: 'New status', + iconCls: 'x-status-custom', + clear: true +}); + +// Auto-clear with custom options: +statusBar.setStatus({ + text: 'New status', + iconCls: 'x-status-custom', + clear: { + wait: 8000, + anim: false, + useDefaults: false + } +}); +</code></pre> + * @return {Ext.ux.StatusBar} this + */ + setStatus : function(o){ + o = o || {}; + + if(typeof o == 'string'){ + o = {text:o}; + } + if(o.text !== undefined){ + this.setText(o.text); + } + if(o.iconCls !== undefined){ + this.setIcon(o.iconCls); + } + + if(o.clear){ + var c = o.clear, + wait = this.autoClear, + defaults = {useDefaults: true, anim: true}; + + if(typeof c == 'object'){ + c = Ext.applyIf(c, defaults); + if(c.wait){ + wait = c.wait; + } + }else if(typeof c == 'number'){ + wait = c; + c = defaults; + }else if(typeof c == 'boolean'){ + c = defaults; + } + + c.threadId = this.activeThreadId; + this.clearStatus.defer(wait, this, [c]); + } + return this; + }, + + /** + * Clears the status {@link #text} and {@link #iconCls}. Also supports clearing via an optional fade out animation. + * @param {Object} config (optional) A config object containing any or all of the following properties. If this + * object is not specified the status will be cleared using the defaults below:<ul> + * <li><tt>anim</tt> {Boolean} : (optional) True to clear the status by fading out the status element (defaults + * to false which clears immediately).</li> + * <li><tt>useDefaults</tt> {Boolean} : (optional) True to reset the text and icon using {@link #defaultText} and + * {@link #defaultIconCls} (defaults to false which sets the text to '' and removes any existing icon class).</li> + * </ul> + * @return {Ext.ux.StatusBar} this + */ + clearStatus : function(o){ + o = o || {}; + + if(o.threadId && o.threadId !== this.activeThreadId){ + // this means the current call was made internally, but a newer + // thread has set a message since this call was deferred. Since + // we don't want to overwrite a newer message just ignore. + return this; + } + + var text = o.useDefaults ? this.defaultText : '', + iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls : '') : ''; + + if(o.anim){ + this.statusEl.fadeOut({ + remove: false, + useDisplay: true, + scope: this, + callback: function(){ + this.setStatus({ + text: text, + iconCls: iconCls + }); + this.statusEl.show(); + } + }); + }else{ + // hide/show the el to avoid jumpy text or icon + this.statusEl.hide(); + this.setStatus({ + text: text, + iconCls: iconCls + }); + this.statusEl.show(); + } + return this; + }, + + /** + * Convenience method for setting the status text directly. For more flexible options see {@link #setStatus}. + * @param {String} text (optional) The text to set (defaults to '') + * @return {Ext.ux.StatusBar} this + */ + setText : function(text){ + this.activeThreadId++; + this.text = text || ''; + if(this.rendered){ + this.statusEl.setText(this.text); + } + return this; + }, + + /** + * Returns the current status text. + * @return {String} The status text + */ + getText : function(){ + return this.text; + }, + + /** + * Convenience method for setting the status icon directly. For more flexible options see {@link #setStatus}. + * See {@link #iconCls} for complete details about customizing the icon. + * @param {String} iconCls (optional) The icon class to set (defaults to '', and any current icon class is removed) + * @return {Ext.ux.StatusBar} this + */ + setIcon : function(cls){ + this.activeThreadId++; + cls = cls || ''; + + if(this.rendered){ + if(this.currIconCls){ + this.statusEl.removeClass(this.currIconCls); + this.currIconCls = null; + } + if(cls.length > 0){ + this.statusEl.addClass(cls); + this.currIconCls = cls; + } + }else{ + this.currIconCls = cls; + } + return this; + }, + + /** + * Convenience method for setting the status text and icon to special values that are pre-configured to indicate + * a "busy" state, usually for loading or processing activities. + * @param {Object/String} config (optional) A config object in the same format supported by {@link #setStatus}, or a + * string to use as the status text (in which case all other options for setStatus will be defaulted). Use the + * <tt>text</tt> and/or <tt>iconCls</tt> properties on the config to override the default {@link #busyText} + * and {@link #busyIconCls} settings. If the config argument is not specified, {@link #busyText} and + * {@link #busyIconCls} will be used in conjunction with all of the default options for {@link #setStatus}. + * @return {Ext.ux.StatusBar} this + */ + showBusy : function(o){ + if(typeof o == 'string'){ + o = {text:o}; + } + o = Ext.applyIf(o || {}, { + text: this.busyText, + iconCls: this.busyIconCls + }); + return this.setStatus(o); + } +}); +Ext.reg('statusbar', Ext.ux.StatusBar); Added: web/doc-editor/trunk/js/ux/extjsPowered/TabCloseMenu.js =================================================================== --- web/doc-editor/trunk/js/ux/extjsPowered/TabCloseMenu.js (rev 0) +++ web/doc-editor/trunk/js/ux/extjsPowered/TabCloseMenu.js 2009-12-19 09:39:39 UTC (rev 292318) @@ -0,0 +1,59 @@ +/*! + * Ext JS Library 3.0.0 + * Copyright(c) 2006-2009 Ext JS, LLC + * [email protected] + * http://www.extjs.com/license + */ +/** + * @class Ext.ux.TabCloseMenu + * @extends Object + * Plugin (ptype = 'tabclosemenu') for adding a close context menu to tabs. + * + * @ptype tabclosemenu + */ +Ext.ux.TabCloseMenu = function(){ + var tabs, menu, ctxItem; + this.init = function(tp){ + tabs = tp; + tabs.on('contextmenu', onContextMenu); + }; + + function onContextMenu(ts, item, e){ + if(!menu){ // create context menu on first right click + menu = new Ext.menu.Menu({ + items: [{ + id: tabs.id + '-close', + text: _('Close Tab'), + handler : function(){ + tabs.remove(ctxItem); + } + },{ + id: tabs.id + '-close-others', + iconCls: 'closeOthersTabs', + text: _('Close Other Tabs'), + handler : function(){ + tabs.items.each(function(item){ + if(item.closable && item != ctxItem){ + tabs.remove(item); + } + }); + } + }]}); + } + ctxItem = item; + var items = menu.items; + items.get(tabs.id + '-close').setDisabled(!item.closable); + var disableOthers = true; + tabs.items.each(function(){ + if(this != item && this.closable){ + disableOthers = false; + return false; + } + }); + items.get(tabs.id + '-close-others').setDisabled(disableOthers); + e.stopEvent(); + menu.showAt(e.getPoint()); + } +}; + +Ext.preg('tabclosemenu', Ext.ux.TabCloseMenu);