<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mondayhero — Flash Creative Daniel Ruuth</title>
	<atom:link href="http://mondayhero.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://mondayhero.com</link>
	<description></description>
	<lastBuildDate>Fri, 10 Jun 2011 11:16:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Broken indexOf in internet explorer</title>
		<link>http://mondayhero.com/2011/06/10/broken-indexof-in-internet-explorer/</link>
		<comments>http://mondayhero.com/2011/06/10/broken-indexof-in-internet-explorer/#comments</comments>
		<pubDate>Fri, 10 Jun 2011 11:12:33 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=153</guid>
		<description><![CDATA[Since IE 7 it&#8217;s seems indexOf for arrays is no longer available, here&#8217;s a short snippet to fix it: if(!Array.indexOf){ Array.prototype.indexOf = function(obj){ for(var i=0; i&#60;this.length; i++){ if(this[i]==obj){ return i; } } return -1; } }]]></description>
			<content:encoded><![CDATA[<p>Since IE 7 it&#8217;s seems indexOf for arrays is no longer available, here&#8217;s a short snippet to fix it:</p>
<pre class="brush: javascript">
if(!Array.indexOf){
	Array.prototype.indexOf = function(obj){
		for(var i=0; i&lt;this.length; i++){
			 if(this[i]==obj){
				 return i;
			}
		}
		return -1;
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2011/06/10/broken-indexof-in-internet-explorer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Assetloading in flash</title>
		<link>http://mondayhero.com/2011/06/10/assetloading-in-flash/</link>
		<comments>http://mondayhero.com/2011/06/10/assetloading-in-flash/#comments</comments>
		<pubDate>Fri, 10 Jun 2011 08:19:43 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[as3]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=144</guid>
		<description><![CDATA[Ever heard of the Asset Factory approach to loading assets in flash? If not here&#8217;s a short brief: 1. Loadingorder has always been something to think about in flash, you don&#8217;t want to fill your initial load wit to much content, then you can&#8217;t actually display even a loading bar to begin with. 2. Opening [...]]]></description>
			<content:encoded><![CDATA[<p>Ever heard of the Asset Factory approach to loading assets in flash? If not here&#8217;s a short brief:<br />
1. Loadingorder has always been something to think about in flash, you don&#8217;t want to fill your initial load wit to much content, then you can&#8217;t actually display even a loading bar to begin with.<br />
2. Opening multiple loading threads can slow down the loading time and increase the tension on the requested server.<br />
3. Keeping track of each object in the loading queue is just a headache if you have enought assets.</p>
<p>Here&#8217;s my approach to working with &#8220;asset factories&#8221;; let&#8217;s start with the code:</p>
<pre class="brush: as3">
package nute.net{
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.display.MovieClip;
	import flash.net.URLRequest;

	public class FactoryLoader{

		private var __progress:Number;
		private var __assetFactory:Loader;

		public var dispatcher:MovieClip;

		function FactoryLoader( url:String = null ){
			dispatcher = new MovieClip();

			if(url!=null){
				__load( url )
			}

		}

		public function load( url:String ){
			__load( url );
		}

		function __load( url:String ):void{
			__assetFactory = new Loader();
			__assetFactory.contentLoaderInfo.addEventListener(Event.COMPLETE, __onComplete);
			__assetFactory.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, __onProgress);
			__assetFactory.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, __onComplete);
			__assetFactory.load( new URLRequest( url) );
		}

		function __onProgress(evt:ProgressEvent):void{
			__progress = evt.bytesLoaded/evt.bytesTotal;
			dispatcher.dispatchEvent( new ProgressEvent("progress") );
		}

		public function get progress():Number{
			return __progress;
		}

		function __onComplete(evt:Event):void{
			__assetFactory.contentLoaderInfo.removeEventListener(Event.COMPLETE, __onComplete);
			__assetFactory.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, __onProgress);
			__assetFactory.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, __onComplete);

			if(evt.type == "ioError"){
				trace('cant load media')
			}else{
				__progress = 1;
			}
			dispatcher.dispatchEvent( evt );
		}

		public function getObjectByClass( className:String):*{
			try{
				var ClassObject:Class = __assetFactory.contentLoaderInfo.applicationDomain.getDefinition( className ) as Class;
				return new ClassObject();
			}catch(e){
				return false;
			}
		}
	}
}</pre>
<p>This is a way of compiling groups of content in seperate swf&#8217;s and loading them as &#8220;asset factories&#8221;.<br />
What the does this class do then? Well, consider creating a flash file with all the classes you need bundled into it, this FactoryLoader will then load the complete set of classes and make them all available trough the &#8220;getObjectByClass&#8221; function.</p>
<p>To load assets with a FactoryLoader, you would do something like this:</p>
<pre class="brush: as3">
[...]
var assetLoader:FactoryLoader = new FactoryLoader();
				assetLoader.dispatcher.addEventListener("complete", onAssetsLoaded);
				assetLoader.dispatcher.addEventListener("progress", onProgress);
				assetLoader.load( 'mybakedassets.swf' );
[...]
</pre>
<pre class="brush: as3">
function onProgress(evt:ProgressEvent):void{
	trace( assetLoader.progress );
}

function onAssetsLoaded(evt:Event){
	var myNewObject:* = assetLoader.getObjectByClass("MyClassObject");
	if(myNewObject){
		addChild(myNewObject) /* or whatever you need to do */
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2011/06/10/assetloading-in-flash/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Time to re-evaluate the standard norm of screen layout?</title>
		<link>http://mondayhero.com/2011/05/12/time-to-re-evaluate-the-standard-norm-of-screen-layout/</link>
		<comments>http://mondayhero.com/2011/05/12/time-to-re-evaluate-the-standard-norm-of-screen-layout/#comments</comments>
		<pubDate>Thu, 12 May 2011 18:40:14 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[thinkpost]]></category>
		<category><![CDATA[Design]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=131</guid>
		<description><![CDATA[Take a look at 10 webpage designs, chances are that about eight or nine have the following design; A &#8220;header&#8221; at the top with a top level navigation and a search field to your right. A submenu residing to your right. A footer with contact or a sitetree. Between the header and the footer the [...]]]></description>
			<content:encoded><![CDATA[<p>Take a look at 10 webpage designs, chances are that about eight or nine have the following design;</p>
<p>A &#8220;header&#8221; at the top with a top level navigation and a search field to your right.<br />
A submenu residing to your right.<br />
A footer with contact or a sitetree.</p>
<p>Between the header and the footer the content float from top to bottom of the page. Ok so there could be some minor takes on what I just said, but on the whole, that&#8217;s how the web looks.</p>
<p>The reasons I think we should re-evaluate that base are a few:<br />
1. A majority of the new computers being produced have a 16:9 or 16:10 screen, leaving a very small top to bottom area when it comes to pixels. All the major browsers keep menues, tabs, locationbar etc at the top or bottom of the screen, leaving you with even less space.</p>
<p>2. We&#8217;re starting to navigate our systems differently, let&#8217;s face it: clicking links and dragging scrollbars around isn&#8217;t as fun as it use to be. Now it&#8217;s all about swiping, tapping and other cool new gestures.</p>
<p>3. Speaking of swiping, there&#8217;s a lot of handhelds out there. Think of the design I described above, not so cool on a 7&#215;5&#8243; display now is it? Here we are back to web 1.0 when we had to make 2 websites for 2 browsers.</p>
<p>What would be the first step towards a more flexibel web layout?</p>
<p><strong>Gestures</strong><br />
I think we should start to designt the things we don&#8217;t need to see:<br />
Swipe to the right or left instead of clicking next/prev in a pagination display.<br />
Dubbletapping to reveal a menu.</p>
<p><strong>Utilizing available space</strong><br />
On most screens there&#8217;s more pixels from left to right than from top to bottom, but the designs are still stuck in the 960 grid. Lets make content more liquid and fill up the page from left to right. There&#8217;s some nice new features in CSS3 called column-count for instance that will be much usefull for this.</p>
<p><strong>Make a proper structure</strong><br />
A proper structure built upon tags, categories or whatever is your terminology, makes for a superb navigation. Why have both a menu, a site structure a taglist and a search field on every page?<br />
Are your site that hard to navigate? Or maybe your visitors just that stupid? Let&#8217;s be honest, quite few users comes to your index page and starts looking for something, they probably got to that specific page on your site because a search engine or a link took them there. For this, a &#8220;related&#8221; section is much more likely to be useful for your visitor rather that a site tree or a taglist.</p>
<p><strong>So in conclusion, what I am saying is:</strong> really think and rethink your design next time you do a layout, don&#8217;t just do as we always have done. It&#8217;s time for something new.</p>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2011/05/12/time-to-re-evaluate-the-standard-norm-of-screen-layout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing around with socket server in Air</title>
		<link>http://mondayhero.com/2011/05/12/playing-around-with-socket-server-in-air/</link>
		<comments>http://mondayhero.com/2011/05/12/playing-around-with-socket-server-in-air/#comments</comments>
		<pubDate>Thu, 12 May 2011 18:30:25 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=122</guid>
		<description><![CDATA[Ok, socket servers are neat, everyone knows this, right? I&#8217;m going to show you how you can put it to use by building an Air app that can controll your spotify app, or any other app really, by waiting for telnet connections and then run applescript calls based on commandos sent by the telnet client. [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, socket servers are neat, everyone knows this, right?</p>
<p>I&#8217;m going to show you how you can put it to use by building an Air app that can controll your spotify app, or any other app really, by waiting for telnet connections and then run applescript calls based on commandos sent by the telnet client. Flexibel approach to controlling a huge set of applications on your mac. This could be achieved on a Windows or nix machine aswell, asumed that you can control whaterver you need to control by commando line.</p>
<p>Lets start with the simple as3 code to create the Socket Server to handle incoming commandos:</p>
<pre class="brush:as3">package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.ProgressEvent;
	import flash.events.ServerSocketConnectEvent;
	import flash.net.ServerSocket;
	import flash.net.Socket;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.utils.ByteArray;

	import flash.desktop.NativeProcess;
	import flash.desktop.NativeProcessStartupInfo;
	import flash.filesystem.File;
	import UserIp;
	public class SpotifyRemote extends Sprite
	{
		private var serverSocket:ServerSocket = new ServerSocket();
		private var clientSocket:Socket;
		private var process:NativeProcess;
		private var localIP:TextField;
		private var localPort:TextField;
		private var logField:TextField;
		private var message:TextField;
		private var ipInfo:UserIp;

		public function SpotifyRemote()
		{
			setupUI();
			if( NativeProcess.isSupported ){
				are_we_native.text = "We dare to shell"
			}else{
				are_we_native.text = "no shell =("
			}
		}

		private function onConnect( event:ServerSocketConnectEvent ):void
		{
			clientSocket = event.socket;
			clientSocket.addEventListener( ProgressEvent.SOCKET_DATA, onClientSocketData );
			log( "Connection from " + clientSocket.remoteAddress + ":" + clientSocket.remotePort );

			if (clientSocket != null &amp;&amp; clientSocket.connected)
				{
					clientSocket.writeUTFBytes( "+OK hello old friend" );
					clientSocket.flush();

				}
		}

		private function onClientSocketData( event:ProgressEvent ):void
		{
			var buffer:ByteArray = new ByteArray();
			clientSocket.readBytes( buffer, 0, clientSocket.bytesAvailable );
			log( "Received: " + buffer.toString() );

			do_shell( buffer.toString() )
		}

		private function bind( event:Event ):void
		{
			if (serverSocket.bound)
			{
				serverSocket.close();
				serverSocket = new ServerSocket();

			}
			serverSocket.bind( parseInt( localPort.text ), localIP.text );
			serverSocket.addEventListener( ServerSocketConnectEvent.CONNECT, onConnect );
			serverSocket.listen();
			log( "Bound to: " + serverSocket.localAddress + ":" + serverSocket.localPort );
		}

		private function send( event:Event ):void
		{
			try
			{
				if (clientSocket != null &amp;&amp; clientSocket.connected)
				{
					clientSocket.writeUTFBytes( message.text );
					clientSocket.flush();
					log( "Sent message to " + clientSocket.remoteAddress + ":" + clientSocket.remotePort );
				}
				else
				{
					log("No socket connection.");
				}
			}
			catch (error:Error)
			{
				log( error.message );
			}
		}

		private function log( text:String ):void
		{
			logField.appendText( text + "\n" );
			logField.scrollV = logField.maxScrollV;
			trace( text );
		}

		private function setupUI():void
		{
			localIP = createTextField(10,10,"Local IP","192.168.0.15");
			localPort = createTextField(10,35,"Local port","8888");
			createTextButton( 170, 60, "Bind", bind );
			message = createTextField(10,85,"Message","Lucy can't drink milk.");
			createTextButton( 170, 110, "Send", send );
			logField = createTextField( 10, 135, "Log", "", false, 200 )
			            ;
			this.stage.nativeWindow.activate();
		}

		private function createTextField( x:int, y:int, label:String, defaultValue:String = '', editable:Boolean = true, height:int = 20 ):TextField
		{
			var labelField:TextField = new TextField();
			labelField.text = label;
			labelField.type = TextFieldType.DYNAMIC;
			labelField.width = 100;
			labelField.x = x;
			labelField.y = y;

			var input:TextField = new TextField();
			input.text = defaultValue;
			input.type = TextFieldType.INPUT;
			input.border = editable;
			input.selectable = editable;
			input.width = 280;
			input.height = height;
			input.x = x + labelField.width;
			input.y = y;

			this.addChild( labelField );
			this.addChild( input );

			return input;
		}

		private function createTextButton( x:int, y:int, label:String, clickHandler:Function ):TextField
		{
			var button:TextField = new TextField();
			button.htmlText = "<span style="text-decoration: underline;"><strong>" + label + "</strong></span>";
			button.type = TextFieldType.DYNAMIC;
			button.selectable = false;
			button.width = 180;
			button.x = x;
			button.y = y;
			button.addEventListener( MouseEvent.CLICK, clickHandler );

			this.addChild( button );
			return button;
		}

		private function trim( s:String ):String{
			return s.replace( /^([\s|\t|\n|\r]+)?(.*)([\s|\t|\n|\r]+)?$/gm, "$2" );
		}

		private function do_shell(args:String){

			args = trim(args);

			args = args.substr(0,4);

			var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
			var file:File = File.applicationDirectory.resolvePath("remote_calls.sh");
			nativeProcessStartupInfo.executable = file;
			var processArgs:Vector. = new Vector.();
			processArgs[0] = args;
			nativeProcessStartupInfo.arguments = processArgs;
			nativeProcessStartupInfo.workingDirectory = File.applicationDirectory;
			process = new NativeProcess();
			process.start(nativeProcessStartupInfo);
			are_we_native.text = '"'+args+'"';
		}
	}
}</pre>
<p>You can go ahead and build this as an air app right away, on line 106 you might want to add your ip address, allthough you can change this once the app is running aswell.</p>
<p>The function we want to take a closer look to is the one called</p>
<pre class="brush:as3">do_shell()</pre>
<p>, this is where the actual calling of functions is being handled. You might see that I&#8217;m calling on a shell script called</p>
<pre class="brush:as3">remote_calls.sh</pre>
<p>, it&#8217;s just a simple shell script that executes some applescript files. Let&#8217;s take a look at it:</p>
<pre class="brush:shell">#!/bin/bash

#
#	Script to logg time spent of files
#	Author: Daniel @ Nute Digital Agency
#

echo $1

if [ $1 = "play" ]
	then
	arch -i386 osascript "play.scpt"
fi

if [ $1 = "stop" ]
	then
	arch -i386 osascript "play.scpt"
fi

if [ $1 = "next" ]
	then
	arch -i386 osascript "next.scpt"
fi

if [ $1 = "back" ]
	then
	arch -i386 osascript "back.scpt"
fi

if [ $1 = "upvo" ]
	then
	arch -i386 osascript "volume_up.scpt"
fi

if [ $1 = "down" ]
	then
	arch -i386 osascript "volume_down.scpt"
fi</pre>
<p>And finally, the applescripts:</p>
<pre class="brush: as3">--play.scpt
tell application "Spotify"
	activate
end tell

tell application "System Events"
	keystroke space
end tell

--next.scpt
tell application "Spotify"
	activate
end tell

tell application "System Events"
	keystroke (ASCII character 29) using {command down} --next
end tell

--back.scpt
tell application "Spotify"
	activate
end tell

tell application "System Events"
	keystroke (ASCII character 28) using {command down}
end tell

--volume_up.scpt
tell application "Spotify"
	activate
end tell

tell application "System Events"
	keystroke (ASCII character 30) using {command down} --volumeup
end tell

--volume_down.scpt
tell application "Spotify"
	activate
end tell

tell application "System Events"
	keystroke (ASCII character 31) using {command down}
end tell</pre>
<p>That it folks!</p>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2011/05/12/playing-around-with-socket-server-in-air/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preparing for Tokyo</title>
		<link>http://mondayhero.com/2010/09/05/preparing-for-tokyo/</link>
		<comments>http://mondayhero.com/2010/09/05/preparing-for-tokyo/#comments</comments>
		<pubDate>Sun, 05 Sep 2010 18:24:15 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=120</guid>
		<description><![CDATA[Leaving for Tokyo within a couple of hours, see you in october!]]></description>
			<content:encoded><![CDATA[<p>Leaving for Tokyo within a couple of hours, see you in october!</p>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2010/09/05/preparing-for-tokyo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Frequent question pt 2</title>
		<link>http://mondayhero.com/2010/09/02/frequent-question-pt-2/</link>
		<comments>http://mondayhero.com/2010/09/02/frequent-question-pt-2/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 09:44:33 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[applescript]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=117</guid>
		<description><![CDATA[In my last post I explained how to get the path of the current window to your pasteboard, now it&#8217;s time to do something with that path you have in your pasteboard. Imagine you have a colleague who&#8217;s using our little script to get his path, he now sends it to you so you can [...]]]></description>
			<content:encoded><![CDATA[<p>In my last post I explained how to get the path of the current window to your pasteboard, now it&#8217;s time to do something with that path you have in your pasteboard.</p>
<p>Imagine you have a colleague who&#8217;s using our little script to get his path, he now sends it to you so you can open the folder he&#8217;s refering to, do the same procedure as last time (create an app of the script below, and drag to your finder toolbar). You press the app, and you are presented with an input, enter the path your mate sent you and presto, you will get a new finder window of that location.</p>
<pre class="brush: shell">
try
	tell application "Finder"
		activate
		set current_path to (the target of the front window) as alias
		set current_path_posix to the POSIX path of current_path as string

		set temp to display dialog "Enter Path" default answer current_path_posix
		set new_location to the text returned of temp

		set macPath to POSIX file new_location as Unicode text

		open macPath

	end tell
end try
</pre>
<p>This example fills the input dialog with the location of the current folder, this could easily be changed to default contain the content of your clipboard, making the example workflow I mentioned even faster.</p>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2010/09/02/frequent-question-pt-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Frequent question</title>
		<link>http://mondayhero.com/2010/08/31/frequent-question/</link>
		<comments>http://mondayhero.com/2010/08/31/frequent-question/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 18:18:39 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[applescript]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=113</guid>
		<description><![CDATA[Copying the path of the current open finder window is something many &#8220;new-to-mac&#8221; friends have asked me. Coming from the world of Windows, this is a well missed feature. Well, this can easily be solved with a little Applescript app residing in your finder toolbar. Consider this: try tell application "Finder" set this_folder to (the [...]]]></description>
			<content:encoded><![CDATA[<p>Copying the path of the current open finder window is something many &#8220;new-to-mac&#8221; friends have asked me. Coming from the world of Windows, this is a well missed feature. Well, this can easily be solved with a little Applescript app residing in your finder toolbar. </p>
<p>Consider this:</p>
<pre class="brush: applescript">try
	tell application "Finder"
		set this_folder to (the target of the front window) as alias
		set this_folder_posix to the POSIX path of this_folder
		set the clipboard to this_folder_posix
	end tell
end try</pre>
<p>Open script editor, paste the code above then save it as an app. Drag the app to the toolbar of your finder window and voila, once you click it, the path of the currently open window is in your clipboard.</p>
<p>Stay tunes for part 2, opening a finder window at the location in your pasteboard.</p>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2010/08/31/frequent-question/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Time tracking – the unobstructive way</title>
		<link>http://mondayhero.com/2010/08/24/time-tracking-%e2%80%93-the-unobstructive-way/</link>
		<comments>http://mondayhero.com/2010/08/24/time-tracking-%e2%80%93-the-unobstructive-way/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 16:10:55 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[applescript]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=103</guid>
		<description><![CDATA[We often talk about how we could time track projects in an unobstructive way at work. I&#8217;ve been in places where time tracking is mandatory and it always comes down to you sitting off office hours trying to fill the gaps of days and days in your time tracking application. What if you could just [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste">We often talk about how we could time track projects in an unobstructive way at work. I&#8217;ve been in places where time tracking is mandatory and it always comes down to you sitting off office hours trying to fill the gaps of days and days in your time tracking application.</div>
<p>What if you could just track the time you have spent on a file, and then based on location of that file see how much time you have spent on a project? This will not give you the complete time spent, but it would give you a ballpark figure to see the time of _actual_ production time for a project.</p>
<p>I&#8217;ve seen some commercial application doing this, so I figured it can&#8217;t be impossible. This is my first attempt in AppleScript:</p>
<pre class="brush: applescript;">tell application "System Events"
	set frontApp to name of first application process whose frontmost is true
end tell

if frontApp is "Adobe Photoshop CS4" then
	try
		tell application "Adobe Photoshop CS4"
			set document_path to file path of front document as string
		end tell
	end try
else if frontApp is "Adobe Illustrator CS4" then
	tell application "Adobe Illustrator"
		set theOutdatedPathObj to the file path of current document
		set document_path to (POSIX path of theOutdatedPathObj) as string
	end tell

else if frontApp is "Adobe After Effects CS4" then
	tell application "System Events"
		tell process "After Effects"
			set document_path to title of window 2
		end tell
	end tell

else if frontApp is "Coda" then
	try
		tell application "Coda"
			set document_path to file path of current editor of document 1 as string
		end tell
	on error
		--do nothing
	end try
else
	tell application frontApp
		try
			if the (count of windows) is not 0 then
				set window_name to name of front window
				set document_path to window_name
			end if
		on error
			set window_name to "could not tell"
			set document_path to "could not tell"
		end try
	end tell
end if

set currentTime to current date
set myFilePath to (path to desktop as string) &#038; "nutelogger.txt" as string
set myFileRef to open for access file myFilePath with write permission
write frontApp &#038; ";" &#038; document_path &#038; ";" &#038; currentTime &#038; ";
" to myFileRef starting at eof
close access myFileRef

-- Get the "hour"
set timeStr to time string of (current date)
set Pos to offset of ":" in timeStr
set theHour to characters 1 thru (Pos - 1) of timeStr as string
set timeStr to characters (Pos + 1) through end of timeStr as string

-- Get the "minute"
set Pos to offset of ":" in timeStr
set theMin to characters 1 thru (Pos - 1) of timeStr as string
set timeStr to characters (Pos + 1) through end of timeStr as string

-- Get the seconds
set Pos to offset of ":" in timeStr
set theSec to characters 1 thru (Pos - 4) of timeStr as string
set timeStr to characters (Pos + 1) through end of timeStr as string
set theSecInt to theSec as integer

set logged_user to short user name of (system info)
-- we sent to the server four times an hour
if theMin is "15" then
	--since this script is called approx 6 times a min, we only upload if secs is less than 12
	if theSecInt is less than 12 then
		set possix_path to POSIX path of myFilePath
		do shell script "curl -T " &#038; possix_path &#038; " ftp://user:password@example.com/private_html/" &#038; logged_user &#038; "-nutelogger.txt"
		--here we should also flush the current logfile
		tell application "GrowlHelperApp"
			set the allNotificationsList to {"Nute Logger", "Nute Logger Updated Server"}

			set the enabledNotificationsList to {"Nute Logger"}
			register as application "Nute Logger" all notifications allNotificationsList default notifications enabledNotificationsList icon of application "AppleScript Editor"

			notify with name "Nute Logger" title "Nute Logger" description "Nute Logger Update Done" application name "Nute Logger"

		end tell
	end if
end if</pre>
<p>The script gets executed every couple of seconds with launchd and isn&#8217;t slowing my machine down the least. The writing to a plain text file could be replaced with a sqlite injection and the push to a server could be limited even more.</p>
<p>As one could see, the drawback of this approach would be that you have to customize it for every application, and if the application doesn&#8217;t support AppleScript, well, then you are out of luck. I was thinking of using lsof to get files of the frontmost app, but this won&#8217;t show you which window that is active, so if you have more than one file open, the time will be wrong since it would count the time you spend in one window on several documents. Another downside would be that you actually have to do a lot of customization here as well since you would like to sort of all the &#8220;dirt&#8221; files and focus on the filetypes you would be working on in each application.</p>
<p>So in the end, maybe some sort of combination of the two, which would anyhow lead you to a world of pain making rules for all applications.</p>
<p>Why isn&#8217;t &#8220;Time Spent&#8221; something that the filesystem would keep track of from the beginning? I could imagine hundreds of situations where this would be most usefull.</p>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2010/08/24/time-tracking-%e2%80%93-the-unobstructive-way/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Snippet of the week: array_to_json</title>
		<link>http://mondayhero.com/2010/08/10/snippet-of-the-week-array_to_json/</link>
		<comments>http://mondayhero.com/2010/08/10/snippet-of-the-week-array_to_json/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 16:30:32 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=97</guid>
		<description><![CDATA[Ok, I&#8217;m not really posting a snippet every week, but bare with me, I&#8217;m trying. Here&#8217;s a snipped for all you unlucky people who&#8217;s server provider is not enabling json support in the php build. I have a habit of always adding &#8220;meta&#8221; fields to my tables when I work on large projects in php [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, I&#8217;m not really posting a snippet every week, but bare with me, I&#8217;m trying.</p>
<p>Here&#8217;s a snipped for all you unlucky people who&#8217;s server provider is not enabling json support in the php build. I have a habit of always adding &#8220;meta&#8221; fields to my tables when I work on large projects in php to enable simple extension without modifying the mysql table, storing data in json format is super for these type of meta fields where you don&#8217;t really now what data is going to be in there tomorrow.</p>
<p>It&#8217;s originally for &#8220;the internet&#8221; but slightly modified by yours truly.</p>
<pre class="brush: php;">function array_to_json( $array ){

    if( !is_array( $array ) ){
        return false;
    }

    $associative = count( array_diff( array_keys($array), array_keys( array_keys( $array )) ));
    if( $associative ){

        $construct = array();
        foreach( $array as $key =&gt; $value ){

            // We first copy each key/value pair into a staging array,
            // formatting each key and value properly as we go.

            // Format the key:
            if( is_numeric($key) ){
                $key = "key_$key";
            }
            $key = "'".addslashes($key)."'";

            // Format the value:
            if( is_array( $value )){
                $value = array_to_json( $value );
            } else if( !is_numeric( $value ) || is_string( $value ) ){
                $value = "'".addslashes($value)."'";
            }

            // Add to staging array:
            $construct[] = "$key: $value";
        }

        // Then we collapse the staging array into the JSON form:
        $result = "{ " . implode( ", ", $construct ) . " }";

    } else { // If the array is a vector (not associative):

        $construct = array();
        foreach( $array as $value ){

            // Format the value:
            if( is_array( $value )){
                $value = array_to_json( $value );
            } else if( !is_numeric( $value ) || is_string( $value ) ){
                $value = "'".addslashes($value)."'";
            }

            // Add to staging array:
            $construct[] = $value;
        }

        // Then we collapse the staging array into the JSON form:
        $result = "[ " . implode( ", ", $construct ) . " ]";
    }

    return $result;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2010/08/10/snippet-of-the-week-array_to_json/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Peddlr</title>
		<link>http://mondayhero.com/2010/08/06/peddlr/</link>
		<comments>http://mondayhero.com/2010/08/06/peddlr/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 13:21:35 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[iPhone]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://mondayhero.com/?p=91</guid>
		<description><![CDATA[I just dived into iPhone webapps again, mainly because my old dev license has run out and I&#8217;m waiting for a new one at my new firm. Turns out, you can get pretty cool stuff working with some creative coding. Allthoug Peddlr isn&#8217;t using that many advanced features, it&#8217;s getting there slowely. So what is [...]]]></description>
			<content:encoded><![CDATA[<p>I just dived into iPhone webapps again, mainly because my old dev license has run out and I&#8217;m waiting for a new one at my new firm.</p>
<p>Turns out, you can get pretty cool stuff working with some creative coding.</p>
<p>Allthoug Peddlr isn&#8217;t using that many advanced features, it&#8217;s getting there slowely.</p>
<p><strong>So what is Peddlr?</strong><br />
Peddlr is a cycle app to monitor your workouts, save statistics and tracks and will work as a motivational coach aswell. With a community edition running in your browser it&#8217;s going to be like a nike+ for peddlers.</p>
<p>The main features for Peddlr will be:</p>
<ul>
<li> Monitor your races with gps data</li>
<li>Ghostrunner for competition mode</li>
<li>Save and share your favorite tracks</li>
<li>Live race mode</li>
<li>Motivational audio feedback</li>
</ul>
<p>The idea is to try getting all of this working true pure html and js goodness, at the moment I&#8217;m using raphaeljs to plot out track and I&#8217;m currently working on how to autoplay audio for the audio feedback.</p>
<p>And here&#8217;s some pics</p>
<p><a href="http://mondayhero.com/wp-content/uploads/peddlr_0.png"><img class="alignnone size-full wp-image-87" title="peddlr_0" src="http://mondayhero.com/wp-content/uploads/peddlr_0.png" alt="" width="600" height="325" /></a></p>
<p>First screen to select workout mode, possible mode will be &#8220;Track&#8221;,&#8221;Freeform&#8221; or &#8220;Challenge&#8221; where &#8220;Challenge&#8221; is a community driven challenge system.</p>
<p><a href="http://mondayhero.com/wp-content/uploads/peddlr_0.png"></a><a href="http://mondayhero.com/wp-content/uploads/peddlr_1.png"><img class="alignnone size-full wp-image-88" style="margin-top: 36px;" title="peddlr_1" src="http://mondayhero.com/wp-content/uploads/peddlr_1.png" alt="" width="600" height="325" /></a></p>
<p>Seconds screen is a example of the &#8220;Track&#8221; mode, here you see your position on the track, and some in race data</p>
<p><a href="http://mondayhero.com/wp-content/uploads/peddlr_1.png"></a><a href="http://mondayhero.com/wp-content/uploads/peddlr_2.png"><img class="alignnone size-full wp-image-89" style="margin-top: 36px;" title="peddlr_2" src="http://mondayhero.com/wp-content/uploads/peddlr_2.png" alt="" width="600" height="325" /></a></p>
<p>Third screen is runningmode where the visual section (right hand side) has been toggled to &#8220;Pace &amp; Elevation&#8221;. This graph is drawn with raphaeljs.</p>
<p><a href="http://mondayhero.com/wp-content/uploads/peddlr_3.png"><img class="alignnone size-full wp-image-90" style="margin-top: 36px;" title="peddlr_3" src="http://mondayhero.com/wp-content/uploads/peddlr_3.png" alt="" width="600" height="325" /></a></p>
<p>Fourth screen is an example of the ghost runner, I&#8217;m not a 100% about this view, since ghost only can be available when you are on a known track, you might just want to add the ghost to the track preview instead (screen 2)</p>
<p>Although the only thing precent at this time is the actual in race view, and the track preview, you can actually try it out by pointing your iphone to <a href="http://www.mondayhero.com/iphone/peddlr/">http://www.mondayhero.com/iphone/peddlr/</a>, save it as a webapp to store data locally.</p>
<p>The app calls my server when you stop the race to store race data, but all together it&#8217;s a fairly small load.</p>
]]></content:encoded>
			<wfw:commentRss>http://mondayhero.com/2010/08/06/peddlr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

