﻿/* HPW Config Based JS */

$config = {};


/* --------------------------------------------------- 
    extend element properties hash for 'extenders'. 
--------------------------------------------------- */
Element.Properties.extenders = {
    get : $lambda(false),
    set : function(value){
        for(var n in value)
        {
            this[n] = value[n].bind ? 
                value[n].bind(this) : value[n];
        }
    }
};

var formatNumber = function(n)
{
    var out = [],
        num = ('' + n).split(''),
        delta = 0;
    
    while( num.length > 0 )
    {
        out.unshift( num.pop() );
        if( num.length > 0 && (( out.length % 3 ) == delta) )
        {
            out.unshift(',');
            delta++;    
        }
    }
    
    return '$' + out.join('');
}

var unFormatNumber = function(n)
{
    return n.replace(/\D/g,'').toInt();
}

/* ---------------------------------------------------
    Tree Class
---------------------------------------------------- */
var Tree = new Class({

    Implements : [ Chain, Events, Options ],
    
    options : {},
    
    initialize : function(options)
    {
        this.setOptions(options);
        
        this.data   = this.options.data;
        this.hidden = this.options.hidden 
                    = $( this.options.hidden );
        
        var tree    = new Element('ul')
                        .addClass('tree');
                
        this.hidden
            .grab( tree, 'after' );
            
        tree.adopt( 
            this.data.map( 
                this.createBranch.bind(this) ) );
                
        tree.instance = this;
        
        this.tree = tree;
        
        return this;
    },
    
    createBranch : function(data)
    {
        var branch = new Element('li',{ 'class' : 'branch' });
        
        if( data.text )
            branch.set({ text : data.text });
            
        if( data.value )
            branch.store( 'value', data.value );
        
        if( data.children )
        {
            var sub_branches = 
                new Element( 'ul',{ 'class' : 'sub-branches' } )
                    .inject( branch )
                    .adopt(
                        $A( data.children )
                            .map( this.createBranch ) );
        }
                    
        return branch;
    }

});

/* --------------------------------------------------- 
    register all config items on 'domready'
--------------------------------------------------- */
window.addEvent('domready',function(){

    var elements = $A([]);
    
    for( var selector in $config )
    {
            $(document.body)
                .getElements(selector)
                    .set( $config[selector] )
                        .each(elements.include, elements);
    }
    
    $A(elements).each(function(e){
        e.fireEvent('init');
    });
});



$config = $extend($config, {
    /* --------------------------------------------------- 
    hoverable (easy mouse over...)
    --------------------------------------------------- */
    '.hoverable': {
        events: {
            mouseenter: function() {
                this.addClass('hover');
            },
            mouseleave: function() {
                this.removeClass('hover');
            }
        }
    },
    /* --------------------------------------------------- 
    clickable : follow the first child link found
    --------------------------------------------------- */
    '.clickable': {
        events: {
            click: function() {
                var A = this.getFirst('a[href]');

                window.location = A.get('href');
            }
        }
    },
    /* --------------------------------------------------- 
    slider
    --------------------------------------------------- */
    '.slider': {
        extenders: {
            setValue: function(step) {
                var value = step ? step * 10000 : 0;
                this.input.set('value', formatNumber(value));
            }
        },
        events: {
            init: function() {

                this.bar = this.getElement('.bar');
                this.knob = this.getElement('.knob');
                this.input = this.getParent('.field').getElement('input');
                this.instance = new Slider(this.bar, this.knob, {
                    onChange: this.setValue.bindWithEvent(this)
                });

                var step = unFormatNumber(this.input.get('value')) / 10000;
                this.instance.set(step);
            }
        }
    },
    '.slider.price-slider': {
        extenders: {
            getRange: function() {
                return [0, 1000000];
            }
        }
    },
    /* --------------------------------------------------- 
    converts raw slider data into price data
    --------------------------------------------------- */
    '.price-input': {
        events: {
            'change': function() {
                var val = this.get('value');
                val = toMoney(val);
                val = val == '$1,000,000' ? val + '+' : val;
                this.set('value', val);
            }
        }
    },
    /* --------------------------------------------------- 
    pretty select boxes
    --------------------------------------------------- */
    '.select-box': {
        extenders: {
            getValue: function(item) {
                return this.getElement('.box')
                            .get('text') || false;
            },
            showList: function() {
                $$('.select-box').each(this.blur);
                this.focus();
                this.list.addClass('show');
                this.setTimeout(3000);
            },
            hideList: function() {
                this.list.removeClass('show');
            },
            setTimeout: function(x) {
                x = x || 500;
                this.store('timeOut',
                    this.hideList.delay(x, this));
            },
            clearTimeout: function() {
                $clear(this.retrieve('timeOut'));
            },
            focus: function(e) {
                e = e || this;
                e.addClass('focus');
                e.getParent().addClass('focus');
            },
            blur: function(e) {
                e = e || this;
                e.removeClass('focus');
                e.getParent().removeClass('focus');
            },
            setSelected: function(e) {
                this.box.set('text', e.get('text'));
                this.getElement('.list .item.selected')
                    .removeClass('selected');
                e.addClass('selected');
                this.input.set('value', e.get('text'));
                this.hideList();
                this.fireEvent('itemSelected');
            }
        },
        events: {
            init: function() {
                this.box = this.getElement('.box');
                this.button = this.getElement('.button');
                this.list = this.getElement('.list');
                this.input = this.getElement('input');
            }
        }
    },
    '.select-box .button': {
        events: {
            click: function() {
                this.getParent('.select-box')
                    .showList();
            }
        }
    },
    '.select-box .list': {
        events: {
            init: function() {
                this._parent =
                    this.getParent('.select-box');
            },
            mouseleave: function() {
                this._parent.setTimeout(200);
            },
            mouseenter: function() {
                this._parent.clearTimeout();
            }
        }
    },
    '.select-box .list .item': {
        events: {
            click: function() {
                this.getParent('.select-box')
                    .setSelected(this);
            },
            mouseenter: function() {
                this.addClass('hover');
            },
            mouseleave: function() {
                this.removeClass('hover');
            }
        }
    },
    /* --------------------------------------------------- 
    message box
    --------------------------------------------------- */
    '#message': {
        extenders: {
            show: function(title, msg) {
                this.getElement('.header').set('text', title);
                this.getElement('.text').set('text', msg);
                this.addClass('show');
                this.center();
            },
            center: function() {
                var w = Window.getSize();
                var m = this.getSize();
                var x = (w.x / 2) - (m.x / 2);
                var y = (w.y / 2) - (m.y / 2);

                this.setStyles({
                    top: y,
                    left: x
                });
            }
        }
    },
    '#message .button': {
        events: {
            click: function() {
                $('message').removeClass('show');
            }
        }
    },
    /* --------------------------------------------------- 
    search message
    --------------------------------------------------- */
    '#search_message': {
        morph: {
            duration: 1000,
            transition: 'elastic:out'
        },
        extenders: {
            _show: function() {

                var b = this
                    .getElement('.body')
                    .setStyle('opacity', 0);

                this.set({ morph: { transition: 'elastic:out'} });
                this.center()
                    .setStyle('display', 'block')
                    .morph({
                        'height': [0, 250],
                        'margin-top': [0, -125]
                    });

                b.show.delay(1000, b);
            },
            _hide: function() {

                var b = this
                    .getElement('.body')
                    .morph({ opacity: 0 });

                /*-------------------------
                the elastic transition
                breaks in ie because it
                can't handle a negative
                height value...
                --------------------------*/
                this.set({ morph: { transition: 'linear'} });
                this.morph.delay(500, this, { height: 0, 'margin-top': 0 });
            },
            show: function(css) {
                if (!css) return this._show();
                this.getElements(css).addClass('show');
            },
            hide: function(css) {
                if (!css) return this._hide();
                this.getElements(css).removeClass('show');
            },
            center: function() {
                this.setStyle('top',
                    (Window.getSize().y / 2) -
                    (this.getSize().y / 2) +
                    Window.getScroll().y);
                return this;
            },
            setMessage: function(title, body) {
                this.getElement('h1').set('text', title);
                this.getElement('h2').set('text', body);
            },
            onSearchRequest: function() {
                this.setMessage('Searching...',
                    'We are currently searching over 10,000 area listings.');
                this.show();
            },
            onSearchSuccess: function(text) {

                this.hide('img');

                var data = JSON.decode(text);

                if (data.error) {
                    this.setMessage('Search Error', data.error);
                    this.show('.cancel-button');
                }

                if (data.message) {
                    this.setMessage('Search Complete', data.message)
                    this.show('.button');
                }
            },
            onSearchFailure: function(sd) {
                alert('search failed ' + sd.toSource());
            }
        },
        events: {
            init: function() {
                this.setStyle('display', 'none');
                this.getElement('.shadow')
                    .set('opacity', 0.5);

                $search = new Request({
                    url: $baseURL + 'services/json.ashx?op=property-search'
                });

                $search.addEvents({
                    'request': this.onSearchRequest.bind(this),
                    'success': this.onSearchSuccess.bind(this),
                    'failure': this.onSearchFailure.bind(this)
                });
            }
        }
    },
    '#search_message .body': {
        morph: {
            duration: 500
        },
        extenders: {
            show: function() {
                this.morph({ 'opacity': 1 });
            },
            hide: function(delay) {
                this.morph({ 'opacity': 0 });
            }
        }
    },
    '#search_message .button.view-button': {
        events: {
            click: function() {
                window.location = $baseURL + 'search/property-results.aspx'
            }
        }
    },
    '#search_message .button.cancel-button': {
        events: {
            click: function() {
                $('search_message').hide();
            }
        }
    },
    /* --------------------------------------------------- 
    generic button
    --------------------------------------------------- */
    '.button': {
        events: {
            mousedown: function(ev) {
                this.addClass('down');
                ev.preventDefault();
            },
            mouseup: function() {
                this.removeClass('down');
            },
            mouseenter: function() {
                this.addClass('hover');
            },
            mouseleave: function() {
                this.removeClass('hover')
                    .removeClass('down');
            }
        }
    },
    /*----------------------------------------------------
    input
    -----------------------------------------------------*/
    'input': {
        events: {
            keypress: function(k) {
                if (k.key != "enter") return;
                var b = $$('.default-button')[0];
                if (b) b.fireEvent('click');
            }
        }
    },
    /* --------------------------------------------------- 
    submit buttons
    --------------------------------------------------- */
    '.submit-button': {
        events: {
            click: function() {
                $$('form')[0].submit();
            }
        }
    },
    /* --------------------------------------------------- 
    tabs
    --------------------------------------------------- */
    '.tab': {
        events: {
            mousedown: function(ev) {
                ev.preventDefault();
            },
            click: function() {

                var container = this.getParent('.tab-view-container');

                var tabs = container.getFirst('.tab-list').getChildren('.tab');

                var views = container.getChildren('.tab-view');

                var curTab = container.getFirst('.tab-list').getFirst('.tab.selected')
                if (curTab)
                    curTab.removeClass('selected');

                var curView = container.getFirst('.tab-view.show');
                if (curView)
                    curView.removeClass('show');

                this.addClass('selected');

                $(this.get('id').replace('_tab', '').replace('_Tab', '')).addClass('show');

                var kids = container.getChildren();

                var input = container.getFirst('input');

                if (input)
                    input.set('value', this.get('id').replace('_Tab', '').replace('_tab', ''));
            }
        }
    },
    /* --------------------------------------------------- 
    table rows
    --------------------------------------------------- */
    '.prop-row': {
        'events': {
            'click': function() { 
                //window.location = this.getElement('a').get('href');
                window.open(this.getElement('a').get('href'), '_blank');

            }
        }
    },
    /* --------------------------------------------------- 
    scrollers
    --------------------------------------------------- */
    '.scroller': {
        extenders: {
            setPeriodical: function(x) {
                x = x || 5000;
                this.store('periodical', this.doScroll.periodical(x, this));
            },
            clearPeriodical: function() {
                $clear(this.retrieve('periodical'));
            },
            doScroll: function() {

                var scroller = this.retrieve('scroller', new Fx.Scroll(this, {
                    //transition:Fx.Transitions.Bounce.easeOut, 
                    duration: 1000
                }));
                var i = this.retrieve('scroll_index', 0);
                var kids = this.getChildren();

                if (i >= kids.length) {
                    i = 0;
                }

                scroller.toElement(kids[i]);

                i++;

                this.store('scroll_index', i);
            }
        },
        'events': {
            'init': function() {
               // this.setPeriodical();
            },
            'mouseenter': function() {
                this.clearPeriodical();
            },
            'mouseleave': function() {
              //  this.setPeriodical();
            }
        }
    },
    /* --------------------------------------------------- 
    photo slide show
    --------------------------------------------------- */
    '.photo-slide-show': {
        'events': {
            'init': function() {

                var ldr = this.getElement('.loader');
                var con = this.get('id') + '-loading'; /* create a que context */


                /* add thumbs */
                var thumbs = this.getElements('.thumbnail');

                for (var i = 0; i < thumbs.length; i++) {
                    $q.add({
                        context: con,
                        element: thumbs[i],
                        props: {
                            opacity: 0.5
                        }
                    });
                }


                /* add loader to que */
                $q.add({
                    context: con,
                    element: ldr,
                    props: {
                        opacity: 0
                    }
                });



                /* setup scroller */
                this.store(
                    'scroller',
                    new Fx.Scroll(this.getElement('.show'), {
                        duration: 500
                    })
                );
            }
        }
    },
    '.photo-slide-show .control': {
        events: {
            click: function() {

                var show = this
                    .getParent('.photo-slide-show')
                    .getElement('.show');

                var pos = show.getScroll();

                var scroller = this
                    .getParent('.photo-slide-show')
                    .retrieve('scroller');

                if (this.hasClass('right'))
                    pos.x += 200;

                if (this.hasClass('left'))
                    pos.x -= 200;

                scroller.start(pos.x, pos.y);
            }
        }
    },
    '.photo-slide-show .loader': {
        morph: {
            duration: 250
        }
    },
    '.photo-slide-show .thumbnail': {
        morph: {
            duration: 500
        },
        styles: {
            opacity: 0,
            display: 'inline-block'
        },
        extenders: {
            onPhotoLoaded: function(img) {
                this.store('cache', img);
                $('light_box').showPhoto(img);
            }
        },

        events: {
            mouseenter: function() {
                this.set({ 'opacity': 1 });
            },
            mouseleave: function() {
                this.set({ 'opacity': 0.5 });
            },
            click: function(ev) {

                ev.preventDefault();

                var sb = $('shadow_box');
                var lb = $('light_box');

                lb.retrieve('photo')
                    .set({ opacity: 0 });

                $q.add({
                    context: 'light-box-appear',
                    element: sb,
                    props: { opacity: 0.75 }
                })
                    .add({
                        context: 'light-box-appear',
                        element: lb,
                        props: { opacity: 1 }
                    });

                var c = this.retrieve('cache');

                /*
                if(!c)
                {
                new Asset.image(
                this.get('href'),
                {
                onload : this.onPhotoLoaded.bind(this)
                }
                );
                }
                else
                {
                lb.showPhoto( c );
                }*/
            }
        }
    },
    '#shadow_box': {
        styles: {
            display: 'block',
            opacity: 0
        }
    },
    '#light_box': {
        styles: {
            display: 'block',
            opacity: 0
        },
        extenders: {
            showPhoto: function(img) {

                img.addClass('photo')
                    .set($config['#light_box .photo'])
                    .replaces(this.retrieve('photo'));

                this.store('photo', img);

                var is = img.getSize();

                /*.add({
                context : 'light-box-appear',
                element : this.getElement('.loader'),
                props   : {
                opacity : 0
                }
                })*/
                $q.add({
                    context: 'light-box-appear',
                    element: this,
                    props: {
                        width: is.x + 20,
                        'margin-left': -(is.x + 20) / 2
                    }
                })
                    .add({
                        context: 'light-box-appear',
                        element: this,
                        props: {
                            height: is.y + 20,
                            'margin-top': -(is.y + 20) / 2
                        }
                    })
                    .add({
                        context: 'light-box-appear',
                        element: img,
                        props: {
                            opacity: 1
                        }
                    });
            }
        },
        events: {
            init: function() {
                this.store('photo',
                    this.getElement('.photo'));
            },
            click: function() {
                $q.add({
                    context: 'light-box-fade',
                    element: this,
                    props: {
                        opacity: 0
                    },
                    options: {
                        onComplete: function() {
                            var e = this.element;
                            if (e.get('opacity') == 0)
                                e.retrieve('photo')
                                        .set({ opacity: 0 });
                        }
                    }
                })
                    .add({
                        context: 'light-box-fade',
                        element: $('shadow_box'),
                        props: {
                            opacity: 0
                        }
                    });
            }
        }
    },
    '#light_box .photo': {
        styles: {
            opacity: 0
        }
    },
    /*--------------------------------------------------------------
    GRID VIEWS
    ---------------------------------------------------------------*/
    /* add delete confirmation...*/
    '.grid-view a:contains(Delete)': {
        events: {
            click: function(ev) {
                if (!confirm("Are you sure you want to delete this item?")) {
                    ev.preventDefault();
                }
            }
        }
    },
    /* make rows selectable... */
    '.grid-view a:contains(Select)': {
        events: {
            init: function() {
                //make parent row clickable
                this.getParent('tr').getElement('td').set({
                    events: {
                        click: (function() { window.location = this.href; }).bind(this)
                    }
                });
            }
        }
    }
});

    var toMoney = function(str)
    {
        str = str.replace(/\D/g,''); //remove non-digits
        
        var chars = str.split('').reverse();
        
        var new_str = '$';
        
        do
        {
            new_str += chars.pop();
            if( chars.length != 0 && 
                chars.length % 3 == 0 )
            {
                new_str += ',';
            }
        }
        while(chars.length > 0);
        
        return new_str;
    }
    
    /* --------------------------------------------------- 
        $global global
    --------------------------------------------------- */
    var $global = {};

    /* --------------------------------------------------- 
        $search global
    --------------------------------------------------- */
    var $search = false;
    
    var $q = {
        cons : {},
        /*--------------------------------------
            add cfg is obj literal : 
            {
                context : queue context,
                element : element to morph,
                props   : props to morph,
                options : morph options
            }
        ----------------------------------------*/
        add : function( cfg ){
            
            /* -----------------------------------
                create the context specified 
                if it does not exist 
            ------------------------------------*/
            if(!$q.cons[cfg.context])
                $q.cons[cfg.context] = []; 
            
            var c = $q.cons[cfg.context];
            var m = cfg.element.get('morph');
            
            if( cfg.options )
                m.setOptions( cfg.options );
            
            /* set context ref */
            m.$qc = c;
            
            /* add chain function */
            m.chain(function(){
            
                /*-------------------------------
                    should be removing the 
                    fx that just completed... 
                ---------------------------------*/
                this.$qc.shift(); 
                var f = this.$qc[0];
                if(f) f();
                
            });
            
            /*-------------------------------
                build morph function that
                goes in the context
                array. 
            ---------------------------------*/
            var f = m.start.bind( m, cfg.props );
                
            c.push(f);    
            
            if( c[0] == f ) f();
            
            return this;
        }
    };



