/**
* Search plugin for Ext.grid.GridPanel, Ext.grid.EditorGrid ver. 2.x or subclasses of them
*
* @author Ing. Jozef Sakalos
* @copyright (c) 2008, by Ing. Jozef Sakalos
* @date 17. January 2008
* @version $Id: Ext.ux.grid.Search.js 120 2008-03-31 00:09:05Z jozo $
*
* @license Ext.ux.grid.Search is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/
/*global Ext */
Ext.ns('Ext.ux.grid');
/**
* @class Ext.ux.grid.Search
* @extends Ext.util.Observable
* @param {Object} config configuration object
* @constructor
*/
Ext.ux.grid.Search = function(config) {
Ext.apply(this, config);
Ext.ux.grid.Search.superclass.constructor.call(this);
}; // eo constructor
Ext.extend(Ext.ux.grid.Search, Ext.util.Observable, {
/**
* @cfg {String} searchText Text to display on menu button
*/
searchText:'Suche'
/**
* @cfg {String} searchTipText Text to display as input tooltip. Set to '' for no tooltip
*/
,searchTipText:'Fügen Sie einen oder mehrere Suchbegriffe'
/**
* @cfg {String} selectAllText Text to display on menu item that selects all fields
*/
,selectAllText:'Alle auswählen'
,fieldsprefix: 'tbl_name'
,additionalField: ''
/**
* @cfg {String} position Where to display the search controls. Valid values are top and bottom (defaults to bottom)
* Corresponding toolbar has to exist at least with mimimum configuration tbar:[] for position:top or bbar:[]
* for position bottom. Plugin does NOT create any toolbar.
*/
,position:'top'
/**
* @cfg {String} iconCls Icon class for menu button (defaults to icon-magnifier)
*/
,iconCls:'icon-magnifier'
/**
* @cfg {String/Array} checkIndexes Which indexes to check by default. Can be either 'all' for all indexes
* or array of dataIndex names, e.g. ['persFirstName', 'persLastName']
*/
,checkIndexes:'all'
/**
* @cfg {Array} disableIndexes Array of index names to disable (not show in the menu), e.g. ['persTitle', 'persTitle2']
*/
,disableIndexes:[]
/**
* @cfg {String} dateFormat how to format date values. If undefined (the default)
* date is formatted as configured in colummn model
*/
,dateFormat:undefined
/**
* @cfg {Boolean} showSelectAll Select All item is shown in menu if true (defaults to true)
*/
,showSelectAll:true
/**
* @cfg {String} mode Use 'remote' for remote stores or 'local' for local stores. If mode is local
* no data requests are sent to server the grid's store is filtered instead (defaults to 'remote')
*/
,mode:'remote'
/**
* @cfg {Number} width Width of input field in pixels (defaults to 100)
*/
,width:300
/**
* @cfg {String} xtype xtype is usually not used to instantiate this plugin but you have a chance to identify it
*/
,xtype:'gridsearch'
/**
* @cfg {Object} paramNames Params name map (defaults to {fields:'fields', query:'query'}
*/
,paramNames: {
fields:'fields'
,query:'query'
,start:0
}
/**
* @cfg {String} shortcutKey Key to fucus the input field (defaults to r = Sea_r_ch). Empty string disables shortcut
*/
,shortcutKey:'r'
/**
* @cfg {String} shortcutModifier Modifier for shortcutKey. Valid values: alt, ctrl, shift (defaults to alt)
*/
,shortcutModifier:'alt'
/**
* @cfg {String} align 'left' or 'right' (defaults to 'left')
*/
/**
* @cfg {Number} minLength force user to type this many character before he can make a search
*/
,minLength: 3
/**
* @cfg {Ext.Panel/String} toolbarContainer Panel (or id of the panel) which contains toolbar we want to render
* search controls to (defaults to this.grid, the grid this plugin is plugged-in into)
*/
// {{{
/**
* private
* @param {Ext.grid.GridPanel/Ext.grid.EditorGrid} grid reference to grid this plugin is used for
*/
,init:function(grid) {
this.grid = grid;
// setup toolbar container if id was given
if('string' === typeof this.toolbarContainer) {
this.toolbarContainer = Ext.getCmp(this.toolbarContainer);
}
// do our processing after grid render and reconfigure
grid.onRender = grid.onRender.createSequence(this.onRender, this);
grid.reconfigure = grid.reconfigure.createSequence(this.reconfigure, this);
} // eo function init
// }}}
// {{{
/**
* private add plugin controls to existing toolbar and calls reconfigure
*/
,onRender:function() {
var panel = this.toolbarContainer || this.grid;
var tb = 'bottom' === this.position ? panel.bottomToolbar : panel.topToolbar;
// add menu
this.menu = new Ext.menu.Menu();
// handle position
if('right' === this.align) {
tb.addFill();
}
else {
tb.addSeparator();
}
// add menu button
tb.add({
text:this.searchText
,menu:this.menu
,iconCls:this.iconCls
});
// add input field (TwinTriggerField in fact)
this.field = new Ext.form.TriggerField({
width: this.width
,selectOnFocus:undefined === this.selectOnFocus ? true : this.selectOnFocus
,triggerClass:'x-form-clear-trigger'
,trigger2Class:'x-form-search-trigger'
,onTriggerClick:this.onTriggerClear.createDelegate(this)
,onTrigger2Click:this.onTriggerSearch.createDelegate(this)
,minLength:this.minLength
});
// install event handlers on input field
this.field.on('render', function() {
this.field.el.dom.qtip = this.searchTipText;
// install key map
var map = new Ext.KeyMap(this.field.el, [{
key:Ext.EventObject.ENTER
,scope:this
,fn:this.onTriggerSearch
},{
key:Ext.EventObject.ESC
,scope:this
,fn:this.onTriggerClear
}]);
map.stopEvent = true;
}, this, {single:true});
tb.add(this.field);
// reconfigure
this.reconfigure();
// keyMap
if(this.shortcutKey && this.shortcutModifier) {
var shortcutEl = this.grid.getEl();
var shortcutCfg = [{
key:this.shortcutKey
,scope:this
,stopEvent:true
,fn:function() {
this.field.focus();
}
}];
shortcutCfg[0][this.shortcutModifier] = true;
this.keymap = new Ext.KeyMap(shortcutEl, shortcutCfg);
}
} // eo function onRender
// }}}
// {{{
/**
* private Clear Trigger click handler
*/
,onTriggerClear:function() {
this.field.setValue('');
this.field.focus();
this.onTriggerSearch();
} // eo function onTriggerClear
// }}}
// {{{
/**
* private Search Trigger click handler (executes the search, local or remote)
*/
,onTriggerSearch:function() {
if(!this.field.isValid()) {
return;
}
var val = this.field.getValue();
var store = this.grid.store;
// grid's store filter
if('local' === this.mode) {
store.clearFilter();
if(val) {
store.filterBy(function(r) {
var retval = false;
this.menu.items.each(function(item) {
if(!item.checked || retval) {
return;
}
var rv = r.get(item.dataIndex);
rv = rv instanceof Date ? rv.format(this.dateFormat || r.fields.get(item.dataIndex).dateFormat) : rv;
var re = new RegExp(val, 'gi');
retval = re.test(rv);
}, this);
if(retval) {
return true;
}
return retval;
}, this);
}
else {
}
}
// ask server to filter records
else {
// clear start (necessary if we have paging)
if(store.lastOptions && store.lastOptions.params) {
store.lastOptions.params[store.paramNames.start] = 0;
}
// get fields to search array
var fields = [];
prefix = this.fieldsprefix;
var extra_field=this.additionalField;
this.menu.items.each(function(item) {
if ((item.checked) && (item.dataIndex) && ((item.dataIndex) != extra_field)){
fields.push(prefix+item.dataIndex);
}
});
if (this.additionalField)
fields.push(this.additionalField);
// add fields and query to baseParams of store
delete(store.baseParams[this.paramNames.fields]);
delete(store.baseParams[this.paramNames.query]);
if (store.lastOptions && store.lastOptions.params) {
delete(store.lastOptions.params[this.paramNames.fields]);
delete(store.lastOptions.params[this.paramNames.query]);
}
if(fields.length) {
store.baseParams[this.paramNames.fields] = Ext.util.JSON.encode(fields);
store.baseParams[this.paramNames.query] = val;
store.baseParams['search'] = 1;
}
// reload store
store.reload();
}
} // eo function onTriggerSearch
// }}}
// {{{
/**
* @param {Boolean} true to disable search (TwinTriggerField), false to enable
*/
,setDisabled:function() {
this.field.setDisabled.apply(this.field, arguments);
} // eo function setDisabled
// }}}
// {{{
/**
* Enable search (TwinTriggerField)
*/
,enable:function() {
this.setDisabled(false);
} // eo function enable
// }}}
// {{{
/**
* Enable search (TwinTriggerField)
*/
,disable:function() {
this.setDisabled(true);
} // eo function disable
// }}}
// {{{
/**
* private (re)configures the plugin, creates menu items from column model
*/
,reconfigure:function() {
// {{{
// remove old items
var menu = this.menu;
menu.removeAll();
// add Select All item plus separator
if(this.showSelectAll) {
menu.add(new Ext.menu.CheckItem({
text:this.selectAllText
,checked:!(this.checkIndexes instanceof Array)
,hideOnClick:false
,handler:function(item) {
var checked = ! item.checked;
item.parentMenu.items.each(function(i) {
if(item !== i && i.setChecked) {
i.setChecked(checked);
}
});
}
}),'-');
}
// }}}
// {{{
// add new items
var cm = this.grid.colModel;
Ext.each(cm.config, function(config) {
var disable = false;
if(config.header && config.dataIndex) {
Ext.each(this.disableIndexes, function(item) {
disable = disable ? disable : item === config.dataIndex;
});
if(!disable) {
menu.add(new Ext.menu.CheckItem({
text:config.header
,hideOnClick:false
,checked:'all' === this.checkIndexes
,dataIndex:config.dataIndex
}));
}
}
}, this);
// }}}
// {{{
// check items
if(this.checkIndexes instanceof Array) {
Ext.each(this.checkIndexes, function(di) {
var item = menu.items.find(function(itm) {
return itm.dataIndex === di;
});
if(item) {
item.setChecked(true, true);
}
}, this);
}
// }}}
} // eo function reconfigure
// }}}
}); // eo extend
// eof
Ext.ns("Ext.ux.grid.GridSummary");
Ext.ux.grid.GridSummary = function(config) {
Ext.apply(this, config);
};
Ext.extend(Ext.ux.grid.GridSummary, Ext.util.Observable, {
init : function(grid) {
this.grid = grid;
this.cm = grid.getColumnModel();
this.view = grid.getView();
var v = this.view;
v.onLayout = this.onLayout; // override GridView's onLayout() method
v.afterMethod('render', this.refreshSummary, this);
v.afterMethod('refresh', this.refreshSummary, this);
v.afterMethod('syncScroll', this.syncSummaryScroll, this);
v.afterMethod('onColumnWidthUpdated', this.doWidth, this);
v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);
v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);
v.afterMethod('onUpdate', this.refreshSummary, this);
v.afterMethod('onRemove', this.refreshSummary, this);
// update summary row on store's add / remove / clear events
grid.store.on('add', this.refreshSummary, this);
grid.store.on('remove', this.refreshSummary, this);
grid.store.on('clear', this.refreshSummary, this);
if (!this.rowTpl) {
this.rowTpl = new Ext.Template(
'
',
'
',
'
{cells}
',
'
',
'
'
);
this.rowTpl.disableFormats = true;
}
this.rowTpl.compile();
if (!this.cellTpl) {
this.cellTpl = new Ext.Template(
'
',
'
{value}
',
"
"
);
this.cellTpl.disableFormats = true;
}
this.cellTpl.compile();
},
calculate : function(rs, cm) {
var data = {}, cfg = cm.config;
for (var i = 0, len = cfg.length; i < len; i++) { // loop through all columns in ColumnModel
var cf = cfg[i], // get column's configuration
cname = cf.dataIndex; // get column dataIndex
// initialise grid summary row data for
// the current column being worked on
data[cname] = 0;
if (cf.summaryType) {
for (var j = 0, jlen = rs.length; j < jlen; j++) {
var r = rs[j]; // get a single Record
data[cname] = Ext.ux.grid.GridSummary.Calculations[cf.summaryType](r.get(cname), r, cname, data, j);
}
}
}
return data;
},
onLayout : function(vw, vh) {
if (Ext.type(vh) != 'number') { // handles grid's height:'auto' config
return;
}
// note: this method is scoped to the GridView
if (!this.grid.getGridEl().hasClass('x-grid-hide-gridsummary')) {
// readjust gridview's height only if grid summary row is visible
this.scroller.setHeight(vh - this.summary.getHeight());
}
},
syncSummaryScroll : function() {
var mb = this.view.scroller.dom;
this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft;
this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)
},
doWidth : function(col, w, tw) {
var s = this.view.summary.dom;
s.firstChild.style.width = tw;
s.firstChild.rows[0].childNodes[col].style.width = w;
},
doAllWidths : function(ws, tw) {
var s = this.view.summary.dom, wlen = ws.length;
s.firstChild.style.width = tw;
cells = s.firstChild.rows[0].childNodes;
for (var j = 0; j < wlen; j++) {
cells[j].style.width = ws[j];
}
},
doHidden : function(col, hidden, tw) {
var s = this.view.summary.dom,
display = hidden ? 'none' : '';
s.firstChild.style.width = tw;
s.firstChild.rows[0].childNodes[col].style.display = display;
},
renderSummary : function(o, cs, cm) {
cs = cs || this.view.getColumnData();
var cfg = cm.config,
buf = [],
last = cs.length - 1;
for (var i = 0, len = cs.length; i < len; i++) {
var c = cs[i], cf = cfg[i], p = {};
p.id = c.id;
p.style = c.style;
p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
if (cf.summaryType || cf.summaryRenderer) {
p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o);
} else {
p.value = '';
}
if (p.value == undefined || p.value === "") p.value = " ";
buf[buf.length] = this.cellTpl.apply(p);
}
return this.rowTpl.apply({
tstyle: 'width:' + this.view.getTotalWidth() + ';',
cells: buf.join('')
});
},
refreshSummary : function() {
var g = this.grid, ds = g.store,
cs = this.view.getColumnData(),
cm = this.cm,
rs = ds.getRange(),
data = this.calculate(rs, cm),
buf = this.renderSummary({data: data}, cs, cm);
if (!this.view.summaryWrap) {
this.view.summaryWrap = Ext.DomHelper.insertAfter(this.view.scroller, {
tag: 'div',
cls: 'x-grid3-gridsummary-row-inner'
}, true);
} else {
this.view.summary.remove();
}
this.view.summary = this.view.summaryWrap.insertHtml('afterbegin', buf, true);
},
toggleSummary : function(visible) { // true to display summary row
var el = this.grid.getGridEl();
if (el) {
if (visible === undefined) {
visible = el.hasClass('x-grid-hide-gridsummary');
}
el[visible ? 'removeClass' : 'addClass']('x-grid-hide-gridsummary');
this.view.layout(); // readjust gridview height
}
},
getSummaryNode : function() {
return this.view.summary
}
});
/*
* all Calculation methods are called on each Record in the Store
* with the following 5 parameters:
*
* v - cell value
* record - reference to the current Record
* colName - column name (i.e. the ColumnModel's dataIndex)
* data - the cumulative data for the current column + summaryType up to the current Record
* rowIdx - current row index
*/
Ext.ux.grid.GridSummary.Calculations = {
sum : function(v, record, colName, data, rowIdx) {
return data[colName] + Ext.num(v, 0);
},
count : function(v, record, colName, data, rowIdx) {
return rowIdx + 1;
},
max : function(v, record, colName, data, rowIdx) {
return Math.max(Ext.num(v, 0), data[colName]);
},
min : function(v, record, colName, data, rowIdx) {
return Math.min(Ext.num(v, 0), data[colName]);
},
average : function(v, record, colName, data, rowIdx) {
var t = data[colName] + Ext.num(v, 0), count = record.store.getCount();
return rowIdx == count - 1 ? (t / count) : t;
}
}
Ext.namespace('Ext.ux.Andrie');
/**
* @class Ext.ux.Andrie.pPageSize
* @extends Ext.PagingToolbar
* A combobox control that glues itself to a PagingToolbar's pageSize configuration property.
* @constructor
* Create a new PageSize plugin.
* @param {Object} config Configuration options
* @author Andrei Neculau - andrei.neculau@gmail.com / http://andreineculau.wordpress.com
* @version 0.6
*/
Ext.ux.Andrie.pPageSize = function(config){
Ext.apply(this, config);
};
Ext.extend(Ext.ux.Andrie.pPageSize, Ext.util.Observable, {
/**
* @cfg {String} beforeText
* Text to display before the comboBox
*/
beforeText: '  ',
/**
* @cfg {String} afterText
* Text to display after the comboBox
*/
afterText: '   Einträge pro Seite anzeigen  ',
/**
* @cfg {Mixed} addBefore
* Toolbar item(s) to add before the PageSizer
*/
addBefore: '-',
/**
* @cfg {Mixed} addAfter
* Toolbar item(s) to be added after the PageSizer
*/
addAfter: null,
/**
* @cfg {Bool} dynamic
* True for dynamic variations, false for static ones
*/
dynamic: false,
/**
* @cfg {Array} variations
* Variations used for determining pageSize options
*/
variations: [5, 10, 20, 50, 100, 200, 500, 1000],
/**
* @cfg {Object} comboCfg
* Combo config object that overrides the defaults
*/
comboCfg: undefined,
init: function(pagingToolbar){
this.pagingToolbar = pagingToolbar;
this.pagingToolbar.pageSizeCombo = this;
this.pagingToolbar.setPageSize = this.setPageSize.createDelegate(this);
this.pagingToolbar.getPageSize = function(){
return this.pageSize;
}
this.pagingToolbar.on('render', this.onRender, this);
},
//private
addSize:function(value){
if (value>0){
this.sizes.push([value]);
}
},
//private
updateStore: function(){
if (this.dynamic) {
var middleValue = this.pagingToolbar.pageSize, start;
middleValue = (middleValue > 0) ? middleValue : 1;
this.sizes = [];
var v = this.variations;
for (var i = 0, len = v.length; i < len; i++) {
this.addSize(middleValue - v[v.length - 1 - i]);
}
this.addToStore(middleValue);
for (var i = 0, len = v.length; i < len; i++) {
this.addSize(middleValue + v[i]);
}
}else{
if (!this.staticSizes){
this.sizes = [];
var v = this.variations;
var middleValue = 0;
for (var i = 0, len = v.length; i < len; i++) {
this.addSize(middleValue + v[i]);
}
this.staticSizes = this.sizes.slice(0);
}else{
this.sizes = this.staticSizes.slice(0);
}
}
this.combo.store.loadData(this.sizes);
this.combo.collapse();
this.combo.setValue(this.pagingToolbar.pageSize);
},
setPageSize:function(value, forced){
var pt = this.pagingToolbar;
this.combo.collapse();
value = parseInt(value) || parseInt(this.combo.getValue());
value = (value>0)?value:1;
if (value == pt.pageSize){
return;
}else if (value < pt.pageSize){
pt.pageSize = value;
var ap = Math.round(pt.cursor/value)+1;
var cursor = (ap-1)*value;
var store = pt.store;
if (cursor > store.getTotalCount()) {
this.pagingToolbar.pageSize = value;
this.pagingToolbar.doLoad(cursor-value);
}else{
store.suspendEvents();
for (var i = 0, len = cursor - pt.cursor; i < len; i++) {
store.remove(store.getAt(0));
}
while (store.getCount() > value) {
store.remove(store.getAt(store.getCount() - 1));
}
store.resumeEvents();
store.fireEvent('datachanged', store);
pt.cursor = cursor;
var d = pt.getPageData();
pt.afterTextEl.el.innerHTML = String.format(pt.afterPageText, d.pages);
pt.field.dom.value = ap;
pt.first.setDisabled(ap == 1);
pt.prev.setDisabled(ap == 1);
pt.next.setDisabled(ap == d.pages);
pt.last.setDisabled(ap == d.pages);
pt.updateInfo();
}
}else{
this.pagingToolbar.pageSize = value;
this.pagingToolbar.doLoad(Math.floor(this.pagingToolbar.cursor/this.pagingToolbar.pageSize) * this.pagingToolbar.pageSize);
}
this.updateStore();
},
//private
onRender: function(){
this.combo = Ext.ComponentMgr.create(Ext.applyIf(this.comboCfg||{}, {
store:new Ext.data.SimpleStore({
fields:['pageSize'],
data:[]
}),
displayField:'pageSize',
valueField:'pageSize',
mode:'local',
triggerAction:'all',
width:80,
emptyText: oc.limit_records,
xtype:'combo',
editable: false
}));
this.combo.setValue(1111);
this.combo.on('select', this.setPageSize, this);
this.updateStore();
if (this.addBefore){
this.pagingToolbar.add(this.addBefore);
}
if (this.beforeText){
this.pagingToolbar.add(this.beforeText);
}
this.pagingToolbar.add(this.combo);
if (this.afterText){
this.pagingToolbar.add(this.afterText);
}
if (this.addAfter){
this.pagingToolbar.add(this.addAfter);
}
}
});
/*!
* Ext JS Library 3.2.1
* Copyright(c) 2006-2010 Ext JS, Inc.
* licensing@extjs.com
* http://www.extjs.com/license
*/
/*!
* Ext JS Library 3.2.0
* Copyright(c) 2006-2010 Ext JS, Inc.
* licensing@extjs.com
* http://www.extjs.com/license
*/
Ext.ns('Ext.ux.grid');
/**
* @class Ext.ux.grid.GroupSummary
* @extends Ext.util.Observable
* A GridPanel plugin that enables dynamic column calculations and a dynamically
* updated grouped summary row.
*/
Ext.ux.grid.GroupSummary = Ext.extend(Ext.util.Observable, {
/**
* @cfg {Function} summaryRenderer Renderer example:
*/
/**
* @cfg {String} summaryType (Optional) The type of
* calculation to be used for the column. For options available see
* {@link #Calculations}.
*/
constructor : function(config){
Ext.apply(this, config);
Ext.ux.grid.GroupSummary.superclass.constructor.call(this);
},
init : function(grid){
this.grid = grid;
var v = this.view = grid.getView();
v.doGroupEnd = this.doGroupEnd.createDelegate(this);
v.afterMethod('onColumnWidthUpdated', this.doWidth, this);
v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this);
v.afterMethod('onColumnHiddenUpdated', this.doHidden, this);
v.afterMethod('onUpdate', this.doUpdate, this);
v.afterMethod('onRemove', this.doRemove, this);
if(!this.rowTpl){
this.rowTpl = new Ext.Template(
'
"
);
this.cellTpl.disableFormats = true;
}
this.cellTpl.compile();
},
/**
* Toggle the display of the summary row on/off
* @param {Boolean} visible true to show the summary, false to hide the summary.
*/
toggleSummaries : function(visible){
var el = this.grid.getGridEl();
if(el){
if(visible === undefined){
visible = el.hasClass('x-grid-hide-summary');
}
el[visible ? 'removeClass' : 'addClass']('x-grid-hide-summary');
}
},
renderSummary : function(o, cs){
cs = cs || this.view.getColumnData();
var cfg = this.grid.getColumnModel().config,
buf = [], c, p = {}, cf, last = cs.length-1;
for(var i = 0, len = cs.length; i < len; i++){
c = cs[i];
cf = cfg[i];
p.id = c.id;
p.style = c.style;
p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
if(cf.summaryType || cf.summaryRenderer){
p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o);
}else{
p.value = '';
}
if(p.value == undefined || p.value === "") p.value = " ";
buf[buf.length] = this.cellTpl.apply(p);
}
return this.rowTpl.apply({
tstyle: 'width:'+this.view.getTotalWidth()+';',
cells: buf.join('')
});
},
/**
* @private
* @param {Object} rs
* @param {Object} cs
*/
calculate : function(rs, cs){
var data = {}, r, c, cfg = this.grid.getColumnModel().config, cf;
for(var j = 0, jlen = rs.length; j < jlen; j++){
r = rs[j];
for(var i = 0, len = cs.length; i < len; i++){
c = cs[i];
cf = cfg[i];
if(cf.summaryType){
data[c.name] = Ext.ux.grid.GroupSummary.Calculations[cf.summaryType](data[c.name] || 0, r, c.name, data);
}
}
}
return data;
},
doGroupEnd : function(buf, g, cs, ds, colCount){
var data = this.calculate(g.rs, cs);
buf.push('', this.renderSummary({data: data}, cs), '');
},
doWidth : function(col, w, tw){
if(!this.isGrouped()){
return;
}
var gs = this.view.getGroups(),
len = gs.length,
i = 0,
s;
for(; i < len; ++i){
s = gs[i].childNodes[2];
s.style.width = tw;
s.firstChild.style.width = tw;
s.firstChild.rows[0].childNodes[col].style.width = w;
}
},
doAllWidths : function(ws, tw){
if(!this.isGrouped()){
return;
}
var gs = this.view.getGroups(),
len = gs.length,
i = 0,
j,
s,
cells,
wlen = ws.length;
for(; i < len; i++){
s = gs[i].childNodes[2];
s.style.width = tw;
s.firstChild.style.width = tw;
cells = s.firstChild.rows[0].childNodes;
for(j = 0; j < wlen; j++){
cells[j].style.width = ws[j];
}
}
},
doHidden : function(col, hidden, tw){
if(!this.isGrouped()){
return;
}
var gs = this.view.getGroups(),
len = gs.length,
i = 0,
s,
display = hidden ? 'none' : '';
for(; i < len; i++){
s = gs[i].childNodes[2];
s.style.width = tw;
s.firstChild.style.width = tw;
s.firstChild.rows[0].childNodes[col].style.display = display;
}
},
isGrouped : function(){
return !Ext.isEmpty(this.grid.getStore().groupField);
},
// Note: requires that all (or the first) record in the
// group share the same group value. Returns false if the group
// could not be found.
refreshSummary : function(groupValue){
return this.refreshSummaryById(this.view.getGroupId(groupValue));
},
getSummaryNode : function(gid){
var g = Ext.fly(gid, '_gsummary');
if(g){
return g.down('.x-grid3-summary-row', true);
}
return null;
},
refreshSummaryById : function(gid){
var g = Ext.getDom(gid);
if(!g){
return false;
}
var rs = [];
this.grid.getStore().each(function(r){
if(r._groupId == gid){
rs[rs.length] = r;
}
});
var cs = this.view.getColumnData(),
data = this.calculate(rs, cs),
markup = this.renderSummary({data: data}, cs),
existing = this.getSummaryNode(gid);
if(existing){
g.removeChild(existing);
}
Ext.DomHelper.append(g, markup);
return true;
},
doUpdate : function(ds, record){
this.refreshSummaryById(record._groupId);
},
doRemove : function(ds, record, index, isUpdate){
if(!isUpdate){
this.refreshSummaryById(record._groupId);
}
},
/**
* Show a message in the summary row.
*
grid.on('afteredit', function(){
var groupValue = 'Ext Forms: Field Anchoring';
summary.showSummaryMsg(groupValue, 'Updating Summary...');
});
*
* @param {String} groupValue
* @param {String} msg Text to use as innerHTML for the summary row.
*/
showSummaryMsg : function(groupValue, msg){
var gid = this.view.getGroupId(groupValue),
node = this.getSummaryNode(gid);
if(node){
node.innerHTML = '
grid.on('afteredit', function(){
var groupValue = 'Ext Forms: Field Anchoring';
summary.showSummaryMsg(groupValue, 'Updating Summary...');
setTimeout(function(){ // simulate server call
// HybridSummary class implements updateSummaryData
summary.updateSummaryData(groupValue,
// create data object based on configured dataIndex
{description: 22, estimate: 888, rate: 888, due: new Date(), cost: 8});
}, 2000);
});
*
* @param {String} groupValue
* @param {Object} data data object
* @param {Boolean} skipRefresh (Optional) Defaults to false
*/
updateSummaryData : function(groupValue, data, skipRefresh){
var json = this.grid.getStore().reader.jsonData;
if(!json.summaryData){
json.summaryData = {};
}
json.summaryData[groupValue] = data;
if(!skipRefresh){
this.refreshSummary(groupValue);
}
},
/**
* Returns the summaryData for the specified groupValue or null.
* @param {String} groupValue
* @return {Object} summaryData
*/
getSummaryData : function(groupValue){
var reader = this.grid.getStore().reader,
json = reader.jsonData,
fields = reader.recordType.prototype.fields,
v;
if(json && json.summaryData){
v = json.summaryData[groupValue];
if(v){
return reader.extractValues(v, fields.items, fields.length);
}
}
return null;
}
});
//backwards compat
Ext.grid.HybridSummary = Ext.ux.grid.HybridSummary;
// vim: ts=4:sw=4:nu:fdc=4:nospell
/*global Ext */
/**
* @class Ext.ux.grid.RowActions
* @extends Ext.util.Observable
*
* RowActions plugin for Ext grid. Contains renderer for icons and fires events when an icon is clicked.
* CSS rules from Ext.ux.RowActions.css are mandatory
*
* Important general information: Actions are identified by iconCls. Wherever an action
* is referenced (event argument, callback argument), the iconCls of clicked icon is used.
* In other words, action identifier === iconCls.
*
* @author Ing. Jozef Sakalos
* @copyright (c) 2008, by Ing. Jozef Sakalos
* @date 22. March 2008
* @version 1.0
* @revision $Id: Ext.ux.grid.RowActions.js 747 2009-09-03 23:30:52Z jozo $
*
* @license Ext.ux.grid.RowActions is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
*
*
* @donate
*
*/
Ext.ns('Ext.ux.grid');
// add RegExp.escape if it has not been already added
if('function' !== typeof RegExp.escape) {
RegExp.escape = function(s) {
if('string' !== typeof s) {
return s;
}
// Note: if pasting from forum, precede ]/\ with backslash manually
return s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, '\\$1');
}; // eo function escape
}
/**
* Creates new RowActions plugin
* @constructor
* @param {Object} config A config object
*/
Ext.ux.grid.RowActions = function(config) {
Ext.apply(this, config);
// {{{
this.addEvents(
/**
* @event beforeaction
* Fires before action event. Return false to cancel the subsequent action event.
* @param {Ext.grid.GridPanel} grid
* @param {Ext.data.Record} record Record corresponding to row clicked
* @param {String} action Identifies the action icon clicked. Equals to icon css class name.
* @param {Integer} rowIndex Index of clicked grid row
* @param {Integer} colIndex Index of clicked grid column that contains all action icons
*/
'beforeaction'
/**
* @event action
* Fires when icon is clicked
* @param {Ext.grid.GridPanel} grid
* @param {Ext.data.Record} record Record corresponding to row clicked
* @param {String} action Identifies the action icon clicked. Equals to icon css class name.
* @param {Integer} rowIndex Index of clicked grid row
* @param {Integer} colIndex Index of clicked grid column that contains all action icons
*/
,'action'
/**
* @event beforegroupaction
* Fires before group action event. Return false to cancel the subsequent groupaction event.
* @param {Ext.grid.GridPanel} grid
* @param {Array} records Array of records in this group
* @param {String} action Identifies the action icon clicked. Equals to icon css class name.
* @param {String} groupId Identifies the group clicked
*/
,'beforegroupaction'
/**
* @event groupaction
* Fires when icon in a group header is clicked
* @param {Ext.grid.GridPanel} grid
* @param {Array} records Array of records in this group
* @param {String} action Identifies the action icon clicked. Equals to icon css class name.
* @param {String} groupId Identifies the group clicked
*/
,'groupaction'
);
// }}}
// call parent
Ext.ux.grid.RowActions.superclass.constructor.call(this);
};
Ext.extend(Ext.ux.grid.RowActions, Ext.util.Observable, {
// configuration options
// {{{
/**
* @cfg {Array} actions Mandatory. Array of action configuration objects. The action
* configuration object recognizes the following options:
*
*
* {Function} callback (optional). Function to call if the action icon is clicked.
* This function is called with same signature as action event and in its original scope.
* If you need to call it in different scope or with another signature use
* createCallback or createDelegate functions. Works for statically defined actions. Use
* callbacks configuration options for store bound actions.
*
*
* {Function} cb Shortcut for callback.
*
*
* {String} iconIndex Optional, however either iconIndex or iconCls must be
* configured. Field name of the field of the grid store record that contains
* css class of the icon to show. If configured, shown icons can vary depending
* of the value of this field.
*
*
* {String} iconCls CSS class of the icon to show. It is ignored if iconIndex is
* configured. Use this if you want static icons that are not base on the values in the record.
*
*
* {Boolean} hide Optional. True to hide this action while still have a space in
* the grid column allocated to it. IMO, it doesn't make too much sense, use hideIndex instead.
*
*
* {String} hideIndex Optional. Field name of the field of the grid store record that
* contains hide flag (falsie [null, '', 0, false, undefined] to show, anything else to hide).
*
*
* {String} qtipIndex Optional. Field name of the field of the grid store record that
* contains tooltip text. If configured, the tooltip texts are taken from the store.
*
*
* {String} tooltip Optional. Tooltip text to use as icon tooltip. It is ignored if
* qtipIndex is configured. Use this if you want static tooltips that are not taken from the store.
*
*
* {String} qtip Synonym for tooltip
*
*
* {String} textIndex Optional. Field name of the field of the grids store record
* that contains text to display on the right side of the icon. If configured, the text
* shown is taken from record.
*
*
* {String} text Optional. Text to display on the right side of the icon. Use this
* if you want static text that are not taken from record. Ignored if textIndex is set.
*
*
* {String} style Optional. Style to apply to action icon container.
*
*
*/
/**
* @cfg {String} actionEvent Event to trigger actions, e.g. click, dblclick, mouseover (defaults to 'click')
*/
actionEvent:'click'
/**
* @cfg {Boolean} autoWidth true to calculate field width for iconic actions only (defaults to true).
* If true, the width is calculated as {@link #widthSlope} * number of actions + {@link #widthIntercept}.
*/
,autoWidth:true
/**
* @cfg {String} dataIndex - Do not touch!
* @private
*/
,dataIndex:''
/**
* @cfg {Boolean} editable - Do not touch!
* Must be false to prevent errors in editable grids
*/
,editable:false
/**
* @cfg {Array} groupActions Array of action to use for group headers of grouping grids.
* These actions support static icons, texts and tooltips same way as {@link #actions}. There is one
* more action config option recognized:
*
*
* {String} align Set it to 'left' to place action icon next to the group header text.
* (defaults to undefined = icons are placed at the right side of the group header.
*
*
*/
/**
* @cfg {Object} callbacks iconCls keyed object that contains callback functions. For example:
*
*/
/**
* @cfg {String} header Actions column header
*/
,header:''
/**
* @cfg {Boolean} isColumn
* Tell ColumnModel that we are column. Do not touch!
* @private
*/
,isColumn:true
/**
* @cfg {Boolean} keepSelection
* Set it to true if you do not want action clicks to affect selected row(s) (defaults to false).
* By default, when user clicks an action icon the clicked row is selected and the action events are fired.
* If this option is true then the current selection is not affected, only the action events are fired.
*/
,keepSelection:false
/**
* @cfg {Boolean} menuDisabled No sense to display header menu for this column
* @private
*/
,menuDisabled:true
/**
* @cfg {Boolean} sortable Usually it has no sense to sort by this column
* @private
*/
,sortable:false
/**
* @cfg {String} tplGroup Template for group actions
* @private
*/
,tplGroup:
''
+'
';
}
};Ext.ns('Ext.ux.window');
/**
* An object that represents a group of {@link Ext.ux.window.MessageWindow} instances
* and provides position management in addition to the standard Window Group features.
* @class Ext.ux.window.MessageWindowGroup
* @extends Ext.WindowGroup
* @constructor
*/
Ext.ux.window.MessageWindowGroup = function (config) {
config = config || {};
var mgr = new Ext.WindowGroup();
mgr.positions = [];
Ext.apply(mgr, config);
return mgr;
};
/**
* The default global Message Window group that is available automatically. To have
* more than one group of Message Windows to utilize separate positioning in addition
* to the standard Window Manager features create additional instances of
* {@link Ext.ux.window.MessageWindowGroup} as needed.
* @class Ext.ux.window.MessageWindowMgr
* @extends Ext.ux.window.MessageWindowGroup
* @singleton
*/
Ext.ux.window.MessageWindowMgr = Ext.ux.window.MessageWindowGroup();
/**
*
If you are looking for a lightweight implementation of Toast or Notification windows this is
* NOT the class you want. This class builds upon the implementation by Edouard Fattal.
* This class creates a specialized Window for notification messages and offers the following features:
*
* Demo link: here
* Forum thread: here
*
* Features:
*
*
+ Message windows may be bound to any element through configuration.
*
+ A single Message Window may be reused or multiple Message Windows may be used simultaneously.
*
+ Message windows can be managed by groups.
*
+ Several configurable options.
*
++ By default, Message Window will not steal focus.
*
*
* Known issues/caveats/bugs/roadmap:
*
*
+ config for custom showFx incomplete
*
+ vertical location of subsequent windows may overlap if height changes.
*
+ add config to limit drag options (for example lock x or y axis, etc.)
*
* @class Ext.ux.window.MessageWindow
* @extends Ext.Window
* @author Michael LeComte (mjlecomte), inspired by Ext.ux.Notification\ToastWindow (Edouard Fattal)
* @license LGPL 3.0
* @version 0.08 - Nov 8, 2008 (ALPHA!!!)
* @donate
*/
Ext.ux.window.MessageWindow = Ext.extend(Ext.Window, {
/**
* @cfg {Boolean} autoDestroy
* The action to take after the message window has been hidden. The default is true which
* will actually remove the window from the DOM and destroy it. False will simply hide the
* window by setting visibility to hidden and applying negative offsets, keeping the window
* available to be redisplayed via the {@link #show} method.
*/
autoDestroy: true,
/**
* @cfg {Boolean} autoHide
* {@link #autoHide}
* True to have message window automatically hide itself (defaults to true).
*/
autoHide: true,
/**
* @cfg {Boolean} autoHeight
* True to use height:'auto', false to use fixed height (defaults to false).
*/
autoHeight: false,
/**
* @cfg {String} bodyStyle
* Custom CSS styles to be applied to the body element in the format expected by
* Ext.Element.applyStyles (defaults to 'text-align:left;padding:10px;').
*/
bodyStyle: 'text-align:left;padding:10px;',
/**
* @cfg {String} baseCls
* The base CSS class to apply to this panel's element (defaults to 'x-window').
*/
/**
* @cfg {String} buttonAlign
* The alignment of any buttons added to this panel. Valid values are 'right', 'left',
* and 'center' (defaults to 'center').
*/
buttonAlign: 'center',
/**
* @cfg {String} cls
* An optional extra CSS class that will be added to this component's Element (defaults
* to 'x-notification'). This can be useful for adding customized styles to the component
* or any of its children using standard CSS rules.
*/
cls: 'x-notification',
/**
* @cfg {Boolean} constrain
* True to constrain the window to the viewport, false to allow it to fall outside of
* the viewport (defaults to true). Optionally the header only can be constrained using
* {@link #constrainHeader}.
*/
constrain: true,
/**
* @cfg {Boolean} constrainHeader
* True to constrain the window header to the viewport, allowing the window body to fall
* outside of the viewport, false to allow the header to fall outside the viewport (defaults
* to true). Optionally the entire window can be constrained using {@link #constrain}.
*/
constrainHeader: true,
/**
* @cfg {Boolean} draggable
* True to allow the window to be dragged by the header bar, false to disable dragging
* (defaults to true). Note that by default the window will be centered in the viewport,
* so if dragging is disabled the window may need to be positioned programmatically after
* render (e.g., myWindow.setPosition(100, 100);).
*/
draggable: true,
/** @cfg {Boolean} floating */
/** @private */
floating: true,
/**
* @cfg {Boolean} focusOnShow
* True to focus the window when shown (defaults to false).
*/
/** @cfg {Boolean} frame */
/** @private */
frame: true,
/**
* @cfg {Ext.ux.window.MessageWindowGroup} manager
* A reference to the MessageWindowGroup that should manage this Message Window (defaults
* to {@link Ext.ux.window.MessageWindowMgr}). Specify a reference to an instance unless
* you want a new manager for each instance:
*
* var group2 = new Ext.ux.window.MessageWindowGroup({
* //override any defaults or add to base class instance
* groupId: 2, //groupId not implemented at this time
* zseed: 2000 //change the zseed (default = 9000)
* });
* var mw1 = new Ext.ux.window.MessageWindow({
* manager: group2//specify the MessageWindowGroup manager (instead of using default manager)
* });
* var mw2 = new Ext.ux.window.MessageWindow({
* manager: group2//specify the MessageWindowGroup manager (instead of using default manager)
* });
* var mw3 = new Ext.ux.window.MessageWindow({
* //will use default manager
* });
*
*/
/**
* @cfg {Function} handleHelp
* Handler function when the help tool is clicked (defaults to {@link Ext#emptyFn}).
* @param {Object} event The click event.
* @param {Object} toolEl The tool Element.
* @param {Object} panel The host Panel.
*/
handleHelp: Ext.emptyFn,
/**
* @cfg {Boolean} help
* True to display tools for help. Defaults to true.
*/
help: true,
/**
* @cfg {Object} hideFx
* Config object for hide effects settings. An example with defaults shown:
*
* hideFx: {
* delay: 5000, //time in milliseconds to delay the start of the effect
* duration: 0.25, //duration of the effect
* mode: 'standard', // null = will not hide
* // 'standard' = traditional window hide (vanish)
* // 'standard' = traditional window hide (vanish)
* // anything else will use the default of ghost
* useProxy: true //default is false to hide window instead
* }
*
*/
hideFx: {
delay: 5000
},
/**
* @cfg {String} hoverCls
* An extra CSS class that will be added to this component's Element when
* hovering over (defaults to 'msg-over').
*/
hoverCls: 'msg-over',
/**
* @cfg {String} iconCls
* A CSS class that will provide a background image to be used as the header icon (defaults
* to 'x-icon-information'). An example custom icon class would be something like:
* .my-icon { background: url(../images/my-icon.gif) 0 6px no-repeat !important;}
*/
iconCls: 'x-icon-information',
/**
* @cfg {Boolean} maximizable
* True to display the 'maximize' tool button and allow the user to maximize the window, false to hide the button
* and disallow maximizing the window (defaults to false). Note that when a window is maximized, the tool button
* will automatically change to a 'restore' button with the appropriate behavior already built-in that will
* restore the window to its previous size.
*/
/**
* @cfg {Boolean} minimizable
* True to display the 'minimize' tool button and allow the user to minimize the window, false to hide the button
* and disallow minimizing the window (defaults to false). Note that this button provides no implementation --
* the behavior of minimizing a window is implementation-specific, so the minimize event must be handled and a
* custom minimize behavior implemented for this option to be useful.
*/
/**
* @cfg {Number} minHeight
* The minimum height in pixels allowed for this window (defaults to 100). Only applies when resizable = true.
*/
minHeight: 40,
/**
* @cfg {Number} minWidth
* The minimum width in pixels allowed for this window (defaults to 200). Only applies when resizable = true.
*/
minWidth: 200,
/**
* @cfg {Boolean} modal
* True to make the window modal and mask everything behind it when displayed, false to display it without
* restricting access to other UI elements (defaults to false).
*/
/**
* @cfg {Array} msgs
* An array to hold the message queue for refreshing messages. Body of the message window will be updated
* from the text element.
* Example:
*
* The first message that will be displayed uses the Title and html config options.
*/
msgs: [],
/**
* @cfg {Boolean} monitorResize
* This is automatically managed based on the value of constrain and constrainToHeader
*/
monitorResize : true,
/**
* @cfg {Function} onEsc
* Allows override of the built-in processing for the escape key. Default action
* is to close the Window (performing whatever action is specified in {@link #closeAction}.
* To prevent the Window closing when the escape key is pressed, specify this as
* Ext.emptyFn (See {@link Ext#emptyFn}).
*/
/**
* @cfg {Object} origin
* Config object for the message origin with the following sample of default properties:
* Example:
*
* //configure a different origin than the default bottom right corner of the window:
* origin: {
* //get window's Ext.element:
* el: Ext.get('northRegion'), //element to align to (defaults to document)
* pos: "bl-bl",//position to align to (see {@link Ext.Element#alignTo} for more details defaults to "br-br").
* offX: 10, //amount to offset horizontally (-20 by default)
* offY: 0 //amount to offset vertically (-20 by default)
* },
*
*/
/**
* @cfg {Boolean} pinOnClick
* True to display the 'pin' tool button and allow the user to pin the window, false
* to hide the button and disallow pinning the window (defaults to true).
*/
pinOnClick: true,
/**
* @cfg {String} pinState
* Specify the initial pin state when the window is first shown. Specify null, 'pin', or the default
* 'unpin'.
* pinState effect
* -------- ------
* null window will show/hide itself, user can not control
* 'pin' window will initially show itself in pinned state, user will need to click unpin to hide
* 'unpin' window will initially show itself in unpinned state, user will need to click pin to keep open
*
*/
pinState: 'unpin',
/**
* @cfg {Boolean} plain
* True to render the window body with a transparent background so that it will blend into the framing
* elements, false to add a lighter background color to visually highlight the body element and separate it
* more distinctly from the surrounding frame (defaults to false).
*/
plain: false,
/**
* @cfg {Boolean} resizable
* True to allow user resizing at each edge and corner of the window, false to disable resizing (defaults to false).
*/
resizable: false,
/**
* @cfg {String} resizeHandles
* A valid {@link Ext.Resizable} handles config string (defaults to 'all'). Only applies when resizable = true.
*/
/**
* @cfg {String} textHelp
* Qtip text to display for help tool (defaults to 'Get hel'). Only applicable if help = true.
*/
textHelp: 'Get help',
/**
* @cfg {String} textPin
* Qtip text to display for pin tool. Only applicable if {@link pinState} == 'pin' or 'unpin'.
*/
textPin: 'Pin this to prevent closing',
/**
* @cfg {String} textUnpin
* Qtip text to display for unpin tool. Only applicable if {@link pinState} == 'pin' or 'unpin'.
*/
textUnpin: 'Unpin this to close',
/**
* @cfg {Number} x
* The X position of the left edge of the Window on initial showing. Defaults to centering the Window within
* the width of the Window's container {@link Ext.Element Element) (The Element that the Window is rendered to).
*/
/**
* @cfg {Number} y
* The Y position of the top edge of the Window on initial showing. Defaults to centering the Window within
* the height of the Window's container {@link Ext.Element Element) (The Element that the Window is rendered to).
*/
/** @private */
initHidden : true,
/** @private */
initComponent : function () {
Ext.apply(this, {
collapsible: false,
footer: false,
minHeight: 20,
stateful: false
});
//if interval is specified automatically show message windows
if (this.interval) {
this.startAutoRefresh();
}
//set up automatic hide/close of window if so configured
if (this.autoHide) {
if (this.pinState === 'unpin') {
this.task = new Ext.util.DelayedTask(this.hide, this);
}
}
//new
else {
this.closable = true;
}
//added this.closable
//call parent
Ext.ux.window.MessageWindow.superclass.initComponent.call(this);
//add listeners
this.on({
hide: {
scope: this,
fn: function () {
if (this.autoDestroy) {
if (this.fireEvent("beforeclose", this) !== false) {
this.fireEvent('close', this);
this.destroy();
}
}
}
},
mouseout: {
scope: this,
fn: this.onMouseout
}
});
//add events
this.addEvents(
/**
* @event activate
* Fires after the window has been visually activated via {@link setActive}.
* @param {Ext.ux.window.MessageWindow} this
*/
/**
* @event deactivate
* Fires after the window has been visually deactivated via {@link setActive}.
* @param {Ext.ux.window.MessageWindow} this
*/
/**
* @event resize
* Fires after the window has been resized.
* @param {Ext.ux.window.MessageWindow} this
* @param {Number} width The window's new width
* @param {Number} height The window's new height
*/
/**
* @event maximize
* Fires after the window has been maximized.
* @param {Ext.ux.window.MessageWindow} this
*/
/**
* @event minimize
* Fires after the window has been minimized.
* @param {Ext.ux.window.MessageWindow} this
*/
/**
* @event restore
* Fires after the window has been restored to its original size after being maximized.
* @param {Ext.ux.window.MessageWindow} this
*/
/**
* @event pinned
* Fires after the window has been pinned.
* @param {Ext.ux.window.MessageWindow} this
*/
'afterpin',
/**
* @event unpinned
* Fires after the window has been unpinned.
* @param {Ext.ux.window.MessageWindow} this
*/
'afterunpin',
/**
* @event click
* Fires after the window has been clicked.
* @param {Ext.ux.window.MessageWindow} this
* @param {Ext.ux.window.MessageWindow} msg The message from the message array if configured.
*/
'click');
},
//override
/** @private */
initEvents: function () {
//use a slighly enhanced Ext.ux.window.MessageWindowMgr instead of the default WindowMgr
this.manager = this.manager || Ext.ux.window.MessageWindowMgr;
//the parent class will register, so no need to do it here:
//this.manager = this.manager || Ext.WindowMgr;
Ext.ux.window.MessageWindow.superclass.initEvents.call(this);
},
focus: function () {
Ext.ux.window.MessageWindow.superclass.focus.call(this);
},
/** @private */
toFront: function () {
if(this.manager.bringToFront(this)){
//only focus if configured as such
if(this.focusOnShow){
this.focus();
}
}
return this;
},
/** @private */
initTools: function () {
this.addTool({
id: 'unpin', // image points left
handler: this.handlePin,
//set initial visibility (also check if pinState is null)
hidden: (!this.pinState || this.pinState === 'pin'),
qtip: this.textPin,
scope: this
});
this.addTool({
id: 'pin',// image points down
handler: this.handleUnpin,
hidden: (!this.pinState || this.pinState === 'unpin'),
qtip: this.textUnpin,
scope: this
});
if (this.help) {
this.addTool({
id: 'help',
handler: this.handleHelp,
qtip: this.textHelp,
scope: this
});
}
},
/** @private */
onRender: function (ct, position) {
Ext.ux.window.MessageWindow.superclass.onRender.call(this, ct, position);
//after call to parent class onRender this.el exists.
//clip part of the window (for example the recurring messages that
//eject from a border have the bottom rounded edge, etc. clipped off.
if (this.clip) {
switch (this.clip) {
case 'bottom':
Ext.destroy(this.getEl().child('.' + this.baseCls + '-bl'));
break;
}
}
//add a class when hovering over in order to disable
//any updates to the window while hovering over
if (true) {
this.el.addClassOnOver(this.hoverCls);
}
//add click listener to body
Ext.fly(this.body.dom).on('click', this.handleClick, this);
},
/**
* Toggles the active pin state.
*/
togglePinState: function (event) {
//check which tool is visible
if (this.tools.unpin.isVisible()) {
this.handlePin(event, this.tools.unpin, this);
} else {
this.handleUnpin(event, this.tools.pin, this);
}
},
/**
* Override to the Panel Class createElement method. This method is called by
* Panel Class' onRender(). Normally the panel class will create a header in the
* *-tc class, to utilize the default box class for styling we'll move the header
* inside the *-mc class to utilize
Ext.Element.boxMarkup:
##HEADER##
CONTAINER
###############
Title
Message
* @param {Object} name
* @param {Object} pnode
*///override panel class method:
// private
createElement : function (name, pnode) {
if (this.shiftHeader) {
switch (name) {
case 'header':
//don't create header yet if putting inside mc, do it when tbar is done
return;
case 'tbar':
Ext.ux.window.MessageWindow.superclass.createElement.call(this, 'header', pnode);
Ext.ux.window.MessageWindow.superclass.createElement.call(this, name, pnode);
return;
}
}
//caught the ones we needed to, call the default implementation
Ext.ux.window.MessageWindow.superclass.createElement.call(this, name, pnode);
},
//override/disable focus, see above.
focus: Ext.emptyFn,
/** @private */
getState : function () {
return Ext.apply(Ext.ux.window.MessageWindow.superclass.getState.call(this) || {}, this.getBox());
},
/**
* Handler for when the message window body is clicked
* @param {Object} event The click event.
*/
handleClick: function (event) {
this.fireEvent('click', this, this.msg);
this.togglePinState(event);
},
/**
* Handler for when pin button is clicked
* @param {Object} event The click event.
* @param {Object} toolEl The tool Element.
* @param {Object} panel The host Panel.
*/
handlePin: function (event, toolEl, panel) {
//hide the unpin button
toolEl.hide();
//show the pin button
this.tools.pin.show();
this.cancelHiding();
this.fireEvent('afterpin', this);
},
/**
* Handler for when pin button is clicked
* @param {Object} event The click event.
* @param {Object} toolEl The tool Element.
* @param {Object} panel The host Panel.
*/
handleUnpin: function (event, toolEl, panel) {
//hide the pin button
toolEl.hide();
//show the unpin button
this.tools.unpin.show();
this.hide();
this.fireEvent('afterunpin', this);
},
/**
* cancel hiding of the window if {@link #autoHide} is true
*/
cancelHiding: function () {
this.addClass('fixed');
if (this.autoHide) {
if (this.pinState === 'unpin') {
this.task.cancel();
}
}
//show the pin button
this.tools.pin.show();
//make sure the unpin button is hidden
this.tools.unpin.hide();
},
//override parent method
/** @private */
animHide: function () {
//remove the position of this element from the manager
this.manager.positions.remove(this.pos);
//element to hide and configured Fx
var w, fx = this.hideFx || {};
//animate using a proxy instead of actual element if so configured
if (fx.useProxy) {
w = this.proxy;
this.proxy.setOpacity(0.5);
this.proxy.show();
var tb = this.getBox(false);
this.proxy.setBox(tb);
this.el.hide();
Ext.apply(fx, tb);
} else {
w = this.el;
}
Ext.applyIf(fx, {
block: false,//default for window is true
callback: this.afterHide,
easing: 'easeOut',//'easeNone';
remove: true,
scope: this
});
switch (fx.mode) {
case 'none':
break;
case 'slideIn':
w[fx.mode]("b", fx);
// w.slideIn("b", fx);
break;
case 'custom':
Ext.callback(fx.callback, fx.scope, [this, w, fx]);//callback(cb,scope,args,delay)
break;
case 'standard':
fx.duration = fx.duration || 0.25;
fx.opacity = 0;
w.shift(fx);
break;
default:
fx.duration = fx.duration || 1;
w.ghost("b", fx);
break;
}
},
//override parent method
/** @private */
afterShow: function () {
Ext.ux.window.MessageWindow.superclass.afterShow.call(this);
//if user moves remove from position manager and cancel hiding
this.on('move', function(){
//remove the position of this element from the manager
this.manager.positions.remove(this.pos);
this.cancelHiding();
}, this);
if (this.autoHide) {
if (this.pinState === 'unpin') {
this.task.delay(this.hideFx.delay);
}
}
},
/**
* some cleanup still needed this method
* sizing / placement issues when height of windows changes
* should recalculate placement based on window height
*/
/** @private */
animShow: function () {
//don't update if hovering over message
//check if visible so it will show initially
if (this.el.isVisible() && this.el.hasClass(this.hoverCls)) {
return;
}
if (this.msgs.length > 1) {
this.updateMsg();
}
/*
//for reference
this.el.disableShadow();
this.setPosition(0, 0);
delete this.el.lastXY;
delete this.el.lastLT;
if(this.x === undefined || this.y === undefined){
var xy = this.el.getAlignToXY(this.container, 'c-c');
var pos = this.el.translatePoints(xy[0], xy[1]);
this.x = this.x === undefined? pos.left : this.x;
this.y = this.y === undefined? pos.top : this.y;
}
this.el.setLeftTop(this.x, this.y);
alignTo : 'tl',
alignToXY : [ 5, (this.el.getComputedHeight() * -1) + 5],
slideDirection : 'b'
console.info('this.el.lastXY',this.el.lastXY);
console.info('this.el.lastLT',this.el.lastLT);
console.info('this.el.x',this.el.x);
console.info('this.el.y',this.el.y);
console.info('this.el.getComputedHeight()',this.el.getComputedHeight());
console.log('====');
*/
//element to hide and configured Fx
var w = this.el, fx = this.showFx || {};
this.origin = this.origin || {};
//apply defaults if not already configured
Ext.applyIf(this.origin, {
el: Ext.getDoc(), //defaults to document
increment: true, //whether to increment position of subsequent messages
pos: "br-br",//position to align to (see {@link Ext.Element#alignTo} for more details defaults to "br-br").
offX: -20, //amount to offset horizontally
offY: -20, //amount to offset vertically
spaY: 5 //vertical spacing between adjacent messages
});
//track positions of each instance
this.pos = 0;
if (this.origin.increment) {
while (this.manager.positions.indexOf(this.pos) > -1) {
this.pos++;
}
this.manager.positions.push(this.pos);
}
var y = this.origin.offY - ((this.getSize().height + this.origin.spaY) * this.pos);
//unused t (used for debugging)
// var t = this.getSize();
//set the window size
this.setSize(this.width || this.minWidth, this.height || this.minHeight);
//increment the vertical position of the window
if (this.origin.increment) {
y = this.origin.offY - ((this.getSize().height + this.origin.spaY) * this.pos);
} else {
y = 0;
}
w.alignTo(
this.origin.el, // element to align to.
this.origin.pos, // position to align to (see {@link Ext.Element#alignTo} for more details).
[ this.origin.offX, y ] // Offset the positioning by [x, y]:
);
w.slideIn('b', {
duration: fx.duration || 1,
callback: this.afterShow,
scope: this
});
},
onMouseout: function () {
//console.info('in onMouseout');
//console.info(arguments);
},
/**
* @param {Object} el
* @param {Object} x
* @param {Object} y
* @private
*/
positionPanel: function (el, x, y) {
if(x && typeof x[1] == 'number'){
y = x[1];
x = x[0];
}
el.pageX = x;
el.pageY = y;
if(x === undefined || y === undefined){ // cannot translate undefined points
return;
}
if(y < 0){ y = 10; }
var p = el.translatePoints(x, y);
el.setLocation(p.left, p.top);
return el;
},
/**
* Specify the message to be shown
* @param {String} msg Message to update the body with.
*/
setMessage: function (msg) {
this.body.update(msg);
},
/**
* Set the title of the message window
* @param {String} title Title of Window
* @param {String} iconCls icon to use in header area
*/
setTitle: function (title, iconCls) {
Ext.ux.window.MessageWindow.superclass.setTitle.call(this, title, iconCls || this.iconCls);
},
/**
* Start recurring messages
* @param {Boolean} update Whether to update the message before starting automatic refreshes.
*/
startAutoRefresh : function(update){
if(update){
this.updateMsg(true);
}
if(this.autoRefreshProcId){
clearInterval(this.autoRefreshProcId);
}
// native javascript function to delay for a specified time before triggering the
// execution of a specific function. After triggering the called function the command
// doesn't complete. Instead it waits for the specified time again and then triggers
// the function again and continues to repeat this process of triggering the function
// at the specified intervals until either the web page is unloaded or the clearInterval
// function is called.
this.autoRefreshProcId = setInterval(this.animShow.createDelegate(this, []), this.interval);
},
/**
* Stop recurring messages
*/
stopAutoRefresh : function(){
if(this.autoRefreshProcId){
clearInterval(this.autoRefreshProcId);
}
},
/**
* Update the message
* @param {String} msg The updated msg
*/
updateMsg: function (msg) {
//don't update if hovering over message
if (this.el && !this.el.hasClass(this.hoverCls)) {
if (msg) {
// console.info('message passed');
} else {
this.msgIndex = this.msgs[this.msgIndex + 1] ? this.msgIndex + 1 : 0;
this.msg = this.msgs[this.msgIndex];
}
//update the innerHTML of element
//this.el.dom.update(this.msg.text);
this.body.update(this.msg.text);
} else {
//console.info('hovering');
}
}
});
//register the xtype
Ext.reg('message-window', Ext.ux.window.MessageWindow);/**
* Ext.ux.form.XCheckbox - checkbox with configurable submit values
*
* @author Ing. Jozef Sakalos
* @version $Id: Ext.ux.form.XCheckbox.js 313 2008-08-18 18:00:16Z jozo $
* @date 10. February 2008
*
*
* @license Ext.ux.form.XCheckbox is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/
/**
* @class Ext.ux.XCheckbox
* @extends Ext.form.Checkbox
*/
Ext.ns('Ext.ux.form');
Ext.ux.form.XCheckbox = Ext.extend(Ext.form.Checkbox, {
submitOffValue: '0',
submitOnValue: '1',
onRender: function(){
this.inputValue = this.submitOnValue;
// call parent
Ext.ux.form.XCheckbox.superclass.onRender.apply(this, arguments);
// create hidden field that is submitted if checkbox is not checked
this.hiddenField = this.wrap.insertFirst({
tag: 'input',
type: 'hidden'
});
// support tooltip
if (this.tooltip) {
this.imageEl.set({
qtip: this.tooltip
});
}
// update value of hidden field
this.updateHidden();
} // eo function onRender
/**
* Calls parent and updates hiddenField
* @private
*/
,
setValue: function(v){
v = this.convertValue(v);
this.updateHidden(v);
Ext.ux.form.XCheckbox.superclass.setValue.apply(this, arguments);
} // eo function setValue
/**
* Updates hiddenField
* @private
*/
,
updateHidden: function(v){
v = undefined !== v ? v : this.checked;
v = this.convertValue(v);
if (this.hiddenField) {
this.hiddenField.dom.value = v ? this.submitOnValue : this.submitOffValue;
this.hiddenField.dom.name = v ? '' : this.el.dom.name;
}
} // eo function updateHidden
/**
* Converts value to boolean
* @private
*/
,
convertValue: function(v){
return (v === true || v === 'true' || v === this.submitOnValue || String(v).toLowerCase() === 'on');
} // eo function convertValue
}); // eo extend
// register xtype
Ext.reg('xcheckbox', Ext.ux.form.XCheckbox);
/**
* Ext.ux.UploadDialog namespace.
*/
Ext.namespace('Ext.ux.UploadDialog');
/**
* File upload browse button.
*
* @class Ext.ux.UploadDialog.BrowseButton
*/
Ext.ux.UploadDialog.BrowseButton = Ext.extend(Ext.Button,
{
input_name : 'file',
input_file : null,
original_handler : null,
original_scope : null,
/**
* @access private
*/
initComponent : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.initComponent.call(this);
this.original_handler = this.handler || null;
this.original_scope = this.scope || window;
this.handler = null;
this.scope = null;
},
/**
* @access private
*/
onRender : function(ct, position)
{
Ext.ux.UploadDialog.BrowseButton.superclass.onRender.call(this, ct, position);
this.createInputFile();
},
/**
* @access private
*/
createInputFile : function()
{
var button_container = this.el.child('.x-btn-center');
button_container.position('relative');
this.input_file = Ext.DomHelper.append(
button_container,
{
tag: 'input',
type: 'file',
size: 1,
name: this.input_name || Ext.id(this.el),
style: 'position: absolute; display: block; border: none; cursor: pointer'
},
true
);
this.input_file.setOpacity(0.0);
this.adjustInputFileBox();
if (this.handleMouseEvents) {
this.input_file.on('mouseover', this.onMouseOver, this);
this.input_file.on('mousedown', this.onMouseDown, this);
}
if(this.tooltip){
if(typeof this.tooltip == 'object'){
Ext.QuickTips.register(Ext.apply({target: this.input_file}, this.tooltip));
}
else {
this.input_file.dom[this.tooltipType] = this.tooltip;
}
}
this.input_file.on('change', this.onInputFileChange, this);
this.input_file.on('click', function(e) { e.stopPropagation(); });
},
/**
* @access private
*/
autoWidth : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.autoWidth.call(this);
this.adjustInputFileBox();
},
/**
* @access private
*/
adjustInputFileBox : function()
{
var btn_cont, btn_box, inp_box, adj;
if (this.el && this.input_file) {
btn_cont = this.el.child('.x-btn-center');
btn_box = btn_cont.getBox();
this.input_file.setStyle('font-size', (btn_box.width * 0.5) + 'px');
inp_box = this.input_file.getBox();
adj = {x: 3, y: 3}
if (Ext.isIE) {
adj = {x: -3, y: 3}
}
this.input_file.setLeft(btn_box.width - inp_box.width + adj.x + 'px');
this.input_file.setTop(btn_box.height - inp_box.height + adj.y + 'px');
}
},
/**
* @access public
*/
detachInputFile : function(no_create)
{
var result = this.input_file;
no_create = no_create || false;
if (typeof this.tooltip == 'object') {
Ext.QuickTips.unregister(this.input_file);
}
else {
this.input_file.dom[this.tooltipType] = null;
}
this.input_file.removeAllListeners();
this.input_file = null;
if (!no_create) {
this.createInputFile();
}
return result;
},
/**
* @access public
*/
getInputFile : function()
{
return this.input_file;
},
/**
* @access public
*/
disable : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.disable.call(this);
this.input_file.dom.disabled = true;
},
/**
* @access public
*/
enable : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.enable.call(this);
this.input_file.dom.disabled = false;
},
/**
* @access public
*/
destroy : function()
{
var input_file = this.detachInputFile(true);
input_file.remove();
input_file = null;
Ext.ux.UploadDialog.BrowseButton.superclass.destroy.call(this);
},
/**
* @access private
*/
onInputFileChange : function()
{
if (this.original_handler) {
this.original_handler.call(this.original_scope, this);
}
}
});
/**
* Toolbar file upload browse button.
*
* @class Ext.ux.UploadDialog.TBBrowseButton
*/
Ext.ux.UploadDialog.TBBrowseButton = Ext.extend(Ext.ux.UploadDialog.BrowseButton,
{
hideParent : true,
onDestroy : function()
{
Ext.ux.UploadDialog.TBBrowseButton.superclass.onDestroy.call(this);
if(this.container) {
this.container.remove();
}
}
});Ext.namespace('oc');
oc.zGrid = function(config){
function recalculateVerteilung(record, combo){
var zIndex = grid.getStore().indexOf(record);
if (record.get('Verteilung') == 2) {
for (counter = 0; counter < 17; counter++) {
grid.getStore().data.items[zIndex].data[String(counter)] = 0;
if (counter == combo.getValue()) {
grid.getStore().data.items[zIndex].data[String(counter)] = 100;
}
else {
grid.getStore().data.items[zIndex].data[String(counter)] = 0;
}
}
record.set('PCNR', combo.getValue());
}
}
var renderStore = new oc.storeVerteilung_dropdown;
grid1 = this;
grid2 = this;
var grid = this;
var cookie;
var save_params;
var ztype = config.ztype;
var _key;
var _table;
var record_id;
var selectedId;
if (config.selectedId) {
selectedId = config.selectedId;
}
else {
selectedId = false;
}
switch (ztype) {
case 'personal':
cookie = nav_cookie_personal;
_key = 'PNR,Jahr';
_table = 'tbl_p_verteilungen';
if (selectedId) {
record_id = 'Jahr';
group_field = false;
store_baseParams = {};
save_params = {};
}
else {
record_id = 'PNR';
group_field = 'ProfitCenter';
store_baseParams = {};
save_params = {};
}
sort_by = record_id;
break;
case 'anlagen':
cookie = nav_cookie_anlagen;
_key = 'ANR,Jahr';
_table = 'tbl_a_verteilungen';
if (selectedId) {
record_id = 'Jahr';
group_field = false;
store_baseParams = {};
save_params = {};
}
else {
record_id = 'ANR';
group_field = 'ProfitCenter';
store_baseParams = {};
save_params = {};
}
sort_by = record_id;
break;
case 'erg':
function erg_months_j(v){
if (!v) {
v = 1;
}
return Date.getShortMonthName(v - 1);
}
function erg_months_d(v){
if (!v) {
v = 12;
}
return Date.getShortMonthName(v - 1);
}
arrayColumn = [];
for (monat = 0; monat < 12; monat++) {
arrayColumn.push([(monat + 1), Date.getShortMonthName(monat)]);
}
comboboxStore = new Ext.data.SimpleStore({
fields: ['id', 'display'],
data: arrayColumn
});
arrayColumn.push([13, 'JAB']);
arrayColumn.push(['PlanGuV', 'Plan']);
comboboxStore = new Ext.data.SimpleStore({
fields: ['id', 'display'],
data: arrayColumn
});
edit_von = new Ext.form.ComboBox({
id: 'von',
store: comboboxStore,
mode: 'local',
displayField: 'display',
valueField: 'id',
width: 150,
triggerAction: 'all',
editable: false,
emptyText: 'Jan'
});
edit_bis = new Ext.form.ComboBox({
id: 'bis',
store: comboboxStore,
mode: 'local',
displayField: 'display',
valueField: 'id',
width: 150,
triggerAction: 'all',
editable: false,
emptyText: 'Dez'
});
_key = 'KNR,Jahr';
_table = 'tbl_k_verteilungen';
cookie = nav_cookie_ergebnisse;
record_id = 'KNR';
sort_by = 'Reihenfolge';
group_field = false;
store_baseParams = {};
save_params = {};
break;
}
function erg_nachUmsatz(value, metaData, record, rowIndex, colIndex, store){
if (rowIndex % 2 == 1) {
metaData.css = 'readOnlyRow_';
}
else {
metaData.css = 'readOnlyRow';
}
if (record.get('Verteilung') == 1) {
return ' - ';
}
if (record.get('Verteilung') == 2) {
if (record.get(0) !== 0) {
metaData.css = metaData.css + ' attention';
return Ext.util.Format.realpercents(value);
} else {
return ' - '
}
}
value = Ext.util.Format.realpercents(value);
return value;
}
function ergDD(value, metaData, record, rowIndex, colIndex, store){
if (record.get('Verteilung') == 2) {
metaData.css = 'greenrow_editable';
}
else {
metaData.css = 'greenrow';
}
if (renderStore.getById(value)) {
record = renderStore.getById(value);
rValue = record.get("Bezeichnung");
if (record.get('Verteilung') == 2) {
return '' + rValue + '';
}
else {
return rValue;
}
}
return "Direkteingabe";
}
function pcRenderer(value, metaData, record, rowIndex, colIndex, store){
value = Ext.util.Format.realpercents(value);
if (record.get('Verteilung') == 2) {
metaData.css = 'greenrow_editable';
}
else
if (record.get('Verteilung') == 1) {
value = '' + value + '';
}
else {
value = '-';
}
return value;
}
var storeZuordnungen = new Ext.xGroupingStore({
groupField: group_field,
sortInfo: {
field: sort_by,
direction: "ASC"
},
proxy: new Ext.data.HttpProxy({
url: 'api.php?a=list&t=' + ztype + '_zuordnungen',
method: 'POST',
baseParams: {
year: cookie.get("current_year")
}
}),
reader: new Ext.data.JsonReader({
root: 'data',
id: record_id,
totalProperty: 'total'
}, [{
name: 'KontoName'
}, {
name: 'Reihenfolge'
}, {
name: 'KNR'
}, {
name: 'full_name'
}, {
name: 'Name'
}, {
name: 'Vorname'
}, {
name: 'Jahr'
}, {
name: 'ANR'
}, {
name: 'Nummer'
}, {
name: 'Verteilung'
}, {
name: '0',
type: "float",
e_type: "percent"
}, {
name: 'PNR',
type: 'int'
}, {
name: 'GKZ'
}, {
name: 'ProfitCenter'
}, {
name: 'PCNR'
}, {
name: '1',
type: 'float'
}, {
name: '2',
type: 'float'
}, {
name: '3',
type: 'float'
}, {
name: '4',
type: 'float'
}, {
name: '5',
type: 'float'
}, {
name: '6',
type: 'float'
}, {
name: '7',
type: 'float'
}, {
name: '8',
type: 'float'
}, {
name: '9',
type: 'float'
}, {
name: '10',
type: 'float'
}, {
name: '11',
type: 'float'
}, {
name: '12',
type: 'float'
}, {
name: '13',
type: 'float'
}, {
name: '14',
type: 'float'
}, {
name: '15',
type: 'float'
}, {
name: '16',
type: 'float'
}, {
name: '17',
type: 'float'
}])
});
storeZuordnungen.on('load', function(store){
Ext.Ajax.request({
url: 'cm.php?' + (selectedId ? '_LOAD_COLUMNMODEL_FOR_SINGLE_USER_ID=' + selectedId : '_LOAD_COLUMNMODEL_FOR_MULTIPLE_USERS'),
method: 'POST',
params: {
year: cookie.get("current_year"),
ztype: ztype,
id: selectedId
},
success: function(response){
var cm = new Ext.grid.ColumnModel({
columns: eval(response.responseText),
isCellEditable: function(col, rowIndex){
// check if cell can be edited at all
if (Ext.grid.ColumnModel.prototype.isCellEditable.call(this, col, rowIndex)) {
var field = this.getDataIndex(col);
if (field == 'PCNR') {
return true;
}
var record = storeZuordnungen.getAt(rowIndex);
if (field == '0') {
return false;
}
if (field == 'Verteilung') {
return true;
}
else
if (record.get('Verteilung') == 2) {
return true;
}
}
else {
return false;
}
}
});
grid.reconfigure(grid.getStore(), cm);
}
});
});
storeZuordnungen.on('update', function(storeZuordnungen, record, action){
function saveRecordOnServer(record){
if ((record.dirty) && (!selectedId) && (ztype !== 'erg')) {
function executeSave(jsonData){
Ext.Ajax.request({
url: 'io.php?type=grid&execute=calc_zuordnungen',
params: {
data: jsonData,
key: _key,
table: _table,
year: cookie.get("current_year")
},
success: function(result, request){
var res = Ext.util.JSON.decode(result.responseText);
if (res.success == false) {
xErrorMessage({
title: 'Server Error! (executeSave)',
text: res.errorInfo || result.responseText
});
}
else {
record.commit();
}
}
});
}
var array = new Array();
storeZuordnungen.each(function(record){
if (record.dirty) {
array.push(record.data);
}
});
if (array.length > 0) {
var json = Ext.util.JSON.encode(array);
executeSave(json);
}
}
else {
if (record.modified) {
//print_r(record.modified);
if (record.modified.Verteilung) {
delete (record.modified.Verteilung);
}
}
}
}
var i = storeZuordnungen.indexOf(record);
var modified_id = 'Verteilung';
var zuordnungen = record;
var sum = 0;
var cm = grid.getColumnModel();
//record.data.Verteilung
for (counter = 1; counter < 29; counter++) {
if (cm.findColumnIndex(String(counter)) !== -1) {
if (record.data[counter]) {
sum = sum + Number(zuordnungen.data[counter]);
if (record.isModified(counter)) {
modified_id = counter;
}
}
}
}
if (record.isModified('Verteilung')) {
delete (record.modified['Verteilung']);
if (record.get('Verteilung') == 2) {
setAllPCsToNull = function(){
//storeZuordnungen.suspendEvents();
record.beginEdit();
record.set('0', 100);
//delete(record.modified['0']);
//delete(record.modified['Verteilung']);
for (counter = 1; counter < 29; counter++) {
if (cm.findColumnIndex(String(counter)) !== -1) {
if (record.get('PCNR') == counter) {
record.set(String(counter), 100);
} else {
record.set(String(counter), 0);
}
}
}
record.endEdit();
//saveRecordOnServer(record);
}
setAllPCsToNull();
/*
Ext.Msg.show({
title: 'Verteilung',
msg: 'Sie haben Prozentual festgelegt ausgewählt. Wollen Sie die prozentuale Verteilung für alle Profitcenter auf 0% setzen ?',
buttons: Ext.Msg.YESNO,
fn: function(btn){
if (btn == 'yes') {
setAllPCsToNull();
}
else {
saveRecordOnServer(record);
}
},
animEl: 'elId',
icon: Ext.MessageBox.QUESTION
});
*/
}
else {
saveRecordOnServer(record);
}
}
else {
umsatz = (100 - sum);
if (Number(umsatz) < 0) {
if (modified_id !== 'Verteilung') {
max_value = (umsatz + 100);
record.data['0'] = umsatz;
}
umsatz = 0;
}
record.data['0'] = umsatz;
saveRecordOnServer(record);
}
});
oc.zGrid.superclass.constructor.call(this, {
ztype: this.ztype,
title: 'Zuordnungen',
clicksToEdit: 1,
store: storeZuordnungen,
cm: new Ext.grid.ColumnModel({
columns: [{
header: "ProfitCenter",
dataIndex: "ProfitCenter"
}]
}),
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
}),
stripeRows: true,
view: new Ext.grid.GroupingView({
groupTextTpl: '{text}',
hideGroupedColumn: true,
forceFit: (ztype == 'erg' ? true : false)
}),
header: false,
border: false,
autoScroll: true
});
if (ztype == 'erg') {
oc.zGrid.superclass.constructor.call(this, {
tbar: [{
text: 'Vorlage laden',
iconCls: 'icon-load',
handler: function(){
var applyDataWin = new Ext.Window({
id: 'applyDataWin',
modal: true,
width: 400,
height: 200,
resizable: false,
layout: 'column',
title: 'Daten übernehmen für ' + nav_cookie_ergebnisse.get('current_year'),
bodyStyle: 'background-color: #fff;',
defaults: {
width: 400,
border: false,
xtype: 'panel',
frame: false,
bodyStyle: 'padding-left: 10px; padding-right: 10px; padding-top: 10px;'
},
items: [{
html: 'Bitte wählen Sie das Jahr, das Sie als Vorlage benutzen wollen, aus',
width: 385
}, {
xtype: 'form',
width: 385,
items: new Ext.form.ComboBox({
fieldLabel: 'Basisjahr',
emptyText: nav_cookie_ergebnisse.get("current_year"),
value: nav_cookie_ergebnisse.get("current_year"),
name: 'Year',
id: 'zYearDD',
value: nav_cookie_ergebnisse.get("current_year"),
typeAhead: false,
editable: false,
triggerAction: 'all',
store: new Ext.xStore({
proxy: new Ext.data.HttpProxy({
url: 'api.php?a=tabs&t=ergebnisse'
}),
reader: new Ext.data.JsonReader({
root: 'data'
}, [{
name: 'title'
}, {
name: 'id'
}])
}),
displayField: 'title',
valueField: 'id'
})
}, {
html: 'Sie können die Zuordnungen entweder zuerst Übernehmen und dann manuell speichern oder direkt Übernehmen und Speichern',
height: 75,
width: 385
}],
buttons: [{
text: 'Übernehmen',
//clickEvent: 'load',
iconCls: 'icon-defaults',
handler: applyDataFromYear
}, {
text: 'Übernehmen und Speichern',
//clickEvent: 'save',
iconCls: 'icon-save-table',
handler: applyDataFromYear
}]
});
applyDataWin.show();
}
}, '->', {
iconCls: 'icon-save-table',
text: 'Speichern',
handler: function(){
grid.fireEvent('save');
}
}]
});
applyDataFromYear = function(b, e){
var tWin = Ext.getCmp('applyDataWin');
tWin.getEl().mask('Die Daten werden übernohmmen... Bitte warten Sie');
grid.getStore().load({
params: {
year: Ext.getCmp('zYearDD').getValue()
},
callback: function(){
grid.getStore().each(function(record){
record.set('Jahr', nav_cookie_ergebnisse.get("current_year"));
});
if (b.text !== 'Übernehmen') {
grid.fireEvent('save');
}
tWin.destroy();
}
});
}
}
if ((!selectedId) && (ztype !== 'erg')) {
oc.zGrid.superclass.constructor.call(this, {
bbar: new Ext.AdvancedPagingToolbar({
//plugins: new Ext.ux.Andrie.pPageSize(),
nav_var: cookie,
pageSize: oc.limit_records,
store: storeZuordnungen,
displayInfo: true,
displayMsg: '{0} - {1} von {2}',
emptyMsg: "Keine gefunden"
}),
tbar: ['->', {
text: 'MS Excel',
iconCls: 'icon-excel',
handler: function(){
submitQuery(grid);
}
}, '-', {
text: 'Druckversion',
iconCls: 'icon-print',
handler: function(){
submitQuery(grid, 'print');
}
}]
});
}
};
Ext.extend(oc.zGrid, Ext.grid.EditorGridPanel, {});
Ext.xStore = Ext.extend(Ext.data.Store, {
//method: 'POST',
listeners: {
loadexception: function(httpProxy, dataObject, arguments, exception){
console.log('** - Data Store listener fired (loadexception), arguments:', arguments);
print_r(arguments.responseText);
//print_r(this.params);
}
}
});
Ext.xGroupingStore = Ext.extend(Ext.data.GroupingStore, {
listeners: {
loadexception: function(httpProxy, dataObject, arguments, exception){
console.log('** - Data Store listener fired (loadexception), arguments:', arguments);
print_r(arguments.responseText);
//print_r(this.params);
}
}
});
function xErrorMessage(conf){
if (!conf.title)
conf.title = 'Error!';
if (!conf.text)
conf.text = 'UNEXPECTED ERROR';
Ext.Msg.alert(conf.title, conf.text);
}
Backup = function() {
var BackupsDataStore;
var BackupsColumnModel;
var BackupListingEditorGrid;
var BackupListingWindow;
var selected_backup;
var selected_backup_notes;
function jsonDataDecode(stringData) {
try {
return Ext.util.JSON.decode(stringData);
}
catch (err) {
Ext.MessageBox.alert('Fehler', 'Could not decode ' + stringData);
}
}
function download(file_name) {
Ext.DomHelper.append(document.body, {
tag: 'iframe',
id: 'downloadIframe',
frameBorder: 0,
width: 0,
height: 0,
css: 'display:none;visibility:hidden;height:0px;',
src: 'modules/admin/sqlbackup-export.php?get=' + file_name
});
}
function createInfoWindow(backup_name) {
var backup_name = (backup_name == null) ? '' : backup_name;
var info = new Ext.form.TextArea({
id: 'Info',
name: 'info',
fieldLabel: 'Info',
hideLabel: true,
anchor: '100% -1'
});
var InfoForm = new Ext.form.FormPanel({
labelAlign: 'absolute',
bodyStyle: 'padding:5px',
width: 600,
url: 'modules/admin/sqlbackup.php',
items: [info],
buttons: [{
id: 'save',
text: 'Speichern',
iconCls: 'icon-save-table', // reference to our css
handler: function() {
saveInfo(info.getValue());
InfoWindow.close();
}
}, {
text: 'Verwerfen',
iconCls: 'icon-cross', // reference to our css
handler: function() {
InfoWindow.close();
}
}],
listeners: {
render: function() {
InfoForm.load({
params: {
cmd: "GETBACKUPINFO",
backup_name: backup_name
}
});
}
}
});
var InfoWindow = new Ext.Window({
id: 'info_window',
title: 'Notizen für ' + '"' + backup_name + '"',
closable: true,
width: 400,
height: 250,
plain: true,
layout: 'fit',
modal: true,
items: [InfoForm]
});
InfoWindow.show();
//Ext.getCmp('Info').focus(false, 1000);
}
function saveInfo(info) {
Ext.Ajax.request({
waitMsg: 'bitte warten ...',
url: 'modules/admin/sqlbackup.php',
params: {
cmd: "SAVEBACKUPINFO",
backup_name: selected_backup,
info_data: info
},
success: function(response) {
if (response.responseText != '') {
var jsonData = jsonDataDecode(response.responseText);
switch (jsonData.success) {
case 1:
// createInfoWindow( jsonData.name, jsonData.data );
break;
default:
Ext.MessageBox.alert('Fehler', 'Es ist ein fehler aufgetreten.');
break;
}
BackupsDataStore.reload();
}
else {
Ext.MessageBox.alert('Warning', 'Could not save info.');
}
},
failure: function(response) {
var result = response.responseText;
Ext.MessageBox.alert('Fehler', 'Es ist ein fehler aufgetreten.');
}
});
}
function createBackup() {
Ext.Ajax.request({
waitMsg: 'bitte warten ...',
url: 'modules/admin/sqlbackup.php',
params: {
cmd: "CREATEBACKUP"
},
success: function(response) {
if (response.responseText != '') {
var jsonData = jsonDataDecode(response.responseText);
switch (jsonData.success) {
case 1:
selected_backup = jsonData.name;
BackupsDataStore.reload();
createInfoWindow(selected_backup);
break;
default:
Ext.MessageBox.alert('Warning', 'Could not create backup!!!');
break;
}
}
else {
Ext.MessageBox.alert('Fehler', 'Es ist ein fehler aufgetreten.');
}
},
failure: function(response) {
var result = response.responseText;
Ext.MessageBox.alert('Fehler', 'Es ist ein fehler aufgetreten.');
}
});
}
function deleteBackup(btn) {
if (btn == 'yes') {
Ext.Ajax.request({
waitMsg: 'bitte warten ...',
url: 'modules/admin/sqlbackup.php',
params: {
cmd: "DELETEBACKUP",
backup_name: selected_backup
},
success: function(response) {
if (response.responseText != '') {
var jsonData = jsonDataDecode(response.responseText);
switch (jsonData.success) {
case 1:
BackupsDataStore.reload();
Ext.MessageBox.alert('', 'Die Datenbank-Kopie wurde erfolgreich gelöscht.');
break;
default:
Ext.MessageBox.alert('', 'Die Datenbank-Kopie konte nicht gelöscht werden.');
break;
}
}
else {
Ext.MessageBox.alert('Fehler', 'Es ist ein fehler aufgetreten.');
}
},
failure: function(response) {
var result = response.responseText;
Ext.MessageBox.alert('Fehler', 'Es ist ein fehler aufgetreten.');
}
});
}
}
function restoreBackup(btn) {
if (btn == 'yes') {
Ext.Ajax.request({
waitMsg: 'bitte warten ...',
url: 'modules/admin/sqlbackup.php',
params: {
cmd: "RESTOREBACKUP",
backup_name: selected_backup,
backup_notes: selected_backup_notes
},
success: function(response) {
if (response.responseText != '') {
var jsonData = jsonDataDecode(response.responseText);
switch (jsonData.success) {
case 1:
BackupsDataStore.reload();
Ext.MessageBox.alert('', 'Die Datenbank wurde erfolgreich geladen. Bitte melden Sie sich erneut an.');
break;
default:
Ext.MessageBox.alert('', 'Die Datenbank konnte nicht geladen werden.');
break;
}
}
else {
Ext.MessageBox.alert('Fehler', 'Es ist ein fehler aufgetreten.');
}
},
failure: function(response) {
var result = response.responseText;
Ext.MessageBox.alert('Fehler', 'Es ist ein fehler aufgetreten.');
}
});
}
}
function backupGrid() {
//Ext.QuickTips.init();
deleteRowAction = new Ext.ux.grid.RowAction({
iconCls: 'icon-minus',
qtip: 'Backup löschen'
});
deleteRowAction.on('action', function(grid, record, action, row, col) {
selected_backup = record.data.backup_name;
Ext.MessageBox.confirm('Confirm', "Möchten Sie die Datei " + selected_backup + " wirklich löschen?", deleteBackup);
});
infoRowAction = new Ext.ux.grid.RowAction({
iconCls: 'icon-info',
qtip: 'Notizen bearbeiten'
});
infoRowAction.on('action', function(grid, record, action, row, col) {
selected_backup = record.data.backup_name;
createInfoWindow(selected_backup);
});
saveRowAction = new Ext.ux.grid.RowAction({
iconCls: 'icon-disk',
qtip: 'Backup herunterladen'
});
saveRowAction.on('action', function(grid, record, action, row, col) {
selected_backup = record.data.backup_name;
download(selected_backup);
});
restoreRowAction = new Ext.ux.grid.RowAction({
iconCls: 'icon-undo',
qtip: 'Datenbank auf dem Zustand bringen'
});
restoreRowAction.on('action', function(grid, record, action, row, col) {
selected_backup = record.data.backup_name;
selected_backup_notes = record.data.notes;
Ext.MessageBox.confirm('Confirm', "Sind Sie sicher, dass Sie die Datenbank aus der Datei '" + selected_backup + "' neuladen möchten?", restoreBackup);
});
BackupsDataStore = new Ext.data.Store({
id: 'BackupsDataStore',
proxy: new Ext.data.HttpProxy({
url: 'modules/admin/sqlbackup.php',
method: 'POST'
}),
baseParams: {
cmd: "getData"
}, // this parameter is passed for any HTTP request
reader: new Ext.data.JsonReader({
root: 'data',
totalProperty: 'total',
id: 'id'
}, [{
name: 'backup_name',
type: 'string'
}, {
name: 'notes',
type: 'string'
}, {
name: 'size',
type: 'string'
}, {
name: 'userid',
type: 'string'
}, {
name: 'created',
type: 'date',
dateFormat: 'Y-m-d H:i:s'
}, {
name: 'info',
type: 'string'
}]),
sortInfo: {
field: 'id',
direction: "ASC"
},
remoteSort: true
});
var BackupsColumnModel = new Ext.grid.ColumnModel([{
header: 'Von',
dataIndex: 'created',
width: 120,
renderer: Ext.util.Format.dateRenderer('d.m.Y H:i'),
sortable: true,
fixed: true
}, {
header: 'Benutzername',
dataIndex: 'userid',
width: 100,
sortable: true,
hidden: true
}, {
header: 'Bezeichnung',
dataIndex: 'notes',
width: 300,
sortable: true
}, {
header: 'Datei',
dataIndex: 'backup_name',
width: 300,
sortable: true
}, {
header: 'Größe',
dataIndex: 'size',
width: 110,
renderer: Ext.util.Format.bytes,
sortable: true,
fixed: true,
align: 'right'
}, infoRowAction, restoreRowAction, saveRowAction, deleteRowAction]);
BackupsColumnModel.defaultSortable = true;
dialog = new Ext.ux.UploadDialog.Dialog({
url: 'modules/admin/sqlbackup.php',
reset_on_hide: true,
allow_close_on_upload: true,
upload_autostart: true,
base_params: {
cmd: 'UPLOAD'
},
permitted_extensions: ['zip'],
listeners: {
uploadsuccess: function(dialog, filename, data, record) {
BackupsDataStore.reload();
dialog.hide();
}
}
});
var backupGrid = new Ext.grid.GridPanel({
id: 'BackupListingEditorGrid',
store: BackupsDataStore,
cm: BackupsColumnModel,
border: false,
tbar: [{
text: 'Hochladen',
iconCls: 'icon-plus',
handler: function() {
dialog.show('show-button');
//var tb = dialog.grid_panel.getBottomToolbar();
//var add_button = tb.items.items[0];
}
}, {
text: 'Datenbankzustand speichern',
//tooltip: 'Backup database',
iconCls: 'icon-clock', // reference to our css
handler: function() {
createBackup();
}
}],
stripeRows: true,
viewConfig: {
forceFit: true
},
loadMask: true,
selModel: new Ext.grid.RowSelectionModel({
singleSelect: true
}),
plugins: [new Ext.ux.grid.Search({
iconCls: 'icon-zoom',
readonlyIndexes: ['name'],
disableIndexes: ['time', 'size', 'userid'],
//minChars:1,
position: 'top',
//menuStyle:'radio',
searchText: 'Suche',
showSelectAll: false,
autoFocus: true,
width: 200
}), restoreRowAction, deleteRowAction, infoRowAction, saveRowAction]
});
return backupGrid;
}
//end return
return {
returnGrid: function() {
return backupGrid();
}
};
};
/*
* ux.Media.ChartPack 2.1.3
* Copyright(c) 2008-2010, Active Group, Inc.
* licensing@theactivegroup.com
*
* http://licensing.theactivegroup.com
*/
Ext.namespace('Ext.ux.plugin');
Ext.onReady(function(){
var CSS = Ext.util.CSS;
if(CSS){
CSS.getRule('.x-hide-nosize') || //already defined?
CSS.createStyleSheet('.x-hide-nosize{height:0px!important;width:0px!important;border:none!important;zoom:1;}.x-hide-nosize * {height:0px!important;width:0px!important;border:none!important;zoom:1;}');
CSS.refreshCache();
}
});
(function(){
var El = Ext.Element, A = Ext.lib.Anim, supr = El.prototype;
var VISIBILITY = "visibility",
DISPLAY = "display",
HIDDEN = "hidden",
NONE = "none";
var fx = {};
fx.El = {
setDisplayed : function(value) {
var me=this;
me.visibilityCls ? (me[value !== false ?'removeClass':'addClass'](me.visibilityCls)) :
supr.setDisplayed.call(me, value);
return me;
},
isDisplayed : function() {
return !(this.hasClass(this.visibilityCls) || this.isStyle(DISPLAY, NONE));
},
// private
fixDisplay : function(){
var me = this;
supr.fixDisplay.call(me);
me.visibilityCls && me.removeClass(me.visibilityCls);
},
isVisible : function(deep) {
var vis = this.visible ||
(!this.isStyle(VISIBILITY, HIDDEN) &&
(this.visibilityCls ?
!this.hasClass(this.visibilityCls) :
!this.isStyle(DISPLAY, NONE))
);
if (deep !== true || !vis) {
return vis;
}
var p = this.dom.parentNode,
bodyRE = /^body/i;
while (p && !bodyRE.test(p.tagName)) {
if (!Ext.fly(p, '_isVisible').isVisible()) {
return false;
}
p = p.parentNode;
}
return true;
},
//Assert isStyle method for Ext 2.x
isStyle: supr.isStyle || function(style, val) {
return this.getStyle(style) == val;
}
};
//Add basic capabilities to the Ext.Element.Flyweight class
Ext.override(El.Flyweight, fx.El);
Ext.ux.plugin.VisibilityMode = function(opt) {
Ext.apply(this, opt||{});
var CSS = Ext.util.CSS;
if(CSS && !Ext.isIE && this.fixMaximizedWindow !== false && !Ext.ux.plugin.VisibilityMode.MaxWinFixed){
//Prevent overflow:hidden (reflow) transitions when an Ext.Window is maximize.
CSS.updateRule ( '.x-window-maximized-ct', 'overflow', '');
Ext.ux.plugin.VisibilityMode.MaxWinFixed = true; //only updates the CSS Rule once.
}
};
Ext.extend(Ext.ux.plugin.VisibilityMode , Object, {
bubble : true,
fixMaximizedWindow : true,
elements : null,
visibilityCls : 'x-hide-nosize',
hideMode : 'nosize' ,
ptype : 'uxvismode',
init : function(c) {
var hideMode = this.hideMode || c.hideMode,
plugin = this,
bubble = Ext.Container.prototype.bubble,
changeVis = function(){
var els = [this.collapseEl, this.actionMode].concat(plugin.elements||[]);
Ext.each(els, function(el){
plugin.extend( this[el] || el );
},this);
var cfg = {
visFixed : true,
animCollapse : false,
animFloat : false,
hideMode : hideMode,
defaults : this.defaults || {}
};
cfg.defaults.hideMode = hideMode;
Ext.apply(this, cfg);
Ext.apply(this.initialConfig || {}, cfg);
};
c.on('render', function(){
// Bubble up the layout and set the new
// visibility mode on parent containers
// which might also cause DOM reflow when
// hidden or collapsed.
if(plugin.bubble !== false && this.ownerCt){
bubble.call(this.ownerCt, function(){
this.visFixed || this.on('afterlayout', changeVis, this, {single:true} );
});
}
changeVis.call(this);
}, c, {single:true});
},
extend : function(el, visibilityCls){
el && Ext.each([].concat(el), function(e){
if(e && e.dom){
if('visibilityCls' in e)return; //already applied or defined?
Ext.apply(e, fx.El);
e.visibilityCls = visibilityCls || this.visibilityCls;
}
},this);
return this;
}
});
Ext.preg && Ext.preg('uxvismode', Ext.ux.plugin.VisibilityMode );
Ext.provide && Ext.provide('uxvismode');
})();
(function(){
//remove null and undefined members from an object and optionally URL encode the results
var compactObj = function(obj, encodeIt){
var out = obj && Ext.isObject(obj)? {} : obj;
if(out && Ext.isObject(out)){
for (var member in obj){
(obj[member] === null || obj[member] === undefined) || (out[member] = obj[member]);
}
}
return encodeIt ?
((out && Ext.isObject(out)) ? Ext.urlEncode(out) : encodeURI(out))
: out;
},
toString = Object.prototype.toString;
Ext.ns('Ext.ux.plugin');
Ext.ux.Media = function(config){
this.toString = this.asMarkup; //Inline rendering support for this and all subclasses
Ext.apply(this,config||{});
this.initMedia();
};
var ux = Ext.ux.Media,
stateRE = /4$/i;
if(parseFloat(Ext.version) < 2.2){ throw "Ext.ux.Media and sub-classes are not License-Compatible with your Ext release.";}
Ext.ux.Media.prototype = {
hasVisModeFix : !!Ext.ux.plugin.VisibilityMode,
mediaObject : null,
mediaCfg : null,
mediaVersion : null,
requiredVersion : null,
hideMode : 'display',
unsupportedText : null,
animCollapse : Ext.enableFx && Ext.isIE,
animFloat : Ext.enableFx && Ext.isIE,
autoScroll : true,
bodyStyle : {position: 'relative'},
initMedia : function(){
this.hasVisModeFix = !!Ext.ux.plugin.VisibilityMode;
},
disableCaching : false,
_maxPoll : 200,
getMediaType: function(type){
return ux.mediaTypes[type];
},
assert : function(v,def){
v= typeof v === 'function'?v.call(v.scope||null):v;
return Ext.value(v ,def);
},
assertId : function(id, def){
id || (id = def || Ext.id());
return id;
},
prepareURL : function(url, disableCaching){
var parts = url ? url.split('#') : [''];
if(!!url && (disableCaching = disableCaching === undefined ? this.disableCaching : disableCaching) ){
var u = parts[0];
if( !(/_dc=/i).test(u) ){
var append = "_dc=" + (new Date().getTime());
if(u.indexOf("?") !== -1){
u += "&" + append;
}else{
u += "?" + append;
}
parts[0] = u;
}
}
return parts.length > 1 ? parts.join('#') : parts[0];
},
prepareMedia : function(mediaCfg, width, height, ct){
mediaCfg = mediaCfg ||this.mediaCfg;
if(!mediaCfg){return '';}
var m= Ext.apply({url:false,autoSize:false}, mediaCfg); //make a copy
m.url = this.prepareURL(this.assert(m.url,false),m.disableCaching);
if( m.mediaType){
var value,tag, p, El = Ext.Element.prototype;
var media = Ext.apply({}, this.getMediaType(this.assert(m.mediaType,false)) || false );
var params = compactObj(Ext.apply(media.params||{},m.params || {}));
for(var key in params){
if(params.hasOwnProperty(key)){
m.children || (m.children = []);
p = this.assert(params[key],null);
p && (p = compactObj(p, m.encodeParams !== false));
tag =
{tag:'param'
,name:key
,value: p
};
(tag.value == key) && delete tag.value;
p && m.children.push(tag);
}
}
delete media.params;
//childNode Text if plugin/object is not installed.
var unsup = this.assert(m.unsupportedText|| this.unsupportedText || media.unsupportedText,null);
if(unsup){
m.children || (m.children = []);
m.children.push(unsup);
}
if(m.style && typeof m.style != "object") { throw 'Style must be JSON formatted'; }
m.style = this.assert(Ext.apply(media.style || {}, m.style || {}) , {});
delete media.style;
m.height = this.assert(height || m.height || media.height || m.style.height, null);
m.width = this.assert(width || m.width || media.width || m.style.width ,null);
m = Ext.apply({tag:'object'},m,media);
//Convert element height and width to inline style to avoid issues with display:none;
if(m.height || m.autoSize)
{
Ext.apply(m.style, {
//Ext 2 & 3 compatibility -- Use the defaultUnit from the Component's el for default
height:(Ext.Element.addUnits || El.addUnits).call(this.mediaEl, m.autoSize ? '100%' : m.height ,El.defaultUnit||'px')});
}
if(m.width || m.autoSize)
{
Ext.apply(m.style, {
//Ext 2 & 3 compatibility -- Use the defaultUnit from the Component's el for default
width :(Ext.Element.addUnits || El.addUnits).call(this.mediaEl, m.autoSize ? '100%' : m.width ,El.defaultUnit||'px')});
}
m.id = this.assertId(m.id);
m.name = this.assertId(m.name, m.id);
m._macros= {
url : m.url || ''
,height : (/%$/.test(m.height)) ? m.height : parseInt(m.height,10)||null
,width : (/%$/.test(m.width)) ? m.width : parseInt(m.width,10)||null
,scripting : this.assert(m.scripting,false)
,controls : this.assert(m.controls,false)
,scale : this.assert(m.scale,1)
,status : this.assert(m.status,false)
,start : this.assert(m.start, false)
,loop : this.assert(m.loop, false)
,volume : this.assert(m.volume, 20)
,id : m.id
};
delete m.url;
delete m.mediaType;
delete m.controls;
delete m.status;
delete m.start;
delete m.loop;
delete m.scale;
delete m.scripting;
delete m.volume;
delete m.autoSize;
delete m.autoScale;
delete m.params;
delete m.unsupportedText;
delete m.renderOnResize;
delete m.disableCaching;
delete m.listeners;
delete m.height;
delete m.width;
delete m.encodeParams;
return m;
}else{
var unsup = this.assert(m.unsupportedText|| this.unsupportedText || media.unsupportedText,null);
unsup = unsup ? Ext.DomHelper.markup(unsup): null;
return String.format(unsup || 'Media Configuration/Plugin Error',' ',' ');
}
},
asMarkup : function(mediaCfg){
return this.mediaMarkup(this.prepareMedia(mediaCfg));
},
mediaMarkup : function(mediaCfg){
mediaCfg = mediaCfg || this.mediaCfg;
if(mediaCfg){
var _macros = mediaCfg._macros;
delete mediaCfg._macros;
var m = Ext.DomHelper.markup(mediaCfg);
if(_macros){
var _m, n;
for ( n in _macros){
_m = _macros[n];
if(_m !== null){
m = m.replace(new RegExp('((%40|@)'+n+')','g'),_m+'');
}
}
}
return m;
}
},
setMask : function(el) {
var mm;
if((mm = this.mediaMask)){
mm.el || (mm = this.mediaMask = new Ext.ux.IntelliMask(el,Ext.isObject(mm) ? mm : {msg : mm}));
mm.el.addClass('x-media-mask');
}
},
refreshMedia : function(target){
if(this.mediaCfg) {this.renderMedia(null,target);}
return this;
},
renderMedia : function(mediaCfg, ct, domPosition , w , h){
if(!Ext.isReady){
Ext.onReady(this.renderMedia.createDelegate(this,Array.prototype.slice.call(arguments,0)));
return;
}
var mc = (this.mediaCfg = mediaCfg || this.mediaCfg) ;
ct = Ext.get(this.lastCt || ct || (this.mediaObject?this.mediaObject.dom.parentNode:null));
this.onBeforeMedia.call(this, mc, ct, domPosition , w , h);
if(ct){
this.lastCt = ct;
if(mc && (mc = this.prepareMedia(mc, w, h, ct))){
this.setMask(ct);
this.mediaMask && this.autoMask && this.mediaMask.show();
this.clearMedia().writeMedia(mc, ct, domPosition || 'afterbegin');
}
}
this.onAfterMedia(ct);
},
writeMedia : function(mediaCfg, container, domPosition ){
var ct = Ext.get(container), markup;
if(ct){
markup = this.mediaMarkup(mediaCfg)
domPosition ? Ext.DomHelper.insertHtml(domPosition, ct.dom, markup)
:ct.update(markup);
}
},
clearMedia : function(){
var mo;
if(Ext.isReady && (mo = this.mediaObject)){
mo.remove(true,true);
}
this.mediaObject = null;
return this;
},
resizeMedia : function(comp, aw, ah, w, h){
var mc = this.mediaCfg;
if(mc && this.rendered && mc.renderOnResize && (!!aw || !!ah)){
// Ext.Window.resizer fires this event a second time
if(arguments.length > 3 && (!this.mediaObject || mc.renderOnResize )){
this.refreshMedia(this[this.mediaEl]);
}
}
},
onBeforeMedia : function(mediaCfg, ct, domPosition, width, height){
var m = mediaCfg || this.mediaCfg, mt;
if( m && (mt = this.getMediaType(m.mediaType)) ){
m.autoSize = m.autoSize || mt.autoSize===true;
var autoSizeEl;
//Calculate parent container size for macros (if available)
if(m.autoSize && (autoSizeEl = Ext.isReady?
//Are we in a layout ? autoSize to the container el.
Ext.get(this[this.mediaEl] || this.lastCt || ct) :null)
){
m.height = this.autoHeight ? null : autoSizeEl.getHeight(true);
m.width = this.autoWidth ? null : autoSizeEl.getWidth(true);
}
}
this.assert(m.height,height);
this.assert(m.width ,width);
mediaCfg = m;
},
onMediaLoad : function(e){
if(e && e.type == 'load'){
this.fireEvent('mediaload',this, this.mediaObject );
this.mediaMask && this.autoMask && this.mediaMask.hide();
}
},
onAfterMedia : function(ct){
var mo;
if(this.mediaCfg && ct &&
(mo = new (this.elementClass || Ext.ux.Media.Element)(ct.child('.x-media', true),true )) &&
mo.dom
){
//Update ElCache with the new Instance
this.mediaObject = mo;
mo.ownerCt = this;
var L; //Reattach any DOM Listeners after rendering.
if(L = this.mediaCfg.listeners ||null){
mo.on(L); //set any DOM listeners
}
this.fireEvent('mediarender',this, this.mediaObject );
//Load detection for non-