PDA

View Full Version : Error in Ext.ux.Printer plugin



fabielsehn
29 Dec 2010, 4:22 AM
I'm using the plugin Ext.ux.Printer Ed Spencer to print the grid.

But an error occurs when using the params attribute on the renderer of any column.

When I order prints the following error appears:


params is null

Below the plugin Ext.ux.Printer:




Ext.ux.Printer = function() {

return {
/**
* @property renderers
* @type Object
* An object in the form {xtype: RendererClass} which is manages the renderers registered by xtype
*/
renderers: {},

/**
* Registers a renderer function to handle components of a given xtype
* @param {String} xtype The component xtype the renderer will handle
* @param {Function} renderer The renderer to invoke for components of this xtype
*/
registerRenderer: function(xtype, renderer) {
this.renderers[xtype] = new (renderer)();
},

/**
* Returns the registered renderer for a given xtype
* @param {String} xtype The component xtype to find a renderer for
* @return {Object/undefined} The renderer instance for this xtype, or null if not found
*/
getRenderer: function(xtype) {
return this.renderers[xtype];
},

/**
* Prints the passed grid. Reflects on the grid's column model to build a table, and fills it using the store
* @param {Ext.Component} component The component to print
*/
print: function(component) {
var xtypes = component.getXTypes().split('/');

//iterate backwards over the xtypes of this component, dispatching to the most specific renderer
for (var i = xtypes.length - 1; i >= 0; i--){
var xtype = xtypes[i],
renderer = this.getRenderer(xtype);

if (renderer != undefined) {
renderer.print(component);
break;
}
}
}
};
}();

/**
* Override how getXTypes works so that it doesn't require that every single class has
* an xtype registered for it.
*/
Ext.override(Ext.Component, {
getXTypes : function(){
var tc = this.constructor;
if(!tc.xtypes){
var c = [], sc = this;
while(sc){ //was: while(sc && sc.constructor.xtype) {
var xtype = sc.constructor.xtype;
if (xtype != undefined) c.unshift(xtype);

sc = sc.constructor.superclass;
}
tc.xtypeChain = c;
tc.xtypes = c.join('/');
}
return tc.xtypes;
}
});

/**
* @class Ext.ux.Printer.BaseRenderer
* @extends Object
* @author Ed Spencer
* Abstract base renderer class. Don't use this directly, use a subclass instead
*/
Ext.ux.Printer.BaseRenderer = Ext.extend(Object, {
/**
* Prints the component
* @param {Ext.Component} component The component to print
*/
print: function(component) {
var name = component && component.getXType
? String.format("print_{0}_{1}", component.getXType(), component.id)
: "print";

var win = window.open('', name,'width=1,height=1');

win.document.write(this.generateHTML(component));
win.document.close();

win.print();
win.close();
},

/**
* Generates the HTML Markup which wraps whatever this.generateBody produces
* @param {Ext.Component} component The component to generate HTML for
* @return {String} An HTML fragment to be placed inside the print window
*/
generateHTML: function(component) {
return new Ext.XTemplate(
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
'<html>',
'<head>',
'<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />',
'<link href="' + this.stylesheetPath + '" rel="stylesheet" type="text/css" media="screen,print" />',
'<title>' + this.getTitle(component) + '</title>',
'</head>',
'<body>',
this.generateBody(component),
'</body>',
'</html>'
).apply(this.prepareData(component));
},

/**
* Returns the HTML that will be placed into the print window. This should produce HTML to go inside the
* <body> element only, as <head> is generated in the print function
* @param {Ext.Component} component The component to render
* @return {String} The HTML fragment to place inside the print window's <body> element
*/
generateBody: Ext.emptyFn,

/**
* Prepares data suitable for use in an XTemplate from the component
* @param {Ext.Component} component The component to acquire data from
* @return {Array} An empty array (override this to prepare your own data)
*/
prepareData: function(component) {
return component;
},

/**
* Returns the title to give to the print window
* @param {Ext.Component} component The component to be printed
* @return {String} The window title
*/
getTitle: function(component) {
return typeof component.getTitle == 'function' ? component.getTitle() : (component.title || "Printing");
},

/**
* @property stylesheetPath
* @type String
* The path at which the print stylesheet can be found (defaults to 'stylesheets/print.css')
*/
stylesheetPath: '../../../../../api/ext/Ext.ux.Printer/print.css'
});

/**
* @class Ext.ux.Printer.ColumnTreeRenderer
* @extends Ext.ux.Printer.BaseRenderer
* @author Ed Spencer
* Helper class to easily print the contents of a column tree
*/
Ext.ux.Printer.ColumnTreeRenderer = Ext.extend(Ext.ux.Printer.BaseRenderer, {

/**
* Generates the body HTML for the tree
* @param {Ext.tree.ColumnTree} tree The tree to print
*/
generateBody: function(tree) {
var columns = this.getColumns(tree);

//use the headerTpl and bodyTpl XTemplates to create the main XTemplate below
var headings = this.headerTpl.apply(columns);
var body = this.bodyTpl.apply(columns);

return String.format('<table>{0}<tpl for=".">{1}</tpl></table>', headings, body);
},

/**
* Returns the array of columns from a tree
* @param {Ext.tree.ColumnTree} tree The tree to get columns from
* @return {Array} The array of tree columns
*/
getColumns: function(tree) {
return tree.columns;
},

/**
* Descends down the tree from the root, creating an array of data suitable for use in an XTemplate
* @param {Ext.tree.ColumnTree} tree The column tree
* @return {Array} Data suitable for use in the body XTemplate
*/
prepareData: function(tree) {
var root = tree.root,
data = [],
cols = this.getColumns(tree),
padding = this.indentPadding;

var f = function(node) {
if (node.hidden === true || node.isHiddenRoot() === true) return;

var row = Ext.apply({depth: node.getDepth() * padding}, node.attributes);

Ext.iterate(row, function(key, value) {
Ext.each(cols, function(column) {
if (column.dataIndex == key) {
row[key] = column.renderer ? column.renderer(value) : value;
}
}, this);
});

//the property used in the first column is renamed to 'text' in node.attributes, so reassign it here
row[this.getColumns(tree)[0].dataIndex] = node.attributes.text;

data.push(row);
};

root.cascade(f, this);

return data;
},

/**
* @property indentPadding
* @type Number
* Number of pixels to indent node by. This is multiplied by the node depth, so a node with node.getDepth() == 3 will
* be padded by 45 (or 3x your custom indentPadding)
*/
indentPadding: 15,

/**
* @property headerTpl
* @type Ext.XTemplate
* The XTemplate used to create the headings row. By default this just uses <th> elements, override to provide your own
*/
headerTpl: new Ext.XTemplate(
'<tr>',
'<tpl for=".">',
'<th width="{width}">{header}</th>',
'</tpl>',
'</tr>'
),

/**
* @property bodyTpl
* @type Ext.XTemplate
* The XTemplate used to create each row. This is used inside the 'print' function to build another XTemplate, to which the data
* are then applied (see the escaped dataIndex attribute here - this ends up as "{dataIndex}")
*/
bodyTpl: new Ext.XTemplate(
'<tr>',
'<tpl for=".">',
'<td style="padding-left: {[xindex == 1 ? "\\{depth\\}" : "0"]}px">\{{dataIndex}\}</td>',
'</tpl>',
'</tr>'
)
});

Ext.ux.Printer.registerRenderer('columntree', Ext.ux.Printer.ColumnTreeRenderer);

/**
* @class Ext.ux.Printer.GridPanelRenderer
* @extends Ext.ux.Printer.BaseRenderer
* @author Ed Spencer
* Helper class to easily print the contents of a grid. Will open a new window with a table where the first row
* contains the headings from your column model, and with a row for each item in your grid's store. When formatted
* with appropriate CSS it should look very similar to a default grid. If renderers are specified in your column
* model, they will be used in creating the table. Override headerTpl and bodyTpl to change how the markup is generated
*/
Ext.ux.Printer.GridPanelRenderer = Ext.extend(Ext.ux.Printer.BaseRenderer, {

/**
* Generates the body HTML for the grid
* @param {Ext.grid.GridPanel} grid The grid to print
*/
generateBody: function(grid) {
var columns = this.getColumns(grid);

//use the headerTpl and bodyTpl XTemplates to create the main XTemplate below
var headings = this.headerTpl.apply(columns);
var body = this.bodyTpl.apply(columns);

return String.format('<table>{0}<tpl for=".">{1}</tpl></table>', headings, body);
},

/**
* Prepares data from the grid for use in the XTemplate
* @param {Ext.grid.GridPanel} grid The grid panel
* @return {Array} Data suitable for use in the XTemplate
*/
prepareData: function(grid) {
//We generate an XTemplate here by using 2 intermediary XTemplates - one to create the header,
//the other to create the body (see the escaped {} below)
var columns = this.getColumns(grid);

//build a useable array of store data for the XTemplate
var data = [];
grid.store.data.each(function(item) {
var convertedData = {};

//apply renderers from column model
Ext.iterate(item.data, function(key, value) {
Ext.each(columns, function(column) {
if (column.dataIndex == key) {
convertedData[key] = column.renderer ? column.renderer(value, null, item) : value;
return false;
}
}, this);
});

data.push(convertedData);
});

return data;
},

/**
* Returns the array of columns from a grid
* @param {Ext.grid.GridPanel} grid The grid to get columns from
* @return {Array} The array of grid columns
*/
getColumns: function(grid) {
var columns = [];

Ext.each(grid.getColumnModel().config, function(col) {
if (col.hidden != true) columns.push(col);
}, this);

return columns;
},

/**
* @property headerTpl
* @type Ext.XTemplate
* The XTemplate used to create the headings row. By default this just uses <th> elements, override to provide your own
*/
headerTpl: new Ext.XTemplate(
'<tr>',
'<tpl for=".">',
'<th>{header}</th>',
'</tpl>',
'</tr>'
),

/**
* @property bodyTpl
* @type Ext.XTemplate
* The XTemplate used to create each row. This is used inside the 'print' function to build another XTemplate, to which the data
* are then applied (see the escaped dataIndex attribute here - this ends up as "{dataIndex}")
*/
bodyTpl: new Ext.XTemplate(
'<tr>',
'<tpl for=".">',
'<td>\{{dataIndex}\}</td>',
'</tpl>',
'</tr>'
)
});

Ext.ux.Printer.registerRenderer('grid', Ext.ux.Printer.GridPanelRenderer);



And my code:




var Contato = Ext.extend(Ext.grid.GridPanel,{

renderTo: 'panel',

initComponent: function()
{

this.store = new Ext.data.JsonStore({
url: 'classes/contato.php',
root: 'results',
totalProperty: 'total',
autoDestroy: true,
remoteSort: true,
scope: this,
baseParams: { action: 'listar' },
fields:['id','nome','tipo','contato_nome','email','atividades','atividadesassinante','tipo_contato_nome','tag'],
sortInfo: {field: 'nome', direction: 'ASC'}
});

this.columnModel = new Ext.grid.ColumnModel(
[{
dataIndex:'nome',
header: 'Contato',
css: 'cursor:pointer;',
width: 400,
sortable: true,
renderer:function(v,params,record){

params.attr = 'ext:qtip="Cell Value = ' + record.data.email + '"';

if(record.data.tipo == 1) return record.data.nome;
else {
if(record.data.contato == null) return record.data.nome;
else return record.data.nome + ' ('+ record.data.contato +')';
}
}
}]
);

Ext.apply(this,{

cm: this.columnModel,
tbar: new Ext.Toolbar({
style: 'padding:7px;border-bottom:1px solid #ccc;background:#FDFDFD',
items: [{

xtype: 'splitbutton',
text: 'Incluir Contato',
iconCls: 'add',
scope: this,
handler: this.incluir,
menuAlign: 'br',
menu: new Ext.menu.Menu({
items: [
{text:'Editar',scope:this,handler: this.editar},
{text:'Excluir',scope:this,handler: this.excluir},'-',
{text:'Print',scope:this,handler: function(){ Ext.ux.Printer.print(this); } }]
})

}]
})
})

Contato.superclass.initComponent.call(this);
}

});




Can anyone help me?