Saving SVG to PNG on your cold fusion server

I built a client side javascript SVG to PNG converter that works on *modern* browsers, however, depending on your target audience the browsers that frequent your site may be less than modern – i.e. IE. In this situation you only have one option, convert the image on the server side and then render it using the good old image tag.

First, cold fusion ships with some outdated batik files (which handle the cfimage tag) , so you will need to update those first, and add the missing files that will add your svg to -> image processing ability. I used the steps found in this post to accomplish the task; I’ll list them here in short format so you can get into the ext chart part of this project.

  1. Stop your cold fusion service
  2. Download the files from the batik website http://xmlgraphics.apache.org/batik/download.cgi
  3. Rename the jar files in /wwwroot/WEB-INF/cfform/jars/  that start with batik by adding the extension .old
  4. Copy the batik jar files into /wwwroot/WEB-INF/lib
  5. Restart Cold Fusion

Next, let’s assume that we have two files, one called convertImage.cfm and one called convertImage.cfc, of course, we want to pass the svg markup to the cfm which will pass the data to the cfc for processing.

<cfcase value="saveChart">
        <cfset saveChart = data.saveChart( svg=form.svg) />
        <cfset json = "{'success':'#saveChart#'}" />
</cfcase>

The code below goes in the cfc file.

<cffunction name="saveChart" >
        <cfargument name="svg" />
            <cftry>
            <cfset svgFile = "c:\websites\temp.svg" />
            <cfset jpgFile = replace("c:\websites\temp.svg", ".svg", ".jpg") />
            <cfset pngFile = (pngPath) />--->
            <cffile action="delete" file="c:\websites\temp.jpg" >

	<cfif FileExists(svgFile)>
            	<cffile action="delete" file="c:\websites\temp.svg" >
            	<cffile action="write" file="c:\websites\temp.svg" output="#svg#" >
           <cfelse>
           	<cffile action="write" file="c:\websites\temp.svg" output="#svg#"  >
           </cfif>

            <cfset t = createObject("java", "org.apache.batik.transcoder.image.JPEGTranscoder").init() />
            <cfset svgURI = createObject("java", "java.io.File").init(svgFile).toURL().toString() />
            <cfset input 	= createObject("java", "org.apache.batik.transcoder.TranscoderInput").init(svgURI) />
            <cfset ostream 	= createObject("java", "java.io.FileOutputStream").init(jpgFile) />
            <cfset output 	= createObject("java", "org.apache.batik.transcoder.TranscoderOutput").init(ostream) />
            <cfset t.transcode(input, output) />
            <cfset ostream.flush() />
            <cfset ostream.close() />

            <cfcatch type="any">
          		 <cfreturn "false" />
            </cfcatch>
            </cftry>
        <cfreturn "true" />
    </cffunction>

The function below would go in your javascript controller.

   saveChart: function(me){
        this.dTask.delay(500, function(){
                var svg = me.up('panel').down('chart').save(
                    {
                        type    :'image/svg+xml'
                    }
                );

                Ext.Ajax.request({
                    url: 'convertImage.cfm?remoteEvent=saveChart',
                    params: {
                        svg: svg
                    },
                    success: function(){
                        // process server response here
                        window.open('temp.jpg');
                    }
                });
        });
    },

Extjs adding file extension validation client side

One of the great things about extjs and all third party javascript libraries is the ease at which you can add the html file upload control to your page, and make it look professional. One of the things that almost every file upload application that I seen in use is a client side validation that is based on file extension, think about it would you like any file type making it to your server, including executables? The following code will add the file extension check to the upload on the client side. All you have to do is use the xtype ‘restfileupload’, and pass the extensions in an array without the period before the letters. Have Fun!

/***********************************************
Adds extension validation at the client side
for the extjs File Upload field. You must
set the extension in an array of strings.
 **********************************************/
Ext.define('Ext.ux.restrictiveFileUpload', {
	extend  : 'Ext.form.field.File',
	alias   : 'widget.restfileupload',
	// Array of acceptable file extensions
	// overridden when decalred with a string
	// of extensions minus the period.
	accept      	: [],
	listeners   	: {
    	validitychange : function(me) {
        	// This gets the part of the file name after the last period
        	var indexofPeriod = me.getValue().lastIndexOf("."),
            	uploadedExtension = me.getValue().substr(indexofPeriod + 1, me.getValue().length - indexofPeriod);
 
        	// See if the extension is in the 
                //array of acceptable file extensions
        	if (!Ext.Array.contains(this.accept, uploadedExtension)){
            	// Add the tooltip below to 
                // the red exclamation point on the form field
      	      me.setActiveError('Please upload files with an extension of :  ' + this.accept.join() + ' only!');
           	// Let the user know why the field is red and blank!
            	Ext.MessageBox.show({
                	title   : 'File Type Error',
                	msg 	: 'Please upload files with an extension of :  ' + this.accept.join() + ' only!',
                	buttons : Ext.Msg.OK,
                	icon	: Ext.Msg.ERROR
            	});
            	// Set the raw value to null so that the extjs form submit
            	// isValid() method will stop submission.
            	me.setRawValue(null);
        	}
    	}
	}
});

Extjs 4.1 UX that will allow multiple remote sorting on columns, and display multiple directional icons

Why?

Ok, so I have come across the need to perform multiple sorting on many occasions, and like most people got a little frustrated with the drag and drop toolbar method that is given in the Extjs examples. I wanted something that the user would intuitively understand since they were used to clicking rows to perform sorting anyway, and I wanted them to see what was being sorted in the same manner that the native sort works. You know that small blue triangle in your column header. It became apparent that this would be a feature that could be used over and over again as this is a really common request so I put together this UX for your Extjs 4.1 grids. I did not do any testing on versions prior to 4.1, so maybe it will work for those, maybe not, consider that fair warning.

Where to get the InlineRemoteMultiSort UX

https://github.com/jmcdonald69124/extjs-multisort-ux

How to use the InlineRemoteMultiSort UX

In your javascript code please make sure you place the files in the following folder, where extjs could be the root of your extjs distribution:

extjs/src/ux/ folder, and place the CSS file in the extjs/src/ux/css folder.

In your grid add the plugin, and pass it the initial ‘default’ sort values.

plugins : [
Ext.create('Ext.ux.InlineRemoteMultiSort', {
 defaultSorters: [
 {property:'col1',   direction:'ASC'},
 {property:'col2',   direction:'ASC'},
 {property:'col3',   direction:'ASC'}
    // ....
 ]
})
]

Of course this assumes that you set your path to the ux folder correctly in your MVC app.js file.

On the server watch out for the following values that are passed in a parameter called ‘sort’:

sort:[
{'item':'col1','direction':'ASC'},
{'item':'col2','direction':'ASC'},
{'item':'col3','direction':'ASC'}
]

If you are using Cold Fusion for your back end code you can parse the incoming form value with this code:

<cfset sorters = deserializeJSON(#form.sort#) />

Watch out for the following

This code will pass a set of brackets [ ] if there are no sorters, please handle this on the server side.

Paging poses a set of issues that will require that the query return the rows that are needed by the page the user is viewing. If you intend to use paging please see this post and pay particular attention to how it uses the start and page number
http://www.learnsomethings.com/2011/11/06/php-code-for-paging-and-remote-filtering-extjs4-grids/ .

Stop the backspace key from going to the previous page in your extjs app

If you have an app with just one view and there is even a small possibility that the user will open the app in a browser that they have been using to cruise around the web and the user will likely use the backspace key in your app then you should think about turning off the backspace == url -1 feature in most browsers.

If you actually want to use the backspace button for its intended purpose and you would like to map ext events to the browser history then a good choice might be using Ext.History, which you can learn about in depth by reading Ed Spencer’ blog post its use. (http://edspencer.net/2009/01/why-you-should-be-using-history-in-your.html )

Turning off the backspace key is pretty straight forward. You would just use Ext’s EventManager and create a listener to check for any keypress events that take place on the page. If the user is not in an input field then you would ignore the default action of the backspace button. Placing the code below right under your Ext.onReady … method will do the trick.

Ext.EventManager.addListener(Ext.getBody(), 'keydown', function(e){
        if(e.getTarget().type != 'text' && e.getKey() == '8' ){
            e.preventDefault();
        }
    }); 

Extjs4 Color Picker in a drop down control for use on forms and in editable grids

Ok so I needed a color picker that I could stick in an editable grid or just use as a form field, but I did not want to render the complete box with the little color squares in the form, and well, a grid is pretty tight on space.

I went ahead and designed a color picker combo box that puts the hex value in the input field and underlines it in the selected color. One of the notable features is the monitorMouseLeave method that is found in Ext.Element, this performs an action after the users mouse leaves an element after a preset amount of time. In the code below it is used to hide the drop down color fields after the user leaves the picker for half a second. This way we don’t force them to make a selection, but do not penalize them for coloring outside of the lines with their mouse.

Ext.define('Ext.ux.ColorPickerCombo', {
	extend: 'Ext.form.field.Trigger',
	alias: 'widget.colorcbo',
	triggerTip: 'Please select a color.',
 	onTriggerClick: function() {
	  var me = this; 
	  picker = Ext.create('Ext.picker.Color', {     
		pickerField: this,     
		ownerCt: this,    
		renderTo: document.body,     
		floating: true,    
		hidden: true,    
		focusOnShow: true,
		style: {
            	backgroundColor: "#fff"
        	} ,
		listeners: {
            	scope:this,
            	select: function(field, value, opts){
		me.setValue('#' + value);
		me.inputEl.setStyle({backgroundColor:value});
		picker.hide();
	},
	show: function(field,opts){
		field.getEl().monitorMouseLeave(500, field.hide, field);
		}
        	}
});
       picker.alignTo(me.inputEl, 'tl-bl?');
       picker.show(me.inputEl);
	}	
});