nickMiddleweek.blog.search();

Monday 15 October 2012

How to change the interval duration in JavaScript with .startDualTimer(d1, d2);

Now there are times when you'll need to kick off a setInterval() timer and modify the duration (or interval timer) after it has started perhaps so the first is different from the n+1 duration. For me, this cropped up recently with a animated image scroller component where we had three timers overall which controlled when to load in a new image and animate them to the left. To start with I just kicked off a standard setInterval() with 7000 milliseconds but this meant the user could potentially wait 14+ seconds for an update which isn't always ideal so we defined the following timers:
  1. Initial component start timer (7000 ms).
  2. IDLE timer, or the default loop timer (5000 ms).
  3. After Interaction timer (3000 ms), so if you moused over the component, I'd pause the animation but we wanted this quicker interval so the user wasn't left waiting for that potential 14+ seconds...
Now there is no way of modifying the duration of a setInterval() once it's started but we can replicate exactly what is required by using setTimeout and a recursive function. I can think of a couple of ways to achieve this, some perhaps being more generic but here's the code I implemented for this particular component...
com.middleweek.strip.prototype.startDualTimer = function (firstDelay, ongoingDelay) {
 "use strict";
 var self = this;
 if (self._internal.timer === null) { // Only start the timer if it's not already started...

  var timeoutHandler = function () {
   "use strict";
   if (self._internal.timer) { // Check to see if it's been stopped.
    self.timerInternalEventHandler();
   }
   self._internal.timer = window.setTimeout(timeoutHandler, ongoingDelay);
  };
 self._internal.timer = window.setTimeout(timeoutHandler, firstDelay);
 }
}
It's all pretty self-explanatory but here we have a function that accepts two values, firstDelay and ongoingDelay. The first call to setTimeout uses the firstDelay which invokes it's private closure function timeoutHandler() which in turns calls the components timerInternalEventHandler() function to do it's magic and then it continues to recursively call the private closure with ongoingDelay, and so forth...

At any time, we can call clearTimeout(self._internal.timer) and then set it to null to cease the magic.

...setInterval's best friend!

Saturday 6 October 2012

JavaScript .getItemMetrics() : Metrics

Having recently crafted a nice little component for fab.com I wanted to share a little utility function that can be used as a basis to help create dynamic self-aware components. The concept is by no means new, I kind of borrowed it from Flex and this one uses jQuery so with a little jiggery pokery you can borrow it too. Here's the code...

com.middleweek.strip.prototype.getItemMetrics = function () {
 "use strict";
 var self = this;

 var item = {};
 item.id = self.createUUID();
 var renderedHTML = self._renderItem(self.renderers.stripItem, item);
 $('body').append(renderedHTML);

 var metric = {};
 metric.width = $('#' + item.id).outerWidth();
 metric.height = $('#' + item.id).outerHeight();
 $('#' + item.id).remove();

 return metric;
};

Now, I quite like using this approach as it means I can style the component externally with CSS and not have to worry about injecting these values into the component or worse, hard-coding these values inside the component as I started off doing.

If you want to return a typed Object, perhaps called Metrics as the blog title suggests, you can either create yourself a predefined JS 'Class' and return that or have a Closure function inside getItemMetrics() and create and return an instance of that...

...
 function Metrics(w,h) {
 "use strict";
  this.width = w;
  this.height = h;
 }
 var jqCache = $('#' + item.id);
 var metric = new Metrics( jqCache.outerWidth(), jqCache.outerHeight() );

 return metric;
...

...neat!

Monday 16 July 2012

How can you find the version of Linux Fedora from the Shell?

Well it's actually super easy, you just open a Shell prompt, type "cat /etc/issue" and press enter...

$ cat /etc/issue

Fedora release 16 (Verne)


And that is it :-)

Wednesday 23 February 2011

An even Smoother HSmoothBox

I'm currently working for a large used car publishing company and we're working on some pretty cool UI's that interface ColdFusion ColdSpring and the Endeca Search Engine. I've been meaning to blog for a while about some personal developments but an issue cropped up with the Open Source HSmoothBox component and I wanted to share the issue and my workaround...

HSmoothBox (as found here: http://strawberrypixel.com/blog/?p=21) also has a little sibling component called VSmoothBox and in a nutshell they are like HBox/ VBox components with animated scrolling.

it's part of a composite component that binds it's dataProvider to the HSmoothBox's dataProvider and each time the composite component's dataProvider setter function is called, we invoke hscroller.scrollToItemIndex(0);

the problem came to light when we were using the HSmoothBox with PopupManager which, has its data model injected via BindingUtils.bindProperty(). First time round, all is fine but on take-two of opening the poppedUp HSmoothBox, it throws a wobbly... This was because the injected data model was fetched from the server and the timings just so made it work on it's first view but attempt numero two meant the dataProvider's ArrayCollection was there already waiting and was being injected into the HSmoothBox before it was fully created.

so, inspecting the lovely Open Source code for HSmoothBox, you can see on it's FlexEvent.CREATION_COMPLETE handler an internal "_scroller" object is created which, is required when we call its scrollToItemIndex() function. The culprit was caught!

now I probably should contact the author as well (and I will) but for now here is the little Class that extends HSmoothBox and fixes the issue.

package com.middleweek.component
{
    import containerEx.HSmoothBox;
    
    import mx.events.FlexEvent;
    
    
    /**
     *
     * @author nick.middleweek 16th February 2011
     *
     * This is to fix component functionality by overriding some methods that are prematurely invoked.
     *
     */
    public class HSmoothBox2B extends HSmoothBox
    {
        /**
         * @private
         * Storage variable to test if the creationComplete phase has executed.
         */
        private var creationCompleted : Boolean = false;
        
        
        /**
         * Constructor
         *
         */
        public function HSmoothBox2B ()
        {
            super();
            this.addEventListener( FlexEvent.CREATION_COMPLETE, onCreationComplete );
        }
        
        
        private function onCreationComplete ( evt : FlexEvent ) : void
        {
            this.creationCompleted = true;
        }
        
        
        override public function scrollToItemIndex ( val : int, immediate : Boolean = false ) : void
        {
            if ( creationCompleted == true )
            {
                super.scrollToItemIndex( val, immediate );
            }
        }
        
        
        override public function head () : void
        {
            if ( creationCompleted == true )
            {
                super.head();
            }
        }
        
        
        override public function tail () : void
        {
            if ( creationCompleted == true )
            {
                super.head();
            }
        }
    
    }
}

now HSmoothBox is even smoother!

Monday 1 November 2010

Word Problems...

a shame it is, but this isn't a Deadmau5 - Word Problems review :)  being slightly more in tune with flex I had a little task to create an ActionScript word spliiter, then display a word summary - a bit like the featurette found in word. there were a few rules to stick to including ignore punctutation but include single quotes as part of the word - as you'd expect. I was going to use Regular Expressions to split the words out but after tinkering, I decide to use good old brute force. Below is a little screenshot of the demo, click that or here and you'll get the working version. the source code is available too so have a play and use it as you please...



happy counting...

Friday 29 October 2010

ActionScript Precision discrepancy problems

mmmm, this is a bit of nightmare, especially for those writing financial software... check this, take a perfectly good number (AS3 Number) such as 11995, then divide it by 1000000, then multiply it by 1000. you would expect to get 11.995, but no, you get 11.995000000000001. then if you multiply by ten, the discrepancy gets slightly worse so each time you apply calculations, you are dealing with the wrong number.

to sort this out, you could roll your own string manipulation functions or there's a neat little static function built into the Number object called toFixed, see the docs: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Number.html#toFixed()

you use it like this...

var num : Number = ( 11995 / 1000000 );
var num2 : Number = num * 1000;
var str2 : String = num2.toFixed( 6 );
var num3 : Number = new Number( str2 );

...easy!

Thursday 28 October 2010

How to set the width of a flex data grid column to the item renderer width?

so we need to set the width of a data grid column to the same size of the item renderer defined for that column. we know we can't specify the width attribute of the DataGridColumn to 100% (check this: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/dataGridClasses/DataGridColumn.html) so if we turn the problem inside out and get the item renderer (IR) to work out how big it is and then set the column width in pixels from there (well we dispatch a custom event from the IR and listen for that event on the datagrid so it's all done propa!).

let's give it a whirl... we need a datagrid with at least one column and let's drop a numeric stepper control inside the columns IR and then we can use that to control the width of the IR which, can then specify the DataGridColumn.width attribute in pixels.

et voila! le source code ist here!