diff --git a/Button.js b/Button.js index ea5baad..7ba0bab 100644 --- a/Button.js +++ b/Button.js @@ -1,6 +1,6 @@ /** * @class Ext.ux.Exporter.Button - * @extends Ext.Button + * @extends Ext.Component * @author Nige White, with modifications from Ed Spencer, with modifications from iwiznia. * Specialised Button class that allows downloading of data via data: urls. * Internally, this is just a link. @@ -11,25 +11,28 @@ * @cfg {Ext.data.Store} store The store to export (alternatively, pass a component with a getStore method) */ Ext.define("Ext.ux.exporter.Button", { - extend: "Ext.Button", + extend: "Ext.Component", alias: "widget.exporterbutton", + html: '

', + config: { + swfPath: '/flash/downloadify.swf', + downloadImage: '/images/ext_reports/download.png', + width: 62, + height: 22, + downloadName: "download" + }, + constructor: function(config) { config = config || {}; - Ext.applyIf(config, { - disabled : true, - text : 'Download', - cls : 'download', - href : "/" - }); - + this.initConfig(); Ext.ux.exporter.Button.superclass.constructor.call(this, config); if (this.store || this.component) { this.setComponent(this.store || this.component, config); } else { var self = this; - this.on("render", function() { // We wait for the combo to be rendered, so we can look up to grab the component containing it + this.on("afterrender", function() { // We wait for the combo to be rendered, so we can look up to grab the component containing it self.setComponent(self.up("gridpanel") || self.up("treepanel"), config); }); } @@ -38,29 +41,25 @@ Ext.define("Ext.ux.exporter.Button", { setComponent: function(component, config) { this.component = component; this.store = !component.is ? component : component.getStore(); // only components or stores, if it doesn't respond to is method, it's a store - var setLink = function() { - var newConf = Ext.clone(config); - this.el.query('a', true)[0].href = 'data:application/vnd.ms-excel;base64,' + Ext.ux.exporter.Exporter.exportAny(this.component, null, newConf); - this.enable(); - }; - - var me = this; - this.store.on("load", setLink, this); - if(Ext.ComponentQuery.is(this.component, "gridpanel")) { - Ext.Array.each(this.component.columns, function(col) { - col.on("show", setLink, me); - col.on("hide", setLink, me); - }); - } + this.setDownloadify(config); }, - onClick : function(e){ - if (e.button != 0) return; - - if (!this.disabled){ - this.fireEvent("click", this, e); - - if (this.handler) this.handler.call(this.scope || this, this, e); - } + setDownloadify: function(config) { + var self = this; + Downloadify.create(this.el.down('p').id,{ + filename: function() { + return self.getDownloadName() + "." + Ext.ux.exporter.Exporter.getFormatterByName(self.formatter).extension; + }, + data: function() { + return Ext.ux.exporter.Exporter.exportAny(self.component, self.formatter, config); + }, + transparent: false, + swf: this.getSwfPath(), + downloadImage: this.getDownloadImage(), + width: this.getWidth(), + height: this.getHeight(), + transparent: true, + append: false + }); } }); \ No newline at end of file diff --git a/Exporter.js b/Exporter.js index d159c8e..f8c590d 100644 --- a/Exporter.js +++ b/Exporter.js @@ -24,7 +24,8 @@ Ext.define("Ext.ux.exporter.Exporter", { func = func + "Store"; component = component.getStore(); } - return this[func](component, formatter, config); + + return this[func](component, this.getFormatterByName(formatter), config); }, /** @@ -34,9 +35,8 @@ Ext.define("Ext.ux.exporter.Exporter", { */ exportGrid: function(grid, formatter, config) { config = config || {}; - formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter(); var columns = Ext.Array.filter(grid.columns, function(col) { - return !col.hidden; + return !col.hidden; // && (!col.xtype || col.xtype != "actioncolumn"); }); Ext.applyIf(config, { @@ -44,7 +44,7 @@ Ext.define("Ext.ux.exporter.Exporter", { columns: columns }); - return Ext.ux.exporter.Base64.encode(formatter.format(grid.store, config)); + return formatter.format(grid.store, config); }, exportStore: function(store, formatter, config) { @@ -55,7 +55,7 @@ Ext.define("Ext.ux.exporter.Exporter", { columns: store.fields ? store.fields.items : store.model.prototype.fields.items }); - return Ext.ux.exporter.Base64.encode(formatter.format(store, config)); + return formatter.format(store, config); }, exportTree: function(tree, formatter, config) { @@ -68,7 +68,13 @@ Ext.define("Ext.ux.exporter.Exporter", { title: tree.title }); - return Ext.ux.exporter.Base64.encode(formatter.format(store, config)); + return formatter.format(store, config); + }, + + getFormatterByName: function(formatter) { + formatter = formatter ? formatter : "excel"; + formatter = !Ext.isString(formatter) ? formatter : Ext.create("Ext.ux.exporter." + formatter + "Formatter." + Ext.String.capitalize(formatter) + "Formatter"); + return formatter; } } }); \ No newline at end of file diff --git a/csvFormatter/CsvFormatter.js b/csvFormatter/CsvFormatter.js index a34c2f3..5e1a085 100644 --- a/csvFormatter/CsvFormatter.js +++ b/csvFormatter/CsvFormatter.js @@ -4,5 +4,53 @@ * Specialised Format class for outputting .csv files */ Ext.define("Ext.ux.exporter.csvFormatter.CsvFormatter", { - extend: "Ext.ux.exporter.Formatter" + extend: "Ext.ux.exporter.Formatter", + contentType: 'data:text/csv;base64,', + separator: ";", + extension: "csv", + + format: function(store, config) { + this.columns = config.columns || (store.fields ? store.fields.items : store.model.prototype.fields.items); + return this.getHeaders() + "\n" + this.getRows(store); + }, + getHeaders: function(store) { + var columns = [], title; + Ext.each(this.columns, function(col) { + var title; + if (col.text != undefined) { + title = col.text; + } else if(col.name) { + title = col.name.replace(/_/g, " "); + title = Ext.String.capitalize(title); + } + + columns.push(title); + }, this); + + return columns.join(this.separator); + }, + getRows: function(store) { + var rows = []; + store.each(function(record, index) { + rows.push(this.geCell(record, index)); + }, this); + + return rows.join("\n"); + }, + geCell: function(record, index) { + var cells = []; + Ext.each(this.columns, function(col) { + var name = col.name || col.dataIndex; + if(name) { + if (Ext.isFunction(col.renderer)) { + var value = col.renderer(record.get(name), null, record); + } else { + var value = record.get(name); + } + cells.push(value); + } + }); + + return cells.join(this.separator); + } }); \ No newline at end of file diff --git a/download.png b/download.png new file mode 100644 index 0000000..7e3bc84 Binary files /dev/null and b/download.png differ diff --git a/downloadify.min.js b/downloadify.min.js new file mode 100644 index 0000000..faf490c --- /dev/null +++ b/downloadify.min.js @@ -0,0 +1,3 @@ +/* Downloadify 0.2 (c) 2009 by Douglas Neiner. Licensed under the MIT license */ +/* See http://github.com/dcneiner/Downloadify for license and more info */ +(function(){Downloadify=window.Downloadify={queue:{},uid:new Date().getTime(),getTextForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getData();return""},getFileNameForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getFilename();return""},getDataTypeForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getDataType();return""},saveComplete:function(a){var b=Downloadify.queue[a];if(b)b.complete();return true},saveCancel:function(a){var b=Downloadify.queue[a];if(b)b.cancel();return true},saveError:function(a){var b=Downloadify.queue[a];if(b)b.error();return true},addToQueue:function(a){Downloadify.queue[a.queue_name]=a},getUID:function(a){if(a.id=="")a.id='downloadify_'+Downloadify.uid++;return a.id}};Downloadify.create=function(a,b){var c=(typeof(a)=="string"?document.getElementById(a):a);return new Downloadify.Container(c,b)};Downloadify.Container=function(d,e){var f=this;f.el=d;f.enabled=true;f.dataCallback=null;f.filenameCallback=null;f.data=null;f.filename=null;var g=function(){f.options=e;if(!f.options.append)f.el.innerHTML="";f.flashContainer=document.createElement('span');f.el.appendChild(f.flashContainer);f.queue_name=Downloadify.getUID(f.flashContainer);if(typeof(f.options.filename)==="function")f.filenameCallback=f.options.filename;else if(f.options.filename)f.filename=f.options.filename;if(typeof(f.options.data)==="function")f.dataCallback=f.options.data;else if(f.options.data)f.data=f.options.data;var a={queue_name:f.queue_name,width:f.options.width,height:f.options.height};var b={allowScriptAccess:'always'};var c={id:f.flashContainer.id,name:f.flashContainer.id};if(f.options.enabled===false)f.enabled=false;if(f.options.transparent===true)b.wmode="transparent";if(f.options.downloadImage)a.downloadImage=f.options.downloadImage;swfobject.embedSWF(f.options.swf,f.flashContainer.id,f.options.width,f.options.height,"10",null,a,b,c);Downloadify.addToQueue(f)};f.enable=function(){var a=document.getElementById(f.flashContainer.id);a.setEnabled(true);f.enabled=true};f.disable=function(){var a=document.getElementById(f.flashContainer.id);a.setEnabled(false);f.enabled=false};f.getData=function(){if(!f.enabled)return"";if(f.dataCallback)return f.dataCallback();else if(f.data)return f.data;else return""};f.getFilename=function(){if(f.filenameCallback)return f.filenameCallback();else if(f.filename)return f.filename;else return""};f.getDataType=function(){if(f.options.dataType)return f.options.dataType;return"string"};f.complete=function(){if(typeof(f.options.onComplete)==="function")f.options.onComplete()};f.cancel=function(){if(typeof(f.options.onCancel)==="function")f.options.onCancel()};f.error=function(){if(typeof(f.options.onError)==="function")f.options.onError()};g()};Downloadify.defaultOptions={swf:'media/downloadify.swf',downloadImage:'images/download.png',width:100,height:30,transparent:true,append:false,dataType:"string"}})();if(typeof(jQuery)!="undefined"){(function($){$.fn.downloadify=function(b){return this.each(function(){b=$.extend({},Downloadify.defaultOptions,b);var a=Downloadify.create(this,b);$(this).data('Downloadify',a)})}})(jQuery)};if(typeof(MooTools)!='undefined'){Element.implement({downloadify:function(a){a=$merge(Downloadify.defaultOptions,a);return this.store('Downloadify',Downloadify.create(this,a))}})}; \ No newline at end of file diff --git a/downloadify.swf b/downloadify.swf new file mode 100644 index 0000000..2a2f01c Binary files /dev/null and b/downloadify.swf differ diff --git a/excelFormatter/ExcelFormatter.js b/excelFormatter/ExcelFormatter.js index 4bff4dd..39c2ea4 100644 --- a/excelFormatter/ExcelFormatter.js +++ b/excelFormatter/ExcelFormatter.js @@ -11,6 +11,8 @@ Ext.define("Ext.ux.exporter.excelFormatter.ExcelFormatter", { "Ext.ux.exporter.excelFormatter.Worksheet", "Ext.ux.exporter.excelFormatter.Workbook" ], + contentType: 'data:application/vnd.ms-excel;base64,', + extension: "xls", format: function(store, config) { var workbook = new Ext.ux.exporter.excelFormatter.Workbook(config); diff --git a/excelFormatter/Worksheet.js b/excelFormatter/Worksheet.js index 5e5e80d..1b18ea2 100644 --- a/excelFormatter/Worksheet.js +++ b/excelFormatter/Worksheet.js @@ -124,7 +124,7 @@ Ext.define("Ext.ux.exporter.excelFormatter.Worksheet", { } else if(col.name) { //make columns taken from Record fields (e.g. with a col.name) human-readable title = col.name.replace(/_/g, " "); - title = title.charAt(0).toUpperCase() + title.substr(1).toLowerCase(); + title = Ext.String.capitalize(title); } cells.push(Ext.String.format('{0}', title));