Creative Music DJ’s of San Diego
A very good friend of mine, Dennis Jones, has been nominated for the best DJ in the San Diego area by KGTV.
Dennis is an exceptional DJ and deserves some hard earned recognition. I would appreciate it if you could take a few minutes out of your busy day and vote for Dennis. He would appreciate it and I would appreciate it as well. After you vote, please comment so I can give you proper credit if he wins!
http://kgtv.cityvoter.com/creative-music-djs-of-san-diego/biz/286774
Playing with Pusher
A couple of weeks ago Ben Nadel did a few excellent blog posts about Pusher, a service in beta stages that offers “real time client push to HTML5 browsers” that support web sockets and falls back to a flash plug-in on browsers that do not support web sockets.
This evening I finally had a few minutes to play around with it between working on other projects. I thought it would be a bit of an ordeal getting things going, but it was surprisingly fast. Pusher is in open beta so getting an account setup took all of a minute (literally).
Since that was far too easy, the next hurdle would be communicating with the service. If you check Ben’s demo code quite a bit of it was more or less preparing the data to be sent to Pusher so it could be pushed to the clients. Ben had a link to pusher.cfc by Bradley Lambert which actually alleviated the hassle.
That is the heavy lifting of setting up your pusher app. I did actually write a few lines of code to setup the remote facade for interacting with pusher.cfc, aside from that everything just worked out of the gate. For those interested, the remote facade for pusher.cfc.
<cfcomponent output="false">
<cffunction name="push" access="remote" returntype="any" returnformat="json">
<cfargument name="channel" type="string" required="true">
<cfargument name="event" type="string" require="true">
<cfargument name="data" type="any" required="true">
<cfargument name="socketID" type="string" required="false" default="">
<cfscript>
var push = getPusher().triggerPush(arguments.channel, arguments.event, serializeJSON(arguments.data), arguments.socketID);
return push;
</cfscript>
</cffunction>
<cffunction name="getPusher" access="private" returntype="any">
<cfscript>
var pusher = createObject("component", "com.pusher");
return pusher;
</cfscript>
</cffunction>
</cfcomponent>
I bound to a few simple events on a test page so I could make sure everything was working, but I did not get much further this evening. Before I started going wild binding to events, I wanted to take a little time and think things out a little bit. What I will say is, if you are looking for real time client push and you don’t feel like dealing the the added complexity of running Blaze/LCDS or the other alternatives, I cannot think of a better way of spending 30 minutes.
cfMud is now up at GitHub
I thought it would be pretty cool to create a MUD based on ColdFusion and jQuery so I thought I would give it a shot and see what I could come up with. This was my first project that would rely heaving on jQuery and using AJAX calls to push data to the server and back to the client. The code is still in EARLY in development, but I am putting it up on my public repo.
The main feature is a clickable map that allows you to move your character around the world. It was designed to be pretty lightweight and caches a large chunk of the map at a time. I don’t the the multi-user part down either, currently it works for one person. Also, the NPC system leaves a lot to be desired, the movement is slow and clunky due to the nature of how it is handled (jQuery sends a heartbeat to the server which handles all the server side NPC management).
I don’t have access to my database server to include schema at the moment, but I will update the repo later on this afternoon with the schema in place.
jqDesktop demo app now at GitHub
A few months ago I was playing around with jQuery quite a bit. I came out with a jQuery desktop-esq demo (which can probably be found here in a download link somewhere) and created a new repository for it at GitHub.
Unfortunately, things happen and both fell by the wayside. I have a few new projects that will be coming up in the near future and GitHub will be used extensively and a buddy told me about a very nice front end for Git called SmartGit. Playing around with it was a good excuse to finally get the repo updated.
If you are looking for a nice GUI for Git I highly recommend it. It is free for non-commercial use and reasonably priced otherwise. It is not open-sourced, but you still cannot beat the price.
If you are interested in checking out the little jQuery Desktop application you can find it here:
I am now using Aptana for development
Lately I have been in flux trying to find a new IDE for development. Over the course of the last year or so I have used quite a few editors. I rely heavily on Dreamweaver, I have used it for so many years it is almost second nature for me. The down side to Dreamweaver is it has a lot of features, many I never use. All those nice features can sometimes make it feel sluggish at times.
I also use jEdit quite a bit for local development. While it does not have all the bells and whistles of a full-featured web IDE, once you are familiar with it, it flies. The one notable exception being the initial load time while it is building the file index. I do miss having SFTP support, code completion, etc. I wanted to find something that was lightweight like jEdit, but with some of the more advanced features found in Dreamweaver.
I have used CFEclipse pretty extensively in the past, but we have had somewhat of a rocky relationship. When it originally came out I had some issues with the SnipEx servers which was one of the main reasons I switched originally. It seems like s/ftp was not supported or if it was, I had problems implementing it with my servers. It is a great project, but I had more impediments where it seemed like Dreamweaver just worked.
With that in mind, last week I set out to give CFEclipse a try again and I must say it has matured since the last time I used it. SFTP integration is working nicely now (although I haven’t had a chance to test synchronization). The SnipEx servers seem quite stable and have grown as well. CFBuilder being built on Eclipse has also taught me many tricks to stream line development. While some of the shortcuts do not work, many of them do. The one issue I did have was related to the File Explorer not being able to create directories.
Which brings me to Aptana. I have heard of it before but I have had neither the time nor the inclination to pick it up. I tried installing Aptana as a plugin in Eclipse but I didn’t have much luck. I decided to to download Aptana and then install CFEclipse as a plugin and I am pleased with the results. The Aptana File view resolved the issue I was having with CFEclipse’s File Explorer, plus it is pretty nice to boot.
I have only used it for a day but I am pleased so far and I look forward to playing around with it some more tomorrow. I still intend on purchasing CFBuilder when I can, but I think this will definitely work for me in the mean time.
Now my next fun project will be to get EGit up and running. I will save that for tomorrow though.
Recreating your jQuery Sortable() sort order
A reader pinged me with an interesting question. He was using jQuery the jQuery sortable behavior to allow users to order widgets on a page and then save their layout. The issue he was having was figuring out how to recreate the layout when the user reloaded the page.
As always there is more than one way to skin a cat, but I came up with a quick demo to illustrate one way to do this. If we have the user defined sort order it should be easy enough to recreate the view. I can think of several other ways to accomplish this, but this was the most straight forward way of handling the problem.
For my example I created a div representing my sortable container. Within the container I created four divs repesenting my sortable children named “div1″ through “div4″ (I am very creative first thing in the morning). I then hard-coded a “user defined” sort order that sorts them from “div4″ down to “div1″. Since I know the sort order it is just a matter of looping through my child elements and putting them in their proper place. This is done by looking at the sort order array and inserting the selected element after the previous element in the sort order. We skip the first element in the sort order since it obviously will not have a previous element. The end result being all the divs nicely ordered, just as the user saved them.
I have a demo application and source available here:
http://demos.kisdigital.com/index.cfm/demos/sortable
Storing complex objects in memcached on Railo
Lately I have been doing a lot of research into making sites run efficiently and to a larger extent, load more quickly. Yesterday I installed memcached and had it up and running on a test server. Once the memcached daemon is installed and ready to go you will just need to install a java client that will work for Railo. My friend Gabe wrote this post that covers what is required to get this up and running on an ACF server. Getting it running on Railo is little different, just extract the jar files for the Java memcached client into the directory that contains your railo.jar file.
I had a simple proof-of-concept application up quickly, I was able to set a string value in the cache and pull it back from the cache easily. Things got a little bit bumpy when I tried to store a complex object in cache. The result coming back from the cache set was coming back as true which would indicate that the object was successfully set in cache. When I tried to get the object back from cache and dump it, it always returned a null value. Logging into memcached through telnet I could see there actually was a value stored for the key but it was not returning.
Since I knew I could store simple values with no problem I decided to take the path of least resistance. Using the Railo serialize() function I could convert complex objects to a string representation and insert it into the cache. When I pull the value out of cache I evaluate() it and return the object value. Since I would end up creating a facade for setting/getting objects in cache this is not really an issue. I know ACF handles this without the need for a work around so it just left me scratching my head. I would imagine the difference is how Railo and ACF implements the data types, but I have not had time to verify this although if I have some free time this afternoon I intend to look in to this.
Here is a code sample I wrote to get this going. Basically it is the same as Gabe’s code with some changes to make it work with Railo.
<cfscript>
serverlist = "127.0.0.1:11211";
serverList = serverlist.split(",");
pool = createObject("java","com.danga.MemCached.SockIOPool");
pool = pool.getInstance();
if(not pool.isInitialized()){
pool.setServers(serverList);
pool.initialize();
poolInit = pool.isInitialized();
}
memcached = createObject("java", "com.danga.MemCached.MemCachedClient");
someData = queryNew('a, b');
queryAddRow(someData, 1);
querySetCell(someData, 'a', 'apple');
querySetCell(someData, 'b', 'orange');
dump(memcached.set("someData", serialize(someData)));
dump(evaluate(memcached.get("someData")));
</cfscript>
Demo site
I have a new site up to house some of the demos I have done. You can now see the chat application in action instead of a screenshot. I also make use of Jason Delmore’s ColdFISH project for code viewing. It is still a work in progress, but it is up and running if you want to check it out.
This is also the first site I have done using Sean Corfield’s Framework One. Things should be pretty stable now, but if you notice any issues I blame it on learning curve.
Easy jQuery multifile uploader
I needed a quick and dirty multi-file uploader for a site, but I did not want to install another plugin or a flash uploader. I am using the jQuery form plugin already to handle AJAX form submissions so I will hook to that to upload my files to the site.
My method basically uses jQuery to inject a form with a filefield into the DOM. I bind to the onchange event of the filefield so when a file is added the current file field is hidden, insert a new blank file field, and update a list of queued files waiting to be uploaded. When the user hits the “Upload Files” button, I iterate through all the “input:file” elements using jQuery and submit the form using the jQuery form plugin with ajaxForm(). Of course, you can remove a file from queue as well by clicking on the X in the queue list.
It is an inelegant solution, but it does work. Here is the code if you want to give it a try:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Multi-file upload</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="/js/jquery.form.js"></script>
</head>
<body>
<div id="uploadContainer"></div>
<input id="btnSubmit" type="button" value="Submit Files" onclick="submitLoop();" />
<div id="fileInfo"/>
<script language="javascript">
$(document).ready(function(){
$container = $('#uploadContainer');
$info = $('#fileInfo');
count=0;
addUpload();
});
function addUpload(){
count++;
$('form').hide();
$container.append('<form id="uploadForm-' + count +'" action="ajaxProxy.cfc?method=upload" enctype="multipart/form-data"><input id="file-' + count + '" name="filename" type="file" onchange="addUpload();" /></form>');
showFileInfo();
}
function removeItem(id){
if( $('#' + id).length){
$('#' + id).remove();
showFileInfo();
}
}
function showFileInfo(){
$info.html('');
$('input:file').each(function(){
if( $(this).val().length ){
$info.append('<div id="display-' + $(this).attr('id') + '"><a href="#" onclick="removeItem(\'' + $(this).parent().attr('id') +'\')">X</a> ' + $(this).val() + '</div>');
}
});
}
function submitLoop(){
$('input:file').each(function(){
var currItem = $(this).attr('id');
if($(this).val()){
$(this).parent().ajaxForm({
async: false,
success: function(data){
var incoming = $.parseJSON(data);
$('#display-' + currItem).append(' <strong>' + incoming.svrMessage + '</strong>');
}
}).submit();
}
});
}
</script>
</body>
</html>
Using jQuery sortable() to set display sort order
I am currently working on wrapping up a web site for a client that has quite a few image and video galleries each with 100+ images. One of the biggest problems I have had with the galleries is being able to sort how they were displayed for the end users. Initially I added in buttons to move the items up and down in the sort, but when you are dealing with a lot of items it can be tedious and aggravating work.
This weekend things came to a head because the client was getting annoyed. They wanted a way to quickly update the item sort so I went about finding the best way to go about it because I love happy clients. My main concern was having items in the database with the same sort order and possibly throwing off the sort. As it turns out, the answer was surprisingly simple.
The web site in question is already using the jQueryUI so modifying the image administrator to use the UI sortable() option was really no hassle what-so-ever. I am using AJAX pretty heavily on the site I just needed to do some editing to my file list page that is included on the page with an AJAX load call.
<cfscript>
catObj = application.transfer.get("categories",url.id);
base = '/path/to/web/root';
filePath = base & catObj.getBaseDirectory();
cq = application.transfer.createQuery("FROM images WHERE images.cat=:id ORDER BY images.sortorder");
cq.setParam("id",url.id,"numeric");
files = application.transfer.listByQuery(cq);
</cfscript>
<cfif files.recordcount>
<div id="sortableContainer" style="margin-top: 48px;">
<cfoutput query="files">
<div id="#ID#" style="width: 600px; margin-bottom: 12px;">
<div style="height: 20px; text-indent: 12px; padding-top: 4px;">Image Header</div>
<div class="ui-widget-content">
<table style="width: 600px;">
<tr>
<td width="75">
<a href="/image_viewer.cfm?id=#ID#" target="_blank" style="color: blue;">
<img src="/#catObj.getBaseDirectory()#/thumbs/#filename#" width="75" height="75"/>
</a>
</td>
<td>
<form id="img#ID#" action="ajaxProxy.cfc" method="post">
<input type="hidden" name="postType" value="updateImage" />
<input type="hidden" name="id" value="#ID#" />
<input type="text" name="Title" value="#Title#" style="width: 200px;" /><br />
<input type="submit" name="Method" value="Update" />
<input type="button" value="Delete" onClick="void(0);" />
<input type="button" value="Set" onClick="void(0);" />
</form>
</td>
</tr>
</table>
</div>
</div>
</cfoutput>
</div>
<div style="padding-bottom: 128px;"/>
<script type="text/javascript">
$('#sortableContainer').sortable({
stop : function(event, ui){
var result = $('#sortableContainer').sortable('toArray');
var sortOrder = '';
for(var i=0; i<result.length; i++){
sortOrder += result[i];
if(i < result.length - 1) sortOrder += ',';
}
setImageSortOrder(sortOrder);
}
});
function setImageSortOrder(order){
$.ajax({
url : 'ajaxProxy.cfc',
data : {
method : 'setImageSortOrder',
sortOrder : order
},
async : false,
success : function(data){
var incoming = $.parseJSON(data);
if(incoming.svrStatus == "-1"){
alert(incoming.svrMessage);
}
}
});
}
</script>
</cfif>
Basically this is just looping through the database and outputting all the images in divs in the div named sortableContainer which has the sortable() interaction applied to it. I also bind to the stop event which will fire when a sortable child is released which will build a string containing the image id’s in the proper sort order. I pass this value to the setImageSortOrder() function which makes an AJAX call to my remote proxy which will update the values in the database.
<cffunction name="setImageSortOrder" access="remote" returntype="struct" returnFormat="JSON">
<cfargument name="sortOrder" type="string" required="yes"/>
<cftry>
<cfscript>
var response = structNew();
var imageObj = "";
var sortCnt = listLen(arguments.sortOrder);
var i = 0;
for(i=1; i lte sortCnt; i++){
imageObj = application.transfer.get("images", listGetAt(arguments.sortOrder, i));
imageObj.setSortOrder(i);
application.transfer.save(imageObj);
}
response['svrStatus'] = "0";
response['svrMessage'] = "Video sort order updated successfully.";
</cfscript>
<cfcatch type="any">
<cfscript>
response['svrStatus'] = "-1";
response['svrMessage'] = cfcatch.Message;
</cfscript>
</cfcatch>
</cftry>
<cfreturn response/>
</cffunction>
The function setting the sort order in the database is pretty straight forward. I am using Transfer ORM for my database interactions, but it would be easy enough to covert the example into a query. Since the jQuery function is passing a list of the image id’s in the correct order I loop through the list and set the sort order of each image to its index in the list. No need to worry about items having the same sort order and displaying incorrectly. It is pretty much fool proof.
Also of note, this code makes use of the $.parseJSON() function added in jQuery 1.4.1. No more having to worry about whether or not a browser can support JSON.parse(). This in itself is a good reason to switch to a newer version of jQuery if you have not already.
Recent Comments