var GRAB = GRAB ||
{
    mediaos: {
        copyright: "&copy; 2010 Grab Networks. All rights reserved.",
        release:{
            version: "0.4.06",
            date:'02/25/2011',
            host:'02'
        },
        license: "",
        environment: {
            suffix:''    
        },
        servers:{
            vcl:{'domain':'vcl.grabnetworks.com'},
            cube:{'domain':'player.grabnetworks.com'}
        },
        core: {
            registry: {
                utils: {
                    register: function(component){
                        // when queue and register components.
                        this.queue(component); // queue the component.
                        
                        switch(component._type._class) {
                            case "player":
                                GRAB.mediaos.core.registry.components.players.push(component); // add the component to the registry.
                                break;
                            case "list":
                                GRAB.mediaos.core.registry.components.lists.push(component); // add the component to the registry.
                                break;
                            case "search":
                                GRAB.mediaos.core.registry.components.search.push(component); // add the component to the registry.
                                break;
                            case "metadata":
                                GRAB.mediaos.core.registry.components.metadata.push(component); // add the component to the registry.
                                break;
                            case "channelList":
                                GRAB.mediaos.core.registry.components.channelLists.push(component); // add the component to the registry.
                                break;
                            default: 
                                return;
                        }

                        return component;
                    },
                    findInRegistry: function(component){
                        switch(component._type) {
                            case 'player':
                                var
                                  componentCount = GRAB.mediaos.core.registry.components.players.length;
                                  
                                for (var i = 0; i < componentCount; i++) {
                                    if (GRAB.mediaos.core.registry.components.players[i].id == component.name) {
                                        return GRAB.mediaos.core.registry.components.players[i];
                                    };
                                };
                                  
                                break;
                            case 'list':
                                var
                                  componentCount = GRAB.mediaos.core.registry.components.lists.length;
                                  
                                for (var i = 0; i < componentCount; i++) {
                                    if (GRAB.mediaos.core.registry.components.lists[i].name == component.name) {
                                        return GRAB.mediaos.core.registry.components.lists[i];
                                    };
                                };

                                break;
                            case 'metadata':
                                // simply return the first (and currently only) metadata display object.
                                return GRAB.mediaos.core.registry.components.metadata[0];
                                break;
                                
                            case 'channelList':
                                var
                                  componentCount = GRAB.mediaos.core.registry.components.channelLists.length;
                                  
                                for (var i = 0; i < componentCount; i++) {
                                    if (GRAB.mediaos.core.registry.components.channelLists[i].name == component.name) {
                                        return GRAB.mediaos.core.registry.components.channelLists[i];
                                    };
                                };

                                break;
                            default: 
                                return;
                        }
                    },
                    queue: function(component){
                        switch(component._type._class) {
                            case 'player':
                                GRAB.mediaos.core.registry.queue.players.push(component);
                                break;
                            case 'list':
                                GRAB.mediaos.core.registry.queue.lists.push(component);
                                break;
                            case 'message':
                                var message = {
                                    'sender':component.sender,
                                    'action':component.action,
                                    'command':component.command,
                                    'id':component.id
                                };
                                GRAB.mediaos.core.registry.queue.message.stack.push(message);
                                break;
                            case 'channelList':
                                GRAB.mediaos.core.registry.queue.channelLists.push(component);
                                break;
                            default: 
                                return;
                        }

                        return component;
                    },
                    minidom: {
                        removeChildNodes: function(){
                            while (this.childNodes[0]){
                                this.removeChild(this.childNodes[0]);
                            };
                            
                            return this;
                        },
                        
                        find: function(componentName){
                            var
                              domComponent = document.getElementById(componentName);
                            return domComponent;
                        },
                        
                        getStyle: function( el, styleProp ) {
                            if (el.currentStyle) {
                                var y = el.currentStyle[styleProp];
                            } else if (window.getComputedStyle) {
                                var y = document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
                            }
                            return y;
                        },
                        
                        event: {
                            addEventSimple: function (obj, evt, fn) {
                                if (obj.addEventListener)
                                    // events are always set to use bubbling phase
                                    obj.addEventListener(evt,fn,false);
                                else if (obj.attachEvent)
                                    obj.attachEvent('on'+evt,fn);
                            },
                            
                            removeEventSimple: function (obj, evt, fn) {
                                if (obj.removeEventListener)
                                    obj.removeEventListener(evt,fn,false);
                                else if (obj.detachEvent)
                                    obj.detachEvent('on'+evt,fn);
                            }
                        },
                        
                        mouse: {
                            _states: {
                                dragging: false,
                                drag_timer: null,
                                cursor: {
                                    x: 0,
                                    y: 0
                                }
                            },
                            
                            dragDrop: {
                                keyHTML: '<a href="#" class="keyLink">#</a>',
                                keySpeed: 10, // pixels per keypress event
                                initialMouseX: undefined,
                                initialMouseY: undefined,
                                startX: undefined,
                                startY: undefined,
                                dXKeys: undefined,
                                dYKeys: undefined,
                                draggedObject: undefined,
                                
                                initElement: function ( element, _options ) {
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                
                                    var _drag_options = {
                                        axis: undefined,
                                        bounds: undefined,
                                        dragCallback: undefined,
                                        dragCallbackArgs: undefined
                                } 
                                
                                    // extract options
                                if ( _options ) {
                                        if ( _options.axis ) {
                                            _drag_options['axis'] = _options.axis;
                                        } 
                                        if ( _options.bounds ) {
                                            _drag_options['bounds'] = _options.bounds;
                                        }
                                        if ( _options.drag_callback ) {
                                            _drag_options['dragCallback'] = _options.drag_callback;
                                        }
                                        if ( _options.drag_callback_args ) {
                                            _drag_options['dragCallbackArgs'] = _options.drag_callback_args;
                                        }
                                    }
                                    
                                    // attach the drag options to the element (dragee)
                                    element['_drag_options'] = _drag_options;
                                    
                                    if (typeof element == 'string')
                                        element = document.getElementById(element);
                                        
                                    element.onmousedown = dragDrop.startDragMouse;
                                    
                                    /* TODO: jpencola - To be fully implemented
                                    element.innerHTML += dragDrop.keyHTML;
                                    var links = element.getElementsByTagName('a');
                                    var lastLink = links[links.length-1];
                                    lastLink.relatedElement = element;
                                    lastLink.onclick = dragDrop.startDragKeys;
                                    */
                                },
                                
                                startDragMouse: function (e) {
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                    
                                    dragDrop.startDrag( this );
                                    var evt = e || window.event;
                                    
                                    dragDrop.initialMouseX = evt.clientX;
                                    dragDrop.initialMouseY = evt.clientY;
                                    
                                    GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( document, 'mousemove', dragDrop.dragMouse );
                                    GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( document, 'mouseup', dragDrop.releaseElement );
                                    return false;
                                },
                                
                                /* TODO: jpencola - needs to be fully implemented
                                startDragKeys: function () {
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                    
                                    dragDrop.startDrag(this.relatedElement);
                                    dragDrop.dXKeys = dragDrop.dYKeys = 0;
                                    GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple(document,'keydown',dragDrop.dragKeys);
                                    GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple(document,'keypress',dragDrop.switchKeyEvents);
                                    this.blur();
                                    return false;
                                },
                                */
                                
                                startDrag: function (obj) {
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                    
                                    if (dragDrop.draggedObject)
                                        dragDrop.releaseElement();
                                            
                                    // make sure that the directional axis option is being honored when we move the element.
                                    if ( obj['_drag_options'].axis == 'x' )
                                        dragDrop.startX = obj.offsetLeft;
                                    else if ( obj['_drag_options'].axis == 'y' ) 
                                        dragDrop.startY = obj.offsetTop;
                                    else {
                                        dragDrop.startX = obj.offsetLeft;
                                        dragDrop.startY = obj.offsetTop;
                                                }
                                        
                                    dragDrop.draggedObject = obj;
                                    obj.className += ' dragged';
                                },

                                dragMouse: function (e) {
                                    GRAB.mediaos.core.registry.utils.minidom.mouse._states.dragging = true;
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                    
                                    var evt = e || window.event;
                                    var dX = evt.clientX - dragDrop.initialMouseX;
                                    var dY = evt.clientY - dragDrop.initialMouseY;
                                    var relativeRect = {};

                                    /*
                                        attempt to re-position the element while abiding by the movement logic
                                        encapsulated in the setPosition() method.
                                        Based on what is returned (t|f), we know that either a move happened or did not
                                    */
                                    if ( dragDrop.setPosition.call( dragDrop.draggedObject, dX, dY) ) {
                                        
                                        switch ( dragDrop.draggedObject['_drag_options'].axis ) {
                                            case 'x':
                                                relativeRect = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( dragDrop.draggedObject );
                                                break;
                                            case 'y':
                                                relativeRect = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( dragDrop.draggedObject );
                                                break;
                                            default:
                                                //
                                                break;
                                        }
                                            
                                        dragDrop.draggedObject['_drag_options'].dragCallback( dragDrop.draggedObject['_drag_options'].dragCallbackArgs, evt, relativeRect );
                                    }
                                    return false;
                                },
                                
                                dragKeys: function(e) {
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                
                                    var evt = e || window.event;
                                    var key = evt.keyCode;
                                    switch (key) {
                                        case 37:    // left
                                        case 63234:
                                            dragDrop.dXKeys -= dragDrop.keySpeed;
                                            break;
                                        case 38:    // up
                                        case 63232:
                                            dragDrop.dYKeys -= dragDrop.keySpeed;
                                            break;
                                        case 39:    // right
                                        case 63235:
                                            dragDrop.dXKeys += dragDrop.keySpeed;
                                            break;
                                        case 40:    // down
                                        case 63233:
                                            dragDrop.dYKeys += dragDrop.keySpeed;
                                            break;
                                        case 13:    // enter
                                        case 27:    // escape
                                            dragDrop.releaseElement();
                                            return false;
                                        default:
                                            return true;
                                }
                                    
                                    dragDrop.setPosition(dragDrop.dXKeys,dragDrop.dYKeys);
                                    if (evt.preventDefault)
                                        evt.preventDefault();
                                    return false;
                            },
                            
                                setPosition: function ( dx, dy ) {
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                    
                                    if ( dragDrop.startX !== undefined ) {
                                        var nx = dragDrop.startX + dx;
                                        
                                        if ( ( this['_drag_options'].bounds.left <= nx ) && ( this['_drag_options'].bounds.right >= nx ) ) {
                                            this.style.left = nx + 'px';
                                            return true;
                                        }
                                    } 
                                    if ( dragDrop.startY !== undefined ) {
                                        var ny = dragDrop.startY + dy;
                                    
                                        if ( ( this['_drag_options'].bounds.top <= ny ) && ( this['_drag_options'].bounds.bottom >= ny ) ) {
                                            this.style.top = dragDrop.startY + dy + 'px';
                                            return true;
                                        }
                                    }
                                    return false;
                                },
                                    
                                switchKeyEvents: function () {
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                    
                                    // for Opera and Safari 1.3
                                    GRAB.mediaos.core.registry.utils.minidom.event.removeEventSimple(document,'keydown',dragDrop.dragKeys);
                                    GRAB.mediaos.core.registry.utils.minidom.event.removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
                                    GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple(document,'keypress',dragDrop.dragKeys);
                                },
                                    
                                releaseElement: function() {
                                    GRAB.mediaos.core.registry.utils.minidom.mouse._states.dragging = false;
                                    var dragDrop = GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop;
                                    
                                    GRAB.mediaos.core.registry.utils.minidom.event.removeEventSimple(document,'mousemove',dragDrop.dragMouse);
                                    GRAB.mediaos.core.registry.utils.minidom.event.removeEventSimple(document,'mouseup',dragDrop.releaseElement);
                                    GRAB.mediaos.core.registry.utils.minidom.event.removeEventSimple(document,'keypress',dragDrop.dragKeys);
                                    GRAB.mediaos.core.registry.utils.minidom.event.removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
                                    GRAB.mediaos.core.registry.utils.minidom.event.removeEventSimple(document,'keydown',dragDrop.dragKeys);
                                    dragDrop.draggedObject.className = dragDrop.draggedObject.className.replace(/dragged/,'');
                                    dragDrop.draggedObject = null;
                                }
                            },
                            
                            cursor: {
                                relative: {
                                    rectangle: function( _e, _element ) {
                                        var 
                                            rect,
                                            _event = _e; 
                                            
                                            if ( !_event ) {
                                                if ( window.event ) {
                                                    _event = window.event;
                                                }
                                            }
                                            rect = {
                                                top: _event.clientY - GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( _element ).top,
                                                left: _event.clientX - GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( _element ).left,
                                                bottom: _event.clientY - GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( _element ).bottom,
                                                right: _event.clientX - GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( _element ).right
                                            };
                                        return rect; 
                                    }
                                }
                            },
                            buttons:{
                                left:{
                                    isDown: false,
                                    isUp: true
                                },
                                right: {
                                    capture: function(e) {
                                        /*
                                        $(this).mousedown( function(e) {
                                            if( e.button == 2 ) {
                                                handler.call( $(this), e );
                                                return false;
                                            } else {
                                                return true;
                                            }
                                        });
                                        $(this)[0].oncontextmenu = function() {
                                            return false;
                                        }
                                        */
                                        if( e.button == 2 ) {
                                            //handler.call( $(this), e );
                                            return false;
                                        } else {
                                            return true;
                                        }
                                    }
                                }
                            },
                            move: function( e ) {
                                var posx = 0;
                                var posy = 0;
                                if (!e) var e = window.event;
                                if (e.pageX || e.pageY)     {
                                    posx = e.pageX;
                                    posy = e.pageY;
                                }
                                else if (e.clientX || e.clientY)    {
                                    posx = e.clientX + document.body.scrollLeft
                                        + document.documentElement.scrollLeft;
                                    posy = e.clientY + document.body.scrollTop
                                        + document.documentElement.scrollTop;
                                }
                                return { x: posx, y: posy };
                            }
                        }
                    }
                },
                queue: {
                    players: [],
                    lists: [],
                    search: [],
                    metadata: [],
                    channelLists: [],
                    message: {
                        process:function(action){
                            switch(action) {
                                case 'onPlayerLoadComplete':
                                    for (var message in this.stack){
                                        if (this.stack[message].action === action) {
                                            switch(this.stack[message].command) {
                                                default: 
                                                    try {
                                                        this.stack[message].command();
                                                    } catch ( error ) {
                                                        //console.log( 'An Error occurred ', error );
                                                    };
                                                    break;
                                            }
                                        }
                                    }
                                    break;
                                case 'onVideoLoadComplete':
                                    for (var message in this.stack){
                                        if (this.stack[message].action === action) {
                                            switch(this.stack[message].command) {
                                                case 'printDescription':
                                                    if (GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.description){
                                                        var description = GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.description;
                                                    }else{
                                                        var description = '';
                                                    };
                                                    document.getElementById(this.stack[message].sender).innerHTML = description;
                                                    break;
                                                case 'printHeadline':
                                                    document.getElementById(this.stack[message].sender).innerHTML = unescape( GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.title );
                                                    break;
                                                case 'printSummary':
                                                    var summary = GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.summary;
                                                    if (!!summary) {
                                                        summary = unescape( summary );
                                                    } else {
                                                        summary = "";
                                                    }
                                                    document.getElementById(this.stack[message].sender).innerHTML = summary;
                                                    break;
                                                case 'printPubdate':
                                                    document.getElementById(this.stack[message].sender).innerHTML = GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.cataloged_at.slice(0,10);
                                                    break;
                                                case 'loadThumbnail':
                                                    var sender = document.getElementById(this.stack[message].sender);
                                                    sender.src = GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.thumbnail_url;
                                                    sender.alt = GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.title;
                                                    break;
                                                case 'loadPreviewImage':
                                                    var
                                                        sender = document.getElementById(this.stack[message].sender),
                                                        xCache = String(new Date().getTime());
                                                        
                                                    sender.src = GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.preview_url + '?xCache=' + xCache;
                                                    sender.alt = GRAB.mediaos.core.registry.components.players[0]._states.asset.metadata.title;
                                                    break;
                                                default: 
                                                    try {
                                                        this.stack[message].command();
                                                    } catch ( error ) {
                                                        //console.log( 'An Error occurred ', error );
                                                    };
                                                    break;
                                            }
                                        }
                                    }
                                    break;
                                case 'onVideoPlay':
                                    for (var message in this.stack){
                                        if (this.stack[message].action === action) {
                                            switch(this.stack[message].command) {
                                                default:
                                                    try {
                                                        this.stack[message].command();
                                                    } catch ( error ) {
                                                        //console.log( 'An Error occurred ', error );
                                                    };
                                                    break;
                                            }
                                        }
                                    }
                                    break;
                                case 'onVideoPause':
                                    for (var message in this.stack){
                                        if (this.stack[message].action === action) {
                                            switch(this.stack[message].command) {
                                                default:
                                                    try {
                                                        this.stack[message].command();
                                                    } catch ( error ) {
                                                        //console.log( 'An Error occurred ', error );
                                                    };
                                                    break;
                                            }
                                        }
                                    }
                                    break;
                                case 'onVideoPlaybackComplete':
                                    for (var message in this.stack){
                                        if (this.stack[message].action === action) {
                                            switch(this.stack[message].command) {
                                                default:
                                                    try {
                                                        this.stack[message].command();
                                                    } catch ( error ) {
                                                        //console.log( 'An Error occurred ', error );
                                                    };
                                                    break;
                                            }
                                        }
                                    }
                                    break;
                                case 'onPrerollAdBegin':
                                    for (var message in this.stack){
                                        if (this.stack[message].action === action) {
                                            switch(this.stack[message].command) {
                                                default:
                                                    try {
                                                        this.stack[message].command();
                                                    } catch ( error ) {
                                                        //console.log( 'An Error occurred ', error );
                                                    };
                                                    break;
                                            }
                                        }
                                    }
                                    break;
                                case 'onPrerollAdComplete':
                                    for (var message in this.stack){
                                        if (this.stack[message].action === action) {
                                            switch(this.stack[message].command) {
                                                default:
                                                    try {
                                                        this.stack[message].command();
                                                    } catch ( error ) {
                                                        //console.log( 'An Error occurred ', error );
                                                    };
                                                    break;
                                            }
                                        }
                                    }
                                    break;
                                case 'onListLoadComplete':
                                    for (var message in this.stack){
                                        if (this.stack[message].action === action) {
                                            switch(this.stack[message].command) {
                                                case 'printKeywords':
                                                    var 
                                                        _component = {"_type":"list", "name":this.stack[message].id},
                                                        registeredList = GRAB.mediaos.core.registry.utils.findInRegistry( _component );
                                                    
                                                    document.getElementById(this.stack[message].sender).innerHTML = unescape(registeredList._states.keywords);
                                                    break;
                                                case 'printPlaylistName':
                                                    var _component = {"_type":"list", "name":this.stack[message].id};
                                                    var registeredList = GRAB.mediaos.core.registry.utils.findInRegistry( _component );
                                                    try {
                                                        document.getElementById(this.stack[message].sender).innerHTML = unescape( registeredList.children[0].children[0]._metadata.playlist_name );
                                                    } catch (e) {}
                                                    break;
                                                default:
                                                    try {
                                                        this.stack[message].command();
                                                    } catch ( error ) {
                                                        //console.log( 'An Error occurred ', error );
                                                    };
                                                    break;
                                            }
                                        }
                                    }
                                    break;
                                default:
                                    //console.log('couldn\'t match the action event type: ', action); 
                                    break;
                            };
                            
                            return;
                },
                        stack:[]
                    }
                },
                components: {
                    players: [],
                    lists: [],
                    search: [],
                    metadata: [],
                    channelLists: []
                },
                manage: {
                    states: function( _player, _traits ){
                        var
                          stateCount = _traits.states.length;
                        
                        for (var n = 0; n < stateCount; n++) {
                            if ( !_player._states ) {
                                _player['_states'] = {};
                            }
                            _player._states[_traits.states[n].name] = _traits.states[n].value;
                        };
                        return;
                    }
                }
            },
            ui: {
                utils: {
                    string: {
                        humanizeSeconds: function(_secs) {
                            if ( _secs >= 1 ) {
                                var 
                                    minutes = Math.floor( _secs / 60 ), // floor the value so that we can work with the whole numbers.
                                    remainder_seconds = String( _secs % 60 ).split('.')[0]; // the remainder from each minute unit. Only work with the whole numbers.
                                
                                // Take the values and find out how many digits ( chars ) we can work with or need to append...
                                var isSingleChar = function( _str ) {
                                    var val = String( _str ).split('.')[0];
                                    val = ( val.length > 1 ) ? false : true;
                                    return val;
                                }
                                
                                // Whenever we are working with a single char value we want to append a leading '0'
                                var whole_minutes = ( isSingleChar( minutes ) ) ? '0'+minutes : minutes;
                                var whole_seconds = ( isSingleChar( remainder_seconds ) ) ? '0'+remainder_seconds : remainder_seconds;
                                return whole_minutes+ ':' +whole_seconds;
                            } 
                            return "00:00";
                        }
                    },
                    viewport: {
                        rectangle: {
                            relative: function( _el ) {
                                var    
                                   target = _el, 
                                   target_width = target.offsetWidth, 
                                   target_height = target.offsetHeight,
                                   target_left = target.offsetLeft,
                                   target_top = target.offsetTop,
                                   gleft = 0, 
                                   gtop = 0,
                                   rect = {};
                                  
                                var moonwalk = function( _parent ) {
                                    if (!!_parent) {
                                        gleft += _parent.offsetLeft;
                                        gtop += _parent.offsetTop;
                                        moonwalk( _parent.offsetParent );
                                    } else {
                                        rect = { 
                                             top: target.offsetTop + gtop, 
                                             left: target.offsetLeft + gleft, 
                                             bottom: (target.offsetTop + gtop) + target_height, 
                                             right: (target.offsetLeft + gleft) + target_width 
                                        };
                                        return rect; 
                                    }
                                };
                                moonwalk( target.offsetParent );
                                return rect;
                            }
                        }
                    }
                },
                events: {
                    flashExternal: function(_args){
                        var
                            domId = _args.id,
                            _component = {"_type":"player", "name":domId},
                            registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component);
                        
                        switch (_args.event) {
                            case 'PlayerSWFReady':
                                //_category_ , _action_, _label_, _value_, __customVar1Name__, __customVar1Value__
                                GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'Ready', 'SWF', 1, 'externalEvent', 'SWFReady');
                                this._playerLoaded( registeredPlayer );
                                break;

                            case 'ContentLoaded':
                                GRAB.mediaos.core.registry.queue.message.process('onVideoLoadComplete');
                                GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'ContentLoaded', 'VIDEO', 1, 'externalEvent', 'ContentLoaded');
                                if ( GRAB.mediaos.core.ui.component.player.autoStart ) {
                                    GRAB.mediaos.core.ui.component.player.play.call( registeredPlayer );
                                }
                                break;
                                
                            case 'ContentError':
                                GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'ContentError', 'VIDEO', 1, 'externalEvent', 'ContentError');
                                break;
                            
                            case 'ContentMetadataLoaded':
                                this._contentMetaData(_args.id);
                                GRAB.mediaos.core.registry.queue.message.process('onVideoMetadataLoaded');
                                break;
                                
                            case 'PreRollPlaybackStarted':
                                
                                //[begin refactor] The creation of the ad object should be done elsewhere ... need to revisit this when the 
                                // core.js is made aware of when ads are returned to the player rather than just by the playback event.
                                var advertisement = {
                                    'type': 'inline', 
                                    'event': 'preroll',
                                    'playing': true
                                };
                                //[end refactor]
                                
                                var advertising = registeredPlayer["_states"].advertising;
                                var hasAds = !!( advertising.ads && (advertising.ads.length > 0) );
                                if (!hasAds) {
                                    advertising['ads'] = [];
                                    advertising.ads.push(advertisement);
                                } else {
                                    var adCount = advertising.ads.length;
                                    for ( var n=0; n<adCount; n++) {
                                        if ( advertising.ads[n].event == 'preroll' ) advertising.ads[n].playing = true;
                                    }
                                }
                                
                                //GRAB.mediaos.core.ui.component.player.controls.hide( registeredPlayer.id  );
                                GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'PreRollPlaybackStarted', 'Advert', 1, 'externalEvent', 'PreRollPlaybackStarted');
                                GRAB.mediaos.core.registry.queue.message.process('onPrerollAdBegin');
                                break;

                            case 'PreRollPlaybackEnded':
                                var advertising = registeredPlayer["_states"].advertising;
                                var hasAds = !!( advertising.ads && (advertising.ads.length > 0) );
                                
                                if ( hasAds ) {
                                    var adCount = advertising.ads.length;
                                    for ( var n=0; n<adCount; n++) {
                                        if ( advertising.ads[n].event == 'preroll' ) {
                                            var existingPrerollAd = advertising.ads[n];
                                            existingPrerollAd['playing'] = false;
                                            break;
                                        }
                                    }
                                }
                            
                                //GRAB.mediaos.core.ui.component.player.controls.show( registeredPlayer.id  );
                                GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'PreRollPlaybackEnded', 'Advert', 1, 'externalEvent', 'PreRollPlaybackEnded');
                                this._advertisementComplete(_args.id);
                                GRAB.mediaos.core.registry.queue.message.process('onPrerollAdComplete');
                                break;

                            case 'VideoKeyFrameUpdate':
                                this._updateTime(_args.id, _args.value);
                                GRAB.mediaos.core.registry.queue.message.process('onClockTick');
                                break;
                                
                            case 'VideoPlaybackEnded':
                                GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'VideoPlaybackEnded', 'VIDEO', 1, 'externalEvent', 'VideoPlaybackEnded');
                                this._videoComplete(_args.id);
                                GRAB.mediaos.core.registry.queue.message.process('onVideoPlaybackComplete');
                                break;
                                
                            case 'VideoPlaybackStarted':
                                // z = r
                                var
                                    _component = {"_type":"player", "name":domId},
                                    registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                                    eventLabel = registeredPlayer._states.asset.metadata.title + ' ['+ registeredPlayer._states.asset.metadata.master_id +']',
                                    grabPlayerTimePosition = registeredPlayer._states.timePosition,
                                    playBtn = registeredPlayer.nextSibling.childNodes[4],
                                    grabAssetClass = registeredPlayer._states.asset.metadata.classification_name;
                                
                                GRAB.mediaos.core.registry.queue.message.process('onVideoPlay');                    
                                
                                if ( registeredPlayer._states.autoplay ) {
                                    GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'VideoPlaybackStarted', eventLabel, grabPlayerTimePosition, 'externalEvent', 'VideoPlaybackStarted via Autoplay');
                                } else {
                                    GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'VideoPlaybackStarted', eventLabel, grabPlayerTimePosition, 'externalEvent', 'VideoPlaybackStarted');
                                }

                                registeredPlayer._states.isPaused = false;
                                registeredPlayer._states.isPlaying = true;
                                
                                playBtn.onmouseup = function() {
                                    GRAB.mediaos.core.ui.component.player.pause.call( registeredPlayer );
                                };
                                
                                playBtn.className = 'pauseBtn';
                                playBtn.setAttribute( 'class', 'pauseBtn' );
                                break;
                                
                            case 'VideoPlaybackPaused':
                                GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'VideoPlaybackPaused', 'VIDEO', 1, 'externalEvent', 'VideoPlaybackPaused');
                                GRAB.mediaos.core.registry.queue.message.process('onVideoPause');
                                break;
                            default:
                                //console.log('no matching event handler found for: '+_args.event);
                                break;
                        }
                    },
                    _playerLoaded: function( registeredPlayer ){
                        var
                            assetData = null,
                            _player = GRAB.mediaos.core.registry.queue.players.shift();
                            
                        switch( registeredPlayer._type._engine ) {
                            case 'gmos':
                                assetData = registeredPlayer._states.assetId;
                                break;
                            case 'osmf':
                                assetData = registeredPlayer._states.guid;
                                //registeredPlayer.loadPreviewImage( registeredPlayer._states.asset.metadata.preview_url );
                                break;
                            default:
                                //console.log('Cannot match engine type: '+registeredPlayer._states._engine);
                                break;
                        }   
                        GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'LOADING', 'VIDEO', 1, 'sender', '_playerLoaded');                            
                        
                        if ( _player._states['loadByDefault'] ) {
                            if ( _player._states.advertising.variables.static) {
                                var supplement_var = ",'vid':'"+ _player._states.asset.metadata.id +"'";
                                _player._states.advertising.variables['dynamic'] = _player._states.advertising.variables.static.substring(0, _player._states.advertising.variables.static.lastIndexOf( '}' ) ) + supplement_var + '}';
                            }
                            _player.loadNewVideo( assetData, _player._states.advertising.variables.dynamic );
                        }

                        _player._states['loaded'] = true;

                        // fire playerloaded reactor
                        GRAB.mediaos.core.registry.queue.message.process('onPlayerLoadComplete');
                        
                        return;
                    },
                    _contentMetaData: function(_playerId) {
                        var
                            _component = {"_type":"player", "name":_playerId},
                            registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                            duration = String(registeredPlayer.videoTotalTime()),
                            scrubber = registeredPlayer.nextSibling.childNodes[1].childNodes[0],
                            sourcelogo = registeredPlayer.parentNode.lastChild;
                        
                        registeredPlayer._states.duration = duration;
                        registeredPlayer._states.providerURL = registeredPlayer.videoSourceURL();
                        registeredPlayer.setVolume( 100 );
                        
                        registeredPlayer.nextSibling.childNodes[0].innerHTML = GRAB.mediaos.core.ui.utils.string.humanizeSeconds(duration);
                        
                        sourcelogo.src = registeredPlayer.videoSourceLogo();
                        sourcelogo.onclick = function(e) {
                            window.open( registeredPlayer._states.providerURL );
                        };
                        return;
                    },
                    
                    // This method is called every time an update message is dispatched from the Video player (SWF in this case)
                    // tread lightly with what gets called/processed here since the interval is frequent +/-20ms.
                    _updateTime: function( _playerId, _secs ) {
                        var
                                _component = {"_type":"player", "name":_playerId},
                                registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                                seekScrub = registeredPlayer.nextSibling.childNodes[2],
                                playbackTimeLbl = registeredPlayer.nextSibling.childNodes[6];

                        // *note* the 'isPlaying' state is set ahead of this event...        
                        // the update incrementer does not already exist,
                        // is the video is currently in the play state,
                        // and the duration is valid...
                        // then go ahead and start a new update interval.
                        if ( !registeredPlayer._states.incrementer && registeredPlayer._states.isPlaying && ( registeredPlayer._states.duration > 0 ) ) {
                                var
                                    distance = registeredPlayer.nextSibling.childNodes[1].offsetWidth,
                                    ms = registeredPlayer._states.duration * 1000,
                                    frequency = Math.floor(ms / distance);
  
                                registeredPlayer._states.incrementer = setInterval( function() {
                                    GRAB.mediaos.core.ui.component.player.controls.seek.increment( seekScrub, registeredPlayer )    
                                }, frequency );
                        }
                        // this is here as a precaution to prevent any further updates from creeping into our state once a video is 
                        // finished playing, paused, buffered, etc.
                        if ( !!registeredPlayer._states.incrementer ) {
                            playbackTimeLbl.innerHTML = GRAB.mediaos.core.ui.utils.string.humanizeSeconds( _secs );
                        }
                        
                        registeredPlayer._states.timePosition = parseInt( _secs );
                    },
                    _videoComplete: function(_playerId){
                        var
                            _component = {"_type":"player", "name":_playerId},
                            registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component);
                        
                        // destroy any interval for the seek update that may exist
                        clearInterval( registeredPlayer._states.incrementer );
                        registeredPlayer._states.incrementer = null;
                        
                        // re-initialize the control states
                        GRAB.mediaos.core.ui.component.player.controls.play.init( registeredPlayer );
                        GRAB.mediaos.core.ui.component.player.controls.seek.scrub.init( registeredPlayer );
                    },
                    
                    _advertisementComplete: function( _playerId ){
                        var
                            _component = {"_type":"player", "name":_playerId},
                            registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component);
                        
                        // destroy any interval for the seek update that may exist
                        clearInterval( registeredPlayer._states.incrementer );
                        registeredPlayer._states.incrementer = null;
                        
                        // re-initialize the control states
                        GRAB.mediaos.core.ui.component.player.controls.play.init( registeredPlayer );
                        GRAB.mediaos.core.ui.component.player.controls.seek.scrub.init( registeredPlayer );
                    }
                },
                component: {
                    reactor:{
                        register: function(){
                            // place item in the message queue stack.
                            this['_type'] = {'_class':'message'};
                            switch(this.type) {
                                case 'player':
                                    GRAB.mediaos.core.registry.utils.queue(this);
                                    break;
                                case 'list':
                                    GRAB.mediaos.core.registry.utils.queue(this);
                                    break;
                                default: 
                                    break;
                            }
                            return;
                        }
                    },
                    // must be called with context
                    move: function() {
                        var 
                            el = this,
                            INTERVAL_MS = 1,
                            steps = 0;

                        if ( this._states.motion_timer !== null ) {
                            clearInterval( this._states.motion_timer );
                            this._states.motion_timer = null;
                        }
                        
                        this._states.motion_x = ( this._states.destination_x ) ? true : false;
                        this._states.motion_y = ( this._states.destination_y ) ? true : false;
                        
                        this._states.start_y = el.offsetTop;
                        this._states.start_x = el.offsetLeft;
                        
                        // check both style properties (top and left) to see if they have 
                        // not been defined in the CSS; which means we need to initialize them.
                        if ( this._states.motion_x ) {
                            if ( isNaN(parseInt( this.style.left )) ) {
                                this.style.left = this._states.start_x+'px';                                            
                            }
                        }
                        
                        if ( this._states.motion_y ) {
                            if ( isNaN(parseInt( this.style.top )) ) {
                                this.style.top = this._states.start_y+'px';                                            
                            }    
                        }
                        
                        // calculate the direction of the movement
                        if ( this._states.start_y < this._states.destination_y ) {
                            this._states.motion_direction = 'down';    
                        } else if ( this._states.start_y > this._states.destination_y ) {
                            this._states.motion_direction = 'up';     
                        } else if ( this._states.start_x < this._states.destination_x ) {
                            this._states.motion_direction = 'right';
                        } else if ( this._states.start_x > this._states.destination_x ) {
                            this._states.motion_direction = 'left';
                        }
                        
                        var cleanupStates = function() {
                            //console.log( 'finished with running time in ms = '+(this._states.motion_currenttick_ms - this._states.motion_epoch_ms) );
                            if (this._states) {
                                clearInterval( this._states.motion_timer );  
                                this._states.motion_x = false;
                                   this._states.motion_y = false;
                                this._states.destination_x = null;
                                this._states.destination_y = null;
                                this._states.motion_timespan = null;
                                this._states.motion_timer = null;
                                this._states.motion_direction = '';
                                this._states.motion_epoch_ms = null;
                                this._states.motion_currenttick_ms = null;
                            }
                        };
                        
                        var updatePosition = function( rate_x, rate_y ) {
                            switch( el._states.motion_direction ) {
                                case 'up':
                                    if ( (el.offsetTop - rate_y) >= el._states.destination_y ) {
                                        // TODO: need to get computed style here in case the style is not specified
                                        el.style.top = ( parseFloat(el.style.top) - rate_y )+'px';    
                                    } else {
                                        el.style.top = el._states.destination_y+'px';
                                        cleanupStates.call( el );
                                    }
                                    break;
                                case 'down':
                                    if ( (el.offsetTop + rate_y) <= el._states.destination_y ) {
                                        // TODO: need to get computed style here in case the style is not specified
                                        el.style.top = ( parseFloat(el.style.top) + rate_y )+'px';    
                                    } else {
                                        el.style.top = el._states.destination_y+'px';
                                        cleanupStates.call( el );
                                    }
                                    break;
                                case 'left':
                                    if ( (el.offsetLeft - rate_x) >= el._states.destination_x ) {
                                        // TODO: need to get computed style here in case the style is not specified
                                        //this.style.left = ( parseFloat(this.style.left) - rate_x )+'px';    
                                    } else {
                                        //this.style.left = this._states.destination_x+'px';
                                        cleanupStates.call( this );
                                    }
                                    break;
                                case 'right':
                                    if ( (el.offsetLeft + rate_x) <= el._states.destination_x ) {
                                        // TODO: need to get computed style here in case the style is not specified
                                        el.style.left = ( parseFloat(el.style.left) - rate_x )+'px';    
                                    } else {
                                        el.style.left = el._states.destination_x+'px';
                                        cleanupStates.call( el );
                                    }
                                    break;
                            }
                        };
                        
                        this._states.motion_timer = setInterval( function() {
                            var
                                elapsed_tick_ms = 0,
                                offset_ms = 1,
                                distanceX = ( el._states.destination_x - el._states.start_x ),
                                distanceY = ( el._states.destination_y - el._states.start_y );

                            // check if we just started the timer loop to initialize the timer values
                            if ( el._states.motion_epoch_ms == null ) {
                                el._states.motion_epoch_ms = new Date().getTime();
                                el._states.motion_currenttick_ms = el._states.motion_epoch_ms;
                            } else {
                                var now = new Date().getTime();
                                elapsed_tick_ms = now - el._states.motion_currenttick_ms;
                                el._states.motion_currenttick_ms = new Date().getTime();
                            }
                            
                            if ( elapsed_tick_ms > INTERVAL_MS ) {
                                offset_ms = elapsed_tick_ms - INTERVAL_MS;
                            }
                            
                            var rate_y = Math.abs(( distanceY / el._states.motion_timespan ) * ( offset_ms + 1 ));
                            var rate_x = Math.abs(( distanceX / el._states.motion_timespan ) * ( offset_ms + 1 )); 
                           
                            updatePosition( rate_x, rate_y );
                        }, INTERVAL_MS );
                    },
                    
                    // must be called with context
                    fade: function() {
                        var 
                            el = this,
                            INTERVAL_MS = 1,
                            steps = 0;
                        
                        if ( this._states.alpha_timer !== null ) {
                            clearInterval( this._states.alpha_timer );
                            this._states.alpha_timer = null;
                        }
                        
                        this._states.alpha_start = parseFloat( GRAB.mediaos.core.registry.utils.minidom.getStyle( el, 'opacity' ) );
                        
                        // Check which direction we are going (up/down)
                        if ( this._states.alpha_destination > this._states.alpha_start ) {
                            this._states.alpha_direction = 'up';    
                        } else if ( this._states.alpha_destination < this._states.alpha_start ) {
                            this._states.alpha_direction = 'down';
                        }
                        
                        var cleanupStates = function() {
                            //console.log( 'finished with running time in ms = '+(this._states.motion_currenttick_ms - this._states.motion_epoch_ms) );
                            clearInterval( this._states.alpha_timer );  
                            this._states.alpha_start = null;
                            this._states.alpha_destination = null;
                            this._states.alpha_timespan = null;
                            this._states.alpha_timer = null;
                            this._states.alpha_direction = '';
                            this._states.motion_currenttick_ms = null;
                            this._states.motion_epoch_ms = null;
                        };
                        
                        var updateAlpha = function( rate ) {
                            switch( el._states.alpha_direction ) {
                                case 'up':
                                    if ( (el.style.opacity + rate ) <= el._states.alpha_destination ) {
                                        el.style.opacity = ( parseFloat(el.style.opacity) + rate );
                                    } else {
                                        el.style.opacity = el._states.alpha_destination;
                                        cleanupStates.call( el );
                                    }                              
                                    break;
                                case 'down':
                                    if ( (el.style.opacity - rate ) >= el._states.alpha_destination ) {
                                        el.style.opacity = ( parseFloat(el.style.opacity) - rate );
                                    } else {
                                        el.style.opacity = el._states.alpha_destination;
                                        cleanupStates.call( el );
                                    }
                                    break;
                            }
                        };
                        
                        this._states.alpha_timer = setInterval( function() {
                            var
                                elapsed_tick_ms = 0,
                                offset_ms = 1,
                                distance = ( el._states.alpha_destination - el._states.alpha_start );

                            // check if we just started the timer loop to initialize the timer values
                            if ( el._states.motion_epoch_ms == null ) {
                                el._states.motion_epoch_ms = new Date().getTime();
                                el._states.motion_currenttick_ms = el._states.motion_epoch_ms;
                            } else {
                                var now = new Date().getTime();
                                elapsed_tick_ms = now - el._states.motion_currenttick_ms;
                                el._states.motion_currenttick_ms = new Date().getTime();
                            }
                            
                            if ( elapsed_tick_ms > INTERVAL_MS ) {
                                offset_ms = elapsed_tick_ms - INTERVAL_MS;
                            }
                            
                            var rate = Math.abs(( distance / el._states.alpha_timespan ) * ( offset_ms + 1 ));
                            updateAlpha( rate );
                        }, INTERVAL_MS );
                    },
                    
                    community:{
                        twitter: {
                            tweet: function(){
                                
                            }
                        }
                    },
                    
                    metadata:{
                        init: function(targetId){
                            var
                                targetElement = GRAB.mediaos.core.registry.utils.minidom.find(targetId);
                                
                            this["_type"] = {
                                "_class": "metadata"
                            };
                            this["_states"] = {
                                "targetElementId": targetId
                            };
                                
                            targetElement.appendChild(this);
                            
                            GRAB.mediaos.core.registry.utils.register(this);
                            
                            return;
                        },
                        display: function(){
                            return;
                        }
                    },
                    list: {
                        reactor:{
                            register: function( _sender, _action, _command, _componentId ){
                                this['type'] = 'list';
                                this['sender'] = _sender;
                                this['action'] = _action;
                                this['command'] = _command;
                                this['id'] = _componentId;
                                return GRAB.mediaos.core.ui.component.reactor.register.call(this);
                            }
                        },
                        
                        load: function( _videoObjects, _keywords ){
                            var
                                videoObjects = undefined;
                                
                            try {
                                videoObjects = eval( "(" + unescape(_videoObjects) + ")" );
                            } catch( e ) {
                                videoObjects = _videoObjects;
                            }   
                            
                            var 
                                targetPlayerId = this._states.targetPlayerId,
                                list = GRAB.mediaos.core.registry.utils.minidom.removeChildNodes.call(this),
                                videoLength = videoObjects.length;
                           
                            var traits = {
                                states: [
                                    {
                                        name: 'keywords',
                                        value: _keywords
                                    } 
                                ]
                            }
                                          
                            GRAB.mediaos.core.registry.manage.states( this, traits );

                            for ( var n=0; n < videoLength; n++ ){
                                var
                                    videoAsset = videoObjects[n].video,
                                    filmstrip_uri = videoAsset["master_filmstrip_uri"],
                                    frame_urls = [],
                                    filename_digitCount = 5;
                                    
                                // take the filmstrip uri and construct urls for the image locations
                                if ( filmstrip_uri ) {
                                    for ( var x=1; x<11; x++ ) {
                                        var 
                                            charLen = String(x).length,
                                            leading_zeros = '',
                                            filename = '';
                                            
                                        for ( var i=charLen; i<filename_digitCount; i++ ) {
                                            leading_zeros += '0'; 
                                        }
                                        filename = leading_zeros+ x +'.jpg'; 
                                        frame_urls.push(filmstrip_uri + filename);
                                    }
                                }
                                videoAsset["frame_urls"] = frame_urls;
                                GRAB.mediaos.core.ui.component.list.asset.render( this, videoAsset, targetPlayerId );
                            }
                            GRAB.mediaos.core.registry.utils.register(this);
                            GRAB.mediaos.core.registry.queue.message.process('onListLoadComplete');
                            return;
                        },
                        
                        draw: function( _videoObjects, _target, _targetPlayerId, _itemCount, _showTitles, _showDurations, _showSummaries, _keywords, _id, targetWindow ){

                            var
                                _target = document.getElementById(_target);
                               
                            this["id"] = _id;
                            this["name"] = _id;

                            this["_type"] = {
                                "_class": "list"
                            };
                            this["_states"] = {
                                "itemCount": _itemCount,
                                "showTitles": _showTitles,
                                "showDurations": _showDurations,
				"showSummaries": _showSummaries,
                                "targetPlayerId": _targetPlayerId,
                                "target": _id,
                                "selectedItem": undefined
                            };
                            
                            _target.appendChild(this);
                            GRAB.mediaos.core.ui.component.list.load.call(this, _videoObjects, _keywords);
                            GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'RENDER', 'LIST', 1, 'sender', 'draw');
                        },
                        asset: {
                            render: function( _list, _data, _targetId ) {
                                var 
                                    videoTitle = escape(_data.title),
                                    videoThumbnailUrl = '',
                                    listItem = document.createElement('div'),
                                    listImage = document.createElement('img'),
                                    listTitle = document.createElement('div'),
                                    listItemSummary = document.createElement( 'div' ),
                                    listItemPubDate = document.createElement( 'div' ),
                                    listProviderIcon = document.createElement('img'),
                                    videoDuration = document.createElement('div'),
                                    targetPlayer = GRAB.mediaos.core.registry.utils.minidom.find( _targetId ),
                                    targetPlayerExists = (targetPlayer && targetPlayer._type._class == 'player'),
                                    item_intervalId,
                                    item_frameIndex = 0;
                                   
                                 /*** Begin custom, demo processing code. ***/
                                 var __listItemTitle__ = unescape( videoTitle );
                                 
                                 /* Begin Finding the thumbnail media asset in the list */
                                 var len = _data.media_assets.length;
                                 for ( var n=0; n<len; n++ ) {
                                     if ( _data.media_assets[n].name.toLowerCase() == 'preview' ) {
                                         videoThumbnailUrl = _data.media_assets[n].url;
                                         break;
                                     } 
                                 }
                                 /* End Finding the thumbnail media asset in the list */
                                 
                                 try {
                                     var
                                        __listItemTitleObject__ = eval(  "(" + __listItemTitle__ + ")"  );
                                        
                                     videoTitle = escape( __listItemTitleObject__.title );
                                     
                                     _data.title = videoTitle;
                                     _data['description'] = __listItemTitleObject__.spec;
                                 } catch (e) {
                                     _data['description'] = '';
                                 };
                                 /*** End custom, demo processing code. ***/
                                 listItem.className = 'list-item';
                                 listItem["_states"] = {};
                                 listItem._states["selected"] = false;
                                 listItem.setAttribute('class','list-item');
                                 _list.appendChild( listItem );
                                 listItem.style.cursor = 'pointer';
                                 
                                 listItem.onclick = function( _targetPlayerExists, _targetId, _videoAsset, _listComponent ) {
                                        return function( e ) {
                                            if ( _listComponent["_states"].selectedItem ) {
                                                _listComponent["_states"].selectedItem.className = 'list-item';
                                                _listComponent["_states"].selectedItem._states.selected = false;
                                            }
        
                                            this.className = this.className.replace( 'list-item', 'list-item selected' );
                                            _listComponent["_states"].selectedItem = this;
                                    
                                            this["_states"]["selected"] = true;
                                            
                                            var player = targetPlayer;
                                            if (!e) 
                                                var e = window.event;
                                            if ( !_targetPlayerExists ) {
                                                player = document.getElementById( _targetId );
                                            }
                                            
                                            GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'ListItemSelect', 'LIST', 1, _videoAsset, 'ListItemSelect');

                                            player._states.duration = _data.duration;
                                            if ( !_videoAsset.contentSource || _videoAsset.contentSource == 'grab networks'){
                                                GRAB.mediaos.core.ui.component.player.init( player );
                                                GRAB.mediaos.core.ui.component.player.video.load.call( player, _videoAsset );
                                            }else{
                                                var thePlayerElement = document.getElementById('grab_dev_player');
                                                
                                                thePlayerElement.innerHTML = '';
                                                thePlayerElement.innerHTML = '\
                                                    <object width="785" height="442">\
                                                    <param name="movie" value="'+ _videoAsset.url +'"></param>\
                                                    <embed src="'+ _videoAsset.url +'"\
                                                    type="application/x-shockwave-flash" width="785" height="442">\
                                                  </embed>\
                                                </object>';
                                            }
                                        };
                                 }( targetPlayerExists, _targetId, _data, _list );
                                 
                                 listItem.onmousedown = function() {
                                    if ( _list["_states"].selectedItem ) {
                                        _list["_states"].selectedItem.className = 'list-item';
                                        _list["_states"].selectedItem._states.selected = false;
                                    }

                                    this.className = this.className.replace( 'list-item', 'list-item selected' );
                                    _list["_states"].selectedItem = this;
                                    this._states.selected = true;
                                            
                                    GRAB.mediaos.core.ui.component.player.autoStart = true;
                                 };
                                 
                                 if ( _data["frame_urls"].length > 0 ) {
                                     listImage.onmouseover = function(e) {
                                        item_intervalId = item_intervalId || setInterval( this.animate, 200 );
                                     };
                                     
                                     listImage.onmouseout = function(e) {
                                        clearInterval( item_intervalId );
                                        item_intervalId = null;
                                        listImage.src = videoThumbnailUrl;
                                     };
                                     
                                     listImage.animate = function() {
                                         item_frameIndex = ( _data["frame_urls"][item_frameIndex] ) ? item_frameIndex : 0;
                                         listImage.src = _data["frame_urls"][item_frameIndex];
                                         ++item_frameIndex;
                                     };
                                 }
                                 
                                 videoTitle = ( unescape(videoTitle) == 'undefined' ) ? 'Title not available' : unescape(videoTitle);
                                 
                                 listImage.src = videoThumbnailUrl;
                                 listImage.width = 92;
                                 listImage.height = 69;
                                 listImage.alt = videoTitle;
                                 listImage.title = videoTitle;
                                 listImage._metadata = _data;
                                 listItem.appendChild( listImage );
                                 
                                 listProviderIcon.className = "list-provider-icon";
                                 listProviderIcon.title = _data.provider_name; 
                                 listProviderIcon.src = _data.provider.small_logo;
                                 listItem.appendChild( listProviderIcon );
                                 
                                 if ( _list["_states"].showTitles == 'true' ) {
                                     listTitle.className = 'list-item-title';
                                    listTitle.setAttribute( 'class', 'list-item-title' );
                                    listTitle.title = videoTitle;
                                    listTitle.innerHTML = '<span class="listItemTitleText">'+videoTitle+'</span><div class="listItemTitleBackground"></div>';                                    
                                    listItem.appendChild( listTitle );    
                                 };
                                 
                                 if ( _list["_states"].showDurations == 'true' ) {
                                     videoDuration.className = 'list-video-duration';
                                    videoDuration.setAttribute('class','list-video-duration');
                                    videoDuration.innerHTML = GRAB.mediaos.core.ui.utils.string.humanizeSeconds( ( _data.duration / 1000 ) );
                                    listItem.appendChild( videoDuration );                                     
                                 };
                                 
                                 var summary = _data.summary;
                                 if (!!summary) {
                                     summary = unescape( summary );
                                 } else {
                                     summary = "";
                                 }
			
				 if ( _list["_states"].showSummaries && _list["_states"].showSummaries == 'true' ) {
                                	 listItemSummary.style.display = 'block';
                                 }else{
                                	 listItemSummary.style.display = 'none';
                                 }
                                                    
                                 listItemSummary.className = 'list-item-summary';
                                 listItemSummary.innerHTML = summary;
                                 listItem.appendChild( listItemSummary );  
                                 
                                 // TODO: this needs to be parameterized at some point
                                 listItemPubDate.style.display = 'none';
                                 listItemPubDate.className = 'list-item-pubdate';
                                
                                 var longDate = _data.cataloged_at.slice(0,10);
                                 var shortDate = longDate.slice(5,7) + '/' + longDate.slice(8,10) + '/' + longDate.slice(2,4);
                                 listItemPubDate.innerHTML = shortDate;
                                 listItem.appendChild( listItemPubDate );   
                            }
                        },
                        
                        getAsset: function( _assetId ){
                            var assets = this.children;
                            var assetCount = assets.length;
                            
                            for ( var n=0; n<assetCount; n++ ){
                                try { var assetMeta = assets[n].children[0]._metadata } catch(error) {};
                                
                                if ( !!assetMeta ) {
                                    if (assetMeta.id == _assetId) {
                                        return {
                                            element: assets[n],
                                            meta: assetMeta
                                        };
                                    }
                                }
                            }
                            return undefined;
                        }
                    },
                    channel: {
                        draw: function( targetId, targetListId, channelList, initialPlaylistId, playlistBaseURL ){
                            var 
                                this_channelList = this,
                                playlistList = undefined,
                                channel_count = channelList.length,
                                target_element = document.getElementById( targetId ),
                                fragment = document.createDocumentFragment(),
                                channel_list_element = document.createElement( 'ul' ),
                                default_channel_element = undefined,
                                channelComponent = {};
                            
                            channelComponent["channels"] = channelList;
                            channelComponent["initial_channel"] = undefined;
                            channelComponent["initial_playlist"] = undefined;
                            channelComponent["current_channel"] = undefined;
                            channelComponent["current_playlist"] = undefined;
                            channelComponent["channelListDomPrefix"] = 'grab-channellist-element-';
                            channelComponent["playlistListDomPrefix"] = 'grab-channel';
                            channelComponent["name"] = targetId;
                            channelComponent["targetListId"] = targetListId;
                            channelComponent["playlistBaseURL"] = playlistBaseURL;
                            
                            channel_list_element.className = 'grab-channel-list';
                            
                            // reference an initial channel and initial playlist **(the references point to the top level object structures of the matched object (channel/playlist). We should consider refactoring these structures to make the OO and associations cleaner)
                            if ( initialPlaylistId ) {
                                for ( var i=0; i<channel_count; i++ ) {
                                    var playlist_count = channelComponent.channels[i].channel.channel_items.length;
                                    
                                    for ( var j=0; j<playlist_count; j++ ) {
                                        if ( channelComponent.channels[i].channel.channel_items[j].channel_item.playlist_id == initialPlaylistId ) {
                                            channelComponent["initial_channel"] = channelComponent.channels[i];
                                            channelComponent["initial_playlist"] = channelComponent.channels[i].channel.channel_items[j];
                                            break;
                                        }
                                    }
                                }
                            } else {
                                // just default to the first channel and first playlist in that channel
                                channelComponent["initial_channel"] = channelComponent.channels[0];
                                channelComponent["initial_playlist"] = channelComponent.channels[0].channel.channel_items[0];
                            }
                            
                            // render each channel element item and sub-components (ie: playlists)
                            for ( var n=0; n<channel_count; n++ ) {
                                var    
                                    channel_item_element = document.createElement( 'li' ),
                                    channel_item_heading = document.createElement( 'h4' );
                                    
                                channel_item_heading.innerHTML = channelComponent.channels[n].channel.name;
                                channel_item_element.appendChild( channel_item_heading );
                                channel_item_element.id = channelComponent["channelListDomPrefix"] + channelComponent.channels[n].channel.id;
                                
                                // UI Event handling 
                                (function() {
                                    var 
                                        this_channel = channelComponent.channels[n],
                                        this_channel_element = channel_item_element;
                                    
                                    var clickHandler = function(e) {
                                        // deselect any existing channels and don't do a select if its the currently selected channel
                                        if ( channelComponent["current_channel"] && ( channelComponent["current_channel"].channel.id !== this_channel.channel.id) ) {
                                            GRAB.mediaos.core.ui.component.channel.deselect( channelComponent, channelComponent["current_channel"] );
                                        };
                                        
                                        // Select the first Playlist in the Channel by default
                                        var playlist_element = document.getElementById( channelComponent['playlistListDomPrefix'] + '-' + this_channel.channel.id + '-playlist-' + this_channel.channel.channel_items[0].channel_item.playlist_id );
                                        GRAB.mediaos.core.ui.component.channel.select.call( this_channel_element, this_channel, channelComponent, playlistBaseURL, this_channel.channel.channel_items[0], playlist_element );
                                    };
                                    GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( channel_item_element, 'click', clickHandler );
                                })();
                                
                                GRAB.mediaos.core.ui.component.channel.playlist.draw( channel_item_element, channelComponent.channels[n], channelComponent, initialPlaylistId, playlistBaseURL );
                                
                                channel_list_element.appendChild( channel_item_element );
                            }
                            
                            fragment.appendChild( channel_list_element );
                            target_element.appendChild( fragment );
                            
                            // manage the registry and queue states
                            GRAB.mediaos.core.ui.component.channel.register( channelComponent );
                            GRAB.mediaos.core.registry.queue.channelLists.shift();
                            
                            // Select the initial Channel
                            // Select the initial Playlist within the Channel
                            var playlist_element = document.getElementById( channelComponent['playlistListDomPrefix'] + '-' + channelComponent["initial_channel"].channel.id + '-playlist-' + channelComponent["initial_playlist"].channel_item.playlist_id );
                            default_channel_element = document.getElementById( channelComponent['channelListDomPrefix']+ channelComponent["initial_channel"].channel.id );
                            GRAB.mediaos.core.ui.component.channel.select.call( default_channel_element, channelComponent["initial_channel"], channelComponent, playlistBaseURL, channelComponent["initial_playlist"], playlist_element );
                            
                            GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'RENDER', 'CHANNEL', 1, 'sender', 'draw');
                        },
                        
                        register: function( channelComponent ) {
                            channelComponent["_type"] = { "_class": "channelList" };
                            GRAB.mediaos.core.registry.utils.register( channelComponent );
                        },
                        
                        deselect: function( _channelComponent, _channel ) {
                            channelItem = document.getElementById( _channelComponent["channelListDomPrefix"]+_channel.channel.id );
                            
                            channelItem.className = channelItem.className.replace( 'selected', '' );
                            channelItem.children[1].className = channelItem.children[1].className.replace( 'selected', '' );
                            
                            if ( _channelComponent["current_playlist"] ) {
                                GRAB.mediaos.core.ui.component.channel.playlist.deselect( _channelComponent, _channelComponent["current_playlist"] );
                            }
                        },
                        
                        select: function( _channel, _channelComponent, _playlistBaseURL, _playlist, _playlistElement ) {
                            // only add the CSS classname if we are selecting a new channel   
                            if ( _channelComponent['current_channel'] == undefined ) {
                                this.className += ' selected';
                            } else if ( _channelComponent['current_channel'].channel.id !== _channel.channel.id ) {
                                this.className += ' selected';
                            }
                            
                            _channelComponent['current_channel'] = _channel;
                            
                            // only select a playlist if its the first time around  ~
                            // or its different than the current one
                            // or if we are selecting the same channel and the current Playlist is not the first one in the Channel
                            if ( _channelComponent['current_playlist'] == undefined ) {
                                GRAB.mediaos.core.ui.component.channel.playlist.select.call( _playlistElement, _playlist, _channelComponent, _playlistBaseURL );
                            } else if ( _playlist.channel_item.channel_id !== _channelComponent['current_playlist'].channel_item.channel_id ) {
                                GRAB.mediaos.core.ui.component.channel.playlist.select.call( _playlistElement, _playlist, _channelComponent, _playlistBaseURL );
                            } else if ( _playlist.channel_item.id != _channelComponent['current_playlist'].channel_item.id ) {
                                GRAB.mediaos.core.ui.component.channel.playlist.select.call( _playlistElement, _playlist, _channelComponent, _playlistBaseURL );                        
                            }
                        },
                        
                        playlist: {
                            draw: function( _channelElement, _channel, _channelComponent, _defaultPlaylistId, _playlistBaseURL) {
                                var
                                    playlist_list_element = document.createElement( 'ul' ),
                                    playlist_count = _channel.channel.channel_items.length,
                                    playlistList = _channel.channel.channel_items;
                                
                                // create the initial unordered list element to hold the channel items
                                playlist_list_element.className = 'grab-playlist-list';
                                
                                for ( var i=0; i<playlist_count; i++ ) {
                                    var 
                                        playlist_item_element = document.createElement( 'li' ),
                                        playlist_item_heading = document.createElement( 'h5' );
                                    
                                    playlist_item_element.id = _channelComponent['playlistListDomPrefix'] + '-' + _channel.channel.id + '-playlist-' + _channel.channel.channel_items[i].channel_item.playlist_id;
                                    playlist_item_element.appendChild( playlist_item_heading );
                                    playlist_item_heading.innerHTML = _channel.channel.channel_items[i].channel_item.playlist_name;
                                    playlist_list_element.appendChild( playlist_item_element );
                                   
                                    // (induced closure for preserving the iterator context)
                                    (function() {
                                        var 
                                            this_playlist = playlistList[i],
                                            this_playlist_element = playlist_item_element;
                                        
                                        var clickHandler = function( event ) {
                                            // prevent the bubbling so that the channel element won't receive the same click event    
                                            if ( !event ) var event = window.event;
                                            event.cancelBubble = true;
                                            if ( event.stopPropagation ) event.stopPropagation();
                                        
                                            // only select a playlist if its different from the initial one
                                            if ( _channelComponent["current_playlist"] && (_channelComponent["current_playlist"] !== this_playlist) ) {
                                                GRAB.mediaos.core.ui.component.channel.playlist.select.call( this_playlist_element, this_playlist, _channelComponent, _playlistBaseURL );
                                            }
                                        };
                                    
                                        GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( this_playlist_element, 'click', clickHandler );
                                    })();
                                }; 
                                
                                _channelElement.appendChild( playlist_list_element );
                            },
                            
                            deselect: function( _channelComponent, _playlist ) {
                                var playlistItem = document.getElementById( _channelComponent["playlistListDomPrefix"] + '-' + _channelComponent['current_channel'].channel.id + '-playlist-' + _playlist.channel_item.playlist_id );
                                if ( playlistItem ) {
                                    playlistItem.className = playlistItem.className.replace( 'selected', '' );
                                    playlistItem.parentNode.className = playlistItem.parentNode.className.replace( 'selected', '' );
                                }
                            },
                            
                            select: function( _playlist, _channelComponent, _playlistBaseURL ) {
                                var this_playlist = this;
                                
                                // Check for selected Playlists and deselect them
                                if ( _channelComponent["current_playlist"] ) {
                                    GRAB.mediaos.core.ui.component.channel.playlist.deselect( _channelComponent, _channelComponent["current_playlist"] );    
                                } 
                                
                                // first check to see if this Playlist is not in the "current channel"
                                if ( _channelComponent.current_channel && (_channelComponent.current_channel.channel.id !== _playlist.channel_item.channel_id) ) {
                                    GRAB.mediaos.core.ui.component.channel.deselect( _channelComponent, _channelComponent["current_channel"] );
                                    
                                    var channel_element = document.getElementById( _channelComponent["channelListDomPrefix"] + _playlist.channel_item.channel_id );
                                    var channel_count = _channelComponent.channels.length;
                                    for ( var n=0; n<channel_count; n++ ) {
                                        if ( _channelComponent.channels[n].channel.id == _playlist.channel_item.channel_id ) {
                                            GRAB.mediaos.core.ui.component.channel.select.call( channel_element, _channelComponent.channels[n], _channelComponent, _playlistBaseURL, _playlist, this );
                                            break;
                                        }
                                    }
                                    return;
                                } else {
                                    //console.log('>> this is a playlist IN the current channel...');
                                }
                                
                                try{
                                    this_playlist.className = ' selected';
                                    this_playlist.parentNode.className = ' selected';
                                } catch(e) {};
                                
                                // Request the new Playlist data
                                var loadSelectedPlaylist = function(_playlistBaseURL){
                                    var
                                        playlistScript = document.createElement('script'),
                                        targetList = document.getElementById('grab-vcl-list'),
                                        playlistId = _playlist.channel_item.playlist_id;
                                    
                                    playlistScript.type='text/javascript';
                                    playlistScript.src = _playlistBaseURL.replace('[PLAYLISTID]',playlistId);
                                    targetList.innerHTML = '';
                                    targetList.appendChild(playlistScript);
                                };
                                loadSelectedPlaylist(_playlistBaseURL);
                                
                                _channelComponent["current_playlist"] = _playlist;
                            }
                        }
                    },
                    search: {
                        draw: function(publicKey, sender, _targetId, limit){
                            var
                                searchComponent = this,
                                sender = document.getElementById(sender),
                                searchResultTargetId = _targetId,
                                _component = {"_type":"list", "name":_targetId},
                                registeredlistCount = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                                searchForm = document.createElement('form'),
                                searchLabel = document.createElement('label'),
                                searchValue = document.createElement('input'),
                                searchBtn = document.createElement('input');

                            this["_states"] = {
                                "target": searchResultTargetId,
                                "limit": limit
                            };
                            
                            this["_type"] = {
                                _class: "search"
                            };
                            
                            this.id = sender.id+'_searchBlock';
                            searchLabel.htmlFor = 'searchValue';
                            //searchLabel.textContent = 'Search Value: ';
                            searchValue.id = sender.id+'_searchValue';
                            searchValue.name = sender.id+'_searchValue';
                            searchValue.type = 'text';
                            searchValue.className = 'searchValue';
                            searchValue.value = 'Enter search term here.';
                            searchValue.onfocus = function(){
                                this.value = (this.value == 'Enter search term here.')?'':this.value;
                            }
                            
                            searchBtn.type = 'submit';
                            searchBtn.id = sender.id+'_searchBtn';
                            searchBtn.onclick = function() {
                                GRAB.mediaos.core.ui.component.search.query( publicKey, searchComponent["_states"].target, document.getElementById(searchValue.id).value, searchComponent["_states"].limit );
                            }
                            searchBtn.setAttribute('default', 'true');
                            searchBtn.className = 'searchBtn';
                            searchBtn.value="Search";
                            
                            searchForm.action = 'javascript: void(0)';
                            searchForm.appendChild(searchValue);
                            searchForm.appendChild(searchBtn);
                            this.appendChild(searchForm);

                            sender.appendChild(this);
                            
                            GRAB.mediaos.core.registry.utils.register(this);
                            
                            GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'RENDER', 'SEARCH', 1, 'sender', 'draw');
                        },
                        query: function(publicKey, resultTargetId, searchValue, limit){
                            var
                                searchScript = document.createElement('script'),
                                senderElement = document.getElementById(resultTargetId);
                            
                            searchScript.id = resultTargetId+'_searchScript';
                            searchScript.type = 'text/javascript';
                            searchScript.src = 'http://'+ GRAB.mediaos.servers.vcl.domain +'/mediaos/vcl'+ GRAB.mediaos.environment.suffix +'/factory/search/{"key":"'+publicKey+'", "sender":{"name":"'+resultTargetId+'"},"query":{"value":"'+searchValue.replace(/"/gi, '')+'"}, "targetObjectId":"'+resultTargetId+'", "limit":"'+limit+'"}.js';
                            
                            senderElement.appendChild(searchScript);
                            GRAB.mediaos.plugins.analytics.google.trackEvent('VCL_SEARCH', 'QUERY', searchValue, 1, 'sender', 'query');
                        },
                        response: (function(){
                            var
                                searchResultTarget = document.getElementById(arguments[0].sender);
                                
                            searchResultTarget.innerHTML = unescape(arguments[0].response);
                            GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'SearchResultsDisplayed', 'SEARCH', 1, 'sender', 'response');
                        })
                    },
                    player: {
                        autoStart: false,
                        
                        init: function( _player ) {
                            if ( _player._states.incrementer ) {
                                clearInterval( _player._states.incrementer );
                                _player._states.incrementer = null;
                            }
                            this.labels.duration.init( _player );
                            this.controls.volume.init( _player );
                            this.controls.play.init( _player );
                            this.controls.seek.scrub.init( _player );
                        },
                        reactor:{
                            register: function(sender, action, command, id){
                                this['type'] = 'player';
                                this['sender'] = sender;
                                this['action'] = action;
                                this['command'] = command;
                                this['id'] = id;
                                return GRAB.mediaos.core.ui.component.reactor.register.call(this);
                            }
                        },
                        reset: function(videoObject, _communityShortUrl){
                            var
                                this_player = this, // we're "calling" this function, so "this" represents who called; a player.
                                registeredPlayerStructure = {"_type":"player", "name":this_player.id},
                                registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(registeredPlayerStructure);

                            var hasAds = !!( this["_states"] && this["_states"].advertising && this["_states"].advertising.ads );
                            if ( hasAds ) {
                                var ads = this["_states"].advertising.ads;
                                var adCount = ads.length;
                                for ( var n=0; n<adCount; n++ ) {
                                    if ( ads[n].type == 'inline' ) ads[n].playing = false;
                                }
                            } 

                            this_player["_states"] = {
                                assetId: 'V'+videoObject['master_id'],
                                guid: 'v'+videoObject['guid'],
                                isPlaying: false,
                                isPaused: true,
                                doLoop: false,
                                isMuted: false,
                                duration: ( !!videoObject["duration"] ) ? GRAB.mediaos.core.ui.utils.string.humanizeSeconds( parseInt(videoObject["duration"]) / 1000 ) : 0,
                                timePosition: 0,
                                isSeeking: false,
                                incrementer: 0,
                                providerURL: null,
                                volume: 100,
                                communityShortUrl: _communityShortUrl,
                                masterStreamUrl: videoObject["master_stream_uri"],
                                asset:{metadata:videoObject},
                                loaded: true,
                                autoplay: ( this["_states"] && this["_states"].autoplay ) ? this["_states"].autoplay : false,
                                loadByDefault: ( this["_states"] ) ? this["_states"].loadByDefault : true,
                                loadFirstListItem: ( this["_states"] ) ? this["_states"].loadFirstListItem : false,
                                advertising: ( this["_states"] ) ? this["_states"].advertising : ''
                            };

                                 /*** Begin custom, demo processing code. ***/
                                 var __assetTitle__ = unescape( this_player._states.asset.metadata.title );
                               
                                 //this_player._states.asset.metadata.description = '';
                                 
                                 try {
                                     var
                                        __assetTitleObject__ = eval(  "(" + __assetTitle__ + ")"  );
                                        
                                     this_player._states.asset.metadata.title = escape( __assetTitleObject__.title );
                                     this_player._states.asset.metadata.description = __assetTitleObject__.spec;
                                 } catch (e) {
                                    
                                 };
                                 /*** End custom, demo processing code. ***/

                            registeredPlayer._states = this_player._states;
                            
                            return true;
                        },
                        video:{
                            load: function( asset ){
                                var
                                    _component = {"_type":"metadata"},
                                    registeredMetadataDisplay = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                                    this_player = this;

                                // check the engine type to pass the correct asset data
                                switch( this._type._engine ) {
                                    case "gmos":
                                    try {
                                            if ( this_player._states.advertising.variables.static ) {
                                                var supplement_var = ",'vid':'"+ asset.id +"'";
                                                this_player._states.advertising.variables['dynamic'] = this_player._states.advertising.variables.static.substring(0, this_player._states.advertising.variables.static.lastIndexOf( '}' ) ) + supplement_var + '}';
                                            }
                                            this_player.loadNewVideo( 'V'+asset.master_id, this_player._states.advertising.variables.dynamic );
                                        } catch (e) {
                                            //console.log(e);
                                        };
                                        break;
                                    case "osmf":
                                        if ( this_player._states.advertising.variables.static ) {
                                            var supplement_var = ",'vid':'"+ asset.id +"'";
                                            this_player._states.advertising.variables['dynamic'] = this_player._states.advertising.variables.static.substring(0, this_player._states.advertising.variables.static.lastIndexOf( '}' ) ) + supplement_var + '}';
                                        }
                                        this_player.loadNewVideo( 'v'+asset.guid, this_player._states.advertising.variables.dynamic );
                                        break;
                                    default:
                                        //console.log('Cannot match engine type of: '+this._type  ._engine);
                                        break;
                                }

                                var playerResetSuccessful = GRAB.mediaos.core.ui.component.player.reset.call(this_player, asset, '');

                                // if a registeredMetadataDisplay exists, load metadata into it.
                                if (registeredMetadataDisplay){
                                    GRAB.mediaos.core.registry.utils.minidom.removeChildNodes.call(registeredMetadataDisplay);
                                    
                                    for ( var property in asset ) {
                                        var metadataItem = document.createElement('li');
                                        
                                        metadataItem.innerHTML = property + ': ' + asset[property];
                                        registeredMetadataDisplay.appendChild(metadataItem);
                                    }
                                }
                                return;
                            }
                        },
                        draw: function(_asset, _class, _playerId, _skinId, _target, _remote_address, _server_name, _communityShortUrl, _engine, _videoObject, _customizations, _relatedAssets, _options){
                            var
                                swf_url = undefined,
                                videoObject = eval( "(" + unescape(_videoObject) + ")" ).video,
                                customizations = _customizations,
                                autoplay = undefined;
                            
                            /* Begin VCL advertising object parsing. */
                            try {
                                var adVariableGroupRef = '';
                                for (var ad_unit_index in _options.view.player.options.advertising.units){
                                        var ad_unit = _options.view.player.options.advertising.units[ad_unit_index];
                                    for(var ad_variable_group_index in ad_unit.variableGroups){
                                        if(ad_variable_group_index < ad_unit.variableGroups.length){
                                            var ad_variable_group = ad_unit.variableGroups[ad_variable_group_index];
                                            adVariableGroupRef += ad_variable_group.name + "={";
                                            for (var ad_variable_group_var_index in ad_variable_group.variables){
                                                if(ad_variable_group_var_index < ad_variable_group.variables.length){
                                                    var adVariableGroupVar = ad_variable_group.variables[ad_variable_group_var_index];
                                                    adVariableGroupRef += "'" + adVariableGroupVar.name + "':'" + adVariableGroupVar.value + "'";
                                                    adVariableGroupRef = adVariableGroupRef.replace( "''", "','" ); // insert a separator when there are multiple key/vals present
                                                }
                                            }
                                            adVariableGroupRef += '}' + '&';
                                        }
                                    }
                                }
                            } catch (e) {
                                var adVariableGroupRef = '';
                            }
                            
                            try {
                                var zoneId = _options.view.player.options.advertising.units[0].zone_id;
                                
                                if (zoneId != ''){
                                    var ad_zone_ref = 'companion_zone_id=' + _options.view.player.options.advertising.units[0].zone_id + '&';
                                } else{
                                    var ad_zone_ref = '';
                                }
                            } catch (e) {
                                var ad_zone_ref = ''
                            }
                            
                            /* End VCL advertising object parsing. */
                           
                            try {
                                autoplay = ( _options.view.player.options.autoplay == 'on' ) ? true : false;
                                if(_engine == "gmos") {
                                    autoplay_param = '&autoplay='+ autoplay;  
                                } else if(_engine == "osmf"){
                                    autoplay_param = '&autoPlay=' + autoplay;  
                                }
                            } catch ( error ) {
                                autoplay = false;
                                autoplay_param = '';
                            }
                            
                            swf_url = 'http://'+ GRAB.mediaos.servers.cube.domain +'/swf/cube.swf?'+ad_zone_ref+adVariableGroupRef+'resourceDNS=player.grabnetworks.com' + autoplay_param +'&jskey=' + _skinId + '&namespace=GRAB.mediaos.core.ui.events&eventhandler=flashExternal&playerid=' + _playerId + '&remoteaddr=' + _remote_address + '&servername=' + _server_name+ '';
                            
                            // if we detect related assets then draw the list
                            if ( _relatedAssets ) {
                                var div = document.createElement('div');
                                div.className = 'related-list';
                                div.setAttribute('class','related-list');
                                GRAB.mediaos.core.ui.component.list.draw.call( div, _relatedAssets, _target, _playerId, 5 );
                            }
                            
                            switch(_engine) {
                                case 'gmos':
                                    var player__ = this;
                                    this.setAttribute('name', _playerId);
                                    this.name = _playerId;
                                    this.setAttribute('id', _playerId);
                                    this.id = _playerId;
                                    this.setAttribute('width', _options.view.player.width);
                                    this.width=_options.view.player.width;
                                    this.setAttribute('height', _options.view.player.height );
                                    this.height=_options.view.player.height;
                                    
                                    this.setAttribute('type','application/x-shockwave-flash');
                                    this.setAttribute('className', 'grab-video-engine');
                                    this.setAttribute('class', 'grab-video-engine');
                                    this.data = swf_url;
                                    this.setAttribute('data', swf_url);
        
                                    this.movie = swf_url;
                                    var param_movie = document.createElement('param');
                                    param_movie.setAttribute('name','movie');
                                    param_movie.setAttribute('value',swf_url);
                                    this.appendChild(param_movie);
                                    
                                    this.src = swf_url;
                                    var param_src = document.createElement('param');
                                    param_src.setAttribute('name','src');
                                    param_src.setAttribute('value',swf_url);
                                    this.appendChild(param_src);

                                    this.allowScriptAccess = 'always';
                                    var param_scriptaccess = document.createElement('param');
                                    param_scriptaccess.setAttribute('name','allowScriptAccess');
                                    param_scriptaccess.setAttribute('value','always');
                                    this.appendChild(param_scriptaccess);
                                    
                                    this.base = '.';
                                    var param_base = document.createElement('param');
                                    param_base.setAttribute('name', "base");
                                    param_base.setAttribute('value','.');
                                    this.appendChild(param_base);
                                    
                                    this.wmode = 'transparent';
                                    var param_wmode = document.createElement('param');
                                    param_wmode.setAttribute('name', "wmode");
                                    param_wmode.setAttribute('value','transparent');
                                    this.appendChild(param_wmode);
                                    
                                    this.allowFullScreen = 'true';
                                    var param_fullscreen = document.createElement('param');
                                    param_fullscreen.setAttribute('name', "allowFullScreen");
                                    param_fullscreen.setAttribute('value','true');
                                    this.appendChild(param_fullscreen);
                                    
                                    this.scale = 'default';
                                    var param_scale = document.createElement('param');
                                    param_scale.setAttribute('name', "scale");
                                    param_scale.setAttribute('value','default');
                                    this.appendChild(param_scale);
                                    break;
                                case 'osmf':
                                    var target_server = 'production';
                                    var swf_url = 'http://player.grabnetworks.com/swf/GrabOSMFPlayer.swf?id=' + _skinId + '&tgt=' + target_server + '&namespace=GRAB.mediaos.core.ui.events&eventhandler=flashExternal&playerid=' + _playerId + '';
                                    this.setAttribute('name', _playerId);
                                    this.name = _playerId;
                                    this.setAttribute('id', _playerId);
                                    this.id = _playerId;
                                    this.setAttribute('width', _options.view.player.width);
                                    this.width=_options.view.player.width;
                                    this.setAttribute('height', _options.view.player.height );
                                    this.height=_options.view.player.height;

                                    this.setAttribute('type','application/x-shockwave-flash');
                                    this.setAttribute('className', 'grab-video-engine');
                                    this.setAttribute('class', 'grab-video-engine');
                                    this.data = swf_url;
                                    this.setAttribute('data', swf_url);

                                    this.movie = swf_url;
                                    var param_movie = document.createElement('param');
                                    param_movie.setAttribute('name','movie');
                                    param_movie.setAttribute('value',swf_url);
                                    this.appendChild(param_movie);

                                    this.src = swf_url;
                                    var param_src = document.createElement('param');
                                    param_src.setAttribute('name','src');
                                    param_src.setAttribute('value',swf_url);
                                    this.appendChild(param_src);

                                    this.allowScriptAccess = 'always';
                                    var param_scriptaccess = document.createElement('param');
                                    param_scriptaccess.setAttribute('name','allowScriptAccess');
                                    param_scriptaccess.setAttribute('value','always');
                                    this.appendChild(param_scriptaccess);

                                    this.base = '.';
                                    var param_base = document.createElement('param');
                                    param_base.setAttribute('name', "base");
                                    param_base.setAttribute('value','.');
                                    this.appendChild(param_base);

                                    this.wmode = 'transparent';
                                    var param_wmode = document.createElement('param');
                                    param_wmode.setAttribute('name', "wmode");
                                    param_wmode.setAttribute('value','transparent');
                                    this.appendChild(param_wmode);

                                    this.allowFullScreen = 'true';
                                    var param_fullscreen = document.createElement('param');
                                    param_fullscreen.setAttribute('name', "allowFullScreen");
                                    param_fullscreen.setAttribute('value','true');
                                    this.appendChild(param_fullscreen);

                                    this.scale = 'default';
                                    var param_scale = document.createElement('param');
                                    param_scale.setAttribute('name', "scale");
                                    param_scale.setAttribute('value','default');
                                    this.appendChild(param_scale);
                                    break;
                                case 'html5':
                                    // to be implemented                                    
                                    break;
                                default:
                                    //
                                    break;
                            }
                            
                            this["_type"] = {
                                _class: "player",
                                _spec: _class,
                                _engine: _engine
                            };
                                
                            /* Auto Target */
                            
                            // find the currently executing script element
                            //var currScriptElement = document.getElementsByTagName('script')[(document.getElementsByTagName('script').length-1)];
                            var currScriptElement = document.getElementById('grab-vcl-video-player-script');
                            
                            // find that scripts parent element
                            var currScriptParent = currScriptElement.parentNode;

                            // create a container to size the player properly
                            var containerElement = document.createElement('DIV');
                            containerElement.style.position = 'relative';
                            containerElement.style.top = 0;
                            containerElement.style.left = 0;
                            containerElement.style.width = _options.view.player.width + 'px';
                            containerElement.style.height = _options.view.player.height + 'px';
                            
                            currScriptParent.insertBefore( containerElement, currScriptElement );
                            
                            // add the new DIV into that parent element
                            var targetElement = document.createElement('DIV');
                            targetElement.id = _options.target.id;
                            targetElement.className = _options.target.classReference;
                            
                            containerElement.appendChild( targetElement );
                            
                            // add the Flash object element to the target
                            targetElement.appendChild( this );    
                            
                            /* End Auto Target */
                            this["_states"] = {};
                                
                            // begin register autoplay reactor
                            this._states['autoplay'] = autoplay;
                            // end register autoplay reactor
                            
                            // tell the player to initially load an asset or remain blank
                            try {
                                this._states['loadByDefault'] = ( _options.view.player.options.loadByDefault == 'true' ) ? true : false;                                
                            } catch (e) {}
                            
                            // tell the player to initially load an associated list's first asset
                            try {
                                this._states['loadFirstListItem'] = ( _options.view.player.options.loadFirstListItem == 'true' ) ? true : false;                                
                            } catch (e) {}   
                            
                            try {
                                // clean the ad variable group value to format it back to proper JSON
                                this._states['advertising'] = {};
                                this._states['advertising']['variables'] = {};
                                this._states['advertising']['variables']['static'] = ( adVariableGroupRef.length > 1 ) ? adVariableGroupRef.substring( adVariableGroupRef.indexOf( '{' ), adVariableGroupRef.lastIndexOf( '&' ) ) : null;
                            } catch(e) {}
                                
                            GRAB.mediaos.core.registry.utils.register(this);
                            var playerResetSuccessful = GRAB.mediaos.core.ui.component.player.reset.call(this, videoObject, _communityShortUrl);
                            
                            GRAB.mediaos.core.ui.component.player.controls.draw(_target, this);
                            GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'INIT', 'PLAYER', 1, 'sender', 'draw');
                        },
                        play: function(){
                            var 
                                player = this,
                                playBtn = player.nextSibling.childNodes[4],
                                eventLabel = player._states.asset.metadata.title + ' ['+ player._states.asset.metadata.master_id +']',
                                grabAssetClass = player._states.asset.metadata.classification_name,
                                grabPlayerTimePosition = player._states.timePosition;
                                 
                            player.playVideo();
                            
                            GRAB.mediaos.plugins.analytics.google.trackEvent('VCL', 'PlaybackPlayRequested', eventLabel, grabPlayerTimePosition, 'externalEvent', 'VideoPlaybackPlayRequested');
                            
                            player._states.isPaused = false;
                            player._states.isPlaying = true;
                            
                            playBtn.onmouseup = function() {
                                GRAB.mediaos.core.ui.component.player.pause.call( player );
                            };
                            
                            playBtn.className = 'pauseBtn';
                            playBtn.setAttribute( 'class', 'pauseBtn' );
                        },
                        pause: function(){
                            var 
                                player = this,
                                playBtn = player.nextSibling.childNodes[4],
                                eventLabel = player._states.asset.metadata.title + ' ['+ player._states.asset.metadata.master_id +']';
                            
                            player.pauseVideo();
                            
                            GRAB.mediaos.plugins.analytics.google.trackEvent(player._states.asset.metadata.classification_name, 'PlaybackPauseRequested', eventLabel, player._states.timePosition, 'externalEvent', 'VideoPlaybackPauseRequested');
                            
                            clearInterval(player._states.incrementer);
                            player._states.incrementer = null;
                            player._states.isPlaying = false;
                            player._states.isPaused = true;

                            playBtn.onmouseup = function() {
                                GRAB.mediaos.core.ui.component.player.play.call( player );
                            };

                            playBtn.className = 'playBtn';
                            playBtn.setAttribute( 'class', 'playBtn' );
                        },
                        labels: {
                            duration: {
                                init: function( _player ) {
                                    var 
                                        formattedDuration = ( _player._states.duration ) ? GRAB.mediaos.core.ui.utils.string.humanizeSeconds( parseInt(_player._states.duration)/1000 ) : "0:00";
                                    
                                    _player.nextSibling.childNodes[0].innerHTML = formattedDuration;
                                }
                            }
                        },
                        controls: {
                            play: {
                                init: function init( _player ) {
                                    var 
                                        playBtn = _player.nextSibling.childNodes[4];
                                        
                                    _player._states.isPlaying = false;
                                    _player._states.isPaused = true;
                                    _player._states.isSeeking = false;
                                    
                                    playBtn.className = 'playBtn';
                                    playBtn.setAttribute( 'class', 'playBtn' );
                                    
                                    playBtn.onmouseup = function(){
                                        GRAB.mediaos.core.ui.component.player.play.call( _player );
                                    }
                                }
                            },
                            seek: {
                                scrub: {
                                    init: function( _player ){
                                        var 
                                            scrubber = _player.nextSibling.childNodes[2],
                                            seekbar = _player.nextSibling.childNodes[1],
                                            playbackTimeLbl = _player.nextSibling.childNodes[6],
                                            track = _player.nextSibling.childNodes[1],
                                            controlbar = _player.nextSibling,
                                            track_relative_left = ( GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( track ).left - GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( _player.nextSibling ).left ),
                                            track_relative_right = track_relative_left + parseInt( track.offsetWidth );
                                        
                                        playbackTimeLbl.innerHTML = GRAB.mediaos.core.ui.utils.string.humanizeSeconds(0); 
                                        
                                        scrubber.style.display = "inline";
                                        scrubber.style.left = track_relative_left - ( scrubber.offsetWidth / 2 ) + "px";

                                        // calculate the difference between the edge of the controlbar to the edge of the seek-track and remove the difference of the scrubber button width
                                        var diffLeft = track_relative_left - parseInt( scrubber.offsetWidth ) / 2;
                                        var diffRight = track_relative_right - parseInt( scrubber.offsetWidth ) / 2;
                                            
                                        GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop.initElement( 
                                            scrubber,
                                            {
                                                'axis': 'x',
                                                'bounds': { 
                                                    top: 0, 
                                                    right: diffRight, 
                                                    bottom: 0, 
                                                    left: diffLeft
                                                }, 
                                                'drag_callback': GRAB.mediaos.core.ui.component.player.controls.seek.scrub.update,
                                                'drag_callback_args': _player
                                            }
                                        );
                                            
                                        seekbar.onmousedown = function( event ) {
                                            GRAB.mediaos.core.ui.component.player.controls.seek.scrub.update( 
                                                _player, event 
                                            );
                                        };
                                        
                                    },
                                    update: function( _player, _event ){
                                        var
                                            scrubber = _player.nextSibling.childNodes[2],
                                            track = _player.nextSibling.childNodes[1],
                                            start_x = track.offsetLeft - ( scrubber.offsetWidth / 2 ),
                                            relativeMouseCoords = GRAB.mediaos.core.registry.utils.minidom.mouse.cursor.relative.rectangle( _event, track ),
                                            x_in_track = relativeMouseCoords.left / track.offsetWidth,
                                            percent_of_stream = 100 * ( relativeMouseCoords.left / track.offsetWidth );
                                         
                                        scrubber.style.left = start_x + ( track.offsetWidth * x_in_track )+'px';
                                        _player.seekVideoTo( percent_of_stream );
                                    }
                                },
                                increment: function( seekTimeLbl, _player ){
                                    var 
                                        offset = seekTimeLbl.offsetLeft;
                                        
                                    seekTimeLbl.style.left = (++offset) + 'px';
                                }
                            },
                            volume: {
                                init: function( _player ) {
                                    var
                                        volumeScrubber = _player.nextSibling.childNodes[3].childNodes[0].childNodes[1],
                                        volumeBtn = _player.nextSibling.childNodes[3].childNodes[1].childNodes[0],
                                        volumeTrack = _player.nextSibling.childNodes[3].childNodes[0].childNodes[0],
                                        volumeGroup = _player.nextSibling.childNodes[3],
                                        volumeBackground = _player.nextSibling.childNodes[3].childNodes[0],
                                        updateValue = 0,
                                        track_relative_top = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( volumeTrack ).top - GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( volumeGroup ).top,
                                        track_relative_bottom = track_relative_top + parseInt( volumeTrack.offsetHeight );

                                    volumeBtn.className = 'volumeBtn-audible';
                                    volumeBtn.setAttribute( 'class', 'volumeBtn-audible' );
                                    volumeBtn.onmouseup = function(){
                                       GRAB.mediaos.core.ui.component.player.controls.volume.mute.call( this, _player );
                                    }
                                    
                                    volumeBackground.style.opacity = '0';
                                    volumeScrubber.style.top = (( volumeBtn.parentNode.previousSibling.offsetHeight / 2 ) - ( volumeScrubber.offsetHeight / 2 ))+'px';

                                    // calculate the difference between the edge of the volumegroup to the edge of the seek-track and remove the difference of the scrubber button width
                                    var diffTop = track_relative_top - parseInt( volumeScrubber.offsetHeight ) / 2;
                                    var diffBottom = track_relative_bottom - parseInt( volumeScrubber.offsetHeight) / 2;
                                
                                    GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop.initElement( 
                                        volumeScrubber,
                                        {
                                            'axis': 'y',
                                            'bounds': { 
                                                top: diffTop, 
                                                right: 0, 
                                                bottom: diffBottom, 
                                                left: 0
                                            },
                                            'drag_callback': GRAB.mediaos.core.ui.component.player.controls.volume.scrub.update,
                                            'drag_callback_args': _player
                                        }
                                    );
                                    
                                    var onVolumeBGMouseDown = function(e) {
                                        var trackElementTop = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( volumeTrack ).top;
                                        var trackElementBottom = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( volumeTrack ).bottom;
                                        
                                        var bgElementTop = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( volumeBackground ).top;
                                        var bgElementBottom = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( volumeBackground ).bottom;
                                        
                                        var trackOffsetTop = trackElementTop - bgElementTop;
                                        var trackOffsetBottom = Math.abs( bgElementBottom - trackElementBottom );
                                        
                                        relativeMouseCoords = GRAB.mediaos.core.registry.utils.minidom.mouse.cursor.relative.rectangle( e, volumeBackground );
                                        
                                        var withinHighestTrackBounds = !!( relativeMouseCoords.top >= trackOffsetTop );
                                        var withinLowestTrackBounds = !!( Math.abs(relativeMouseCoords.bottom) >= trackOffsetBottom );
                                        
                                        if ( withinHighestTrackBounds && withinLowestTrackBounds ) {
                                            GRAB.mediaos.core.ui.component.player.controls.volume.scrub.update( _player, e );    
                                        }
                                    }
                                   
                                    GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( volumeBackground, 'mousedown', onVolumeBGMouseDown );
                                    
                                    var volbtn_traits = {
                                            states: [
                                                {
                                                    name: 'destination_x',
                                                    value: 0
                                                },
                                                {
                                                    name: 'destination_y',
                                                    value: 0
                                                },
                                                {
                                                    name: 'motion_timespan',
                                                    value: 0
                                                },
                                                {
                                                    name: 'motion_x',
                                                    value: false
                                                },
                                                {
                                                    name: 'motion_y',
                                                    value: false
                                                },
                                                {
                                                    name: 'motion_timer',
                                                    value: null
                                                }
                                            ]
                                    };
                                    volumeBtn["_states"] = {};
                                    GRAB.mediaos.core.registry.manage.states( volumeBtn, volbtn_traits );
                                    
                                    var volgroup_traits = {
                                            states: [
                                                {
                                                    name: 'destination_x',
                                                    value: 0
                                                },
                                                {
                                                    name: 'destination_y',
                                                    value: 0
                                                },
                                                {
                                                    name: 'motion_timespan',
                                                    value: 0
                                                },
                                                {
                                                    name: 'motion_x',
                                                    value: false
                                                },
                                                {
                                                    name: 'motion_y',
                                                    value: false
                                                },
                                                {
                                                    name: 'motion_timer',
                                                    value: null
                                                }
                                            ]
                                    };
                                    volumeGroup["_states"] = {};
                                    GRAB.mediaos.core.registry.manage.states( volumeGroup, volgroup_traits );
                                    
                                    var volBackground_traits = {
                                            states: [
                                                {
                                                    name: 'alpha_destination',
                                                    value: null
                                                },
                                                {
                                                    name: 'alpha_timespan',
                                                    value: null
                                                },
                                                {
                                                    name: 'alpha_timer',
                                                    value: null
                                                }
                                            ]
                                    };
                                    volumeBackground["_states"] = {};
                                    GRAB.mediaos.core.registry.manage.states( volumeBackground, volBackground_traits ); 
                                },
                                scrub: {
                                    update: function( _player, _event ) {
                                        var
                                            traits = {},
                                            scrubber = _player.nextSibling.childNodes[3].childNodes[0].childNodes[1],
                                            track = _player.nextSibling.childNodes[3].childNodes[0].childNodes[0],
                                            relativeTrackCoords = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( track ),
                                            relative_scrubber_coords = GRAB.mediaos.core.ui.utils.viewport.rectangle.relative( scrubber ),
                                            relativeMouseCoords = GRAB.mediaos.core.registry.utils.minidom.mouse.cursor.relative.rectangle( _event, track ),
                                            distance_from_max = relativeTrackCoords.top + relativeMouseCoords.top,
                                            y_in_track = relativeMouseCoords.top / track.offsetHeight,
                                            calculated_vol = Math.abs( (Math.floor( 100 * y_in_track )) - 100);
                                            
                                        scrubber.style.top = ( 100 - calculated_vol ) + ( scrubber.offsetHeight / 2 ) + 'px'; // subtract 100 to invert the value
                                            
                                        _player.setVolume( calculated_vol );
                                            
                                        traits = {
                                            states: [
                                                {
                                                    name: 'volume',
                                                    value: calculated_vol
                                                }
                                        ]};
                                        
                                        //check where we are and the states ... if the volume was muted then we need to unmute
                                        if ( calculated_vol > 10 ) {
                                            if ( _player._states.isMuted ) {
                                                traits.states.push(
                                                    {
                                                        name: 'isMuted',
                                                        value: false
                                                    }
                                                );
                                                _player.nextSibling.childNodes[3].childNodes[1].childNodes[0].className = 'volumeBtn-audible';
                                                _player.nextSibling.childNodes[3].childNodes[1].childNodes[0].setAttribute( 'class', 'volumeBtn-audible' );
                                            }
                                        } else {
                                            if ( !_player._states.isMuted ) {
                                                traits.states.push(
                                                    {
                                                        name: 'isMuted',
                                                        value: true
                                                    }
                                                );
                                                _player.nextSibling.childNodes[3].childNodes[1].childNodes[0].className = 'volumeBtn-muted';
                                                _player.nextSibling.childNodes[3].childNodes[1].childNodes[0].setAttribute( 'class', 'volumeBtn-muted' );
                                            }
                                        }
                                        
                                        GRAB.mediaos.core.registry.manage.states(_player, traits);
                                    }
                                },
                                mute: function(_player){
                                    var
                                        volumeScrubber = _player.nextSibling.childNodes[3].childNodes[0].childNodes[1], 
                                        traits;
                                    
                                    if (_player._states.isMuted) {
                                        traits = {
                                            states: [{
                                                name: 'isMuted',
                                                value: false
                                            },
                                            {
                                                name: 'volume',
                                                value: 100
                                            }]
                                        };
                                        var verticalOffset = volumeScrubber.offsetHeight / 2;
                                        volumeScrubber.style.top = verticalOffset+"px";
                                        this.className = 'volumeBtn-audible';
                                        this.setAttribute( 'class', 'volumeBtn-audible');
                                        _player.setVolume(100);
                                    } else {
                                        traits = {
                                            states: [{
                                                name: 'isMuted',
                                                value: true
                                            },
                                            {
                                                name: 'volume',
                                                value: 0
                                            }]
                                        };
                                        volumeScrubber.style.top = (volumeScrubber.offsetParent.offsetHeight - 25) + "px";
                                        
                                        this.className = 'volumeBtn-muted';
                                        this.setAttribute( 'class', 'volumeBtn-muted');
                                        _player.setVolume(0);
                                    }
                                    
                                    GRAB.mediaos.core.registry.manage.states(_player, traits);
                                },
                                
                                fadeIn: function( _playerId ) {
                                    var 
                                        _component = {"_type":"player", "name":_playerId.id},
                                        registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry( _component ),
                                        volumeBackground = registeredPlayer.nextSibling.childNodes[3].childNodes[0],
                                        volBackground_traits = {
                                            states: [
                                            {
                                                name: 'alpha_destination',
                                                value: 1
                                            },
                                            {
                                                name: 'alpha_timespan',
                                                value: 300
                                            }]
                                        }; 
                                        
                                    GRAB.mediaos.core.registry.manage.states( volumeBackground, volBackground_traits ); 
                                    GRAB.mediaos.core.ui.component.fade.call( volumeBackground );      
                                },
                                
                                fadeOut: function( _playerId ) {
                                    
                                    var 
                                        _component = {"_type":"player", "name":_playerId.id},
                                        registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry( _component ),
                                        volumeBackground = registeredPlayer.nextSibling.childNodes[3].childNodes[0],
                                        volBackground_traits = {
                                            states: [
                                            {
                                                name: 'alpha_destination',
                                                value: 0
                                            },
                                            {
                                                name: 'alpha_timespan',
                                                value: 300
                                            }]
                                        };
                                        
                                    GRAB.mediaos.core.registry.manage.states( volumeBackground, volBackground_traits );
                                    GRAB.mediaos.core.ui.component.fade.call( volumeBackground );
                                },
                                
                                show: function(_playerId){
                                    if (GRAB.mediaos.core.registry.utils.minidom.mouse.buttons.left.isUp) {

                                        var 
                                           _component = {"_type":"player", "name":_playerId.id},
                                           registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                                           volumeBtn = registeredPlayer.nextSibling.childNodes[3].childNodes[1].childNodes[0],
                                           volumeBackground = registeredPlayer.nextSibling.childNodes[3].childNodes[0],
                                           volumeGroup = registeredPlayer.nextSibling.childNodes[3];
                                       
                                       var volBtn_traits = {
                                            states: [
                                            {
                                                name: 'destination_y',
                                                value: 121
                                            },
                                            {
                                                name: 'motion_timespan',
                                                value: 300
                                            }]
                                        };
                                        var volGroup_traits = {
                                            states: [
                                            {
                                                name: 'destination_y',
                                                value: -121
                                            },
                                            {
                                                name: 'motion_timespan',
                                                value: 300
                                            }]
                                        };

                                        GRAB.mediaos.core.registry.manage.states( volumeBtn, volBtn_traits );
                                        GRAB.mediaos.core.registry.manage.states( volumeGroup, volGroup_traits );
                                        
                                        GRAB.mediaos.core.ui.component.move.call( volumeGroup );
                                        GRAB.mediaos.core.ui.component.move.call( volumeBtn );
                                        
                                        this.fadeIn( _playerId );
                                    }
                                },
                                
                                hide: function( _playerId ){
                                    if (GRAB.mediaos.core.registry.utils.minidom.mouse.buttons.left.isUp) {
                                        
                                        var 
                                           _component = {"_type":"player", "name":_playerId.id},
                                           registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                                           volumeBtn = registeredPlayer.nextSibling.childNodes[3].childNodes[1].childNodes[0],
                                           volumeBackground = registeredPlayer.nextSibling.childNodes[3].childNodes[0],
                                           volumeGroup = registeredPlayer.nextSibling.childNodes[3];
                                           
                                        var volBtn_traits = {
                                                states: [
                                                {
                                                    name: 'destination_y',
                                                    value: 0
                                                },
                                                {
                                                    name: 'motion_timespan',
                                                    value: 400
                                                }]
                                            };
                                        var volGroup_traits = {
                                            states: [
                                            {
                                                name: 'destination_y',
                                                value: 0
                                            },
                                            {
                                                name: 'motion_timespan',
                                                value: 400
                                            }]
                                        };

                                        GRAB.mediaos.core.registry.manage.states( volumeBtn, volBtn_traits );
                                        GRAB.mediaos.core.registry.manage.states( volumeGroup, volGroup_traits );

                                        if ( GRAB.mediaos.core.registry.utils.minidom.mouse._states.dragging ) {
                                            GRAB.mediaos.core.registry.utils.minidom.mouse.dragDrop.releaseElement();                                        
                                        }
                                        
                                        GRAB.mediaos.core.ui.component.move.call( volumeGroup );
                                        GRAB.mediaos.core.ui.component.move.call( volumeBtn );
                                        
                                        this.fadeOut( _playerId );
                                        
                                    }
                                }
                            },
                            draw: function( _target, _player ) {
                                var
                                    _target = document.getElementById(_target),
                                    communityIcon = document.createElement('div'),
                                    sourcelogo = document.createElement('img'),
                                    controlbar = document.createElement('div'),
                                    playBtn = document.createElement('div'),
                                    durationLbl = document.createElement('div'),
                                    playbackTimeLbl = document.createElement('div'),
                                    seekBar = document.createElement('div'),
                                    seekScrub = document.createElement('div'),
                                    volumeBtn = document.createElement('div'),
                                    volumeBackground = document.createElement('div'),
                                    volumeForeground = document.createElement('div'),
                                    volumeTrack = document.createElement('div'),
                                    volumeControl = document.createElement('div'),
                                    volumeNub = document.createElement('div'),
                                    menuBtn = document.createElement('div');
                                
                                _target.onmousedown = 'GRAB.mediaos.core.registry.utils.minidom.mouse.buttons.left.isDown = true;';
                                _target.onmouseup = 'GRAB.mediaos.core.registry.utils.minidom.mouse.buttons.left.isUp = true;';
                                
                                var handlePlayerWrapperMouseOut = function( e ) {
                                    GRAB.mediaos.core.ui.component.player.controls.hide( _player.id  );
                                };
                               
                                var handlePlayerMouseOver = function( e ) {
                                    GRAB.mediaos.core.ui.component.player.controls.show( _player.id );
                                };
                                
                                GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( _player.parentNode, 'mouseover', handlePlayerMouseOver );
                                GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( _player, 'mouseout', handlePlayerWrapperMouseOut );
                                
                                controlbar.id = _player.id + 'controlBar';
                                controlbar.className = 'controlBar';
                                controlbar.setAttribute('class', 'controlBar');
                                
                                var handleControlbarMouseOut = function( e ) {
                                    var target = e.srcElement || e.target;
                                    if (target != this) return;
                                    var related = e.relatedTarget || e.toElement;
                                    
                                    try {
                                        while (related != this && related.nodeName != 'BODY')
                                        related = related.parentNode;
                                    } catch (error){
                                        GRAB.mediaos.core.ui.component.player.controls.hide( _player.id );
                                        return;
                                    }
                                    if (related == this) return;
                                    GRAB.mediaos.core.ui.component.player.controls.hide( _player.id );
                                };
                                
                                GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( controlbar, 'mouseout', handleControlbarMouseOut );
                                
                                seekBar.id = _player.id + 'seekBar';
                                seekBar.className = 'seekBar';
                                seekBar.setAttribute('class', 'seekBar');
                                
                                seekScrub.setAttribute('id', _player.id + 'seekScrub');
                                
                                seekScrub.className = 'seekScrub';
                                seekScrub.setAttribute('class', 'seekScrub');

                                volumeControl.setAttribute('id', _player.id + 'volumeControl');
                                volumeControl.className = 'volumeControl';
                                volumeControl.setAttribute('class', 'volumeControl');
                                
                                volumeBackground.setAttribute('id', _player.id + 'volumeBackground');
                                volumeBackground.className = 'volumeBackground';
                                volumeBackground.setAttribute('class', 'volumeBackground');
                                volumeControl.appendChild(volumeBackground);
                                
                                volumeTrack.setAttribute( 'id', _player.id + 'volumeTrack' );
                                volumeTrack.className = 'volumeTrack';
                                volumeTrack.setAttribute( 'class', 'volumeTrack' );
                                volumeBackground.appendChild( volumeTrack );
                                
                                volumeNub.setAttribute('id', _player.id + 'volumeNub');
                                volumeNub.className = 'volumeNub';
                                volumeNub.setAttribute('class', 'volumeNub');
                                volumeBackground.appendChild(volumeNub);
                                
                                volumeForeground.setAttribute('id', _player.id + 'volumeForeground');
                                volumeForeground.className = 'volumeForeground';
                                volumeForeground.setAttribute('class', 'volumeForeground');
                                volumeControl.appendChild(volumeForeground);
                                
                                volumeBtn.setAttribute('id', _player.id + 'volumeBtn');
                                volumeForeground.appendChild(volumeBtn);
                                
                                playBtn.id = _player.id + 'playBtn';
                                playBtn.setAttribute('id', _player.id + 'playBtn');
                                playBtn.className = 'playBtn';
                                playBtn.setAttribute('class', 'playBtn');
                                
                                playbackTimeLbl.id = _player.id + 'playbackTimeLbl';
                                playbackTimeLbl.className = 'playbackTimeLbl';
                                playbackTimeLbl.setAttribute('class','playbackTimeLbl');
                                
                                durationLbl.id = _player.id + 'grabDurationLbl';
                                durationLbl.className = 'grabDurationLbl';
                                durationLbl.setAttribute('class', 'grabDurationLbl');
                                
                                menuBtn.id = _player.id + '-grabMenuBtn';
                                menuBtn.className = 'grabMenuBtn';
                                menuBtn.setAttribute('class', 'grabMenuBtn');
                                
                                communityIcon.id = _player.id + '-grab-community-icon';
                                communityIcon.className = 'grab-community-icon grab-comment-icon';
                                communityIcon.setAttribute('class', 'grab-community-icon grab-comment-icon');
                                communityIcon.onmouseup = function() {
                                    window.open( "http://twitter.com/home?status=Check out this @GrabNetworks video! "+ _player._states.communityShortUrl );
                                }
                                                                
                                controlbar.appendChild( durationLbl );
                                controlbar.appendChild( seekBar );
                                controlbar.appendChild( seekScrub );
                                controlbar.appendChild( volumeControl );
                                controlbar.appendChild( playBtn );
                                controlbar.appendChild( communityIcon );
                                controlbar.appendChild( playbackTimeLbl );
                                controlbar.appendChild( menuBtn );
                                
                                sourcelogo.id = _player.id + 'sourceLogo';
                                sourcelogo.className = 'sourceLogo';
                                sourcelogo.setAttribute('class', 'sourceLogo');
                                
                                _target.appendChild( controlbar );
                                _target.appendChild( sourcelogo );
                                
                                var handleVolumeOver = function(e) {
                                    GRAB.mediaos.core.ui.component.player.controls.volume.show( _player );
                                };
                                
                                var handleVolumeOut = function(e) {
                                    GRAB.mediaos.core.ui.component.player.controls.volume.hide( _player );
                                };
                                
                                GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( volumeControl, 'mouseover', handleVolumeOver );
                                GRAB.mediaos.core.registry.utils.minidom.event.addEventSimple( volumeBackground, 'mouseout', handleVolumeOut );
                                
                                GRAB.mediaos.core.ui.component.player.init( _player );
                                return;
                            },
                            hide: function( _playerId ){
                                var 
                                    _component = {"_type":"player", "name":_playerId},
                                    registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                                    sourcelogo = registeredPlayer.nextSibling.nextSibling,
                                    controls = registeredPlayer.nextSibling,
                                    sourcelogo_traits = {
                                        states: [
                                        {
                                            name: 'alpha_destination',
                                            value: 0
                                        },
                                        {
                                            name: 'alpha_timespan',
                                            value: 300
                                        }]
                                    };
                                
                                if ( sourcelogo ) {
                                    GRAB.mediaos.core.registry.manage.states( sourcelogo, sourcelogo_traits ); 
                                    GRAB.mediaos.core.ui.component.fade.call( sourcelogo );
                                }
                                
                                if (GRAB.mediaos.core.registry.utils.minidom.mouse.buttons.left.isUp) {
                                    controls.style.visibility = 'hidden';
                                }
                            },
                            show: function( _playerId ){
                                var 
                                    _component = {"_type":"player", "name":_playerId},
                                    registeredPlayer = GRAB.mediaos.core.registry.utils.findInRegistry(_component),
                                    sourcelogo_traits = {
                                        states: [
                                        {
                                            name: 'alpha_destination',
                                            value: 0.9
                                        },
                                        {
                                            name: 'alpha_timespan',
                                            value: 300
                                        }]
                                    };

                                try{
                                    var controls = registeredPlayer.nextSibling;
                                }catch(ex){};

                                try{
                                    var sourcelogo = registeredPlayer.nextSibling.nextSibling;
                                }catch(ex){};
                                    
                                var isPrerollPlaying = false;
                                try {
                                    var advertising = registeredPlayer._states.advertising;
                                    var adCount = advertising.ads.length;
                                    for (var n = 0; n < adCount; n++) {
                                        if (advertising.ads[n].event == 'preroll') {
                                            var prerollAd = advertising.ads[n];
                                            if ( prerollAd.playing ) isPrerollPlaying = true;
                                        }
                                    }
                                            
                                } catch(error) {};
                                
                                if ( !isPrerollPlaying ) {
                                    if ( sourcelogo ) {        
                                        GRAB.mediaos.core.registry.manage.states( sourcelogo, sourcelogo_traits ); 
                                        GRAB.mediaos.core.ui.component.fade.call( sourcelogo );   
                                    }
                                        
                                    if (GRAB.mediaos.core.registry.utils.minidom.mouse.buttons.left.isUp && controls) {
                                        controls.style.visibility = 'visible';
                                    } 
                                }
                            }
                        }
                    }
                }
            }
        },
        plugins:{
            analytics:{
                google:{
                    __init__:(function(){
                        try {
                            _gaq.push(
                                ['_setAccount', 'UA-12672074-1'],
                                ['_setDomainName', 'none'],
                                ['_setAllowLinker', true],
                                ['_setAllowHash', false],
                                ['_trackEvent','VCL','INIT', 'CORE', 1]
                            );
                        } catch (e) {
                            //console.log(e);
                        }
                    })(),
                    trackEvent: function( _category_ , _action_, _label_, _value_, __customVar1Name__, __customVar1Value__){
                        try {
                            _gaq.push(
                                ['_setAccount', 'UA-12672074-1'],
                                ['_setDomainName', 'none'],
                                ['_setAllowLinker', true],
                                ['_setAllowHash', false],
                                ['_setCustomVar', 1, __customVar1Name__, __customVar1Value__, 1],
                                ['_trackEvent', _category_, _action_, _label_, _value_]
                            );
                        } catch (e) {
                            //console.log(e);
                        }
                    }
                }
            }
        }
    },
    
    extensions: {
        controls: {
                buttons: {
                    previous: {
                        init: function( _domId ) {
                            this.states = {
                                element: document.getElementById(_domId),
                                enabledClassName: "enabled",
                                disabledClassName: "disabled"
                            };
                            
                            this.states.element.onclick = this.onClickHandler;
                            var canScroll = !!(GRAB.extensions.component.filmstrip.states.firstVisibleSceneIndex > 0 );
                            (canScroll) ? this.enable() : this.disable();
                        },
                        
                        enable: function() {
                            this.states.element.className = this.states.enabledClassName;
                        },
                        
                        disable: function() {
                            this.states.element.className = this.states.disabledClassName;
                        },
                        
                        onClickHandler: function() {
                            GRAB.extensions.component.filmstrip.showPreviousScenes();
                        }
                    },
                    
                    next: {
                        init: function( _domId ) {
                            this.states = {
                                element: document.getElementById(_domId),
                                enabledClassName: "enabled",
                                disabledClassName: "disabled"
                            };
                            
                            this.states.element.onclick = this.onClickHandler;
                            
                            var maxSceneCount = GRAB.extensions.component.filmstrip.states.currentSceneCount - 1;
                            var canScroll = !!(GRAB.extensions.component.filmstrip.states.lastVisibleSceneIndex < maxSceneCount );
                            (canScroll) ? this.enable() : this.disable();
                        },
                        
                        enable: function() {
                            this.states.element.className = this.states.enabledClassName;
                        },
                        
                        disable: function() {
                            this.states.element.className = this.states.disabledClassName;
                        },
                        
                        onClickHandler: function() {
                            GRAB.extensions.component.filmstrip.showNextScenes();
                        }
                    }
                }
            },
            
            component: {
                filmstrip: {
                    init: function( _domId, _scenes, _registeredList, _changeSetCallback ) {
                        this.reset();
                        this.states["domId"] = _domId;
                        this.states["changeSetCallback"] = _changeSetCallback;
                        this.states["registeredList"] = _registeredList;
                        
                        var filmstripElement = document.getElementById(this.states.domId);
                        filmstripElement.style.left = "0px";
                        
                        var sceneCount = _scenes.length;
                        for (var n = 0; n < sceneCount; n++) {
                            this.addScene(_scenes[n]);
                        };
                    },
                    
                    reset: function() {
                        this.states = {};
                        this.states["width"] = 696;
                        this.states["maxScenesPerSet"] = 5;
                        this.states["currentSceneCount"] = 0;
                        this.states["incompleteSetIndex"] = 0;
                        this.states["firstVisibleSceneIndex"] = 0;
                        this.states["lastVisibleSceneIndex"] = 0;
                        this.states["scenes"] = [];
                        this.states.currentSceneElement;
                    },
                    
                    createSceneMarker: function(_scene) {
                        var sceneMarkerElement = document.createElement("DIV");
                        sceneMarkerElement.className = "marker";
                        _scene.states.element.appendChild(sceneMarkerElement);
                    },
                    
                    positionSceneMarker: function(){
                        var markerElement = document.getElementById('vcl-scene-marker');
                        var columnIndex = GRAB.extensions.component.filmstrip.states.currentSceneElement._states.filmstripColumnIndex;
                        switch(columnIndex) {
                            case 1:
                                offsetX = 19 + 73;
                                break;
                            case 2:
                                offsetX = 161 + 73;
                                break;
                            case 3:
                                offsetX = 303 + 73;
                                break;
                            case 4:
                                offsetX = 445 + 73;
                                break;
                            case 5:
                                offsetX = 587 + 73;
                                break;
                        }
                        markerElement.style.left = offsetX + 'px';
                    },
                    
                    showSceneMarker: function(){
                        var markerElement = document.getElementById('vcl-scene-marker');
                        markerElement.style.display = "block";
                    },
                    
                    hideSceneMarker: function(){
                        var markerElement = document.getElementById('vcl-scene-marker');
                        markerElement.style.display = "none";
                    },
                    
                    addScene: function(_scene) {
                        var playIconOverlay = document.createElement("DIV");
                        playIconOverlay.className = "vcl-scene-play-overlay-disabled";
                        
                        _scene.states.element.appendChild( playIconOverlay );
                        _scene.states.element.style.display = "none";
                        _scene.states.element.style.position = "absolute";
                        _scene.states.element.style.left = 0 + "px";
                        
                        if (!_scene.states.element._states) _scene.states.element["_states"] = {};
                        _scene.states.element._states["playoverlayElement"] = playIconOverlay;
                        _scene.states.element._states["filmstripColumnIndex"] = 0;
                        
                        _scene.states.element.onmouseup = function(){
                            GRAB.extensions.component.filmstrip.states.currentSceneElement = this;
                            GRAB.extensions.component.filmstrip.hideDetailsBalloon();
                            GRAB.extensions.component.filmstrip.hideScenePlayOverlay();
                            GRAB.extensions.component.filmstrip.positionSceneMarker();
                            GRAB.extensions.component.filmstrip.showSceneMarker();
                        };
                        
                        this.states.scenes.push(_scene);
                        this.states.currentSceneCount += 1;
                    },
                    
                    hideSceneDetail: function(){
                        GRAB.extensions.component.filmstrip.hideDetailsBalloon();
                        //this._states.playoverlayElement.className = "vcl-scene-play-overlay-disabled";
                    },
                    
                    showSceneDetail: function(){
                        var hasMetadata = ( this.children && this.children[0] && this.children[0]._metadata ); 
                        if (hasMetadata) {
                            var balloonElement = document.getElementById("vcl-scene-details-balloon");
                            var balloonTitleElement = document.getElementById("vcl-scene-details-title");
                            var balloonDurationElement = document.getElementById("vcl-scene-details-duration");
                            var balloonSummaryElement = document.getElementById("vcl-scene-details-summary");
                            var meta = this.children[0]._metadata;
                            var duration_seconds = parseInt(meta.duration) / 1000;
                            var offsetX;
                            
                            var summary = meta.summary;
                            if (!!summary) {
                                summary = unescape( summary );
                            } else {
                                summary = "";
                            }
                            
                            balloonElement.style.display = "block";
                            balloonTitleElement.innerHTML = unescape(meta.title);
                            balloonDurationElement.innerHTML = "(" + GRAB.mediaos.core.ui.utils.string.humanizeSeconds(duration_seconds) + ")";
                            balloonSummaryElement.innerHTML = summary;
                            
                            switch(this._states.filmstripColumnIndex) {
                                case 1:
                                    offsetX = 19;
                                    break;
                                case 2:
                                    offsetX = 161;
                                    break;
                                case 3:
                                    offsetX = 303;
                                    break;
                                case 4:
                                    offsetX = 445;
                                    break;
                                case 5:
                                    offsetX = 587;
                                    break;
                            }
                            
                            balloonElement.style.left = offsetX + "px";
                            
                            //this._states.playoverlayElement.className = "vcl-scene-play-overlay-enabled";
                        }
                    },
                    
                    hideDetailsBalloon: function(){
                        var balloonElement = document.getElementById("vcl-scene-details-balloon");
                        balloonElement.style.display = "none";
                    },
                    
                    hideScenePlayOverlay: function() {
                        var sceneElement = GRAB.extensions.component.filmstrip.states.currentSceneElement;
                        sceneElement._states.playoverlayElement.className = "vcl-scene-play-overlay-disabled";
                    },
                    
                    selectScene: function( _sceneElement ) {
                        var registeredList = GRAB.extensions.component.filmstrip.states.registeredList;
                        var sceneCount = registeredList.children.length;
                        
                        if (this.states.currentSceneElement) {
                            this.deselectScene(this.states.currentSceneElement);
                        }
                        this.states.currentSceneElement = _sceneElement;
                        
                        for ( var n=0; n<sceneCount; n++ ){
                            var assetId = registeredList.children[n].children[0]._metadata.id;
                            var sceneId = _sceneElement.children[0]._metadata.id;
                            if (assetId == sceneId) {
                                var currentSceneIndex = n;
                                break;
                            }
                        }

                        var sceneIsInView = !!( (currentSceneIndex >= GRAB.extensions.component.filmstrip.states.firstVisibleSceneIndex ) && ( currentSceneIndex <= GRAB.extensions.component.filmstrip.states.lastVisibleSceneIndex ) );
                        GRAB.extensions.component.filmstrip.showSceneMarker();
                        GRAB.extensions.component.filmstrip.positionSceneMarker();
                        if (!sceneIsInView) GRAB.extensions.component.filmstrip.hideSceneMarker();
                    },
                    
                    deselectScene: function( _sceneElement ) {
                        this.states.currentSceneElement = undefined;
                    },
                    
                    showRangeOfScenes: function( _startIndex, _endIndex ) {
                        if ( _startIndex < 0 ) _startIndex = 0, _endIndex = 4;
                        
                        var endExceedsBounds = !!(_endIndex >= this.states.scenes.length);
                        if (_endIndex <= _startIndex) return false;
                        
                        GRAB.extensions.component.filmstrip.hideSceneMarker();
                        
                        if (endExceedsBounds) {
                            var exceededBy = _endIndex - this.states.scenes.length;
                            _startIndex -= exceededBy + 1;
                            _endIndex = this.states.scenes.length - 1;
                        }
                        
                        for ( var i=this.states.firstVisibleSceneIndex; i<= this.states.lastVisibleSceneIndex; i++ ) {
                            var prevScene = this.states.scenes[i];
                            prevScene.states.element.style.display = "none";
                        }
                        
                        var columnIndex = 0;
                        for ( var n=_startIndex; n<=_endIndex; n++ ) {
                            var scene = this.states.scenes[n];
                            scene.states.element._states.filmstripColumnIndex = columnIndex+1;
                            this.positionScene(scene, columnIndex);
                            
                            scene.states.element.style.display = "block";
                            
                            var isSceneSelected = !!( scene.states.element._states.selected && GRAB.extensions.component.filmstrip.states.currentSceneElement );
                            if (isSceneSelected){
                                GRAB.extensions.component.filmstrip.positionSceneMarker();
                                GRAB.extensions.component.filmstrip.showSceneMarker();
                            }
                            
                            columnIndex += 1;
                        }
                        this.states.firstVisibleSceneIndex = _startIndex;
                        this.states.lastVisibleSceneIndex = _endIndex;
                    },
                    
                    showNextScenes: function(){
                        var sceneOffset = this.states.maxScenesPerSet;
                        var newFirstIndex = this.states.firstVisibleSceneIndex + sceneOffset;
                        var newLastIndex = this.states.lastVisibleSceneIndex + sceneOffset;
                        this.showRangeOfScenes(newFirstIndex, newLastIndex);
                        
                        this.states.changeSetCallback();
                    },
                    
                    showPreviousScenes: function(){
                        var sceneOffset = this.states.maxScenesPerSet;
                        var newFirstIndex = this.states.firstVisibleSceneIndex - sceneOffset;
                        var newLastIndex = this.states.lastVisibleSceneIndex - sceneOffset;
                        this.showRangeOfScenes(newFirstIndex, newLastIndex);
                        
                        this.states.changeSetCallback();
                    },
                    
                    positionScene: function( _scene, _columnIndex ){
                        var distanceFromLeft = _columnIndex * (_scene.states.leftMargin + _scene.states.width);
                        _scene.states.element.style.left = distanceFromLeft + "px";
                    }
                }
            }
        }
    };

