Download Firefox -  a safer, easier to use web browser. Return to iribbit.net - Leap into the online experience! Return to iribbit.net - Leap into the online experience! iribbit.net - Leap into the online experience!

Project News :.

The latest project to launch was the site for Gorilla Offroad Company. Aside from their main site, a social media strategy was develop to launch the company into various industry specific automobile enthusist discussion board communities as well as popular social media fronts like Facebook, Pinterest, and Twitter.


Valid XHTML 1.0 Transitional

Valid CSS!

Section 508 Compliant

powered by: Macromedia ColdFusion MX

made with: Macromedia Dreamweaver MX

What is RSS

XML - often denotes RSS Feed information.

Macromedia - ColdFusion Programming
white horizontal rule

ColdFusion News :.

To bring a little life to my site, I've pulled a couple What is RSS Feeds into this page. You can currently choose between the technology related news stories from the following news sources:



You are currently viewing and RSS Feed from Raymond Camden's Blog.



My Modern Web Conference presenation is now available online

As the title says, my presentation from the Modern Web Conference is now available to watch online. I've embedded it below. You can find the complete list of videos here.


(Wed, 29 Oct 2014 16:15:00 -0400)
[view article in new window]

Beautiful


(Sat, 25 Oct 2014 03:40:00 -0400)
[view article in new window]

Yesterday


(Thu, 23 Oct 2014 16:09:00 -0400)
[view article in new window]

OOO for a bit so why not say hi to each other?

As I despise email auto responders I'll use this as my official OOO (Out Of Office) notification for the next two weeks. I do not expect to be blogging at all. I probably won't be on Twitter. Emails will probably pile up as well. Everything will be back to normal(ish) around November 1st. In the meantime...

Every year or so I do a survey of my readers to find out what they are interested in, how well I'm meeting those needs, etc. I thought it might be kind of cool if my regular readers would like to introduce themselves to each other. For those who feel comfortable doing so - introduce yourself, say what you do, and have a nice little chat going as OT as you would like.


(Thu, 16 Oct 2014 15:12:00 -0400)
[view article in new window]

Thoughts on Integrating Ionic into an Existing Application

Earlier this week a user asked me a question about integrating Ionic into an existing application.

I had some thoughts on this and spent some time talking to Holly Schinsky as well about the topic. Here are some things to consider in no particular order.

First, remember that Ionic is, at the simplest level, an Angular application with CSS and directives. These directives both simplify the use of the CSS and provide various UX features like "Pull to Refresh." The Ionic "family" (not really a term they use) contains more than that, stuff like the CLI improvements and their visual creator, etc., but we're focusing this discussion on just the end result - the application.

One option would be to just use the CSS. That would allow you to keep your current application as is and just update styling where appropriate - changing classes to ULs and DIVs etc to match the Ionic way of doing things. That won't give you any of the directives or UX stuff, but it is an option.

Another option would be to migrate your code completely. This could be a huge undertaking. If your current application isn't using an MVC framework of any sort then you're going to have to do a lot of breaking stuff up. I think that's an improvement in general so it is time well spent, but you should be prepared to spend that time.

And obviously if you don't know Angular going into it, you must spend some time getting familiar with it. I am very much an Angular Newbie. I can build... things... but I have lot to learn. With that being said, I feel like I know enough to do cool stuff with Ionic. But I would not recommend trying to use Ionic with no existing Angular skills. I think one day spent doing Angular's tutorial and perusing the docs will give you at least enough context to look at Ionic, but you will want to plan time to get up to speed with Angular in general.

So what if you are using an existing MVC framework, like Backbone? I'm a bit rusty with Backbone but I had thought that this could perhaps make things a bit easier. You have code split into controllers and services anyway, right? But this is where Holly set me straight. She reminded me that Backbone is very different from Angular. I'm going to quote her here:

angular is DOM extension

backbone is less rigid

angular, you have to follow certain patterns and ways of doing things, backbone you can use loosely

So it may not be easier at all if you are switching from Backbone. It may be worthwhile to google "Backbone to Angular" or Ember, etc. That particular part of the process will apply to Ionic.

Do folks have any opinions on this? Please share below.


(Thu, 16 Oct 2014 09:35:00 -0400)
[view article in new window]

Nunjucks templating by Mozilla

This is mainly just a FYI type post, but earlier this week I discovered Nunjucks, a client-side templating language by Mozilla. I've been pretty much sold on Handlebars as my template language, but Nunjucks has a lot going for it too. Out of the box it seems to support a lot more than Handlebars (inheritance and asynchronous support for example) and the template synax is as friendly as Handlebars'.

Of course, my only real requirement for template syntax is to not suck as bad as Jade but that's just me.

It supports client-side (obviously) and server-side (for Node) so it's ready to go pretty much anywhere. I'd love to see this supported in Harp in the future.

If you want to take it for a test drive, I built an online Nunjucks tester here: http://www.raymondcamden.com/demos/2014/oct/15/test.html. You can't test everything there of course (inheritance for example), but you can quickly test out some of the syntax and see how it feels.


(Wed, 15 Oct 2014 09:39:00 -0400)
[view article in new window]

Delaying an Edge Animate asset until visible - Part 6

Welcome back to the thread that won't die. I've blogged (see related links below) about this topic six times now. It started off as something simple - making an Edge Animate animation wait to run until visible - but it has turned into a pretty complex set of entries discussing not only how to do it but alternatives and other modifications. Today's entry is rather simple though as it just covers updates for the October 2014 release of Edge Animate.

Reader @jdesi posted a comment this morning about an issue he was having with my code in the latest release of Edge Animate. (You can read details about that update here: Edge Animate reduces runtime size by 55%, "Save to Custom Folders" feature, new Preloader options, and more!) I did some digging and discovered a few different issues with my code.

Before I go any further, please note that I worked on a modified form of the first demo I built for this feature. My later entries in this thread made the behavior a bit more complex. I'm assuming people can apply the updates I describe below to those versions as well.

The first thing I discovered is that jQuery is no longer included by default in the HTML template. This is discussed in the blog entry I linked to above and while I could have certainly worked around needing jQuery, it was simpler to just add it back in. I did so in the index.html file and included it before the Edge JavaScript include.

The next thing I noticed was that sym.element wasn't available. I checked the (updated) JavaScript API and saw that a new API existed: sym.getSymbolElement

The next change was a bit more subtle (but still documented!) - the element will now be wrapped in jQuery, if you have included it. From the docs:

"Note: If you have added jQuery as an external dependency in the Edge Composition, then sym.getSymbolElement() will return a jQuery wrapper, as AdobeEdge.$ gets redefined to jQuery in such cases. You can use any of the jQuery APIs on the result in this case."

So with that being the case, the method I wrote to check if the element was in view was able to remove the $ wrappers. Here is the updated version of the code.

      Symbol.bindSymbolAction(compId, symbolName, "creationComplete", function(sym, e) {

		function isScrolledIntoView(elem) {
			var docViewTop = $(window).scrollTop();
			var docViewBottom = docViewTop + $(window).height();

			var elemTop = elem.offset().top;
			var elemBottom = elemTop + elem.height();
		
			return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
			  && (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
		}		  

		var element = sym.getSymbolElement();
		if(isScrolledIntoView(element)) {
			sym.play(0) 
		} else {
			$(window).on("scroll", function(e) {
				if(isScrolledIntoView(element)) {
					console.log('Start me up');	
					sym.play(0);
					$(window).off("scroll");
				}
			});
			
		}
		  
		  
      });

You can test this version here: http://www.raymondcamden.com/demos/2014/oct/14/test.html. As a reminder, this one won't pause if you scroll out and won't restart if you scroll back in. That's covered by later versions of my demo and can be used if you simply apply the fixes described here to them. Enjoy!


(Tue, 14 Oct 2014 15:33:00 -0400)
[view article in new window]

My review of Ionic's Visual Application Builder

Let me begin by saying that - like most developers I think - I have a pretty strong distrust for visual builders for applications. I've been burned by too many tools that create something pretty on screen but generate a horrible mess of code behind the scenes. I think there are definitely tools that do a good job of it now, but once you've been scarred by seeing div tags nested twenty layers deep, you get a bit sensitive. I've recently become a bit more open minded about it. XCode, in general, has a very powerful UI building metaphor to it and I kinda dig how the Android tools handle it in Eclipse as well. Now that you understand how I approach these tools, let me talk to you a bit about the upcoming Ionic Creator tool from the folks behind Ionic.

Ionic Creator is currently in private beta. For a while now folks have been able to sign up for testing and the Ionic team is inviting new batches of people at regular intervals. Earlier this week I was invited to the beta and gave it a spin. When you fire up the tool for the first time, you're prompted to create a new project. You can specify a starter page based on a few preset templates. This list is a bit bigger than what the CLI provides but for the most part I think you can figure out what each does.

Once your project is created you're provided with a blank slate for your first page.

At the time of this review, there was a pretty serious bug where the project would load the page in an invalid state. If you try to do anything at all now, for the most part, it won't work. The clue is the lack of a header on the page. If you see this, hit reload, and notice how it changes:

It is a small thing, but I ran into this whenever I loaded, or changed, projects. Once past this then it is a simple matter to begin dragging and dropping components onto the page. Components include buttons, cards, images, lists, and form elements. You can also drop in an HTML or Markdown component for free form typing. Currently the application will not let you drop a form element onto the page unless you put it inside a form component. That's good, but there isn't any feedback as to why you can't drop the component. I've already filed an issue suggesting they provide some feedback. Here is my attempt to add some basic controls to the page.

Notice that the upper left hand corner is used as a simple tree view. You can select items there to edit properties or select them on the page itself. Each component has different things you can modify. As an example, it is pretty easy to modify the list:

You can also select items on the page and move them up. Creator intelligently handles "collections" so moving the list will also move the list items. Adding new pages is also a simple matter:

Each page has a name as as a "routing url". You can then specify that a button, for example, will link to another page. I created a new page called Other and kept the default routing url of /page2. I went back to my first page, selected one of the buttons, and set it to load up the new page:

So for the most part, that's it for the 'drag/drop' aspect. You can setup the components as you see fit and create as many pages as you would like. Once you're done playing around with the widgets, you can easily test it directly in the web page itself:

I haven't tested the preview mode very hard, but basic links do work just fine:

Ok, so, that's not bad. But what about the code? Creator provides three different ways to get to the bits. Clicking Export brings up your choices:

The first one simply provides you with a unique ID to use at the command line. This is probably the one most folks will use. As far as I know this is a one way street. You can't push back changes you made locally to Creator, but honestly there is probably no good way to handle what people would send back in. Obviously the first line, npm install doesn't make sense if you already have the CLI installed. There should probably be a note there warning folks they don't need to reinstall Cordova and the Ionic CLI. Then again, the audience for this is probably more on the newbie side and may include people who haven't ever used the CLI.

The Zip File option is just that, a zip of your code. Finally, the Raw HTML is a version of your application. I say version because they combine the HTML and JavaScript into one file to make it easier to cut and paste. I see the logic of that but it still bugs me a bit. ;) I just noticed that the zip version is also one file. Again, I don't like that, but that's just me.

If you source a new project via the code given in the export prompt you get a 'proper' Ionic project that you can immediately begin using. Oddly, some of the application logic is in index.html as opposed to app.js, but that may be a personal preference type thing. Ignoring that though you can go from the visual builder to your simulator in seconds - yep - seconds:

So, final verdict? I'm not sure this is a tool I'd use for my demos, but I'm probably not the target audience. I could definitely see using this as a prototype builder though. Or even asking a semi-technical client to take it for a spin and see what they like. It could save some time in terms of bootstrapping the application and I see some very strong value there. I think if it was tied to a service like PhoneGap Build, it would be a huge win for folks.


(Fri, 10 Oct 2014 13:18:00 -0400)
[view article in new window]

Cordova, the Camera plugin, AngularJS, and Ninja Cats.

Just a random tip for folks who may run into this in the future. I'm working on a mobile app for a client and I'm using both Cordova and AngularJS. The application allows people to select a photo from their gallery or take a new picture. It then renders a thumbnail to the web page. It supports any number of selections so my view simply loops over an array.

<img ng-repeat="pic in groupPics[group.part]" ng-src="{{pic}}" ng-click="removePicture(group.part,pic)" class="img-thumbnail" style="width:120px; height: 120px">

Pretty simple, right? In my testing I always used the simulator as it doesn't have a real camera, and I typically tested on iOS only since they were testing Android. Also, the camera is pretty simple to use so it just plain works most of the time.

But then the client reported something odd. Whenever he selected a picture from the gallery, the image thumbnail would show up broken. I quickly ran it (and since I said quickly you know I used Genymotion and not the Android emulator) and confirmed it failed. Like any other good hybrid developer I fired up my dev tools and checked the console. This is what I saw.

GET unsafe:content://com.android.providers.media.documents/document/image%3A21

Some Googling turned up this Stackoverflow post. Long story short - it is an Angular security measure. I've run into Angular security stuff before (trying to inject HTML into the DOM) so this isn't the first time I've had an issue like this, but it threw me for a loop since it worked in iOS. If you look at the file URI returned by Camera/Gallery selections though it makes a bit more sense. Here is an example of a file URI returned from iOS (spaces added so it will wrap):

file:///Users/ray/Library/Developer/CoreSimulator/Devices/ C8202B3B-300B-4819-8CD3-4C4AA690CE7C/ data/Applications/D82BF64E-6DD1-4645-B637-BCF65001FD29/tmp/cdv_photo_003.jpg

The exact same code on Android returns a file URI like so:

content://com.android.providers.media.documents/document/image%3A21

Angular sees this as something weird and says, "No Way Man!". Luckily the fix is simple. In my application's configure block, I added this:

$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|content):/);

So, keep it in mind if you are using the camera in a Cordova/AngularJS application.

Ninja cat provided for no good reason.


(Fri, 10 Oct 2014 08:51:00 -0400)
[view article in new window]

Another bug with queryExecute - Threads

Wow, not a good morning for one of my favorite new features of ColdFusion 11. This morning I reported on a bug found with queryExecute by a user on StackOverflow. I did some more digging and found that if you use queryExecute inside a thread, it returns an undefined value. Here is a simple test case:

<cfscript>
	
	data = querynew("id", "varchar", [{id:"a"}, {id:"b"}]);
	
	cfthread(name="d1") {
		thread.result = queryExecute("select * from data", {}, {dbtype:"query"});
	}
	cfthread(name="d2") {
		var result = queryExecute("select sleep(2), title from tblblogentries limit 0,1", {}, {datasource:"myblog"});
		thread.foo = 1;
		thread.result = result;
	}
	cfthread(action="join",name="d1,d2");
	writedump(cfthread);
</cfscript>

<cfdump var="#variables#" showudfs="false" >

In the code above I'm running two threads that use queryExecute. In the first thread the value of result is undefined. In the second thread it throws an error because result is not defined.

So, you can't use queryExecute inside a thread call. I've reported this here: https://bugbase.adobe.com/index.cfm?event=bug&id=3836820.


(Thu, 09 Oct 2014 10:08:00 -0400)
[view article in new window]

Bug with queryExecute - use with caution

One of the nicer features in ColdFusion 11 was the addition of queryExecute. It lets you run a query from cfscript easier than using the component based system that was added in the past. However, a StackOverflow user discovered an interesting bug with it.

Scott J. posted a question to StackOverflow about something odd he saw in ColdFusion's debugging output when he used queryExecute. Imagine the following simple call:

data = queryExecute("select * from tblblogentries limit 0,1", {}, {datasource:"myblog"});

If you turn on ColdFusion Debugging, you would expect to see "data" as a query. Instead he saw this:

It looks like ColdFusion is assigning a temporary variable to the query before returning it to the variable you specify. If you run multiple queryExecute calls they use the same variable. If you use a tag-based query it works correctly. If you remember, the debug templates are simply ColdFusion files. I checked in there to ensure there wasn't a bug, but as far as I can see, it is working right.

Also, for fun, I did: _queryname_var0 = 9; and yep - it gets overwritten. Oddly it won't exist in the Variables scope, but if you use it as a variable and then run queryExecute, it gets removed completely. I wouldn't go so far as to say queryExecute is unsafe to use, but, you may want to ensure you are not using a variable with the same name. It also makes debugging a bit more difficult as you will have multiple items in the report with the same name.

I've filed a bug report: https://bugbase.adobe.com/index.cfm?event=bug&id=3836702


(Thu, 09 Oct 2014 06:06:00 -0400)
[view article in new window]

Timing out users by role in a ColdFusion Application

Late last month a reader asked me if it was possible to override the session timeout so that he could provide different time outs based on a user role. As far as I know there is no direct way of doing this. There may be a way if you get to the underlying Java Session stuff, but I recommended something simpler - if you keep a variable for when the user last hit your site and do a quick time check, you can easily log them out early. To be clear, this is not the same as ending the session, but honestly, thats not what he really needed. He simply needed to toggle a flag (loggedin) from true to false if that time limit had expired. I thought I'd whip up a quick set of example code to demonstrate this.

Two quick notes before I continue. I wrote this using ColdFusion 11. What I'm demonstrating here could easily be done in ColdFusion MX and higher. I'm not going to rewrite it in tags. Ditto for the member functions I used. It should be trivial to port that to ColdFusion 10 as well. Secondly, I didn't use a framework for the two apps I built. I wanted to keep it super simple.

Ok, let's start off with an incredibly simple application that enforces login. First, the Application.cfc.

component {
	
	this.name="diff_session_v1";
	this.sessionManagement="true";
	
	public boolean function onApplicationStart() {
		application.userService = new model.userservice();
		return true;
	}
		
	public boolean function onRequestStart(string req) {
		
		//login attempt
		if(form.keyExists("login") && form.keyExists("username") && form.keyExists("password")) {
			if(application.userService.authenticate(form.username,form.password)) {
				session.isLoggedIn=true;	
			}
		}
		
		if(!session.isloggedin && req.listLast("/") != 'login.cfm') {
			location(url="login.cfm",addToken=false);
		}
		
		if(url.keyExists("init")) {
			applicationStop();
			location(url="./", addToken=false);	
		}
		return true;
	}
	
	public void function onSessionStart() {
		session.isloggedin=false;
	}
	
}

I'm assuming nothing here is new to folks. This is the same authentication logic you have probably used in a hundred or so applications. My userservice.cfc is literally a method that checks if username and password are "admin". I won't bother sharing that (but you can see it in the attachment). My index.cfm simply says "Hello World" and the login.cfm file is a form, nothing more. Again, this is just the bare minimum. Now let's look at the updated version.

component {
	
	this.name="diff_session_v2a";
	this.sessionManagement="true";
	//two minute timeout by default
	this.sessionTimeout = createTimeSpan(0,0,2,0);
	
	public boolean function onApplicationStart() {
		application.userService = new model.userservice();
		return true;
	}
		
	public boolean function onRequestStart(string req) {

		//timeout for non admins
		if(session.isloggedin && session.auth.role == "user" && dateDiff("s",session.lasthit,now()) > 60) {
			session.isLoggedIn=false;
			session.delete("auth");	
		}
		
		//login attempt
		if(form.keyExists("login") && form.keyExists("username") && form.keyExists("password")) {
			var authResult = application.userService.authenticate(form.username,form.password);
			if(authResult.status) {
				session.isLoggedIn=true;	
				session.auth = authResult;
			}
		}
		
		if(!session.isloggedin && req.listLast("/") != 'login.cfm') {
			location(url="login.cfm",addToken=false);
		}
		
		if(url.keyExists("init")) {
			applicationStop();
			location(url="./", addToken=false);	
		}
		return true;
	}
	
	public void function onRequestEnd(string req) {
		if(session.isLoggedIn) session.lasthit = now();
	}
		
	public void function onSessionStart() {
		session.isloggedin=false;
	}
	
}

Let's cover the important changes, one by one.

First, I've specified a timeout for the Application. Technically this isn't required, but it makes it a bit easier to test. The biggest change is in onRequestStart. Whereas before we simply had two checks (one for logging in, one to see if authenticated), we've added a new check to see if the user is logged in, has a role of user, and has been idle for more than 60 seconds. I kinda feel bad about this logic being here, it seems like perhaps it should be in the userService, but, I think you get the point. If we determine that "too much" time has passed (and the value is arbitrary), then we mark the user as logged out.

I do want to share the userService now as it is a tiny bit more complex. It now returns a structure that includes a status and user information as well.

component {

	public struct function authenticate(required string username, required string password) {
		//admin:admin
		if(username == "admin" && password == "admin") {
			return { id:1, role:"admin", status:true};	
		}
		if(username == "user" && password == "user") {
			return { id:2, role:"user", status:true};	
		}
		return { status:false };
	}	
}

Anyway, I hope this is useful. I've included both versions as an attachment to this blog entry.


(Wed, 08 Oct 2014 10:27:00 -0400)
[view article in new window]

Cordova and Large Asset Downloads - An Abstract

Doing something a bit different today. A PhoneGap user contacted me yesterday with an interesting problem. He and I discussed it over a quick Google Hangout, and I thought I'd write up some thoughts about our discussion. Ultimately I want to build a proof of concept around this idea, but I thought I'd start first with an explanation, sans code, to see what people thought.

The problem, at a high level, involves downloading data files to a PhoneGap/Cordova application after the user has installed it. These would not be required downloads. Think more of things like DLC, or additional songs for a game, optional items. His question was how an application could be architected to support such a system. Here is what I told him. (And as always, I welcome other opinions in the comments below.)

The first thing I mentioned is that he would need some form of application server in order to handle hosting the resources. This application server needs to be able to respond to a request asking what resources are available. How the server responds isn't really important. A JSON-encoded array of URLs, with perhaps some meta information about each resource, would be sufficient. "Application Server" need not be anything complex. In fact, you could build something with Parse.com to handle the entire process. But at the end of the day you need that "responder" that can list what resources are available for download.

On the client side, you then need to be able to ask that server for a list. Obviously this is nothing more than an XHR request. You could add a layer of complexity to the process by supporting a filter. For example, if the server has 10 resources available and the client has downloaded 5 of them, maybe there is some way for the client to send that information to the server so that server only responds with what is new. Again, how complex you build this is up to you. I'd imagine that a simple list, even of 100-200 items, would transfer so fast (even on mobile) that you wouldn't need to worry about filtering.

So - you've got two parts now, server side and client side. Fetching the resources isn't terribly difficult using the File Transfer plugin. Handling a bunch of these so you don't intefere with normal application usage is another matter. In a SPA, you could simply fire off a method to do these while the user carries on their merry way. In theory then these resources just become available when they get downloaded. If you grab one at a time you can even gracefully handle the application being killed off half way through. (To be clear, I need to test that. If I download a file called foo.jpg and it doesn't finish because the application is killed, does that file exist on the file system but in a corrupt state? I'll find out!)

That's the issue at a high level. The user who spoke with me asked me to take a look at this with jQuery Mobile, and I know I'm all about AngularJS and Ionic now, but I'm going to give it a shot there first to see if I can get a proof of concept working. What about you? Have you built something like this? Do you have any advice?


(Tue, 07 Oct 2014 15:31:00 -0400)
[view article in new window]

CreativeSDK (really) Launches

So a while ago I mentioned I was working on the CreativeSDK project. My role is to help out with documentation, including tweaks to the API guides and writing articles. As someone still pretty new to ObjectiveC, my articles are pretty simple, but hopefully that's exactly the kind of content that can help people use it. The SDK is now public and you can peruse some of the terribly exciting articles I wrote that demonstrate things like CC file access and PSD extraction.

The best place to start though is the Getting Started article, which walks you through project set up (XCode is pretty darn impressive by the way) and how to handle basic authentication with Creative Cloud.

Check it out at http://creativesdk.adobe.com.


(Mon, 06 Oct 2014 16:37:00 -0400)
[view article in new window]

ColdFusion Jedi is no more...

I've already had multiple people ping me about this so I thought it was a good idea to make sure folks knew I was aware. I have not used the coldfusionjedi.com domain in a long time, but each year I was renewing. After some advice from a reader, I put it up for auction and sold it. So - yep - I know that requests for coldfusionjedi.com go someplace else. I also have some blog entries that may link to that domain. I'll correct them as I run across them.


(Mon, 06 Oct 2014 12:30:00 -0400)
[view article in new window]


© The connection to the CAMDEN's RSS feed has timed out - please try again later. We are sorry for any inconvenience this may have caused.