A New “Manifesto”

DESIGN, ILLUSTRATION, VIDEO ON 27 April 2011

Absolutely love the cool visuals and fantastic flat colour motion graphics in this brilliant new promo from of all companies… Bacardi.

Through a mix of live action set-ups and simple animation, the ad encourages us to ditch technology and get together over a rum or two.

Can’t think of any recent campaigns from Bacardi that stick in my mind, I’d have to go all the way back to those “Auntie Berol” ads to recall one off the top of my head, but definitely seems a like a departure from the Bacardi ads of old, which can only be a good thing.

clickFields jQuery Plugin

DEVELOPMENT ON 26 April 2011

clickFields is a simple jQuery plugin that allows you to place form field description values within the individual fields and then have them automatically cleared when the user clicks the field. The plugin uses the “defaultValue” attribute and also changes input fields with a CSS class of “password” to a password field type.

Form showing description values inside each form field

The clickFields jQuery Plugin

(function($){
	$.fn.clickFields = function(options) {  

		var defaults = {
			passClass : 'password',
		 	input : true,
		 	textarea : true
		};

	 	var opts = $.extend(defaults, options);

	 	return this.each(function() {
	 		var self = this;

			if(opts.input)
			{
				$('input:not(:submit)', self).each(function(){
                                       handle(this);
                                 });
			}

			if(opts.textarea)
			{
			 	$('textarea', self).each(function(){
				 	handle(this);
				});
			}

		 	function handle(field)
		 	{
			 	$(field).focus(function(){ 

			 		if($(field).val()==field.defaultValue){
			 			if($(field).hasClass(opts.passClass))
			 			{
							$(field)[0].setAttribute('type','password');
						}
			 			$(field).val("");
			 		}

	 			});

				$(field).blur(function(){

	 				if($(field).val()==""){
	 					if($(field).hasClass(opts.passClass))
	 					{
	 						$(field)[0].setAttribute('type','text');
	 					}
	 					$(field).val(field.defaultValue);
	 				}

				});
	 		}

	 	});

	};
})(jQuery);

Using the clickFields jQuery Plugin

<!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 content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>clickFields.js Demo</title>

	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
	<script type="text/javascript" src="clickFields.js"></script>

	<script type="text/javascript">

		$(document).ready(function () {

			$('#myform').clickFields({
                               passClass: 'password', // the CSS class name for a password field
                               input: true, // allow clickFields on input fields
                               textarea: true // allow clickFields on textarea fields
                        });

		});	

	</script>

</head>

<body>

	<form id="myform">

		<input type="text" name="username" value="Your Username" />
		<input type="text" name="password" value="Your Password" class="password" />

		<input type="submit" name="submit" value="Go" />
	</form>

</body>

</html>

Click here to download the clickFields.js jQuery plugin

Mobile Evolution

VIDEO ON 20 April 2011

Fantastic piece of cutting edge 3D Projection created for Vodaphone and showing the evolution of the mobile handset. Check it out!

Underground Survival

DESIGN, ILLUSTRATION ON 19 April 2011


Check out these superb illustrations by Luke Shuman for WIRED UK, depicting an underground bunker capable of sustaining a whole community during an apocalyptic event.

 

Mix it up

DESIGN, DEVELOPMENT ON 12 April 2011

Ahh. The sweet smell of nostalgia. Remember the good old days when your entire music collection couldn’t fit in your pocket, but you could just about squeeze 20 of your favourite tracks onto a battered old cassette tape. Well now you can simulate the good old days thanks to this clever bods who created mixibits.com. This neat little site allows you to create your own custom mix tapes by searching out your favourite tracks and adding them to a virtual cassette tape of your chosen design. You can then share your mix via Facebook connect, (my only criticism is that it offers no other obvious methods of sharing your mix).

You also have the option to listen to other users mixes and purchase tracks you like via the Amazon MP3 store. Cool.

ASP.NET MVC Virtual Path Provider

DEVELOPMENT ON 10 April 2011

I’ve read several articles showing how to implement a custom VirtualPathProvider to load ASP.NET MVC views direct from SQL database storage. This type of implementation really extends the CMS possibilities of ASP.NET MVC and reduces the barrier of entry for designers and UX developers to be able to edit and develop website content using Microsoft’s Razor View Engine from within any web browser.

Like all the articles both you and I have probably already seen, this example also demonstrates how to implement a custom VirtualPathProvider but it additionally demonstrates how to handle the specific issue of updating a “View” whilst ensuring the VirtualPathProvider only reloads the view once it has been updated and not on every single request.

VirtualPathProvider Override Methods

The VirtualPathProvider has two override methods that can be used to handle requests. The first method I looked at was the “GetCacheDependency” method which is poorly documented and seems to be over complicated when all I wanted was a request to reload once it had been updated.

The second override method is “GetFileHash” which returns the time stamp of the requested file so that the VirtualPathProvider reloads the request once the files time stamp value changes. The problem I had with this is how to handle the time stamp value for every request to my VirtualPathProvider. In this article we demonstrate a simple technique that uses a GUID value as both the file hash and also the ID of the requested view.

The Database Schema

Here you can see the database table has an “ID” field and a “GUID” field. We use the ID field throughout the application to handle all the CRUD methods and the GUID value to handle VirtualPathProvider requests using the GetFileHash method.

Updating the View

The following method demonstrates how we assign a new GUID to the GUID field every time the view has been updated.

namespace iO.Controllers
{
    [HandleError]
    public class AdminController : Controller
    {
        [HttpPost, ValidateInput(false)]
        public ActionResult EditView(Template template)
        {
            if (ModelState.IsValid)
            {
                  //assign a new GUID every time the view is updated
                  template.Guid = Guid.NewGuid();
                  yourDataRepository.UpdateTemplate(template);
            }
            return View();
        }
    }
}

The View Controller

The View Controller method shows how we get the view by the ID field and return it’s GUID value as a string to the view result. You could use a friendly UrlKey/Permalink to get the view if required.


namespace iO.Controllers
{
    [HandleError]
    public class ViewController : Controller
    {
        public ActionResult GetView(int ID)
        {
            myModel model = new myModel();
            model.Template = yourDataRepository.GetTemplateByID(ID);
            ViewData.Model = model;
            return View(model.Template.Guid.ToString());
        }
    }
}

The VirtualPathProvider

The VirtualPathProvider shows how we use the virtualPath value to check if the request has been made by the “ViewController” controller and returns the virtualPath in the GetFileHash method. Remember that the virtualPath uses the requested views GUID value which only changes once the view is Updated using the “EditView” method

namespace iO.Mvc.Providers
{
    public class MvcVirtualPathProvider : VirtualPathProvider
    {
        // virtualPath example >>  "~/Views/View/21EC2020-3AEA-1069-A2DD-08002B30309D.cshtml"
        private bool IsPathVirtual(string virtualPath)
        {
            string path = VirtualPathUtility.ToAppRelative(virtualPath);

            // returns true if the path is requested by the "ViewController" controller
            if (path.StartsWith("~/Views/View", StringComparison.InvariantCultureIgnoreCase)
            {
                return true;
            }
            return false;
        }

        public override bool FileExists(string virtualPath)
        {
            if (IsPathVirtual(virtualPath))
            {
                SimpleVirtualFile file = (SimpleVirtualFile)GetFile(virtualPath);
                if (file.Exists)
                {
                    return true;
                }
                return false;
            }
            return Previous.FileExists(virtualPath);
        }

        public override VirtualFile GetFile(string virtualPath)
        {
            if (IsPathVirtual(virtualPath))
            {
                return new SimpleVirtualFile(virtualPath);
            }
            return Previous.GetFile(virtualPath);
        }

        // Simply return the virtualPath on every request.
        public override string GetFileHash(string virtualPath, System.Collections.IEnumerable virtualPathDependencies)
        {
            if (IsPathVirtual(virtualPath))
            {
                    // Returns the virtual path value which is made up of the views GUID value that only
                    // changes once the view has been updated - essentially working like an updated FileHash
                    // but also the ID of the requested view
                    return virtualPath;
            }
            return base.GetFileHash(virtualPath, virtualPathDependencies);
        }

        private class SimpleVirtualFile : VirtualFile
        {
            private IDataRepository yourDataRepository;
            private string content;

            public bool Exists
            {
                get { return (content != null); }
            }

            public SimpleVirtualFile(string virtualPath)
                : base(virtualPath)
            {
                yourDataRepository = new DataRepository();
                GetContent();
            }

            public override Stream Open()
            {
                ASCIIEncoding encoding = new ASCIIEncoding();
                return new MemoryStream(encoding.GetBytes(this.content), false);
            }

            protected void GetContent()
            {
                if (IsPathVirtual(virtualPath))
                {
                        // your GetTemplateByPath method would need to split the virtualPath string to retrieve
                       // the GUID value and request the View from the SQL database using the GUID value instead
                       // of the ID Primary Key field.
                        Template template = yourDataRepository.GetTemplateByPath(VirtualPath);
                        if (template != null)
                        {
                            this.content = "@model dynamic \r\n" + template.Content.ToString();
                        }
                }
            }
        }

        // just implement the default override and return null if the path is a Virtual Path
        public override CacheDependency GetCacheDependency(string virtualPath,
            System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
        {
            if (IsPathVirtual(virtualPath))
            {
                return null;
            }
            return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }
    }
}

This simple technique works really well and makes your VirtualPathProvider operate in the same way as requesting a physical file from disk in addition to removing the need to implement CacheDependencies or SQLCacheDependencies.

Commenting on our Blog is closed at the moment but feel free to use our contact form if you have any questions, comments or feedback.

This website is built using iO Engine CMS. iO Engine will launch as an open source community project later this year.

Visit iO Engine

This website is hosted on AIR BASE
using an AIR CORE DEDICATED SERVER. AIRBASE is due to launch later this year.

Visit Airbase