summaryrefslogtreecommitdiffstats
path: root/deluge/ui/web/js/ext-extensions-debug.js
diff options
context:
space:
mode:
authorDamien Churchill <damoc@gmail.com>2010-01-24 02:55:32 +0000
committerDamien Churchill <damoc@gmail.com>2010-01-24 02:55:32 +0000
commit92d19fd58dbda0fd507340f9e1616e81d50efd70 (patch)
treee6bca57875974dc6fe6e920f9a62a6f38b4c77d9 /deluge/ui/web/js/ext-extensions-debug.js
parentb4b95c942376c06764127fc21ae450b51cfc8b5c (diff)
downloaddeluge-92d19fd58dbda0fd507340f9e1616e81d50efd70.tar.gz
deluge-92d19fd58dbda0fd507340f9e1616e81d50efd70.tar.bz2
deluge-92d19fd58dbda0fd507340f9e1616e81d50efd70.zip
initial commit of the big js layout overhall (ui loads but there are parts missing)
Diffstat (limited to 'deluge/ui/web/js/ext-extensions-debug.js')
-rw-r--r--deluge/ui/web/js/ext-extensions-debug.js2803
1 files changed, 1969 insertions, 834 deletions
diff --git a/deluge/ui/web/js/ext-extensions-debug.js b/deluge/ui/web/js/ext-extensions-debug.js
index 7eca42e56..ff8a64392 100644
--- a/deluge/ui/web/js/ext-extensions-debug.js
+++ b/deluge/ui/web/js/ext-extensions-debug.js
@@ -1,168 +1,640 @@
+/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+Ext.ns('Ext.ux.grid');
+
/**
- * Copyright (c) 2008, Steven Chim
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- * * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * @class Ext.ux.grid.BufferView
+ * @extends Ext.grid.GridView
+ * A custom GridView which renders rows on an as-needed basis.
*/
+Ext.ux.grid.BufferView = Ext.extend(Ext.grid.GridView, {
+ /**
+ * @cfg {Number} rowHeight
+ * The height of a row in the grid.
+ */
+ rowHeight: 19,
+
+ /**
+ * @cfg {Number} borderHeight
+ * The combined height of border-top and border-bottom of a row.
+ */
+ borderHeight: 2,
+
+ /**
+ * @cfg {Boolean/Number} scrollDelay
+ * The number of milliseconds before rendering rows out of the visible
+ * viewing area. Defaults to 100. Rows will render immediately with a config
+ * of false.
+ */
+ scrollDelay: 100,
+
+ /**
+ * @cfg {Number} cacheSize
+ * The number of rows to look forward and backwards from the currently viewable
+ * area. The cache applies only to rows that have been rendered already.
+ */
+ cacheSize: 20,
+
+ /**
+ * @cfg {Number} cleanDelay
+ * The number of milliseconds to buffer cleaning of extra rows not in the
+ * cache.
+ */
+ cleanDelay: 500,
+
+ initTemplates : function(){
+ Ext.ux.grid.BufferView.superclass.initTemplates.call(this);
+ var ts = this.templates;
+ // empty div to act as a place holder for a row
+ ts.rowHolder = new Ext.Template(
+ '<div class="x-grid3-row {alt}" style="{tstyle}"></div>'
+ );
+ ts.rowHolder.disableFormats = true;
+ ts.rowHolder.compile();
+
+ ts.rowBody = new Ext.Template(
+ '<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
+ '<tbody><tr>{cells}</tr>',
+ (this.enableRowBody ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>' : ''),
+ '</tbody></table>'
+ );
+ ts.rowBody.disableFormats = true;
+ ts.rowBody.compile();
+ },
-Ext.namespace("Ext.ux.form");
+ getStyleRowHeight : function(){
+ return Ext.isBorderBox ? (this.rowHeight + this.borderHeight) : this.rowHeight;
+ },
-/**
- * Ext.ux.form.ToggleField class
- *
- * @author Damien Churchill
- * @version v0.1
- *
- * @class Ext.ux.form.ToggleField
- * @extends Ext.form.TriggerField
- */
-Ext.ux.form.ToggleField = Ext.extend(Ext.form.Field, {
+ getCalculatedRowHeight : function(){
+ return this.rowHeight + this.borderHeight;
+ },
- cls: 'x-toggle-field',
+ getVisibleRowCount : function(){
+ var rh = this.getCalculatedRowHeight();
+ var visibleHeight = this.scroller.dom.clientHeight;
+ return (visibleHeight < 1) ? 0 : Math.ceil(visibleHeight / rh);
+ },
- initComponent: function() {
- Ext.ux.form.ToggleField.superclass.initComponent.call(this);
+ getVisibleRows: function(){
+ var count = this.getVisibleRowCount();
+ var sc = this.scroller.dom.scrollTop;
+ var start = (sc == 0 ? 0 : Math.floor(sc/this.getCalculatedRowHeight())-1);
+ return {
+ first: Math.max(start, 0),
+ last: Math.min(start + count + 2, this.ds.getCount()-1)
+ };
+ },
- this.toggle = new Ext.form.Checkbox();
- this.toggle.on('check', this.onToggleCheck, this);
+ doRender : function(cs, rs, ds, startRow, colCount, stripe, onlyBody){
+ var ts = this.templates, ct = ts.cell, rt = ts.row, rb = ts.rowBody, last = colCount-1;
+ var rh = this.getStyleRowHeight();
+ var vr = this.getVisibleRows();
+ var tstyle = 'width:'+this.getTotalWidth()+';height:'+rh+'px;';
+ // buffers
+ var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;
+ for (var j = 0, len = rs.length; j < len; j++) {
+ r = rs[j]; cb = [];
+ var rowIndex = (j+startRow);
+ var visible = rowIndex >= vr.first && rowIndex <= vr.last;
+ if (visible) {
+ for (var i = 0; i < colCount; i++) {
+ c = cs[i];
+ p.id = c.id;
+ p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
+ p.attr = p.cellAttr = "";
+ p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
+ p.style = c.style;
+ if (p.value == undefined || p.value === "") {
+ p.value = "&#160;";
+ }
+ if (r.dirty && typeof r.modified[c.name] !== 'undefined') {
+ p.css += ' x-grid3-dirty-cell';
+ }
+ cb[cb.length] = ct.apply(p);
+ }
+ }
+ var alt = [];
+ if(stripe && ((rowIndex+1) % 2 == 0)){
+ alt[0] = "x-grid3-row-alt";
+ }
+ if(r.dirty){
+ alt[1] = " x-grid3-dirty-row";
+ }
+ rp.cols = colCount;
+ if(this.getRowClass){
+ alt[2] = this.getRowClass(r, rowIndex, rp, ds);
+ }
+ rp.alt = alt.join(" ");
+ rp.cells = cb.join("");
+ buf[buf.length] = !visible ? ts.rowHolder.apply(rp) : (onlyBody ? rb.apply(rp) : rt.apply(rp));
+ }
+ return buf.join("");
+ },
- this.input = new Ext.form.TextField({
- disabled: true
- });
+ isRowRendered: function(index){
+ var row = this.getRow(index);
+ return row && row.childNodes.length > 0;
},
- onRender: function(ct, position) {
- if (!this.el) {
- this.panel = new Ext.Panel({
- cls: this.groupCls,
- layout: 'table',
- layoutConfig: {
- columns: 2
- },
- border: false,
- renderTo: ct
- });
- this.panel.ownerCt = this;
- this.el = this.panel.getEl();
+ syncScroll: function(){
+ Ext.ux.grid.BufferView.superclass.syncScroll.apply(this, arguments);
+ this.update();
+ },
- this.panel.add(this.toggle);
- this.panel.add(this.input);
- this.panel.doLayout();
+ // a (optionally) buffered method to update contents of gridview
+ update: function(){
+ if (this.scrollDelay) {
+ if (!this.renderTask) {
+ this.renderTask = new Ext.util.DelayedTask(this.doUpdate, this);
+ }
+ this.renderTask.delay(this.scrollDelay);
+ }else{
+ this.doUpdate();
+ }
+ },
+
+ onRemove : function(ds, record, index, isUpdate){
+ Ext.ux.grid.BufferView.superclass.onRemove.apply(this, arguments);
+ if(isUpdate !== true){
+ this.update();
+ }
+ },
- this.toggle.getEl().parent().setStyle('padding-right', '10px');
+ doUpdate: function(){
+ if (this.getVisibleRowCount() > 0) {
+ var g = this.grid, cm = g.colModel, ds = g.store;
+ var cs = this.getColumnData();
+
+ var vr = this.getVisibleRows();
+ for (var i = vr.first; i <= vr.last; i++) {
+ // if row is NOT rendered and is visible, render it
+ if(!this.isRowRendered(i)){
+ var html = this.doRender(cs, [ds.getAt(i)], ds, i, cm.getColumnCount(), g.stripeRows, true);
+ this.getRow(i).innerHTML = html;
+ }
+ }
+ this.clean();
}
- Ext.ux.form.ToggleField.superclass.onRender.call(this, ct, position);
},
- // private
- onResize: function(w, h) {
- this.panel.setSize(w, h);
- this.panel.doLayout();
+ // a buffered method to clean rows
+ clean : function(){
+ if(!this.cleanTask){
+ this.cleanTask = new Ext.util.DelayedTask(this.doClean, this);
+ }
+ this.cleanTask.delay(this.cleanDelay);
+ },
- // we substract 10 for the padding :-)
- var inputWidth = w - this.toggle.getSize().width - 10;
- this.input.setSize(inputWidth, h);
+ doClean: function(){
+ if (this.getVisibleRowCount() > 0) {
+ var vr = this.getVisibleRows();
+ vr.first -= this.cacheSize;
+ vr.last += this.cacheSize;
+
+ var i = 0, rows = this.getRows();
+ // if first is less than 0, all rows have been rendered
+ // so lets clean the end...
+ if(vr.first <= 0){
+ i = vr.last + 1;
+ }
+ for(var len = this.ds.getCount(); i < len; i++){
+ // if current row is outside of first and last and
+ // has content, update the innerHTML to nothing
+ if ((i < vr.first || i > vr.last) && rows[i].innerHTML) {
+ rows[i].innerHTML = '';
+ }
+ }
+ }
},
- onToggleCheck: function(toggle, checked) {
- this.input.setDisabled(!checked);
+ layout: function(){
+ Ext.ux.grid.BufferView.superclass.layout.call(this);
+ this.update();
}
});
-Ext.reg('togglefield', Ext.ux.form.ToggleField);
+/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+Ext.ns('Ext.ux.form');
/**
- * Ext.ux.form.Spinner Class
- *
- * @author Steven Chim
- * @version Spinner.js 2008-08-27 v0.35
- *
- * @class Ext.ux.form.Spinner
- * @extends Ext.form.TriggerField
- */
-Ext.ux.form.Spinner = function(config){
- Ext.ux.form.Spinner.superclass.constructor.call(this, config);
- this.addEvents({
- 'spin' : true,
- 'spinup' : true,
- 'spindown' : true
+ * @class Ext.ux.form.FileUploadField
+ * @extends Ext.form.TextField
+ * Creates a file upload field.
+ * @xtype fileuploadfield
+ */
+Ext.ux.form.FileUploadField = Ext.extend(Ext.form.TextField, {
+ /**
+ * @cfg {String} buttonText The button text to display on the upload button (defaults to
+ * 'Browse...'). Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
+ * value will be used instead if available.
+ */
+ buttonText: 'Browse...',
+ /**
+ * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
+ * text field (defaults to false). If true, all inherited TextField members will still be available.
+ */
+ buttonOnly: false,
+ /**
+ * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
+ * (defaults to 3). Note that this only applies if {@link #buttonOnly} = false.
+ */
+ buttonOffset: 3,
+ /**
+ * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
+ */
+
+ // private
+ readOnly: true,
+
+ /**
+ * @hide
+ * @method autoSize
+ */
+ autoSize: Ext.emptyFn,
+
+ // private
+ initComponent: function(){
+ Ext.ux.form.FileUploadField.superclass.initComponent.call(this);
+
+ this.addEvents(
+ /**
+ * @event fileselected
+ * Fires when the underlying file input field's value has changed from the user
+ * selecting a new file from the system file selection dialog.
+ * @param {Ext.ux.form.FileUploadField} this
+ * @param {String} value The file value returned by the underlying file input field
+ */
+ 'fileselected'
+ );
+ },
+
+ // private
+ onRender : function(ct, position){
+ Ext.ux.form.FileUploadField.superclass.onRender.call(this, ct, position);
+
+ this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
+ this.el.addClass('x-form-file-text');
+ this.el.dom.removeAttribute('name');
+ this.createFileInput();
+
+ var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
+ text: this.buttonText
+ });
+ this.button = new Ext.Button(Ext.apply(btnCfg, {
+ renderTo: this.wrap,
+ cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
+ }));
+
+ if(this.buttonOnly){
+ this.el.hide();
+ this.wrap.setWidth(this.button.getEl().getWidth());
+ }
+
+ this.bindListeners();
+ this.resizeEl = this.positionEl = this.wrap;
+ },
+
+ bindListeners: function(){
+ this.fileInput.on({
+ scope: this,
+ mouseenter: function() {
+ this.button.addClass(['x-btn-over','x-btn-focus'])
+ },
+ mouseleave: function(){
+ this.button.removeClass(['x-btn-over','x-btn-focus','x-btn-click'])
+ },
+ mousedown: function(){
+ this.button.addClass('x-btn-click')
+ },
+ mouseup: function(){
+ this.button.removeClass(['x-btn-over','x-btn-focus','x-btn-click'])
+ },
+ change: function(){
+ var v = this.fileInput.dom.value;
+ this.setValue(v);
+ this.fireEvent('fileselected', this, v);
+ }
+ });
+ },
+
+ createFileInput : function() {
+ this.fileInput = this.wrap.createChild({
+ id: this.getFileInputId(),
+ name: this.name||this.getId(),
+ cls: 'x-form-file',
+ tag: 'input',
+ type: 'file',
+ size: 1
+ });
+ },
+
+ reset : function(){
+ this.fileInput.remove();
+ this.createFileInput();
+ this.bindListeners();
+ Ext.ux.form.FileUploadField.superclass.reset.call(this);
+ },
+
+ // private
+ getFileInputId: function(){
+ return this.id + '-file';
+ },
+
+ // private
+ onResize : function(w, h){
+ Ext.ux.form.FileUploadField.superclass.onResize.call(this, w, h);
+
+ this.wrap.setWidth(w);
+
+ if(!this.buttonOnly){
+ var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
+ this.el.setWidth(w);
+ }
+ },
+
+ // private
+ onDestroy: function(){
+ Ext.ux.form.FileUploadField.superclass.onDestroy.call(this);
+ Ext.destroy(this.fileInput, this.button, this.wrap);
+ },
+
+ onDisable: function(){
+ Ext.ux.form.FileUploadField.superclass.onDisable.call(this);
+ this.doDisable(true);
+ },
+
+ onEnable: function(){
+ Ext.ux.form.FileUploadField.superclass.onEnable.call(this);
+ this.doDisable(false);
+
+ },
+
+ // private
+ doDisable: function(disabled){
+ this.fileInput.dom.disabled = disabled;
+ this.button.setDisabled(disabled);
+ },
+
+
+ // private
+ preFocus : Ext.emptyFn,
+
+ // private
+ alignErrorIcon : function(){
+ this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
+ }
+
+});
+
+Ext.reg('fileuploadfield', Ext.ux.form.FileUploadField);
+
+// backwards compat
+Ext.form.FileUploadField = Ext.ux.form.FileUploadField;
+Ext.ux.JSLoader = function(options) {
+ Ext.ux.JSLoader.scripts[++Ext.ux.JSLoader.index] = {
+ url: options.url,
+ success: true,
+ jsLoadObj: null,
+ options: options,
+ onLoad: options.onLoad || Ext.emptyFn,
+ onError: options.onError || Ext.ux.JSLoader.stdError,
+ scope: options.scope || this
+ };
+
+ Ext.Ajax.request({
+ url: options.url,
+ scriptIndex: Ext.ux.JSLoader.index,
+ success: function(response, options) {
+ var script = Ext.ux.JSLoader.scripts[options.scriptIndex];
+ try {
+ eval(response.responseText);
+ } catch(e) {
+ script.success = false;
+ script.onError(script.options, e);
+ }
+ if (script.success) {
+ script.onLoad.call(script.scope, script.options);
+ }
+ },
+ failure: function(response, options) {
+ var script = Ext.ux.JSLoader.scripts[options.scriptIndex];
+ script.success = false;
+ script.onError(script.options, response.status);
+ }
});
- this.initStrategy();
}
+Ext.ux.JSLoader.index = 0;
+Ext.ux.JSLoader.scripts = [];
+Ext.ux.JSLoader.stdError = function(options, e) {
+ window.alert('Error loading script:\n\n' + options.url + '\n\nstatus: ' + e);
+}
+/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/**
+ * @class Ext.ux.Spinner
+ * @extends Ext.util.Observable
+ * Creates a Spinner control utilized by Ext.ux.form.SpinnerField
+ */
+Ext.ux.Spinner = Ext.extend(Ext.util.Observable, {
+ incrementValue: 1,
+ alternateIncrementValue: 5,
+ triggerClass: 'x-form-spinner-trigger',
+ splitterClass: 'x-form-spinner-splitter',
+ alternateKey: Ext.EventObject.shiftKey,
+ defaultValue: 0,
+ accelerate: false,
+
+ constructor: function(config){
+ Ext.ux.Spinner.superclass.constructor.call(this, config);
+ Ext.apply(this, config);
+ this.mimicing = false;
+ },
-Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
- triggerClass : 'x-form-spinner-trigger',
- splitterClass : 'x-form-spinner-splitter',
+ init: function(field){
+ this.field = field;
- alternateKey : Ext.EventObject.shiftKey,
- strategy : undefined,
+ field.afterMethod('onRender', this.doRender, this);
+ field.afterMethod('onEnable', this.doEnable, this);
+ field.afterMethod('onDisable', this.doDisable, this);
+ field.afterMethod('afterRender', this.doAfterRender, this);
+ field.afterMethod('onResize', this.doResize, this);
+ field.afterMethod('onFocus', this.doFocus, this);
+ field.beforeMethod('onDestroy', this.doDestroy, this);
+ },
- //private
- onRender : function(ct, position){
- Ext.ux.form.Spinner.superclass.onRender.call(this, ct, position);
+ doRender: function(ct, position){
+ var el = this.el = this.field.getEl();
+ var f = this.field;
+
+ if (!f.wrap) {
+ f.wrap = this.wrap = el.wrap({
+ cls: "x-form-field-wrap"
+ });
+ }
+ else {
+ this.wrap = f.wrap.addClass('x-form-field-wrap');
+ }
+
+ this.trigger = this.wrap.createChild({
+ tag: "img",
+ src: Ext.BLANK_IMAGE_URL,
+ cls: "x-form-trigger " + this.triggerClass
+ });
- this.splitter = this.wrap.createChild({tag:'div', cls:this.splitterClass, style:'width:13px; height:2px;'});
- this.splitter.show().setRight( (Ext.isIE) ? 1 : 2 );
- this.splitter.show().setTop(10);
+ if (!f.width) {
+ this.wrap.setWidth(el.getWidth() + this.trigger.getWidth());
+ }
+
+ this.splitter = this.wrap.createChild({
+ tag: 'div',
+ cls: this.splitterClass,
+ style: 'width:13px; height:2px;'
+ });
+ this.splitter.setRight((Ext.isIE) ? 1 : 2).setTop(10).show();
this.proxy = this.trigger.createProxy('', this.splitter, true);
this.proxy.addClass("x-form-spinner-proxy");
- this.proxy.setStyle('left','0px');
+ this.proxy.setStyle('left', '0px');
this.proxy.setSize(14, 1);
this.proxy.hide();
- this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", {dragElId: this.proxy.id});
+ this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", {
+ dragElId: this.proxy.id
+ });
+ this.initTrigger();
this.initSpinner();
},
- //private
- initTrigger : function(){
+ doAfterRender: function(){
+ var y;
+ if (Ext.isIE && this.el.getY() != (y = this.trigger.getY())) {
+ this.el.position();
+ this.el.setY(y);
+ }
+ },
+
+ doEnable: function(){
+ if (this.wrap) {
+ this.wrap.removeClass(this.field.disabledClass);
+ }
+ },
+
+ doDisable: function(){
+ if (this.wrap) {
+ this.wrap.addClass(this.field.disabledClass);
+ this.el.removeClass(this.field.disabledClass);
+ }
+ },
+
+ doResize: function(w, h){
+ if (typeof w == 'number') {
+ this.el.setWidth(w - this.trigger.getWidth());
+ }
+ this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth());
+ },
+
+ doFocus: function(){
+ if (!this.mimicing) {
+ this.wrap.addClass('x-trigger-wrap-focus');
+ this.mimicing = true;
+ Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, {
+ delay: 10
+ });
+ this.el.on('keydown', this.checkTab, this);
+ }
+ },
+
+ // private
+ checkTab: function(e){
+ if (e.getKey() == e.TAB) {
+ this.triggerBlur();
+ }
+ },
+
+ // private
+ mimicBlur: function(e){
+ if (!this.wrap.contains(e.target) && this.field.validateBlur(e)) {
+ this.triggerBlur();
+ }
+ },
+
+ // private
+ triggerBlur: function(){
+ this.mimicing = false;
+ Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this);
+ this.el.un("keydown", this.checkTab, this);
+ this.field.beforeBlur();
+ this.wrap.removeClass('x-trigger-wrap-focus');
+ this.field.onBlur.call(this.field);
+ },
+
+ initTrigger: function(){
this.trigger.addClassOnOver('x-form-trigger-over');
this.trigger.addClassOnClick('x-form-trigger-click');
},
- //private
- initSpinner : function(){
+ initSpinner: function(){
+ this.field.addEvents({
+ 'spin': true,
+ 'spinup': true,
+ 'spindown': true
+ });
+
this.keyNav = new Ext.KeyNav(this.el, {
- "up" : function(e){
+ "up": function(e){
e.preventDefault();
this.onSpinUp();
},
- "down" : function(e){
+ "down": function(e){
e.preventDefault();
this.onSpinDown();
},
- "pageUp" : function(e){
+ "pageUp": function(e){
e.preventDefault();
this.onSpinUpAlternate();
},
- "pageDown" : function(e){
+ "pageDown": function(e){
e.preventDefault();
this.onSpinDownAlternate();
},
- scope : this
+ scope: this
});
- this.repeater = new Ext.util.ClickRepeater(this.trigger);
- this.repeater.on("click", this.onTriggerClick, this, {preventDefault:true});
- this.trigger.on("mouseover", this.onMouseOver, this, {preventDefault:true});
- this.trigger.on("mouseout", this.onMouseOut, this, {preventDefault:true});
- this.trigger.on("mousemove", this.onMouseMove, this, {preventDefault:true});
- this.trigger.on("mousedown", this.onMouseDown, this, {preventDefault:true});
- this.trigger.on("mouseup", this.onMouseUp, this, {preventDefault:true});
- this.wrap.on("mousewheel", this.handleMouseWheel, this);
+ this.repeater = new Ext.util.ClickRepeater(this.trigger, {
+ accelerate: this.accelerate
+ });
+ this.field.mon(this.repeater, "click", this.onTriggerClick, this, {
+ preventDefault: true
+ });
+
+ this.field.mon(this.trigger, {
+ mouseover: this.onMouseOver,
+ mouseout: this.onMouseOut,
+ mousemove: this.onMouseMove,
+ mousedown: this.onMouseDown,
+ mouseup: this.onMouseUp,
+ scope: this,
+ preventDefault: true
+ });
+
+ this.field.mon(this.wrap, "mousewheel", this.handleMouseWheel, this);
this.dd.setXConstraint(0, 0, 10)
this.dd.setYConstraint(1500, 1500, 10);
@@ -170,933 +642,1596 @@ Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
this.dd.startDrag = this.startDrag.createDelegate(this);
this.dd.onDrag = this.onDrag.createDelegate(this);
},
-
- initStrategy: function() {
- /*
- jsakalos suggestion
- http://extjs.com/forum/showthread.php?p=121850#post121850 */
- if('object' == typeof this.strategy && this.strategy.xtype) {
- switch(this.strategy.xtype) {
- case 'number':
- this.strategy = new Ext.ux.form.Spinner.NumberStrategy(this.strategy);
- break;
-
- case 'date':
- this.strategy = new Ext.ux.form.Spinner.DateStrategy(this.strategy);
- break;
-
- case 'time':
- this.strategy = new Ext.ux.form.Spinner.TimeStrategy(this.strategy);
- break;
-
- default:
- delete(this.strategy);
- break;
- }
- delete(this.strategy.xtype);
- }
-
- if(this.strategy == undefined){
- this.strategy = new Ext.ux.form.Spinner.NumberStrategy();
- }
- },
- //private
- onMouseOver : function(){
- if(this.disabled){
+ onMouseOver: function(){
+ if (this.disabled) {
return;
}
var middle = this.getMiddle();
- this.__tmphcls = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown';
- this.trigger.addClass(this.__tmphcls);
+ this.tmpHoverClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown';
+ this.trigger.addClass(this.tmpHoverClass);
},
//private
- onMouseOut : function(){
- this.trigger.removeClass(this.__tmphcls);
+ onMouseOut: function(){
+ this.trigger.removeClass(this.tmpHoverClass);
},
//private
- onMouseMove : function(){
- if(this.disabled){
+ onMouseMove: function(){
+ if (this.disabled) {
return;
}
var middle = this.getMiddle();
- if( ((Ext.EventObject.getPageY() > middle) && this.__tmphcls == "x-form-spinner-overup") ||
- ((Ext.EventObject.getPageY() < middle) && this.__tmphcls == "x-form-spinner-overdown")){
+ if (((Ext.EventObject.getPageY() > middle) && this.tmpHoverClass == "x-form-spinner-overup") ||
+ ((Ext.EventObject.getPageY() < middle) && this.tmpHoverClass == "x-form-spinner-overdown")) {
}
},
//private
- onMouseDown : function(){
- if(this.disabled){
+ onMouseDown: function(){
+ if (this.disabled) {
return;
}
var middle = this.getMiddle();
- this.__tmpccls = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown';
- this.trigger.addClass(this.__tmpccls);
+ this.tmpClickClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown';
+ this.trigger.addClass(this.tmpClickClass);
},
//private
- onMouseUp : function(){
- this.trigger.removeClass(this.__tmpccls);
+ onMouseUp: function(){
+ this.trigger.removeClass(this.tmpClickClass);
},
//private
- onTriggerClick : function(){
- if(this.disabled || this.getEl().dom.readOnly){
+ onTriggerClick: function(){
+ if (this.disabled || this.el.dom.readOnly) {
return;
}
var middle = this.getMiddle();
var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down';
- this['onSpin'+ud]();
+ this['onSpin' + ud]();
},
//private
- getMiddle : function(){
+ getMiddle: function(){
var t = this.trigger.getTop();
var h = this.trigger.getHeight();
- var middle = t + (h/2);
+ var middle = t + (h / 2);
return middle;
},
-
+
//private
//checks if control is allowed to spin
- isSpinnable : function(){
- if(this.disabled || this.getEl().dom.readOnly){
- Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly
+ isSpinnable: function(){
+ if (this.disabled || this.el.dom.readOnly) {
+ Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly
return false;
}
return true;
},
- handleMouseWheel : function(e){
+ handleMouseWheel: function(e){
//disable scrolling when not focused
- if(this.wrap.hasClass('x-trigger-wrap-focus') == false){
+ if (this.wrap.hasClass('x-trigger-wrap-focus') == false) {
return;
}
var delta = e.getWheelDelta();
- if(delta > 0){
+ if (delta > 0) {
this.onSpinUp();
e.stopEvent();
- } else if(delta < 0){
- this.onSpinDown();
- e.stopEvent();
}
+ else
+ if (delta < 0) {
+ this.onSpinDown();
+ e.stopEvent();
+ }
},
//private
- startDrag : function(){
+ startDrag: function(){
this.proxy.show();
this._previousY = Ext.fly(this.dd.getDragEl()).getTop();
},
//private
- endDrag : function(){
+ endDrag: function(){
this.proxy.hide();
},
//private
- onDrag : function(){
- if(this.disabled){
+ onDrag: function(){
+ if (this.disabled) {
return;
}
var y = Ext.fly(this.dd.getDragEl()).getTop();
var ud = '';
- if(this._previousY > y){ud = 'Up';} //up
- if(this._previousY < y){ud = 'Down';} //down
-
- if(ud != ''){
- this['onSpin'+ud]();
+ if (this._previousY > y) {
+ ud = 'Up';
+ } //up
+ if (this._previousY < y) {
+ ud = 'Down';
+ } //down
+ if (ud != '') {
+ this['onSpin' + ud]();
}
this._previousY = y;
},
//private
- onSpinUp : function(){
- if(this.isSpinnable() == false) {
+ onSpinUp: function(){
+ if (this.isSpinnable() == false) {
return;
}
- if(Ext.EventObject.shiftKey == true){
+ if (Ext.EventObject.shiftKey == true) {
this.onSpinUpAlternate();
return;
- }else{
- this.strategy.onSpinUp(this);
}
- this.fireEvent("spin", this);
- this.fireEvent("spinup", this);
- this.fireEvent("change", this);
+ else {
+ this.spin(false, false);
+ }
+ this.field.fireEvent("spin", this);
+ this.field.fireEvent("spinup", this);
},
//private
- onSpinDown : function(){
- if(this.isSpinnable() == false) {
+ onSpinDown: function(){
+ if (this.isSpinnable() == false) {
return;
}
- if(Ext.EventObject.shiftKey == true){
+ if (Ext.EventObject.shiftKey == true) {
this.onSpinDownAlternate();
return;
- }else{
- this.strategy.onSpinDown(this);
}
- this.fireEvent("spin", this);
- this.fireEvent("spindown", this);
- this.fireEvent("change", this);
+ else {
+ this.spin(true, false);
+ }
+ this.field.fireEvent("spin", this);
+ this.field.fireEvent("spindown", this);
},
//private
- onSpinUpAlternate : function(){
- if(this.isSpinnable() == false) {
+ onSpinUpAlternate: function(){
+ if (this.isSpinnable() == false) {
return;
}
- this.strategy.onSpinUpAlternate(this);
- this.fireEvent("spin", this);
- this.fireEvent("spinup", this);
- this.fireEvent("change", this);
+ this.spin(false, true);
+ this.field.fireEvent("spin", this);
+ this.field.fireEvent("spinup", this);
},
//private
- onSpinDownAlternate : function(){
- if(this.isSpinnable() == false) {
+ onSpinDownAlternate: function(){
+ if (this.isSpinnable() == false) {
return;
}
- this.strategy.onSpinDownAlternate(this);
- this.fireEvent("spin", this);
- this.fireEvent("spindown", this);
- this.fireEvent("change", this);
+ this.spin(true, true);
+ this.field.fireEvent("spin", this);
+ this.field.fireEvent("spindown", this);
},
-
- setValue: function(value) {
- value = this.strategy.fixBoundries(value);
- Ext.ux.form.Spinner.superclass.setValue.call(this, value);
- }
+ spin: function(down, alternate){
+ var v = parseFloat(this.field.getValue());
+ var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
+ (down == true) ? v -= incr : v += incr;
+
+ v = (isNaN(v)) ? this.defaultValue : v;
+ v = this.fixBoundries(v);
+ this.field.setRawValue(v);
+ },
+
+ fixBoundries: function(value){
+ var v = value;
+
+ if (this.field.minValue != undefined && v < this.field.minValue) {
+ v = this.field.minValue;
+ }
+ if (this.field.maxValue != undefined && v > this.field.maxValue) {
+ v = this.field.maxValue;
+ }
+
+ return this.fixPrecision(v);
+ },
+
+ // private
+ fixPrecision: function(value){
+ var nan = isNaN(value);
+ if (!this.field.allowDecimals || this.field.decimalPrecision == -1 || nan || !value) {
+ return nan ? '' : value;
+ }
+ return parseFloat(parseFloat(value).toFixed(this.field.decimalPrecision));
+ },
+
+ doDestroy: function(){
+ if (this.trigger) {
+ this.trigger.remove();
+ }
+ if (this.wrap) {
+ this.wrap.remove();
+ delete this.field.wrap;
+ }
+
+ if (this.splitter) {
+ this.splitter.remove();
+ }
+
+ if (this.dd) {
+ this.dd.unreg();
+ this.dd = null;
+ }
+
+ if (this.proxy) {
+ this.proxy.remove();
+ }
+
+ if (this.repeater) {
+ this.repeater.purgeListeners();
+ }
+ }
});
-Ext.reg('uxspinner', Ext.ux.form.Spinner);
+//backwards compat
+Ext.form.Spinner = Ext.ux.Spinner;
+/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+Ext.ns('Ext.ux.form');
/**
- * Copyright (c) 2008, Steven Chim
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- * * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * @class Ext.ux.form.SpinnerField
+ * @extends Ext.form.NumberField
+ * Creates a field utilizing Ext.ux.Spinner
+ * @xtype spinnerfield
*/
+Ext.ux.form.SpinnerField = Ext.extend(Ext.form.NumberField, {
+ actionMode: 'wrap',
+ deferHeight: true,
+ autoSize: Ext.emptyFn,
+ onBlur: Ext.emptyFn,
+ adjustSize: Ext.BoxComponent.prototype.adjustSize,
-/***
- * Abstract Strategy
- */
-Ext.ux.form.Spinner.Strategy = function(config){
- Ext.apply(this, config);
-};
-
-Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
- defaultValue : 0,
- minValue : undefined,
- maxValue : undefined,
- incrementValue : 1,
- alternateIncrementValue : 5,
- validationTask : new Ext.util.DelayedTask(),
-
- onSpinUp : function(field){
- this.spin(field, false, false);
- },
+ constructor: function(config) {
+ var spinnerConfig = Ext.copyTo({}, config, 'incrementValue,alternateIncrementValue,accelerate,defaultValue,triggerClass,splitterClass');
+
+ var spl = this.spinner = new Ext.ux.Spinner(spinnerConfig);
- onSpinDown : function(field){
- this.spin(field, true, false);
+ var plugins = config.plugins
+ ? (Ext.isArray(config.plugins)
+ ? config.plugins.push(spl)
+ : [config.plugins, spl])
+ : spl;
+
+ Ext.ux.form.SpinnerField.superclass.constructor.call(this, Ext.apply(config, {plugins: plugins}));
},
- onSpinUpAlternate : function(field){
- this.spin(field, false, true);
+ // private
+ getResizeEl: function(){
+ return this.wrap;
},
- onSpinDownAlternate : function(field){
- this.spin(field, true, true);
+ // private
+ getPositionEl: function(){
+ return this.wrap;
},
- spin : function(field, down, alternate){
- this.validationTask.delay(500, function(){field.validate()});
- //extend
+ // private
+ alignErrorIcon: function(){
+ if (this.wrap) {
+ this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
+ }
},
- fixBoundries : function(value){
- return value;
- //overwrite
+ validateBlur: function(){
+ return true;
}
-
});
-/***
- * Concrete Strategy: Numbers
+Ext.reg('spinnerfield', Ext.ux.form.SpinnerField);
+
+//backwards compat
+Ext.form.SpinnerField = Ext.ux.form.SpinnerField;
+/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
*/
-Ext.ux.form.Spinner.NumberStrategy = function(config){
- Ext.ux.form.Spinner.NumberStrategy.superclass.constructor.call(this, config);
-};
+/**
+ * @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>
+ * <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']
+ })
+});
-Ext.extend(Ext.ux.form.Spinner.NumberStrategy, Ext.ux.form.Spinner.Strategy, {
+// 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
+});
- allowDecimals : true,
- decimalPrecision : 2,
-
- spin : function(field, down, alternate){
- Ext.ux.form.Spinner.NumberStrategy.superclass.spin.call(this, field, down, alternate);
+// Set the status bar to show that something is processing:
+sb.showBusy();
- var v = parseFloat(field.getValue());
- var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
+// processing....
- (down == true) ? v -= incr : v += incr ;
- v = (isNaN(v)) ? this.defaultValue : v;
- v = this.fixBoundries(v);
- field.setRawValue(v);
- },
+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']
+ })
+});
- fixBoundries : function(value){
- var v = value;
+// 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 <b>initially</b> set as the status message. This string
+ * will be set as innerHTML (html tags are accepted) for the toolbar item.
+ * If not specified, the value set for <code>{@link #defaultText}</code>
+ * will be used.
+ */
+ /**
+ * @cfg {String} iconCls
+ * A CSS class that will be <b>initially</b> set as the status bar icon and is
+ * expected to provide a background image (defaults to '').
+ * 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 2px;
+}
- if(this.minValue != undefined && v < this.minValue){
- v = this.minValue;
- }
- if(this.maxValue != undefined && v > this.maxValue){
- v = this.maxValue;
- }
+// Setting a default icon:
+var sb = new Ext.ux.StatusBar({
+ defaultIconCls: 'x-status-custom'
+});
+
+// Changing the icon:
+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 <code>{@link #iconCls}</code> applied when calling
+ * <code>{@link #showBusy}</code> (defaults to <tt>'x-status-busy'</tt>).
+ * It can be overridden at any time by passing the <code>iconCls</code>
+ * argument into <code>{@link #showBusy}</code>.
+ */
+ busyIconCls : 'x-status-busy',
+ /**
+ * @cfg {String} busyText
+ * The default <code>{@link #text}</code> applied when calling
+ * <code>{@link #showBusy}</code> (defaults to <tt>'Loading...'</tt>).
+ * It can be overridden at any time by passing the <code>text</code>
+ * argument into <code>{@link #showBusy}</code>.
+ */
+ busyText : 'Loading...',
+ /**
+ * @cfg {Number} autoClear
+ * The number of milliseconds to wait after setting the status via
+ * <code>{@link #setStatus}</code> before automatically clearing the status
+ * text and icon (defaults to <tt>5000</tt>). Note that this only applies
+ * when passing the <tt>clear</tt> argument to <code>{@link #setStatus}</code>
+ * since that is the only way to defer clearing the status. This can
+ * be overridden by specifying a different <tt>wait</tt> value in
+ * <code>{@link #setStatus}</code>. Calls to <code>{@link #clearStatus}</code>
+ * always clear the status bar immediately and ignore this value.
+ */
+ autoClear : 5000,
+
+ /**
+ * @cfg {String} emptyText
+ * The text string to use if no text has been set. Defaults to
+ * <tt>'&nbsp;'</tt>). If there are no other items in the toolbar using
+ * an empty string (<tt>''</tt>) for this value would end up in the toolbar
+ * height collapsing since the empty string will not maintain the toolbar
+ * height. Use <tt>''</tt> if the toolbar should collapse in height
+ * vertically when no text is specified and there are no other items in
+ * the toolbar.
+ */
+ emptyText : '&nbsp;',
+
+ // private
+ activeThreadId : 0,
- return this.fixPrecision(v);
- },
-
// private
- fixPrecision : function(value){
- var nan = isNaN(value);
- if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
- return nan ? '' : value;
+ initComponent : function(){
+ if(this.statusAlign=='right'){
+ this.cls += ' x-status-right';
}
- return Number(value).toFixed(this.decimalPrecision);
+ Ext.ux.StatusBar.superclass.initComponent.call(this);
+ },
+
+ // private
+ afterRender : function(){
+ Ext.ux.StatusBar.superclass.afterRender.call(this);
+
+ var right = this.statusAlign == 'right';
+ this.currIconCls = this.iconCls || this.defaultIconCls;
+ this.statusEl = new Ext.Toolbar.TextItem({
+ cls: 'x-status-text ' + (this.currIconCls || ''),
+ 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);
+ }
-/***
- * Concrete Strategy: Date
- */
-Ext.ux.form.Spinner.DateStrategy = function(config){
- Ext.ux.form.Spinner.DateStrategy.superclass.constructor.call(this, config);
-};
-
-Ext.extend(Ext.ux.form.Spinner.DateStrategy, Ext.ux.form.Spinner.Strategy, {
- defaultValue : new Date(),
- format : "Y-m-d",
- incrementValue : 1,
- incrementConstant : Date.DAY,
- alternateIncrementValue : 1,
- alternateIncrementConstant : Date.MONTH,
-
- spin : function(field, down, alternate){
- Ext.ux.form.Spinner.DateStrategy.superclass.spin.call(this);
-
- var v = field.getRawValue();
-
- v = Date.parseDate(v, this.format);
- var dir = (down == true) ? -1 : 1 ;
- var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
- var dtconst = (alternate == true) ? this.alternateIncrementConstant : this.incrementConstant;
+ 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;
+ },
- if(typeof this.defaultValue == 'string'){
- this.defaultValue = Date.parseDate(this.defaultValue, this.format);
- }
+ /**
+ * 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;
+ }
- v = (v) ? v.add(dtconst, dir*incr) : this.defaultValue;
+ var text = o.useDefaults ? this.defaultText : this.emptyText,
+ iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls : '') : '';
+
+ if(o.anim){
+ // animate the statusEl Ext.Element
+ this.statusEl.el.fadeOut({
+ remove: false,
+ useDisplay: true,
+ scope: this,
+ callback: function(){
+ this.setStatus({
+ text: text,
+ iconCls: iconCls
+ });
+
+ this.statusEl.el.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;
+ },
- v = this.fixBoundries(v);
- field.setRawValue(Ext.util.Format.date(v,this.format));
+ /**
+ * 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);
+Ext.namespace("Ext.ux.form");
+
+/**
+ * Ext.ux.form.ToggleField class
+ *
+ * @author Damien Churchill
+ * @version v0.1
+ *
+ * @class Ext.ux.form.ToggleField
+ * @extends Ext.form.TriggerField
+ */
+Ext.ux.form.ToggleField = Ext.extend(Ext.form.Field, {
+
+ cls: 'x-toggle-field',
+
+ initComponent: function() {
+ Ext.ux.form.ToggleField.superclass.initComponent.call(this);
+
+ this.toggle = new Ext.form.Checkbox();
+ this.toggle.on('check', this.onToggleCheck, this);
+
+ this.input = new Ext.form.TextField({
+ disabled: true
+ });
},
-
- //private
- fixBoundries : function(date){
- var dt = date;
- var min = (typeof this.minValue == 'string') ? Date.parseDate(this.minValue, this.format) : this.minValue ;
- var max = (typeof this.maxValue == 'string') ? Date.parseDate(this.maxValue, this.format) : this.maxValue ;
- if(this.minValue != undefined && dt < min){
- dt = min;
- }
- if(this.maxValue != undefined && dt > max){
- dt = max;
+ onRender: function(ct, position) {
+ if (!this.el) {
+ this.panel = new Ext.Panel({
+ cls: this.groupCls,
+ layout: 'table',
+ layoutConfig: {
+ columns: 2
+ },
+ border: false,
+ renderTo: ct
+ });
+ this.panel.ownerCt = this;
+ this.el = this.panel.getEl();
+
+ this.panel.add(this.toggle);
+ this.panel.add(this.input);
+ this.panel.doLayout();
+
+ this.toggle.getEl().parent().setStyle('padding-right', '10px');
}
+ Ext.ux.form.ToggleField.superclass.onRender.call(this, ct, position);
+ },
- return dt;
- }
+ // private
+ onResize: function(w, h) {
+ this.panel.setSize(w, h);
+ this.panel.doLayout();
+ // we substract 10 for the padding :-)
+ var inputWidth = w - this.toggle.getSize().width - 10;
+ this.input.setSize(inputWidth, h);
+ },
+
+ onToggleCheck: function(toggle, checked) {
+ this.input.setDisabled(!checked);
+ }
});
+Ext.reg('togglefield', Ext.ux.form.ToggleField);
+/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+Ext.ns('Ext.ux.tree');
-/***
- * Concrete Strategy: Time
+/**
+ * @class Ext.ux.tree.TreeGridSorter
+ * @extends Ext.tree.TreeSorter
*/
-Ext.ux.form.Spinner.TimeStrategy = function(config){
- Ext.ux.form.Spinner.TimeStrategy.superclass.constructor.call(this, config);
-};
-
-Ext.extend(Ext.ux.form.Spinner.TimeStrategy, Ext.ux.form.Spinner.DateStrategy, {
- format : "H:i",
- incrementValue : 1,
- incrementConstant : Date.MINUTE,
- alternateIncrementValue : 1,
- alternateIncrementConstant : Date.HOUR
-});
+Ext.ux.tree.TreeGridSorter = Ext.extend(Ext.tree.TreeSorter, {
+ /**
+ * @cfg {Array} sortClasses The CSS classes applied to a header when it is sorted. (defaults to <tt>['sort-asc', 'sort-desc']</tt>)
+ */
+ sortClasses : ['sort-asc', 'sort-desc'],
+ /**
+ * @cfg {String} sortAscText The text displayed in the 'Sort Ascending' menu item (defaults to <tt>'Sort Ascending'</tt>)
+ */
+ sortAscText : 'Sort Ascending',
+ /**
+ * @cfg {String} sortDescText The text displayed in the 'Sort Descending' menu item (defaults to <tt>'Sort Descending'</tt>)
+ */
+ sortDescText : 'Sort Descending',
+
+ constructor : function(tree, config) {
+ if(!Ext.isObject(config)) {
+ config = {
+ property: tree.columns[0].dataIndex || 'text',
+ folderSort: true
+ }
+ }
-Ext.tree.ColumnTree = Ext.extend(Ext.tree.TreePanel, {
- lines:false,
- borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
- cls:'x-column-tree',
-
- onRender : function(){
- Ext.tree.ColumnTree.superclass.onRender.apply(this, arguments);
- this.headers = this.body.createChild(
- {cls:'x-tree-headers'},this.innerCt.dom);
-
- var cols = this.columns, c;
- var totalWidth = 0;
-
- for(var i = 0, len = cols.length; i < len; i++){
- c = cols[i];
- totalWidth += c.width;
- this.headers.createChild({
- cls:'x-tree-hd ' + (c.cls?c.cls+'-hd':''),
- cn: {
- cls:'x-tree-hd-text',
- html: c.header
- },
- style:'width:'+(c.width-this.borderWidth)+'px;'
- });
+ Ext.ux.tree.TreeGridSorter.superclass.constructor.apply(this, arguments);
+
+ this.tree = tree;
+ tree.on('headerclick', this.onHeaderClick, this);
+ tree.ddAppendOnly = true;
+
+ me = this;
+ this.defaultSortFn = function(n1, n2){
+
+ var dsc = me.dir && me.dir.toLowerCase() == 'desc';
+ var p = me.property || 'text';
+ var sortType = me.sortType;
+ var fs = me.folderSort;
+ var cs = me.caseSensitive === true;
+ var leafAttr = me.leafAttr || 'leaf';
+
+ if(fs){
+ if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
+ return 1;
+ }
+ if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
+ return -1;
+ }
+ }
+ var v1 = sortType ? sortType(n1.attributes[p]) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
+ var v2 = sortType ? sortType(n2.attributes[p]) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
+ if(v1 < v2){
+ return dsc ? +1 : -1;
+ }else if(v1 > v2){
+ return dsc ? -1 : +1;
+ }else{
+ return 0;
+ }
+ };
+
+ tree.on('afterrender', this.onAfterTreeRender, this, {single: true});
+ tree.on('headermenuclick', this.onHeaderMenuClick, this);
+ },
+
+ onAfterTreeRender : function() {
+ var hmenu = this.tree.hmenu;
+ hmenu.insert(0,
+ {itemId:'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
+ {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
+ );
+ this.updateSortIcon(0, 'asc');
+ },
+
+ onHeaderMenuClick : function(c, id, index) {
+ if(id === 'asc' || id === 'desc') {
+ this.onHeaderClick(c, null, index);
+ return false;
+ }
+ },
+
+ onHeaderClick : function(c, el, i) {
+ if(c && !this.tree.headersDisabled){
+ var me = this;
+
+ me.property = c.dataIndex;
+ me.dir = c.dir = (c.dir === 'desc' ? 'asc' : 'desc');
+ me.sortType = c.sortType;
+ me.caseSensitive === Ext.isBoolean(c.caseSensitive) ? c.caseSensitive : this.caseSensitive;
+ me.sortFn = c.sortFn || this.defaultSortFn;
+
+ this.tree.root.cascade(function(n) {
+ if(!n.isLeaf()) {
+ me.updateSort(me.tree, n);
+ }
+ });
+
+ this.updateSortIcon(i, c.dir);
}
- this.headers.createChild({cls:'x-clear'});
- // prevent floats from wrapping when clipped
- this.headers.setWidth(totalWidth);
- this.innerCt.setWidth(totalWidth);
+ },
+
+ // private
+ updateSortIcon : function(col, dir){
+ var sc = this.sortClasses;
+ var hds = this.tree.innerHd.select('td').removeClass(sc);
+ hds.item(col).addClass(sc[dir == 'desc' ? 1 : 0]);
}
-});
+});/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/**
+ * @class Ext.tree.ColumnResizer
+ * @extends Ext.util.Observable
+ */
+Ext.tree.ColumnResizer = Ext.extend(Ext.util.Observable, {
+ /**
+ * @cfg {Number} minWidth The minimum width the column can be dragged to.
+ * Defaults to <tt>14</tt>.
+ */
+ minWidth: 14,
-Ext.tree.ColumnTreeNode = Ext.extend(Ext.tree.TreeNode, {
-
- setColumnValue: function(index, value) {
- var t = this.getOwnerTree();
- var oldValue = this[t.columns[index].dataIndex];
- this[t.columns[index].dataIndex] = value;
- this.attributes[[t.columns[index].dataIndex]] = value;
- if (this.rendered) {
- this.ui.onColumnValueChange(this, index, value, oldValue);
- }
- this.fireEvent('columnvaluechange', this, index, value, oldValue);
- }
-});
+ constructor: function(config){
+ Ext.apply(this, config);
+ Ext.tree.ColumnResizer.superclass.constructor.call(this);
+ },
-Ext.tree.ColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
- focus: Ext.emptyFn, // prevent odd scrolling behavior
-
- onColumnValueChange: function(n, colIndex, value, oldValue) {
- if (this.rendered) {
- var c = n.getOwnerTree().columns[colIndex];
- this.columnNodes[colIndex].innerHTML = (c.renderer ? c.renderer(value, n, null) : value);
- }
- },
+ init : function(tree){
+ this.tree = tree;
+ tree.on('render', this.initEvents, this);
+ },
+
+ initEvents : function(tree){
+ tree.mon(tree.innerHd, 'mousemove', this.handleHdMove, this);
+ this.tracker = new Ext.dd.DragTracker({
+ onBeforeStart: this.onBeforeStart.createDelegate(this),
+ onStart: this.onStart.createDelegate(this),
+ onDrag: this.onDrag.createDelegate(this),
+ onEnd: this.onEnd.createDelegate(this),
+ tolerance: 3,
+ autoStart: 300
+ });
+ this.tracker.initEl(tree.innerHd);
+ tree.on('beforedestroy', this.tracker.destroy, this.tracker);
+ },
+
+ handleHdMove : function(e, t){
+ var hw = 5,
+ x = e.getPageX(),
+ hd = e.getTarget('.x-treegrid-hd', 3, true);
+
+ if(hd){
+ var r = hd.getRegion(),
+ ss = hd.dom.style,
+ pn = hd.dom.parentNode;
+
+ if(x - r.left <= hw && hd.dom !== pn.firstChild) {
+ var ps = hd.dom.previousSibling;
+ while(ps && Ext.fly(ps).hasClass('x-treegrid-hd-hidden')) {
+ ps = ps.previousSibling;
+ }
+ if(ps) {
+ this.activeHd = Ext.get(ps);
+ ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
+ }
+ } else if(r.right - x <= hw) {
+ var ns = hd.dom;
+ while(ns && Ext.fly(ns).hasClass('x-treegrid-hd-hidden')) {
+ ns = ns.previousSibling;
+ }
+ if(ns) {
+ this.activeHd = Ext.get(ns);
+ ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
+ }
+ } else{
+ delete this.activeHd;
+ ss.cursor = '';
+ }
+ }
+ },
+ onBeforeStart : function(e){
+ this.dragHd = this.activeHd;
+ return !!this.dragHd;
+ },
+
+ onStart : function(e){
+ this.tree.headersDisabled = true;
+ this.proxy = this.tree.body.createChild({cls:'x-treegrid-resizer'});
+ this.proxy.setHeight(this.tree.body.getHeight());
+
+ var x = this.tracker.getXY()[0];
+
+ this.hdX = this.dragHd.getX();
+ this.hdIndex = this.tree.findHeaderIndex(this.dragHd);
+
+ this.proxy.setX(this.hdX);
+ this.proxy.setWidth(x-this.hdX);
+
+ this.maxWidth = this.tree.outerCt.getWidth() - this.tree.innerBody.translatePoints(this.hdX).left;
+ },
+
+ onDrag : function(e){
+ var cursorX = this.tracker.getXY()[0];
+ this.proxy.setWidth((cursorX-this.hdX).constrain(this.minWidth, this.maxWidth));
+ },
+
+ onEnd : function(e){
+ var nw = this.proxy.getWidth(),
+ tree = this.tree;
+
+ this.proxy.remove();
+ delete this.dragHd;
+
+ tree.columns[this.hdIndex].width = nw;
+ tree.updateColumnWidths();
+
+ setTimeout(function(){
+ tree.headersDisabled = false;
+ }, 100);
+ }
+});/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/**
+ * @class Ext.ux.tree.TreeGridNodeUI
+ * @extends Ext.tree.TreeNodeUI
+ */
+Ext.ux.tree.TreeGridNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+ isTreeGridNodeUI: true,
+
renderElements : function(n, a, targetNode, bulkRender){
+ var t = n.getOwnerTree(),
+ cols = t.columns,
+ c = cols[0],
+ i, buf, len;
+
this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
- var t = n.getOwnerTree();
- var cols = t.columns;
- var bw = t.borderWidth;
- var c = cols[0];
-
- var cb = typeof a.checked == 'boolean';
- var href = a.href ? a.href : Ext.isGecko ? "" : "#";
-
- var buf = [
- '<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
- '<div class="x-tree-col" style="width:',c.width-bw,'px;">',
- '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
- '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
- '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
- cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
- '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
- a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
- '<span unselectable="on">', n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</span></a>",
- "</div>"];
- for(var i = 1, len = cols.length; i < len; i++){
- c = cols[i];
-
- buf.push('<div class="x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
- '<div class="x-tree-col-text">',(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]),"</div>",
- "</div>");
- }
- buf.push(
- '<div class="x-clear"></div></div>',
- '<ul class="x-tree-node-ct" style="display:none;"></ul>',
- "</li>");
+ buf = [
+ '<tbody class="x-tree-node">',
+ '<tr ext:tree-node-id="', n.id ,'" class="x-tree-node-el ', a.cls, '">',
+ '<td class="x-treegrid-col">',
+ '<span class="x-tree-node-indent">', this.indentMarkup, "</span>",
+ '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
+ '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon', (a.icon ? " x-tree-node-inline-icon" : ""), (a.iconCls ? " "+a.iconCls : ""), '" unselectable="on">',
+ '<a hidefocus="on" class="x-tree-node-anchor" href="', a.href ? a.href : '#', '" tabIndex="1" ',
+ a.hrefTarget ? ' target="'+a.hrefTarget+'"' : '', '>',
+ '<span unselectable="on">', (c.tpl ? c.tpl.apply(a) : a[c.dataIndex] || c.text), '</span></a>',
+ '</td>'
+ ];
+
+ for(i = 1, len = cols.length; i < len; i++){
+ c = cols[i];
+ buf.push(
+ '<td class="x-treegrid-col ', (c.cls ? c.cls : ''), '">',
+ '<div unselectable="on" class="x-treegrid-text"', (c.align ? ' style="text-align: ' + c.align + ';"' : ''), '>',
+ (c.tpl ? c.tpl.apply(a) : a[c.dataIndex]),
+ '</div>',
+ '</td>'
+ );
+ }
+
+ buf.push(
+ '</tr><tr class="x-tree-node-ct"><td colspan="', cols.length, '">',
+ '<table class="x-treegrid-node-ct-table" cellpadding="0" cellspacing="0" style="table-layout: fixed; display: none; width: ', t.innerCt.getWidth() ,'px;"><colgroup>'
+ );
+ for(i = 0, len = cols.length; i<len; i++) {
+ buf.push('<col style="width: ', (cols[i].hidden ? 0 : cols[i].width) ,'px;" />');
+ }
+ buf.push('</colgroup></table></td></tr></tbody>');
if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
- this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
- n.nextSibling.ui.getEl(), buf.join(""));
+ this.wrap = Ext.DomHelper.insertHtml("beforeBegin", n.nextSibling.ui.getEl(), buf.join(''));
}else{
- this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
+ this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(''));
}
this.elNode = this.wrap.childNodes[0];
- this.ctNode = this.wrap.childNodes[1];
+ this.ctNode = this.wrap.childNodes[1].firstChild.firstChild;
var cs = this.elNode.firstChild.childNodes;
this.indentNode = cs[0];
this.ecNode = cs[1];
this.iconNode = cs[2];
- var index = 3;
- if(cb){
- this.checkbox = cs[3];
- // fix for IE6
- this.checkbox.defaultChecked = this.checkbox.checked;
- index++;
- }
- this.anchor = cs[index];
- this.columnNodes = [cs[index].firstChild];
- for(var i = 1, len = cols.length; i < len; i++){
- this.columnNodes[i] = this.elNode.childNodes[i].firstChild;
- }
+ this.anchor = cs[3];
+ this.textNode = cs[3].firstChild;
+ },
+
+ // private
+ animExpand : function(cb){
+ this.ctNode.style.display = "";
+ Ext.ux.tree.TreeGridNodeUI.superclass.animExpand.call(this, cb);
}
});
-Ext.form.FileUploadField = Ext.extend(Ext.form.TextField, {
- /**
- * @cfg {String} buttonText The button text to display on the upload button (defaults to
- * 'Browse...'). Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
- * value will be used instead if available.
- */
- buttonText: 'Browse...',
- /**
- * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
- * text field (defaults to false). If true, all inherited TextField members will still be available.
- */
- buttonOnly: false,
- /**
- * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
- * (defaults to 3). Note that this only applies if {@link #buttonOnly} = false.
- */
- buttonOffset: 3,
- /**
- * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
- */
-
- // private
- readOnly: true,
-
- /**
- * @hide
- * @method autoSize
- */
- autoSize: Ext.emptyFn,
+Ext.ux.tree.TreeGridRootNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+ isTreeGridNodeUI: true,
// private
- initComponent: function(){
- Ext.form.FileUploadField.superclass.initComponent.call(this);
+ render : function(){
+ if(!this.rendered){
+ this.wrap = this.ctNode = this.node.ownerTree.innerCt.dom;
+ this.node.expanded = true;
+ }
- this.addEvents(
- /**
- * @event fileselected
- * Fires when the underlying file input field's value has changed from the user
- * selecting a new file from the system file selection dialog.
- * @param {Ext.form.FileUploadField} this
- * @param {String} value The file value returned by the underlying file input field
- */
- 'fileselected'
- );
+ if(Ext.isWebKit) {
+ // weird table-layout: fixed issue in webkit
+ var ct = this.ctNode;
+ ct.style.tableLayout = null;
+ (function() {
+ ct.style.tableLayout = 'fixed';
+ }).defer(1);
+ }
+ },
+
+ destroy : function(){
+ if(this.elNode){
+ Ext.dd.Registry.unregister(this.elNode.id);
+ }
+ delete this.node;
},
- // private
- onRender : function(ct, position){
- Ext.form.FileUploadField.superclass.onRender.call(this, ct, position);
+ collapse : Ext.emptyFn,
+ expand : Ext.emptyFn
+});/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/**
+ * @class Ext.ux.tree.TreeGridLoader
+ * @extends Ext.tree.TreeLoader
+ */
+Ext.ux.tree.TreeGridLoader = Ext.extend(Ext.tree.TreeLoader, {
+ createNode : function(attr) {
+ if (!attr.uiProvider) {
+ attr.uiProvider = Ext.ux.tree.TreeGridNodeUI;
+ }
+ return Ext.tree.TreeLoader.prototype.createNode.call(this, attr);
+ }
+});/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+(function() {
+ Ext.override(Ext.list.Column, {
+ init : function() {
+ if(!this.type){
+ this.type = "auto";
+ }
+
+ var st = Ext.data.SortTypes;
+ // named sortTypes are supported, here we look them up
+ if(typeof this.sortType == "string"){
+ this.sortType = st[this.sortType];
+ }
+
+ // set default sortType for strings and dates
+ if(!this.sortType){
+ switch(this.type){
+ case "string":
+ this.sortType = st.asUCString;
+ break;
+ case "date":
+ this.sortType = st.asDate;
+ break;
+ default:
+ this.sortType = st.none;
+ }
+ }
+ }
+ });
+
+ Ext.tree.Column = Ext.extend(Ext.list.Column, {});
+ Ext.tree.NumberColumn = Ext.extend(Ext.list.NumberColumn, {});
+ Ext.tree.DateColumn = Ext.extend(Ext.list.DateColumn, {});
+ Ext.tree.BooleanColumn = Ext.extend(Ext.list.BooleanColumn, {});
+
+ Ext.reg('tgcolumn', Ext.tree.Column);
+ Ext.reg('tgnumbercolumn', Ext.tree.NumberColumn);
+ Ext.reg('tgdatecolumn', Ext.tree.DateColumn);
+ Ext.reg('tgbooleancolumn', Ext.tree.BooleanColumn);
+})();
+/*!
+ * Ext JS Library 3.1.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/**
+ * @class Ext.ux.tree.TreeGrid
+ * @extends Ext.tree.TreePanel
+ *
+ * @xtype treegrid
+ */
+Ext.ux.tree.TreeGrid = Ext.extend(Ext.tree.TreePanel, {
+ rootVisible : false,
+ useArrows : true,
+ lines : false,
+ borderWidth : Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
+ cls : 'x-treegrid',
+
+ columnResize : true,
+ enableSort : true,
+ reserveScrollOffset : true,
+ enableHdMenu : true,
+
+ columnsText : 'Columns',
+
+ initComponent : function() {
+ if(!this.root) {
+ this.root = new Ext.tree.AsyncTreeNode({text: 'Root'});
+ }
- this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
- this.el.addClass('x-form-file-text');
- this.el.dom.removeAttribute('name');
+ // initialize the loader
+ var l = this.loader;
+ if(!l){
+ l = new Ext.ux.tree.TreeGridLoader({
+ dataUrl: this.dataUrl,
+ requestMethod: this.requestMethod,
+ store: this.store
+ });
+ }else if(Ext.isObject(l) && !l.load){
+ l = new Ext.ux.tree.TreeGridLoader(l);
+ }
+ else if(l) {
+ l.createNode = function(attr) {
+ if (!attr.uiProvider) {
+ attr.uiProvider = Ext.ux.tree.TreeGridNodeUI;
+ }
+ return Ext.tree.TreeLoader.prototype.createNode.call(this, attr);
+ }
+ }
+ this.loader = l;
+
+ Ext.ux.tree.TreeGrid.superclass.initComponent.call(this);
- this.fileInput = this.wrap.createChild({
- id: this.getFileInputId(),
- name: this.name||this.getId(),
- cls: 'x-form-file',
- tag: 'input',
- type: 'file',
- size: 1
- });
+ this.initColumns();
- var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
- text: this.buttonText
- });
- this.button = new Ext.Button(Ext.apply(btnCfg, {
- renderTo: this.wrap
- }));
+ if(this.enableSort) {
+ this.treeGridSorter = new Ext.ux.tree.TreeGridSorter(this, this.enableSort);
+ }
- if(this.buttonOnly){
- this.el.hide();
- this.wrap.setWidth(this.button.getEl().getWidth());
+ if(this.columnResize){
+ this.colResizer = new Ext.tree.ColumnResizer(this.columnResize);
+ this.colResizer.init(this);
}
- this.fileInput.on('change', function(){
- var v = this.fileInput.dom.value;
- this.setValue(v);
- this.fireEvent('fileselected', this, v);
- }, this);
+ var c = this.columns;
+ if(!this.internalTpl){
+ this.internalTpl = new Ext.XTemplate(
+ '<div class="x-grid3-header">',
+ '<div class="x-treegrid-header-inner">',
+ '<div class="x-grid3-header-offset">',
+ '<table cellspacing="0" cellpadding="0" border="0"><colgroup><tpl for="columns"><col /></tpl></colgroup>',
+ '<thead><tr class="x-grid3-hd-row">',
+ '<tpl for="columns">',
+ '<td class="x-grid3-hd x-grid3-cell x-treegrid-hd" style="text-align: {align};" id="', this.id, '-xlhd-{#}">',
+ '<div class="x-grid3-hd-inner x-treegrid-hd-inner" unselectable="on">',
+ this.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
+ '{header}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
+ '</div>',
+ '</td></tpl>',
+ '</tr></thead>',
+ '</div></table>',
+ '</div></div>',
+ '</div>',
+ '<div class="x-treegrid-root-node">',
+ '<table class="x-treegrid-root-table" cellpadding="0" cellspacing="0" style="table-layout: fixed;"></table>',
+ '</div>'
+ );
+ }
+
+ if(!this.colgroupTpl) {
+ this.colgroupTpl = new Ext.XTemplate(
+ '<colgroup><tpl for="columns"><col style="width: {width}px"/></tpl></colgroup>'
+ );
+ }
},
-
- // private
- getFileInputId: function(){
- return this.id+'-file';
+
+ initColumns : function() {
+ var cs = this.columns,
+ len = cs.length,
+ columns = [],
+ i, c;
+
+ for(i = 0; i < len; i++){
+ c = cs[i];
+ if(!c.isColumn) {
+ c.xtype = c.xtype ? (/^tg/.test(c.xtype) ? c.xtype : 'tg' + c.xtype) : 'tgcolumn';
+ c = Ext.create(c);
+ }
+ c.init(this);
+ columns.push(c);
+
+ if(this.enableSort !== false && c.sortable !== false) {
+ c.sortable = true;
+ this.enableSort = true;
+ }
+ }
+
+ this.columns = columns;
},
-
- // private
- onResize : function(w, h){
- Ext.form.FileUploadField.superclass.onResize.call(this, w, h);
+
+ onRender : function(){
+ Ext.tree.TreePanel.superclass.onRender.apply(this, arguments);
+
+ this.el.addClass('x-treegrid');
- this.wrap.setWidth(w);
+ this.outerCt = this.body.createChild({
+ cls:'x-tree-root-ct x-treegrid-ct ' + (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')
+ });
- if(!this.buttonOnly){
- var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
- this.el.setWidth(w);
+ this.internalTpl.overwrite(this.outerCt, {columns: this.columns});
+
+ this.mainHd = Ext.get(this.outerCt.dom.firstChild);
+ this.innerHd = Ext.get(this.mainHd.dom.firstChild);
+ this.innerBody = Ext.get(this.outerCt.dom.lastChild);
+ this.innerCt = Ext.get(this.innerBody.dom.firstChild);
+
+ this.colgroupTpl.insertFirst(this.innerCt, {columns: this.columns});
+
+ if(this.hideHeaders){
+ this.header.dom.style.display = 'none';
+ }
+ else if(this.enableHdMenu !== false){
+ this.hmenu = new Ext.menu.Menu({id: this.id + '-hctx'});
+ if(this.enableColumnHide !== false){
+ this.colMenu = new Ext.menu.Menu({id: this.id + '-hcols-menu'});
+ this.colMenu.on({
+ scope: this,
+ beforeshow: this.beforeColMenuShow,
+ itemclick: this.handleHdMenuClick
+ });
+ this.hmenu.add({
+ itemId:'columns',
+ hideOnClick: false,
+ text: this.columnsText,
+ menu: this.colMenu,
+ iconCls: 'x-cols-icon'
+ });
+ }
+ this.hmenu.on('itemclick', this.handleHdMenuClick, this);
}
- },
-
- // private
- preFocus : Ext.emptyFn,
-
- // private
- getResizeEl : function(){
- return this.wrap;
},
- // private
- getPositionEl : function(){
- return this.wrap;
+ setRootNode : function(node){
+ node.attributes.uiProvider = Ext.ux.tree.TreeGridRootNodeUI;
+ node = Ext.ux.tree.TreeGrid.superclass.setRootNode.call(this, node);
+ if(this.innerCt) {
+ this.colgroupTpl.insertFirst(this.innerCt, {columns: this.columns});
+ }
+ return node;
},
-
- // private
- alignErrorIcon : function(){
- this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
- }
-});
-Ext.reg('fileuploadfield', Ext.form.FileUploadField);
-
-/**
- * Ext.ux.FullProgressBar Class
- *
- * @author Damien Churchill <damoxc@gmail.com>
- * @version 1.2
- *
- * @class Ext.deluge.ProgressBar
- * @extends Ext.ProgressBar
- * @constructor
- * @param {Object} config Configuration options
- */
-Ext.ux.FullProgressBar = Ext.extend(Ext.ProgressBar, {
- initComponent: function() {
- Ext.ux.FullProgressBar.superclass.initComponent.call(this);
- },
-
- updateProgress: function(value, text, animate) {
- this.value = value || 0;
- if (text) {
- this.updateText(text);
- }
-
- if (this.rendered) {
- var w = Math.floor(value*this.el.dom.firstChild.offsetWidth / 100.0);
- this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
- if (this.textTopEl) {
- //textTopEl should be the same width as the bar so overflow will clip as the bar moves
- this.textTopEl.removeClass('x-hidden').setWidth(w);
- }
- }
- this.fireEvent('update', this, value, text);
- return this;
- }
-});
-Ext.reg('fullprogressbar', Ext.ux.FullProgressBar);
+ initEvents : function() {
+ Ext.ux.tree.TreeGrid.superclass.initEvents.apply(this, arguments);
+
+ this.mon(this.innerBody, 'scroll', this.syncScroll, this);
+ this.mon(this.innerHd, 'click', this.handleHdDown, this);
+ this.mon(this.mainHd, {
+ scope: this,
+ mouseover: this.handleHdOver,
+ mouseout: this.handleHdOut
+ });
+ },
+
+ onResize : function(w, h) {
+ Ext.ux.tree.TreeGrid.superclass.onResize.apply(this, arguments);
+
+ var bd = this.innerBody.dom;
+ var hd = this.innerHd.dom;
+ if(!bd){
+ return;
+ }
-// Allow radiogroups to be treated as a single form element.
-Ext.override(Ext.form.RadioGroup, {
+ if(Ext.isNumber(h)){
+ bd.style.height = this.body.getHeight(true) - hd.offsetHeight + 'px';
+ }
- afterRender: function() {
- var that = this;
- this.items.each(function(i) {
- that.relayEvents(i, ['check']);
- });
- Ext.form.RadioGroup.superclass.afterRender.call(this)
+ if(Ext.isNumber(w)){
+ var sw = Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
+ if(this.reserveScrollOffset || ((bd.offsetWidth - bd.clientWidth) > 10)){
+ this.setScrollOffset(sw);
+ }else{
+ var me = this;
+ setTimeout(function(){
+ me.setScrollOffset(bd.offsetWidth - bd.clientWidth > 10 ? sw : 0);
+ }, 10);
+ }
+ }
},
- getName: function() {
- return this.items.first().getName();
+ updateColumnWidths : function() {
+ var cols = this.columns,
+ colCount = cols.length,
+ groups = this.outerCt.query('colgroup'),
+ groupCount = groups.length,
+ c, g, i, j;
+
+ for(i = 0; i<colCount; i++) {
+ c = cols[i];
+ for(j = 0; j<groupCount; j++) {
+ g = groups[j];
+ g.childNodes[i].style.width = (c.hidden ? 0 : c.width) + 'px';
+ }
+ }
+
+ for(i = 0, groups = this.innerHd.query('td'), len = groups.length; i<len; i++) {
+ c = Ext.fly(groups[i]);
+ if(cols[i] && cols[i].hidden) {
+ c.addClass('x-treegrid-hd-hidden');
+ }
+ else {
+ c.removeClass('x-treegrid-hd-hidden');
+ }
+ }
+
+ var tcw = this.getTotalColumnWidth();
+ Ext.fly(this.innerHd.dom.firstChild).setWidth(tcw + (this.scrollOffset || 0));
+ this.outerCt.select('table').setWidth(tcw);
+ this.syncHeaderScroll();
+ },
+
+ getVisibleColumns : function() {
+ var columns = [],
+ cs = this.columns,
+ len = cs.length,
+ i;
+
+ for(i = 0; i<len; i++) {
+ if(!cs[i].hidden) {
+ columns.push(cs[i]);
+ }
+ }
+ return columns;
},
- getValue: function() {
- var v;
- v = this.items.first().getGroupValue();
- //this.items.each(function(item) {
- // v = item.getRawValue();
- // return !item.getValue();
- //});
- return v;
+ getTotalColumnWidth : function() {
+ var total = 0;
+ for(var i = 0, cs = this.getVisibleColumns(), len = cs.length; i<len; i++) {
+ total += cs[i].width;
+ }
+ return total;
},
- setValue: function(v) {
- if (!this.items.each) return;
- this.items.each(function(item) {
- var checked = (item.el.getValue() == String(v));
- if (item.rendered) {
- item.el.dom.checked = checked;
- item.el.dom.defaultChecked = checked;
- item.wrap[checked ? 'addClass' : 'removeClass'](item.checkedCls);
- }
- });
- }
-});
+ setScrollOffset : function(scrollOffset) {
+ this.scrollOffset = scrollOffset;
+ this.updateColumnWidths();
+ },
-Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, {
-
- // private
- defaultType: 'uxspinner',
-
- // private
- groupCls: 'x-form-uxspinner-group',
-
- colCfg: {},
-
- // private
- onRender : function(ct, position){
- if(!this.el){
- var panelCfg = {
- cls: this.groupCls,
- layout: 'column',
- border: false,
- renderTo: ct
- };
- var colCfg = Ext.apply({
- defaultType: this.defaultType,
- layout: 'form',
- border: false,
- labelWidth: 60,
- defaults: {
- hideLabel: true,
- anchor: '100%'
- }
- }, this.colCfg);
-
- if(this.items[0].items){
-
- // The container has standard ColumnLayout configs, so pass them in directly
-
- Ext.apply(panelCfg, {
- layoutConfig: {columns: this.items.length},
- defaults: this.defaults,
- items: this.items
- })
- for(var i=0, len=this.items.length; i<len; i++){
- Ext.applyIf(this.items[i], colCfg);
- };
-
- }else{
-
- // The container has field item configs, so we have to generate the column
- // panels first then move the items into the columns as needed.
-
- var numCols, cols = [];
-
- if(typeof this.columns == 'string'){ // 'auto' so create a col per item
- this.columns = this.items.length;
- }
- if(!Ext.isArray(this.columns)){
- var cs = [];
- for(var i=0; i<this.columns; i++){
- cs.push((100/this.columns)*.01); // distribute by even %
- }
- this.columns = cs;
- }
-
- numCols = this.columns.length;
-
- // Generate the column configs with the correct width setting
- for(var i=0; i<numCols; i++){
- var cc = Ext.apply({items:[]}, colCfg);
- cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
- if(this.defaults){
- cc.defaults = Ext.apply(cc.defaults || {}, this.defaults)
- }
- cols.push(cc);
- };
-
- // Distribute the original items into the columns
- if(this.vertical){
- var rows = Math.ceil(this.items.length / numCols), ri = 0;
- for(var i=0, len=this.items.length; i<len; i++){
- if(i>0 && i%rows==0){
- ri++;
- }
- if(this.items[i].fieldLabel){
- this.items[i].hideLabel = false;
- }
- cols[ri].items.push(this.items[i]);
- };
- }else{
- for(var i=0, len=this.items.length; i<len; i++){
- var ci = i % numCols;
- if(this.items[i].fieldLabel){
- this.items[i].hideLabel = false;
- }
- cols[ci].items.push(this.items[i]);
- };
- }
-
- Ext.apply(panelCfg, {
- layoutConfig: {columns: numCols},
- items: cols
- });
- }
-
- this.panel = new Ext.Panel(panelCfg);
- this.el = this.panel.getEl();
-
- if(this.forId && this.itemCls){
- var l = this.el.up(this.itemCls).child('label', true);
- if(l){
- l.setAttribute('htmlFor', this.forId);
- }
- }
-
- var fields = this.panel.findBy(function(c){
- return c.isFormField;
- }, this);
-
- this.items = new Ext.util.MixedCollection();
- this.items.addAll(fields);
-
- this.items.each(function(field) {
- field.on('change', this.onFieldChange, this);
- }, this);
- }
-
- Ext.ux.form.SpinnerGroup.superclass.onRender.call(this, ct, position);
- },
-
- onFieldChange: function(spinner, value) {
- this.fireEvent('change', this, this.getValue());
- },
-
- initValue : Ext.emptyFn,
+ // private
+ handleHdDown : function(e, t){
+ var hd = e.getTarget('.x-treegrid-hd');
+
+ if(hd && Ext.fly(t).hasClass('x-grid3-hd-btn')){
+ var ms = this.hmenu.items,
+ cs = this.columns,
+ index = this.findHeaderIndex(hd),
+ c = cs[index],
+ sort = c.sortable;
+
+ e.stopEvent();
+ Ext.fly(hd).addClass('x-grid3-hd-menu-open');
+ this.hdCtxIndex = index;
+
+ this.fireEvent('headerbuttonclick', ms, c, hd, index);
+
+ this.hmenu.on('hide', function(){
+ Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
+ }, this, {single:true});
+
+ this.hmenu.show(t, 'tl-bl?');
+ }
+ else if(hd) {
+ var index = this.findHeaderIndex(hd);
+ this.fireEvent('headerclick', this.columns[index], hd, index);
+ }
+ },
- getValue: function() {
- var value = [this.items.getCount()];
- this.items.each(function(item, i) {
- value[i] = Number(item.getValue());
- });
- return value;
- },
+ // private
+ handleHdOver : function(e, t){
+ var hd = e.getTarget('.x-treegrid-hd');
+ if(hd && !this.headersDisabled){
+ index = this.findHeaderIndex(hd);
+ this.activeHdRef = t;
+ this.activeHdIndex = index;
+ var el = Ext.get(hd);
+ this.activeHdRegion = el.getRegion();
+ el.addClass('x-grid3-hd-over');
+ this.activeHdBtn = el.child('.x-grid3-hd-btn');
+ if(this.activeHdBtn){
+ this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
+ }
+ }
+ },
+
+ // private
+ handleHdOut : function(e, t){
+ var hd = e.getTarget('.x-treegrid-hd');
+ if(hd && (!Ext.isIE || !e.within(hd, true))){
+ this.activeHdRef = null;
+ Ext.fly(hd).removeClass('x-grid3-hd-over');
+ hd.style.cursor = '';
+ }
+ },
+
+ findHeaderIndex : function(hd){
+ hd = hd.dom || hd;
+ var cs = hd.parentNode.childNodes;
+ for(var i = 0, c; c = cs[i]; i++){
+ if(c == hd){
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ // private
+ beforeColMenuShow : function(){
+ var cols = this.columns,
+ colCount = cols.length,
+ i, c;
+ this.colMenu.removeAll();
+ for(i = 1; i < colCount; i++){
+ c = cols[i];
+ if(c.hideable !== false){
+ this.colMenu.add(new Ext.menu.CheckItem({
+ itemId: 'col-' + i,
+ text: c.header,
+ checked: !c.hidden,
+ hideOnClick:false,
+ disabled: c.hideable === false
+ }));
+ }
+ }
+ },
+
+ // private
+ handleHdMenuClick : function(item){
+ var index = this.hdCtxIndex,
+ id = item.getItemId();
+
+ if(this.fireEvent('headermenuclick', this.columns[index], id, index) !== false) {
+ index = id.substr(4);
+ if(index > 0 && this.columns[index]) {
+ this.setColumnVisible(index, !item.checked);
+ }
+ }
+
+ return true;
+ },
+
+ setColumnVisible : function(index, visible) {
+ this.columns[index].hidden = !visible;
+ this.updateColumnWidths();
+ },
- getRawValue: function() {
- var value = [this.items.getCount()];
- this.items.each(function(item, i) {
- value[i] = Number(item.getRawValue());
- });
- return value;
- },
+ /**
+ * Scrolls the grid to the top
+ */
+ scrollToTop : function(){
+ this.innerBody.dom.scrollTop = 0;
+ this.innerBody.dom.scrollLeft = 0;
+ },
- setValue: function(value) {
- this.items.each(function(item, i) {
- item.setValue(value[i]);
- });
- },
+ // private
+ syncScroll : function(){
+ this.syncHeaderScroll();
+ var mb = this.innerBody.dom;
+ this.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
+ },
- setRawValue: function(value) {
- this.items.each(function(item, i) {
- item.setRawValue(value[i]);
- });
- }
-});
-Ext.reg('uxspinnergroup', Ext.ux.form.SpinnerGroup);
-
-// Taken from http://extjs.com/forum/showthread.php?t=75273
-// remove spaces for hidden elements and make show(), hide(), enable() and disable() act on the label. don't use hideLabel with this
-//Ext.override(Ext.layout.FormLayout, {
-// renderItem: function(c, position, target) {
-// if (c && !c.rendered && c.isFormField && c.inputType != 'hidden') {
-// var args = [
-// c.id, c.fieldLabel,
-// c.labelStyle||this.labelStyle||'',
-// this.elementStyle||'',
-// typeof c.labelSeparator == 'undefined' ? this.labelSeparator : c.labelSeparator,
-// (c.itemCls||this.container.itemCls||'') + (c.hideLabel ? ' x-hide-label' : ''),
-// c.clearCls || 'x-form-clear-left'
-// ];
-// if(typeof position == 'number') {
-// position = target.dom.childNodes[position] || null;
-// }
-// if (position) {
-// c.formItem = this.fieldTpl.insertBefore(position, args, true);
-// }
-// else {
-// c.formItem = this.fieldTpl.append(target, args, true);
-// }
-// c.actionMode = 'formItem';
-// c.render('x-form-el-'+c.id);
-// c.container = c.formItem;
-// c.actionMode = 'container';
-// }
-// else {
-// Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
-// }
-// }
-//});
-Ext.override(Ext.form.TriggerField, {
- actionMode: 'wrap',
- onShow: Ext.form.TriggerField.superclass.onShow,
- onHide: Ext.form.TriggerField.superclass.onHide
+ // private
+ syncHeaderScroll : function(){
+ var mb = this.innerBody.dom;
+ this.innerHd.dom.scrollLeft = mb.scrollLeft;
+ this.innerHd.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)
+ },
+
+ registerNode : function(n) {
+ Ext.ux.tree.TreeGrid.superclass.registerNode.call(this, n);
+ if(!n.uiProvider && !n.isRoot && !n.ui.isTreeGridNodeUI) {
+ n.ui = new Ext.ux.tree.TreeGridNodeUI(n);
+ }
+ }
});
-Ext.ux.JSLoader = function(options) {
- Ext.ux.JSLoader.scripts[++Ext.ux.JSLoader.index] = {
- url: options.url,
- success: true,
- jsLoadObj: null,
- options: options,
- onLoad: options.onLoad || Ext.emptyFn,
- onError: options.onError || Ext.ux.JSLoader.stdError,
- scope: options.scope || this
- };
-
- Ext.Ajax.request({
- url: options.url,
- scriptIndex: Ext.ux.JSLoader.index,
- success: function(response, options) {
- var script = Ext.ux.JSLoader.scripts[options.scriptIndex];
- try {
- eval(response.responseText);
- } catch(e) {
- script.success = false;
- script.onError(script.options, e);
- }
- if (script.success) script.onLoad.call(script.scope, script.options);
- },
- failure: function(response, options) {
- var script = Ext.ux.JSLoader.scripts[options.scriptIndex];
- script.success = false;
- script.onError(script.options, response.status);
- }
- });
-}
-Ext.ux.JSLoader.index = 0;
-Ext.ux.JSLoader.scripts = [];
-Ext.ux.JSLoader.stdError = function(options, e) {
- // throw(e);
- window.alert('Error loading script:\n\n' + options.url + '\n\nstatus: ' + e);
-}
+Ext.reg('treegrid', Ext.ux.tree.TreeGrid); \ No newline at end of file