/*
 * Ext JS Library 2.1
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */

Ext.app.SearchField = Ext.extend(
	 Ext.form.TwinTriggerField, {
		  initComponent : function(){
			   Ext.app.SearchField.superclass.initComponent.call(this);
			   this.on('specialkey', function(f, e){
							if(e.getKey() == e.ENTER){
								 this.onTrigger2Click();
							}
					   }, this);
		  },

		  validationEvent:false,
		  validateOnBlur:false,
		  trigger1Class:'x-form-clear-trigger',
		  trigger2Class:'x-form-search-trigger',
		  hideTrigger1:true,
		  width:105,
		  hasSearch : false,
		  paramName : 'query',

		  onTrigger1Click : function(){
			   if(this.hasSearch){
					this.el.dom.value = '';
					var o = {start: 0};
					this.store.baseParams = this.store.baseParams || {};
					this.store.baseParams[this.paramName] = '';
					this.store.reload({params:o});
					this.triggers[0].hide();
					this.hasSearch = false;
			   }
		  },

		  onTrigger2Click : function(){
			   var v = this.getRawValue();
			   if(v.length < 1){
					this.onTrigger1Click();
					return;
			   }

			   trackALFEvent('/ALF/Search/PickUp/' + v);
			   var o = {start: 0};
			   this.store.baseParams = this.store.baseParams || {};
			   this.store.baseParams[this.paramName] = v;
			   this.store.reload({params:o});
			   this.hasSearch = true;
			   this.triggers[0].show();
		  }
	 });
;
// some data used in the examples
Ext.namespace('Ext.exampledata');

Ext.exampledata.states = [
	 [       1 ,'AL'       , translate('Alabama')],
	 [       2 ,'AK'       , translate('Alaska')],
	 [       3 ,'AS'       , translate('American Samoa')],
	 [       4 ,'AZ'       , translate('Arizona')],
	 [       5 ,'AR'       , translate('Arkansas')],
	 [       6 ,'CA'       , translate('California')],
	 [       7 ,'CO'       , translate('Colorado')],
	 [       8 ,'CT'       , translate('Connecticut')],
	 [       9 ,'DE'       , translate('Delaware')],
	 [      10 ,'DC'       , translate('District of Columbia')],
	 [      11 ,'FM'       , translate('Federated States of Micronesia')],
	 [      12 ,'FL'       , translate('Florida')],
	 [      13 ,'GA'       , translate('Georgia')],
	 [      14 ,'GU'       , translate('Guam')],
	 [      15 ,'HI'       , translate('Hawaii')],
	 [      16 ,'ID'       , translate('Idaho')],
	 [      17 ,'IL'       , translate('Illinois')],
	 [      18 ,'IN'       , translate('Indiana')],
	 [      19 ,'IA'       , translate('Iowa')],
	 [      20 ,'KS'       , translate('Kansas')],
	 [      21 ,'KY'       , translate('Kentucky')],
	 [      22 ,'LA'       , translate('Louisiana')],
	 [      23 ,'ME'       , translate('Maine')],
	 [      24 ,'MH'       , translate('Marshall Islands')],
	 [      25 ,'MD'       , translate('Maryland')],
	 [      26 ,'MA'       , translate('Massachusetts')],
	 [      27 ,'MI'       , translate('Michigan')],
	 [      28 ,'MN'       , translate('Minnesota')],
	 [      29 ,'MS'       , translate('Mississippi')],
	 [      30 ,'MO'       , translate('Missouri')],
	 [      31 ,'MT'       , translate('Montana')],
	 [      32 ,'NE'       , translate('Nebraska')],
	 [      33 ,'NV'       , translate('Nevada')],
	 [      34 ,'NH'       , translate('New Hampshire')],
	 [      35 ,'NJ'       , translate('New Jersey')],
	 [      36 ,'NM'       , translate('New Mexico')],
	 [      37 ,'NY'       , translate('New York')],
	 [      38 ,'NC'       , translate('North Carolina')],
	 [      39 ,'ND'       , translate('North Dakota')],
	 [      40 ,'MP'       , translate('Northern Mariana Islands')],
	 [      41 ,'OH'       , translate('Ohio')],
	 [      42 ,'OK'       , translate('Oklahoma')],
	 [      43 ,'OR'       , translate('Oregon')],
	 [      44 ,'PW'       , translate('Palau')],
	 [      45 ,'PA'       , translate('Pennsylvania')],
	 [      46 ,'PR'       , translate('Puerto Rico')],
	 [      47 ,'RI'       , translate('Rhode Island')],
	 [      48 ,'SC'       , translate('South Carolina')],
	 [      49 ,'SD'       , translate('South Dakota')],
	 [      50 ,'TN'       , translate('Tennessee')],
	 [      51 ,'TX'       , translate('Texas')],
	 [      52 ,'UT'       , translate('Utah')],
	 [      53 ,'VT'       , translate('Vermont')],
	 [      54 ,'VI'       , translate('Virgin Islands')],
	 [      55 ,'VA'       , translate('Virginia')],
	 [      56 ,'WA'       , translate('Washington')],
	 [      57 ,'WV'       , translate('West Virginia')],
	 [      58 ,'WI'       , translate('Wisconsin')],
	 [      59 ,'WY'       , translate('Wyoming')]
];
;
// simple array store
var stateStore = new Ext.data.SimpleStore({
	 fields: ['value', 'abbr', 'text'],
	 data : Ext.exampledata.states // from states.js
});

var stateCombo = new Ext.form.ComboBox({
	 name:'statename',
	 id:'address-state-combo',
	 store: stateStore,
	 displayField:'text',
	 typeAhead: true,
	 mode: 'local',
	 triggerAction: 'all',
	 emptyText:translate('Select a state...'),
	 selectOnFocus:true,
	 fieldLabel:translate('State'),
	 valueField:'abbr',
	 tabIndex:5,
	 allowBlank:false,
	 blankText:translate('State is required'),
	 forceSelection:true,
	 hiddenName:'state'
});
;
/*!
 * Ext JS Library 3.2.1
 * Copyright(c) 2006-2010 Ext JS, Inc.
 * licensing@extjs.com
 * http://www.extjs.com/license
 */
/**
 * @class Ext.ux.StatusBar
 * <p>Basic status bar component that can be used as the bottom toolbar of any {@link Ext.Panel}.  In addition to
 * supporting the standard {@link Ext.Toolbar} interface for adding buttons, menus and other items, the StatusBar
 * provides a greedy status element that can be aligned to either side and has convenient methods for setting the
 * status text and icon.  You can also indicate that something is processing using the {@link #showBusy} method.</p>
 * <pre><code>
new Ext.Panel({
    title: 'StatusBar',
    // etc.
    bbar: new Ext.ux.StatusBar({
        id: 'my-status',

        // defaults to use when the status is cleared:
        defaultText: 'Default status text',
        defaultIconCls: 'default-icon',

        // values to set initially:
        text: 'Ready',
        iconCls: 'ready-icon',

        // any standard Toolbar items:
        items: [{
            text: 'A Button'
        }, '-', 'Plain Text']
    })
});

// Update the status bar later in code:
var sb = Ext.getCmp('my-status');
sb.setStatus({
    text: 'OK',
    iconCls: 'ok-icon',
    clear: true // auto-clear after a set interval
});

// Set the status bar to show that something is processing:
sb.showBusy();

// processing....

sb.clearStatus(); // once completeed
</code></pre>
 * @extends Ext.Toolbar
 * @constructor
 * Creates a new StatusBar
 * @param {Object/Array} config A config object
 */
Ext.ux.StatusBar = Ext.extend(Ext.Toolbar, {
    /**
     * @cfg {String} statusAlign
     * The alignment of the status element within the overall StatusBar layout.  When the StatusBar is rendered,
     * it creates an internal div containing the status text and icon.  Any additional Toolbar items added in the
     * StatusBar's {@link #items} config, or added via {@link #add} or any of the supported add* methods, will be
     * rendered, in added order, to the opposite side.  The status element is greedy, so it will automatically
     * expand to take up all sapce left over by any other items.  Example usage:
     * <pre><code>
// Create a left-aligned status bar containing a button,
// separator and text item that will be right-aligned (default):
new Ext.Panel({
    title: 'StatusBar',
    // etc.
    bbar: new Ext.ux.StatusBar({
        defaultText: 'Default status text',
        id: 'status-id',
        items: [{
            text: 'A Button'
        }, '-', 'Plain Text']
    })
});

// By adding the statusAlign config, this will create the
// exact same toolbar, except the status and toolbar item
// layout will be reversed from the previous example:
new Ext.Panel({
    title: 'StatusBar',
    // etc.
    bbar: new Ext.ux.StatusBar({
        defaultText: 'Default status text',
        id: 'status-id',
        statusAlign: 'right',
        items: [{
            text: 'A Button'
        }, '-', 'Plain Text']
    })
});
</code></pre>
     */
    /**
     * @cfg {String} defaultText
     * The default {@link #text} value.  This will be used anytime the status bar is cleared with the
     * <tt>useDefaults:true</tt> option (defaults to '').
     */
    /**
     * @cfg {String} defaultIconCls
     * The default {@link #iconCls} value (see the iconCls docs for additional details about customizing the icon).
     * This will be used anytime the status bar is cleared with the <tt>useDefaults:true</tt> option (defaults to '').
     */
    /**
     * @cfg {String} text
     * A string that will be <b>initially</b> set as the status message.  This string
     * will be set as innerHTML (html tags are accepted) for the toolbar item.
     * If not specified, the value set for <code>{@link #defaultText}</code>
     * will be used.
     */
    /**
     * @cfg {String} iconCls
     * A CSS class that will be <b>initially</b> set as the status bar icon and is
     * expected to provide a background image (defaults to '').
     * Example usage:<pre><code>
// Example CSS rule:
.x-statusbar .x-status-custom {
    padding-left: 25px;
    background: transparent url(images/custom-icon.gif) no-repeat 3px 2px;
}

// Setting a default icon:
var sb = new Ext.ux.StatusBar({
    defaultIconCls: 'x-status-custom'
});

// Changing the icon:
sb.setStatus({
    text: 'New status',
    iconCls: 'x-status-custom'
});
</code></pre>
     */

    /**
     * @cfg {String} cls
     * The base class applied to the containing element for this component on render (defaults to 'x-statusbar')
     */
    cls : 'x-statusbar',
    /**
     * @cfg {String} busyIconCls
     * The default <code>{@link #iconCls}</code> applied when calling
     * <code>{@link #showBusy}</code> (defaults to <tt>'x-status-busy'</tt>).
     * It can be overridden at any time by passing the <code>iconCls</code>
     * argument into <code>{@link #showBusy}</code>.
     */
    busyIconCls : 'x-status-busy',
    /**
     * @cfg {String} busyText
     * The default <code>{@link #text}</code> applied when calling
     * <code>{@link #showBusy}</code> (defaults to <tt>'Loading...'</tt>).
     * It can be overridden at any time by passing the <code>text</code>
     * argument into <code>{@link #showBusy}</code>.
     */
    busyText : 'Loading...',
    /**
     * @cfg {Number} autoClear
     * The number of milliseconds to wait after setting the status via
     * <code>{@link #setStatus}</code> before automatically clearing the status
     * text and icon (defaults to <tt>5000</tt>).  Note that this only applies
     * when passing the <tt>clear</tt> argument to <code>{@link #setStatus}</code>
     * since that is the only way to defer clearing the status.  This can
     * be overridden by specifying a different <tt>wait</tt> value in
     * <code>{@link #setStatus}</code>. Calls to <code>{@link #clearStatus}</code>
     * always clear the status bar immediately and ignore this value.
     */
    autoClear : 5000,

    /**
     * @cfg {String} emptyText
     * The text string to use if no text has been set.  Defaults to
     * <tt>'&nbsp;'</tt>).  If there are no other items in the toolbar using
     * an empty string (<tt>''</tt>) for this value would end up in the toolbar
     * height collapsing since the empty string will not maintain the toolbar
     * height.  Use <tt>''</tt> if the toolbar should collapse in height
     * vertically when no text is specified and there are no other items in
     * the toolbar.
     */
    emptyText : '&nbsp;',

    // private
    activeThreadId : 0,

    // private
    initComponent : function(){
        if(this.statusAlign=='right'){
            this.cls += ' x-status-right';
        }
        Ext.ux.StatusBar.superclass.initComponent.call(this);
    },

    // private
    afterRender : function(){
        Ext.ux.StatusBar.superclass.afterRender.call(this);

        var right = this.statusAlign == 'right';
        this.currIconCls = this.iconCls || this.defaultIconCls;
        this.statusEl = new Ext.Toolbar.TextItem({
            cls: 'x-status-text ' + (this.currIconCls || ''),
            text: this.text || this.defaultText || ''
        });

        if(right){
            this.add('->');
            this.add(this.statusEl);
        }else{
            this.insert(0, this.statusEl);
            this.insert(1, '->');
        }
        this.doLayout();
    },

    /**
     * Sets the status {@link #text} and/or {@link #iconCls}. Also supports automatically clearing the
     * status that was set after a specified interval.
     * @param {Object/String} config A config object specifying what status to set, or a string assumed
     * to be the status text (and all other options are defaulted as explained below). A config
     * object containing any or all of the following properties can be passed:<ul>
     * <li><tt>text</tt> {String} : (optional) The status text to display.  If not specified, any current
     * status text will remain unchanged.</li>
     * <li><tt>iconCls</tt> {String} : (optional) The CSS class used to customize the status icon (see
     * {@link #iconCls} for details). If not specified, any current iconCls will remain unchanged.</li>
     * <li><tt>clear</tt> {Boolean/Number/Object} : (optional) Allows you to set an internal callback that will
     * automatically clear the status text and iconCls after a specified amount of time has passed. If clear is not
     * specified, the new status will not be auto-cleared and will stay until updated again or cleared using
     * {@link #clearStatus}. If <tt>true</tt> is passed, the status will be cleared using {@link #autoClear},
     * {@link #defaultText} and {@link #defaultIconCls} via a fade out animation. If a numeric value is passed,
     * it will be used as the callback interval (in milliseconds), overriding the {@link #autoClear} value.
     * All other options will be defaulted as with the boolean option.  To customize any other options,
     * you can pass an object in the format:<ul>
     *    <li><tt>wait</tt> {Number} : (optional) The number of milliseconds to wait before clearing
     *    (defaults to {@link #autoClear}).</li>
     *    <li><tt>anim</tt> {Number} : (optional) False to clear the status immediately once the callback
     *    executes (defaults to true which fades the status out).</li>
     *    <li><tt>useDefaults</tt> {Number} : (optional) False to completely clear the status text and iconCls
     *    (defaults to true which uses {@link #defaultText} and {@link #defaultIconCls}).</li>
     * </ul></li></ul>
     * Example usage:<pre><code>
// Simple call to update the text
statusBar.setStatus('New status');

// Set the status and icon, auto-clearing with default options:
statusBar.setStatus({
    text: 'New status',
    iconCls: 'x-status-custom',
    clear: true
});

// Auto-clear with custom options:
statusBar.setStatus({
    text: 'New status',
    iconCls: 'x-status-custom',
    clear: {
        wait: 8000,
        anim: false,
        useDefaults: false
    }
});
</code></pre>
     * @return {Ext.ux.StatusBar} this
     */
    setStatus : function(o){
        o = o || {};

        if(typeof o == 'string'){
            o = {text:o};
        }
        if(o.text !== undefined){
            this.setText(o.text);
        }
        if(o.iconCls !== undefined){
            this.setIcon(o.iconCls);
        }

        if(o.clear){
            var c = o.clear,
                wait = this.autoClear,
                defaults = {useDefaults: true, anim: true};

            if(typeof c == 'object'){
                c = Ext.applyIf(c, defaults);
                if(c.wait){
                    wait = c.wait;
                }
            }else if(typeof c == 'number'){
                wait = c;
                c = defaults;
            }else if(typeof c == 'boolean'){
                c = defaults;
            }

            c.threadId = this.activeThreadId;
            this.clearStatus.defer(wait, this, [c]);
        }
        return this;
    },

    /**
     * Clears the status {@link #text} and {@link #iconCls}. Also supports clearing via an optional fade out animation.
     * @param {Object} config (optional) A config object containing any or all of the following properties.  If this
     * object is not specified the status will be cleared using the defaults below:<ul>
     * <li><tt>anim</tt> {Boolean} : (optional) True to clear the status by fading out the status element (defaults
     * to false which clears immediately).</li>
     * <li><tt>useDefaults</tt> {Boolean} : (optional) True to reset the text and icon using {@link #defaultText} and
     * {@link #defaultIconCls} (defaults to false which sets the text to '' and removes any existing icon class).</li>
     * </ul>
     * @return {Ext.ux.StatusBar} this
     */
    clearStatus : function(o){
        o = o || {};

        if(o.threadId && o.threadId !== this.activeThreadId){
            // this means the current call was made internally, but a newer
            // thread has set a message since this call was deferred.  Since
            // we don't want to overwrite a newer message just ignore.
            return this;
        }

        var text = o.useDefaults ? this.defaultText : this.emptyText,
            iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls : '') : '';

        if(o.anim){
            // animate the statusEl Ext.Element
            this.statusEl.el.fadeOut({
                remove: false,
                useDisplay: true,
                scope: this,
                callback: function(){
                    this.setStatus({
	                    text: text,
	                    iconCls: iconCls
	                });

                    this.statusEl.el.show();
                }
            });
        }else{
            // hide/show the el to avoid jumpy text or icon
            this.statusEl.hide();
	        this.setStatus({
	            text: text,
	            iconCls: iconCls
	        });
            this.statusEl.show();
        }
        return this;
    },

    /**
     * Convenience method for setting the status text directly.  For more flexible options see {@link #setStatus}.
     * @param {String} text (optional) The text to set (defaults to '')
     * @return {Ext.ux.StatusBar} this
     */
    setText : function(text){
        this.activeThreadId++;
        this.text = text || '';
        if(this.rendered){
            this.statusEl.setText(this.text);
        }
        return this;
    },

    /**
     * Returns the current status text.
     * @return {String} The status text
     */
    getText : function(){
        return this.text;
    },

    /**
     * Convenience method for setting the status icon directly.  For more flexible options see {@link #setStatus}.
     * See {@link #iconCls} for complete details about customizing the icon.
     * @param {String} iconCls (optional) The icon class to set (defaults to '', and any current icon class is removed)
     * @return {Ext.ux.StatusBar} this
     */
    setIcon : function(cls){
        this.activeThreadId++;
        cls = cls || '';

        if(this.rendered){
	        if(this.currIconCls){
	            this.statusEl.removeClass(this.currIconCls);
	            this.currIconCls = null;
	        }
	        if(cls.length > 0){
	            this.statusEl.addClass(cls);
	            this.currIconCls = cls;
	        }
        }else{
            this.currIconCls = cls;
        }
        return this;
    },

    /**
     * Convenience method for setting the status text and icon to special values that are pre-configured to indicate
     * a "busy" state, usually for loading or processing activities.
     * @param {Object/String} config (optional) A config object in the same format supported by {@link #setStatus}, or a
     * string to use as the status text (in which case all other options for setStatus will be defaulted).  Use the
     * <tt>text</tt> and/or <tt>iconCls</tt> properties on the config to override the default {@link #busyText}
     * and {@link #busyIconCls} settings. If the config argument is not specified, {@link #busyText} and
     * {@link #busyIconCls} will be used in conjunction with all of the default options for {@link #setStatus}.
     * @return {Ext.ux.StatusBar} this
     */
    showBusy : function(o){
        if(typeof o == 'string'){
            o = {text:o};
        }
        o = Ext.applyIf(o || {}, {
            text: this.busyText,
            iconCls: this.busyIconCls
        });
        return this.setStatus(o);
    }
});
Ext.reg('statusbar', Ext.ux.StatusBar);
;
/*!
 * Ext JS Library 3.2.1
 * Copyright(c) 2006-2010 Ext JS, Inc.
 * licensing@extjs.com
 * http://www.extjs.com/license
 */
/**
 * @class Ext.ux.ValidationStatus
 * A {@link Ext.ux.StatusBar} plugin that provides automatic error notification when the
 * associated form contains validation errors.
 * @extends Ext.Component
 * @constructor
 * Creates a new ValiationStatus plugin
 * @param {Object} config A config object
 */
Ext.ux.ValidationStatus = Ext.extend(Ext.Component, {
    /**
     * @cfg {String} errorIconCls
     * The {@link #iconCls} value to be applied to the status message when there is a
     * validation error. Defaults to <tt>'x-status-error'</tt>.
     */
    errorIconCls : 'x-status-error',
    /**
     * @cfg {String} errorListCls
     * The css class to be used for the error list when there are validation errors.
     * Defaults to <tt>'x-status-error-list'</tt>.
     */
    errorListCls : 'x-status-error-list',
    /**
     * @cfg {String} validIconCls
     * The {@link #iconCls} value to be applied to the status message when the form
     * validates. Defaults to <tt>'x-status-valid'</tt>.
     */
    validIconCls : 'x-status-valid',
    
    /**
     * @cfg {String} showText
     * The {@link #text} value to be applied when there is a form validation error.
     * Defaults to <tt>'The form has errors (click for details...)'</tt>.
     */
    showText : 'The form has errors (click for details...)',
    /**
     * @cfg {String} showText
     * The {@link #text} value to display when the error list is displayed.
     * Defaults to <tt>'Click again to hide the error list'</tt>.
     */
    hideText : 'Click again to hide the error list',
    /**
     * @cfg {String} submitText
     * The {@link #text} value to be applied when the form is being submitted.
     * Defaults to <tt>'Saving...'</tt>.
     */
    submitText : 'Saving...',
    
    // private
    init : function(sb){
        sb.on('render', function(){
            this.statusBar = sb;
            this.monitor = true;
            this.errors = new Ext.util.MixedCollection();
            this.listAlign = (sb.statusAlign=='right' ? 'br-tr?' : 'bl-tl?');
            
            if(this.form){
                this.form = Ext.getCmp(this.form).getForm();
                this.startMonitoring();
                this.form.on('beforeaction', function(f, action){
                    if(action.type == 'submit'){
                        // Ignore monitoring while submitting otherwise the field validation
                        // events cause the status message to reset too early
                        this.monitor = false;
                    }
                }, this);
                var startMonitor = function(){
                    this.monitor = true;
                };
                this.form.on('actioncomplete', startMonitor, this);
                this.form.on('actionfailed', startMonitor, this);
            }
        }, this, {single:true});
        sb.on({
            scope: this,
            afterlayout:{
                single: true,
                fn: function(){
                    // Grab the statusEl after the first layout.
                    sb.statusEl.getEl().on('click', this.onStatusClick, this, {buffer:200});
                } 
            }, 
            beforedestroy:{
                single: true,
                fn: this.onDestroy
            } 
        });
    },
    
    // private
    startMonitoring : function(){
        this.form.items.each(function(f){
            f.on('invalid', this.onFieldValidation, this);
            f.on('valid', this.onFieldValidation, this);
        }, this);
    },
    
    // private
    stopMonitoring : function(){
        this.form.items.each(function(f){
            f.un('invalid', this.onFieldValidation, this);
            f.un('valid', this.onFieldValidation, this);
        }, this);
    },
    
    // private
    onDestroy : function(){
        this.stopMonitoring();
        this.statusBar.statusEl.un('click', this.onStatusClick, this);
        Ext.ux.ValidationStatus.superclass.onDestroy.call(this);
    },
    
    // private
    onFieldValidation : function(f, msg){
        if(!this.monitor){
            return false;
        }
        if(msg){
            this.errors.add(f.id, {field:f, msg:msg});
        }else{
            this.errors.removeKey(f.id);
        }
        this.updateErrorList();
        if(this.errors.getCount() > 0){
            if(this.statusBar.getText() != this.showText){
                this.statusBar.setStatus({text:this.showText, iconCls:this.errorIconCls});
            }
        }else{
            this.statusBar.clearStatus().setIcon(this.validIconCls);
        }
    },
    
    // private
    updateErrorList : function(){
        if(this.errors.getCount() > 0){
	        var msg = '<ul>';
	        this.errors.each(function(err){
	            msg += ('<li id="x-err-'+ err.field.id +'"><a href="#">' + err.msg + '</a></li>');
	        }, this);
	        this.getMsgEl().update(msg+'</ul>');
        }else{
            this.getMsgEl().update('');
        }
    },
    
    // private
    getMsgEl : function(){
        if(!this.msgEl){
            this.msgEl = Ext.DomHelper.append(Ext.getBody(), {
                cls: this.errorListCls+' x-hide-offsets'
            }, true);
            
            this.msgEl.on('click', function(e){
                var t = e.getTarget('li', 10, true);
                if(t){
                    Ext.getCmp(t.id.split('x-err-')[1]).focus();
                    this.hideErrors();
                }
            }, this, {stopEvent:true}); // prevent anchor click navigation
        }
        return this.msgEl;
    },
    
    // private
    showErrors : function(){
        this.updateErrorList();
        this.getMsgEl().alignTo(this.statusBar.getEl(), this.listAlign).slideIn('b', {duration:0.3, easing:'easeOut'});
        this.statusBar.setText(this.hideText);
        this.form.getEl().on('click', this.hideErrors, this, {single:true}); // hide if the user clicks directly into the form
    },
    
    // private
    hideErrors : function(){
        var el = this.getMsgEl();
        if(el.isVisible()){
	        el.slideOut('b', {duration:0.2, easing:'easeIn'});
	        this.statusBar.setText(this.showText);
        }
        this.form.getEl().un('click', this.hideErrors, this);
    },
    
    // private
    onStatusClick : function(){
        if(this.getMsgEl().isVisible()){
            this.hideErrors();
        }else if(this.errors.getCount() > 0){
            this.showErrors();
        }
    }
});;
function trackALFEvent(eventName)
{
	 if(nd_pageTracker)
	 {
		  try
		  {
			   nd_pageTracker._trackPageview(eventName);
		  }
		  catch(e)
		  {
			   /* Do nothing */
			   ;
		  }
	 }
}
;
Ext.override(
	 Ext.Panel, {
		  onDisable : function() {
			   // super
			   if (this.disableChildsOnly) {
					this.disableChildren(this.items);
			   } else {
					Ext.Panel.superclass.onDisable.apply(this, arguments);
			   }
		  },

		  /***
		  * disableChildren
		  * disable child-fields recursively
		  * @param {Ext.util.MixedCollection} items
		  */
		  disableChildren : function(items) {
			   if(items == undefined) 
			   {
					items = this.items;	
			   }
			   
			   var fn = function(i) {
					if (i instanceof Ext.Component) 
					{
						 i.disable();
					}
					else if (i.items instanceof Ext.util.MixedCollection) 
					{
						 i.items.each(fn);
					}			
			   }		
			   this.items.each(fn);
		  },

		  /***
		  * onEnable
		  * provide FieldSet-specific impl of onEnable to recursively enable child fields.
		  */
		  onEnable : function() {
			   // super
			   if (this.disableChildsOnly) 
			   {
					this.enableChildren(this.items);
			   } 
			   else 
			   {
					Ext.Panel.superclass.onEnable.apply(this, arguments);
			   }
		  },
		  
		  /***
		  * enableChildren
		  * enable child-fields recursively
		  * @author Chris Scott
		  * @param {Object} items
		  */
		  enableChildren : function(items) {
			   if(items == undefined) 
			   {
					items = this.items;	
			   }		
			   
			   var fn = function(i) {
					if (i instanceof Ext.Component) 
					{
						 i.enable();
					}
					else if (i.items instanceof Ext.util.MixedCollection) 
					{
						 i.items.each(fn);
					}			
			   }		
			   this.items.each(fn);
		  }
	 }
);

Ext.apply(
	 Ext.form.VTypes, 
	 {
		  password: function(val, field) 
		  {
			   if (field.initialPassField) 
			   {
					var pwd = Ext.getCmp(field.initialPassField);
					return (val == pwd.getValue());
			   }
			   return true;
		  },
		  confirmemail: function(val, field) 
		  {
			   if(Ext.form.VTypes.email(val, field))
			   {
					if(field.initialEmailField)
					{
						 var eml = Ext.getCmp(field.initialEmailField);
						 return(val == eml.getValue());
					}
					return true;
			   }
			   return false;
		  },
  
		  passwordText: translate('Passwords do not match'),
		  confirmemailText: translate('Emails do not match')
	 }
);

Ext.namespace('Ext.NovaDine');

var addressTypeData = [
	 [1, translate("Residential")   ],
	 [2, translate("Business") ],
	 [3, translate("University")]
];

var addressTypeStore = new Ext.data.SimpleStore({
	 fields:['value', 'text'],
	 data: addressTypeData
});

Ext.NovaDine.Registration = function() {
	 var regoStateCombo = new Ext.form.ComboBox({
		  name:'statename',
		  store: stateStore,
		  fieldLabel:translate('State'),
		  displayField:'text',
		  valueField:'abbr',
		  typeAhead: true,
		  mode: 'local',
		  triggerAction: 'all',
		  emptyText:translate('Select a state...'),
		  selectOnFocus:true,
		  tabIndex:214,
		  allowBlank:false,
		  itemCls:'x-status-required',
		  blankText:translate('State is required'),
		  forceSelection:true,
		  hiddenName:'state'
	 });

	 var regoAddressTypeCombo = new Ext.form.ComboBox({
		  name:'address_type',
		  store: addressTypeStore,
		  fieldLabel:translate('Address Type'),
		  displayField:'text',
		  valueField:'value',
		  typeAhead: true,
		  mode: 'local',
		  triggerAction: 'all',
		  emptyText:translate('Type of address...'),
		  selectOnFocus:true,
		  tabIndex:209,
		  allowBlank:false,
		  itemCls:'x-status-required',
		  blankText:translate('Address Type is required'),
		  forceSelection:true,
		  hiddenName:'addresstype'
	 });

	 var rightFormItems = [{
		  xtype:'fieldset',
		  anchor:'100%',
		  autoHeight:true,
		  layout:'form',
		  title:translate('Address'),
		  id:'rego-right-panel',
		  defaultType:'textfield',
		  disableChildsOnly:true,
		  items:[ regoAddressTypeCombo, {
			   fieldLabel: translate('Number'),
			   name: 'stNum',
			   width: 50,
			   allowBlank:false,
			   itemCls:'x-status-required',
			   xtype:'textfield',
			   tabIndex:210,
			   blankText: translate('Street Number is required')
		  }, {
			   fieldLabel: translate('Street'),
			   name: 'address1',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   tabIndex:211,
			   blankText: translate('Street is required')
		  }, {
			   fieldLabel: translate('Suite'),
			   name: 'address2',
			   width: 50,
			   tabIndex:212
		  }, {
			   fieldLabel: translate('City'),
			   name: 'city',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   tabIndex:213,
			   blankText: translate('City is required')
		  }, regoStateCombo, {
			   fieldLabel: translate('Zip'),
			   name: 'zipcode',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   tabIndex:215,
			   blankText: translate('Zip is required')
		  }]}, {
			   fieldLabel: translate('Promo Code'),
			   name: 'zone',
			   allowBlank:true,
			   tabIndex:216
		  }];
	 
	 var leftFormItems = [ {
		  xtype:'fieldset',
		  anchor:'100%',
		  autoHeight:true,
		  layout:'form',
		  labelWidth:110,
		  title:translate('Details'),
		  id:'left-right-panel',
		  defaults: {anchor:'-20', width:230, validationDelay:500},
		  defaultType:'textfield',
		  items:[ {
			   id:'user-rego-form-companyname',
			   fieldLabel:translate('Company'),
			   tabIndex:201,
			   name:'companyname'
		  }, {
			   fieldLabel:translate('First Name'),
			   tabIndex:202,
			   name:'firstname',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   blankText:translate('First Name is required')
		  }, {
			   fieldLabel:translate('Last Name'),
			   tabIndex:203,
			   name:'lastname',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   blankText:translate('Last Name is required')
		  }, {
			   fieldLabel: translate('Phone Number'),
			   name: 'cellphone',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   tabIndex:204,
			   blankText: translate('Phone Number is required'),
			   maxLength: 10,
			   maxLengthText:translate('Phone Number should be 10 digits'),
			   minLength: 10,
			   minLengthText:translate('Phone Number should be 10 digits'),
			   maskRe: /[0-9]/,
			   stripCharsRe:/[^0-9]/
		  }, {
			   fieldLabel: translate('Email'),
			   name: 'email',
			   id:'rego-user-email',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   vtype:'email',
			   tabIndex:205,
			   blankText:translate("Email is required")
		  }, {
			   fieldLabel: translate('Confirm Email'),
			   name: 'confirmemail',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   vtype:'confirmemail',
			   initialEmailField:'rego-user-email',
			   tabIndex:206,
			   blankText:translate("Confirm Email is required")
		  }, {
			   fieldLabel: translate('Password'),
			   name: 'password',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   tabIndex:207,
			   inputType:'password',
			   id:'registration-password',
			   blankText:translate("Password is required")
		  }, {
			   fieldLabel: translate('Confirm Password'),
			   name: 'confirmpassword',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   tabIndex:208,
			   vtype:'password',
			   inputType:'password',
			   initialPassField:'registration-password',
			   blankText:translate("Confirm Password is required")
		  }, {

			   hideLabel:true,
			   name: 'optin',
			   id: 'registration-optin',
			   allowBlank:false,
			   itemCls:'x-status-required',
			   tabIndex:208,
			   xtype:'checkbox',
			   width: 340,
			   blankText:translate("Special Offers is required"),
			   // boxLabel: translate('Subscribe')
			   boxLabel: translate('Sign me up to receive exclusive offers')
		  }]
	 }];

	 var registrationFormBody = new Ext.form.FormPanel({
		  id: 'user-rego-form',
		  width:600,
		  autoHeight:true,
		  border:false,
		  items:[{
			   layout:'column',
			   items:[ {						 
					columnWidth:.5,
					layout:'form',
					defaults:{autoHeight:true},
					border:false,
					defaultType:'textfield',
					items:leftFormItems
			   }, {
					columnWidth:.5,
					border:false,
					defaultType:'textfield',
					layout:'form',
					defaults:{autoHeight:true},
					items: rightFormItems
			   }
					]}
			   ]}
		  );


	 var registrationForm = new Ext.Panel({
			   autoHeight:true,
			   border:false,
			   items:registrationFormBody,
			   bbar: new Ext.ux.StatusBar({
					id:'registration-statusbar',
					defaultText: translate('Please Enter Your Details'),
					submitText: translate('Saving...'),
					plugins: new Ext.ux.ValidationStatus(
						 {form:'user-rego-form', 
						  showText: translate('Click to see errors')})
			   })
	 });

	 var registrationWindow = new Ext.Window({
		  title:translate('Registration'),
		  layout:'fit',
		  items:registrationForm,
		  hidden:true,
		  constrain:true,
		  modal:true,
		  resizable:false,
		  y:0,
		  closeAction:'hide',
		  width:618,
		  autoHeight:true
	 });

	 var AddressRecord = Ext.data.Record.create(
		  [
			   'stNum', 'address1', 'address2', 'city',
			   'state', 'zip'
		  ]);
												
	 registrationFormBody.addButton({
		  text:translate('Cancel'),
		  handler:function()
		  {
			   registrationFormBody.getForm().reset();
			   registrationWindow.hide();
		  }
	 });
	 
	 var regoReader = new Ext.data.JsonReader(
		  {
			   root: 'rows',
			   totalProperty: 'count',
			   id: 'id'
		  }, 
		  ['success','url', 'cookie', 'errormessage']
	 );


	 var registrationFailed = function(msg, markField)
	 {
		  if(markField)
		  {
			   registrationFormBody.getForm().markInvalid({'rego-user-email': msg});
		  }
		  var sb = Ext.getCmp('registration-statusbar');
		  sb.setStatus({'text':msg, iconCls:'x-status-error'});
	 };

	 var registrationCallback = function(result, callback, success)
	 {
		  if(!result)
		  {
			   trackALFEvent('/ALF/Register/Fail/Timeout');			   
			   registrationFailed(translate('Registration timed out, please wait a few minutes and then try to save.'), false);
			   return;
		  }
		  if(!success)
		  {
			   trackALFEvent('/ALF/Register/Fail/Error');			   
			   registrationFailed(translate('An error occurred during registration process.'),
								  false);
			   return;
		  }
		  var record = result.records[0];
		  if(!record.get('success'))
		  {
			   trackALFEvent('/ALF/Register/Fail/Fail');
			   registrationFailed(record.get('errormessage'), true);
			   return;
		  }
		  cookie = record.get('cookie')
		  trackALFEvent('/ALF/Register/Success');
		  loginSetCookie('__ac', cookie, '', '/', '', false);
		  callback();
	 };

	 var doRegistration = function(form, callback)
	 {
		  var rp = Ext.getCmp('rego-right-panel');
		  rp.enable();

		  var dv = Ext.getCmp('search-results');
		  var records = dv.getSelectedRecords();
		  var client_lat = '';
		  var client_lon = '';
		  var delivery_restid = '';
		  if(records.length)
		  {
			   var record = records[0];
			   client_lat = record.get('client_lat');
			   client_lon = record.get('client_lon');
			   delivery_restid = record.get('restaurantid');
		  }
		  params = form.getValues();
		  params.longitude = client_lon;
		  params.latitude = client_lat;
		  params.delivery_restid = delivery_restid;
		  params.phone = params.cellphone;
		  params.password = '"' + params.password + '"';
		  params.json = true;
		  var rtp = new Ext.data.ScriptTagProxy({
			  url : absolute_urls + 'register',
			  timeout:30000,
			  api: {
				  'read': absolute_urls + 'register'
			  }
		  });
		  rtp.doRequest('read', null, 
						params, regoReader, registrationCallback, this, callback);
//		  rtp.load(params, regoReader, registrationCallback, this, callback);
	 };
	 
	 var validateStartOrder = function()
	 {
		  var dv = Ext.getCmp('search-results');
		  var records = dv.getSelectedRecords();
		  if(!records.length)
		  {
			   return false;
		  }
		  var record = records[0];

		  var tdf = Ext.getCmp('loc-display-form').getForm();
		  var params = tdf.getValues();

		  var isGroupOrder = params.groupOrdering || false;

		  var restid = record.get('restaurantid');
		  var orderMode = record.get('ordermode');

		  if(isGroupOrder && !tdf.isValid())
		  {
			   return false;
		  }
		  if(isGroupOrder && params.cutofftime == translate('Order Time is too early'))
		  {
			   return false;
		  }
		  if(!isGroupOrder)
		  {
			   if(!params.time || 
				  params.time == translate('Select a time'))
			   {
					return false;
			   }
			   if(params.time == translate('No Times Available'))
			   {
					return false;
			   }
		  }
		  return true;
	 };

	 var doStartOrder = function() 
	 {
		  var dataView = Ext.getCmp('search-results');
		  var records = dataView.getSelectedRecords();
		  var record = records[0];
		  var tdf = Ext.getCmp('loc-display-form').getForm();
		  var params = tdf.getValues();

		  var isGroupOrder = params.groupOrdering || false;
		  var restid = record.get('restaurantid');
		  var orderMode = record.get('ordermode');

		  params.restid = restid;
		  params.servicetype = orderMode;
		  params.isgrouporder = isGroupOrder;
		  params.customerlocid = -1;

		  if(orderMode == 1)
		  {
			   trackALFEvent('/ALF/Register/StartOrder/Delivery');
		  }
		  else
		  {
			   trackALFEvent('/ALF/Register/StartOrder/PickUp');
		  }

		  
		  var qString = Ext.urlEncode(params);
		  fpRedirect(absolute_url + 'ordernow' + '?' + qString);
		  
	 };
	 var registrationComplete = function()
	 {
		  Ext.getCmp('registration-statusbar').setStatus(
			   {
					text:translate('Save Complete'),
					iconCls:'',
					clear:true
			   });
		  if(validateStartOrder())
		  {
			   doStartOrder();
			   return;
		  }
		  fpRedirect(window.top.location);
	 }
	 var doRegister = function()
	 {
		  var form = registrationFormBody.getForm();
		  if(!form.isValid())
		  {
			   return;
		  }
		  var sb = Ext.getCmp('registration-statusbar');
		  sb.showBusy('Saving...');
		  doRegistration(form, registrationComplete);
	 };
	 registrationFormBody.addButton({text:translate('Save...'), handler:doRegister});
	 
	 var doRegistrationForm = function() {
		  var rp = Ext.getCmp('rego-right-panel');
		  rp.enable();
		  
		  (function(){
			   var ai = Ext.getCmp('user-rego-form-companyname');
			   ai.focus();}).defer(100);
		  (function(){
			   var af = Ext.getCmp('user-address-form').getForm();
			   if(af && !af.isDirty())
			   {
					af.reset();
					if(af.isValid())
					{
						 var r = new AddressRecord(af.getValues());
						 if(r.get('stNum'))
						 {
							  registrationFormBody.getForm().loadRecord(r);
							  registrationFormBody.getForm().clearInvalid();
							  rp.disable();
						 }
					}
					af.clearInvalid();
			   }
			   
		  }).defer(100);
		  registrationWindow.show();

		  var cb = Ext.getCmp("registration-optin");
		  cb.setValue(optInDefault);
	 };
	 return doRegistrationForm;
};
;
//$Rev: 3987 $
Ext.namespace('Ext.NovaDine');

Ext.NovaDine.Address = function(searchFunc)
{
	 var doDeliverySearch = searchFunc;

	 var baseAddressFormItems = [{
		  xtype:'label',
		  text:translate('Enter Your Address'),
		  width: 180,
		  style:'padding-bottom:5px;font-size:12px;font-weight:bold;text-align:center;',
		  cls:'x-form-item'
	 }, {
		  name:'zone',
		  xtype:'hidden'
	 }, {
		  fieldLabel: translate('Street Number'),
		  labelWidth: 120,
		  name: 'stNum',
		  width: 50,
		  allowBlank:false,
		  xtype:'textfield',
		  tabIndex:1,
		  blankText: translate('Street Number is required'),
		  labelStyle:'width:80px !important; padding-left:0px !important;',
		  ctCls:'streetNumberField'
	 },
	 {
		  fieldLabel: translate('Street'),
		  name: 'address1',
		  allowBlank:false,
		  tabIndex:2,
		  blankText: translate('Street is required')
	 },
	 {
		  fieldLabel: translate('Suite'),
		  name: 'address2',
		  width: 50,
		  tabIndex:3
	 },
	 {
		  fieldLabel: translate('City'),
		  name: 'city',
		  allowBlank:false,
		  tabIndex:4,
		  blankText: translate('City is required')
	 },
								 stateCombo,
	 {
		  fieldLabel: translate('Zip'),
		  name: 'zipcode',
		  allowBlank:false,
		  tabIndex:6,
		  blankText: translate('Zip is required')
	 }];

	 var addressFormBody = new Ext.form.FormPanel({
		  id:'user-address-form',
		  labelWidth: 42,
		  width: 'auto',
		  border:false,
		  height:217,
		  defaultType: 'textfield',
		  defaults: { width:136 },
		  layoutConfig: {
			   labelSeparator: ':'
		  },
		  items:baseAddressFormItems
	 });

	 addressFormBody.getForm().trackResetOnLoad = true;

	 addressFormBody.addButton(
		  translate('Search...'), 
		  function() 
		  {
			   var form = addressFormBody.getForm();
			   if(form.isValid())
			   {
					// To track if the form is
					// changed..
					var v = form.getValues(false);
					form.setValues(v);

					// Off to the races..
					var sb = Ext.getCmp('form-statusbar');
					sb.showBusy(translate('Searching...'));
					doDeliverySearch(
						 form,
						 function(){
							  Ext.getCmp('form-statusbar').setStatus({
								   text:translate('Search Complete'),
								   iconCls:'',
								   clear:true
							  });
							  Ext.get('panel2_title').addClass('yc-active');
							  Ext.get('panel1_title').removeClass('yc-active');
							  Ext.get('panel3_title').removeClass('yc-active');
						 });
			   }
		  }
	 );

	 var addressForm = new Ext.Panel({
		  title:translate('Delivery'),
		  // iconCls:'delivery-tab',
		  border:false,
		  height:276,
		  width:200,
		  layout: 'fit',
		  items: addressFormBody,
		  bbar: new Ext.ux.StatusBar({
			   id: 'form-statusbar',
			   defaultText: translate('Enter Your Address'),
			   submitText: translate('Searching...'),
			   plugins: new Ext.ux.ValidationStatus({form:'user-address-form', showText: translate('Click to see errors')})
		  })
	 });


	 var guestLoginReader = new Ext.data.JsonReader({
		 root: 'rows',
		 totalProperty: 'count',
		 id: 'id'
	 }, [
		 'success','url', 'cookie', 'errormessage'
	 ]);

	 var loginWindow = new Ext.NovaDine.Login();
	 var doRegistrationForm = new Ext.NovaDine.Registration();

	 var doStartGuestOrder = function(customerLocId) 
	 {
		  var dataView = Ext.getCmp('search-results');
		  var records = dataView.getSelectedRecords();
		  var record = records[0];
		  var tdf = Ext.getCmp('loc-display-form').getForm();
		  var params = tdf.getValues();

		  var isGroupOrder = false;
		  var restid = record.get('restaurantid');
		  var orderMode = record.get('ordermode');

		  params.restid = restid;
		  params.servicetype = orderMode;
		  params.isgrouporder = isGroupOrder;
		  params.customerlocid = customerLocId;

		  trackALFEvent('/ALF/GuestLogin/StartOrder/PickUp');
		  
		  var qString = Ext.urlEncode(params);
		  fpRedirect(absolute_url + 'ordernow' + '?' + qString);
	 };

	 var validateStartGuestOrder = function()
	 {
		  var dv = Ext.getCmp('search-results');
		  if(!dv)
		  {
			   return false;
		  }

		  var records = dv.getSelectedRecords();

		  if(!records.length)
		  {
			   return false;
		  }
		  var record = records[0];

		  var tdf = Ext.getCmp('loc-display-form').getForm();

		  if(!tdf)
		  {
			   return false;
		  }

		  var params = tdf.getValues();

		  params.groupOrdering = false;

		  if(!params.time || 
			 params.time == translate('Select a time'))
		  {
			  return false;
		  }
		  if(params.time == translate('No Times Available'))
		  {
			  return false;
		  }
		  return true;
	 };


	 var loginFailed = function(message) 
	 {
		 Ext.Msg.show({title:translate('Login Failed'), 
					   msg:message, 
					   buttons:Ext.Msg.OK, y:100});
	 };

	 var guestLoginCallback = function(result, args, success)
	 {
		  if(!result)
		  {
			   trackALFEvent('/ALF/GuestLogin/Fail/Timeout');
			   loginFailed(translate('The server took too long to respond, please try again later.'));
		  }

		  if(!success)
		  {
			   trackALFEvent('/ALF/GuestLogin/Fail/Error');
			   loginFailed(translate('An error occurred during login process.'));
			   return;
		  }

		  var record = result.records[0];
		  if(!record.get('success'))
		  {
			   trackALFEvent('/ALF/GuestLogin/Fail/Fail');
			   loginFailed(record.get('errormessage'));
			   return;
		  }
		  var cookie = record.get('cookie');
		  trackALFEvent('/ALF/GuestLogin/Success');
		  loginSetCookie('__ac', cookie, '', '/', '', false);

		  if(validateStartGuestOrder())
		  {
			  doStartGuestOrder(-1);
			  return;
		  }
		  fpRedirect(record.get('url'));
	 };

	 var doGuestRegister = function() {
		 var stp = new Ext.data.ScriptTagProxy({
			 url : absolute_urls + 'guestRegister',
			 timeout:25000,
			 api: {
				 'read': absolute_urls + 'guestRegister'
			 }
		 });
		 stp.doRequest('read', null,
					   {json:true}, guestLoginReader, guestLoginCallback);
		 
	 };

	 var doLoginForm = function() {
		  loginWindow.show();
		  loginWindow.focus();
		  (function(){
			   var ai = Ext.getCmp('user-login-form-ac_name');
			   ai.focus();}).defer(100);
	 };

	 var userTBar = [ //'<b>Find A Restaurant</b>',
		  '<b>'+translate('Returning Users') + '</b>', '-',
					  new Ext.Button({ 
						   text:translate('Login'), 
						   iconCls:'login-menu',
						   handler:doLoginForm
					  }),
					  '->', 
					  '<b>'+translate('New Users')+'</b>', '-',
					  new Ext.Button({ 
						   text:translate('Register'), 
						   iconCls:'register-menu',
						   handler:doRegistrationForm}
						   )

	 ];
	 return({
		  addressForm:addressForm,
		  userTBar:userTBar,
		  loggedIn:false,
		  doLogin:doLoginForm,
		  doRegister:doRegistrationForm,
		  doGuestRegister:doGuestRegister
	 });
};
;
Ext.namespace('Ext.NovaDine');

Ext.NovaDine.ZipCode = function(ds){
	 var zipPanel = new Ext.Panel( {
		  title:translate('Pick Up'),
		  // iconCls:'pickup-tab',
		  tbar: [
			   translate('Zip') + ': ', ' ',
			   new Ext.app.SearchField({
					store: ds,
					width:75
			   })
		  ]
	 });	
	return zipPanel; 
}	 
;
Ext.namespace('Ext.NovaDine');

function loginSetCookie( name, value, expires, path, domain, secure ) 
{
	 // set time, it's in milliseconds
	 var today = new Date();
	 today.setTime( today.getTime() );
	 
	 /*
	   if the expires variable is set, make the correct 
	   expires time, the current script below will set 
	   it for x number of days, to make it for hours, 
	   delete * 24, for minutes, delete * 60 * 24
	 */
	 if ( expires )
	 {
		  expires = expires * 1000 * 60 * 60 * 24;
	 }
	 var expires_date = new Date( today.getTime() + (expires) );

	 document.cookie = name + "=" +escape( value ) +
		  ( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) + 
		  ( ( path ) ? ";path=" + path : "" ) + 
		  ( ( domain ) ? ";domain=" + domain : "" ) +
		  ( ( secure ) ? ";secure" : "" );
}

Ext.NovaDine.Login = function()
{
	 var loginReader = new Ext.data.JsonReader(
		  {
			   root: 'rows',
			   totalProperty: 'count',
			   id: 'id'
		  }, 
		  ['success','url', 'cookie', 'errormessage']
	 );
	 
	 var loginFailedOK = function(buttonId, text)
	 {
		  loginWindow.show();
		  
	 };

	 var loginFailed = function(message) 
	 {
		  var form = loginForm.getForm();
		  form.clearInvalid();
		  form.reset();
		  loginWindow.hide();
		  Ext.Msg.show({title:translate('Login Failed'), msg:message, buttons:Ext.Msg.OK, y:100, fn:loginFailedOK});
	 };

	 var validateStartOrder = function()
	 {
		  var dv = Ext.getCmp('search-results');
		  if(!dv)
		  {
			   return false;
		  }

		  var records = dv.getSelectedRecords();

		  if(!records.length)
		  {
			   return false;
		  }
		  var record = records[0];

		  var tdf = Ext.getCmp('loc-display-form').getForm();

		  if(!tdf)
		  {
			   return false;
		  }

		  var params = tdf.getValues();

		  var isGroupOrder = params.groupOrdering || false;

		  var restid = record.get('restaurantid');
		  var orderMode = record.get('ordermode');

		  if(isGroupOrder && !tdf.isValid())
		  {
			   return false;
		  }

		  if(isGroupOrder && params.cutofftime == translate('Order Time is too early'))
		  {
			   return false;
		  }

		  if(!isGroupOrder)
		  {
			   if(!params.time || 
				  params.time == translate('Select a time'))
			   {
					return false;
			   }
			   if(params.time == translate('No Times Available'))
			   {
					return false;
			   }
		  }
		  return true;
	 };

	 var doStartOrder = function(customerLocId) 
	 {
		  var dataView = Ext.getCmp('search-results');
		  var records = dataView.getSelectedRecords();
		  var record = records[0];
		  var tdf = Ext.getCmp('loc-display-form').getForm();
		  var params = tdf.getValues();

		  var isGroupOrder = params.groupOrdering || false;
		  var restid = record.get('restaurantid');
		  var orderMode = record.get('ordermode');

		  params.restid = restid;
		  params.servicetype = orderMode;
		  params.isgrouporder = isGroupOrder;
		  params.customerlocid = customerLocId;

		  if(orderMode == 1)
		  {
			   trackALFEvent('/ALF/Login/StartOrder/Delivery');
		  }
		  else
		  {
			   trackALFEvent('/ALF/Login/StartOrder/PickUp');
		  }
		  
		  var qString = Ext.urlEncode(params);
		  fpRedirect(absolute_url + 'ordernow' + '?' + qString);
		  
	 };

	 var addressCallback = function(options, success, response)
	 {
		  if(success)
		  {
			   trackALFEvent('/ALF/Login/SaveAddress/Success');
			   var custLoc = response.responseText;
			   doStartOrder(custLoc);
			   return;
		  }
		  // couldn't store the address...
		  // Refresh the page and see if they can start over logged in
		  trackALFEvent('/ALF/Login/SaveAddress/Fail');
		  fpRedirect(options.params.fail_url);
	 };

	 var loginCallback = function(result, args, success)
	 {
		  if(!result)
		  {
			   trackALFEvent('/ALF/Login/Fail/Timeout');
			   loginFailed(translate('The server took too long to respond, please try again later.'));
		  }

		  if(!success)
		  {
			   trackALFEvent('/ALF/Login/Fail/Error');
			   loginFailed(translate('An error occurred during login process.'));
			   return;
		  }

		  var record = result.records[0];
		  if(!record.get('success'))
		  {
			   trackALFEvent('/ALF/Login/Fail/Fail');
			   loginFailed(record.get('errormessage'));
			   return;
		  }
		  var cookie = record.get('cookie');
		  trackALFEvent('/ALF/Login/Success');
		  loginSetCookie('__ac', cookie, '', '/', '', false);

		  // Don't add addresses if the
		  // Order isn't valid to start anyway
		  if(validateStartOrder())
		  {

			   var af = Ext.getCmp('user-address-form').getForm();

			   // We track on reset, if someone is trying to be crafty
			   // this reloads the address form to the values used
			   // when they searched...
			   af.reset();

			   var dataView = Ext.getCmp('search-results');
			   var records = dataView.getSelectedRecords();

			   // Don't add the address if it's not valid either
			   if(af.isValid() && records.length) 
			   {
					var o_record = records[0];

					// Only add the address if the current
					// record set is for delivery
					if(o_record.get('ordermode') == 1)
					{
						 var params = af.getValues(false);
						 var sc = Ext.getCmp('address-state-combo');

						 // We now use the abbr to handle state
						 // var si = sc.store.find('value', params.state);
						 // var sr = sc.store.getAt(si);
						 // params.statecode = sr.get('abbr');

						 params.statecode = sc.getValue();
						 params.delivery_restid = o_record.get('restaurantid');
						 params.latitude = o_record.get('client_lat');
						 params.longitude = o_record.get('client_lon');
						 params.fail_url = o_record.get('url');
						 params.json = true;

						 Ext.Ajax.request({
							  url:absolute_url + 'saveAddress',
							  params:params,
							  callback:addressCallback
						 });
						 return;
					}
			   }
			   doStartOrder(-1);
			   return;
		  }
		  fpRedirect(record.get('url'));
	 };

	 var doFormLogin = function(form)
	 {
		  if(form.isValid())
		  {
			  var stp = new Ext.data.ScriptTagProxy({
				  url : absolute_urls + 'login',
				  timeout:25000,
				  api: {
					  read: absolute_urls + 'login'
				  }
			  });
			  
			  params = { ac_name:form.findField('ac_name').getValue(),
						 ac_password:form.findField('ac_pass').getValue(),
						 json:true};
			  stp.doRequest('read', null,
							params, loginReader, loginCallback);
/*			   
			   stp.load(params, 
						loginReader,
						loginCallback);
*/

		  }
	 };

	 var doLogin = function(button, event) 
	 {
		  var form = loginForm.getForm();
		  doFormLogin(form);
	 };
	 
	 var doKeyLogin = function(key, event) 
	 {
		  doLogin().createDelegate(this);
	 };

	 var cancelLogin = function(button, event) 
	 {
		  var form = loginForm.getForm();
		  form.clearInvalid();
		  form.reset();
		  loginWindow.hide();
	 };

	 var loginForm = new Ext.form.FormPanel({
		  id:'user-login-form',
		  labelWidth: 55,
		  buttonAlign:'center',
		  width: 'auto',
		  height:'auto',
		  autoHeight:true,
		  defaultType: 'textfield',
		  keys: [{
			   key: Ext.EventObject.ENTER,
			   fn: doLogin,
			   scope:this
		  }, {
			   key:Ext.EventObject.ESC,
			   fn: cancelLogin,
			   scope:this
		  }],
		  defaults: { width:218 },
		  layoutConfig: {
			   labelSeparator: ':'
		  },
		  items:[ {
			   fieldLabel: translate('Email'),
			   id:'user-login-form-ac_name',
			   name: 'ac_name',
			   allowBlank:false,
			   vtype:'email',
			   tabIndex:101
		  }, {
			   fieldLabel: translate('Password'),
			   name: 'ac_pass',
			   allowBlank:false,
			   tabIndex:102,
			   inputType:'password'
		  } ]
	 } );

	 loginForm.addButton({
		  text:translate('Login'),
		  tabIndex:103,
		  type:'submit'
	 }, doLogin, loginForm );

	 loginForm.addButton({
		  text:translate('Cancel'),
		  tabIndex:104
	 }, cancelLogin, loginForm);

	 loginForm.addButton({ 
		  text:translate('Forgot Password'),
		  iconCls:'forgot-password',
		  handler:function()
		  { fpRedirect('/login/forgottenPassword'); }
	 });

	 var loginWindow = new Ext.Window({
		  title:translate('Login'),
		  layout:'fit',
		  width:310,
		  height:180,
		  autoHeight:true,
		  items:[loginForm],
		  hidden:true,
		  constrain:true,
		  modal:true,
		  resizable:false,
		  y:150,
		  closeAction:'hide'
	 });
	 return loginWindow;
};
;
/**
 * @author Shea Frederick
 * http://www.vinylfox.com
 */

Ext.namespace('Ext.ux');
 
/**
 * This extension adds Google maps functionality to any panel or panel based component (ie: windows).
 * @class Ext.ux.GMapPanel
 * @extends Ext.Panel
 * @param {Object} config The config object
 */
Ext.ux.GMapPanel = Ext.extend(Ext.Panel, {
	 respErrors: [{
		  code: G_GEO_BAD_REQUEST,
		  msg: 'A directions request could not be successfully parsed. For example, the request may have been rejected if it contained more than the maximum number of waypoints allowed.' 
	 },{
		  code: G_GEO_SERVER_ERROR,
		  msg: 'A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.'
	 },{
		  code: G_GEO_MISSING_QUERY,
		  msg: 'The HTTP q parameter was either missing or had no value. For geocoding requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.'
	 },{
		  code: G_GEO_MISSING_ADDRESS,
		  msg: 'Synonym for G_GEO_MISSING_QUERY.' 
	 },{
		  code: G_GEO_UNKNOWN_ADDRESS,
		  msg: 'No corresponding geographic location could be found for the specified address. This may be due to the fact that the address is relatively new, or it may be incorrect.' 
	 },{
		  code: G_GEO_UNAVAILABLE_ADDRESS,
		  msg: 'The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons.' 
	 },{
		  code: G_GEO_UNKNOWN_DIRECTIONS,
		  msg: 'The GDirections object could not compute directions between the points mentioned in the query. This is usually because there is no route available between the two points, or because we do not have data for routing in that region.'
	 },{
		  code: G_GEO_BAD_KEY,
		  msg: 'The given key is either invalid or does not match the domain for which it was given.' 
	 },{
		  code: G_GEO_TOO_MANY_QUERIES,
		  msg: 'The given key has gone over the requests limit in the 24 hour period or has submitted too many requests in too short a period of time. If you\'re sending multiple requests in parallel or in a tight loop, use a timer or pause in your code to make sure you don\'t send the requests too quickly.' 
	 }],
	 respErrorTitle : 'Error',
	 geoErrorMsgUnable : 'Unable to Locate the Address you provided',
	 geoErrorTitle : 'Address Location Error',
	 geoErrorMsgAccuracy : 'The address provided has a low accuracy.<br><br>Level {0} Accuracy (8 = Exact Match, 1 = Vague Match)',
	 /**
	 * @cfg {String} gmapType
	 * The type of map to display, generic options available are: 'map', 'panorama'. 
	 * More specific maps can be used by specifying the google map type:
	 * 
	 * G_NORMAL_MAP displays the default road map view
	 * G_SATELLITE_MAP displays Google Earth satellite images
	 * G_HYBRID_MAP displays a mixture of normal and satellite views
	 * G_DEFAULT_MAP_TYPES contains an array of the above three types, useful for iterative processing.
	 * G_PHYSICAL_MAP displays a physical map based on terrain information. 
	 * G_MOON_ELEVATION_MAP displays a shaded terrain map of the surface of the Moon, color-coded by altitude.
	 * G_MOON_VISIBLE_MAP displays photographic imagery taken from orbit around the moon.
	 * G_MARS_ELEVATION_MAP displays a shaded terrain map of the surface of Mars, color-coded by altitude.
	 * G_MARS_VISIBLE_MAP displays photographs taken from orbit around Mars.
	 * G_MARS_INFRARED_MAP displays a shaded infrared map of the surface of Mars, where warmer areas appear brighter and colder areas appear darker.
	 * G_SKY_VISIBLE_MAP displays a mosaic of the sky, as seen from Earth, covering the full celestial sphere.
	 * 
	 * These map types can be used within a configuration like this:  { gmapType: G_MOON_VISIBLE_MAP }
	 */
	 /**
	 * @cfg {Object} setCenter
	 * A center starting point for the map. The map needs to be centered before it can be used.
	 * The config can contain an address to geocode, and even a marker
	 * \{
		  *   geoCodeAddr: '4 Yawkey Way, Boston, MA, 02215-3409, USA',
	 *   marker: \{title: 'Fenway Park'\}
	 * \}
	 * Or it can simply be a lat/lng. Either way, a marker is not required, all we are really looking for here is a starting center point for the map.
	 * \{
		  *   lat: 42.339641,
	 *   lng: -71.094224
	 * \}
	 */
	 /**
     * @cfg {Number} zoomLevel
     * The zoom level to initialize the map at, generally between 1 (whole planet) and 40 (street). Also used as the zoom level for panoramas, zero specifies no zoom at all.
     */
	 /**
     * @cfg {Number} yaw
     * The Yaw, or rotational direction of the users perspective in degrees. Only applies to panoramas.
     */
	 /**
     * @cfg {Number} pitch
     * The pitch, or vertical direction of the users perspective in degrees. Default is 0 (zero), straight ahead. Valid values are between +90 (straight up) and -90 (straight down). 
     */
	 /**
     * @cfg {Boolean} displayGeoErrors
     * True to display geocoding errors to the end user via a message box.
     */
	 /**
     * @cfg {Boolean} minGeoAccuracy
     * The level (between 1 & 8) to display an accuracy error below. Defaults to seven (7).
     * see: http://code.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy
     */
	 /**
     * @cfg {Array} mapConfOpts
     * Array of strings representing configuration methods to call, a full list can be found here: http://code.google.com/apis/maps/documentation/reference.html#GMap2
     */
	 /**
     * @cfg {Array} mapControls
     * Array of strings representing map controls to initialize, a full list can be found here: http://code.google.com/apis/maps/documentation/reference.html#GControlImpl
     */
	 // private
	 initComponent : function()
	 {
        
		  var defConfig = {
			   plain: true,
			   zoomLevel: 0,
			   yaw: 180,
			   pitch: 0,
			   gmapType: 'map',
			   border: false,
			   displayGeoErrors: false,
			   minGeoAccuracy: 7,
			   mapDefined: false,
			   mapDefinedGMap: false
		  };
        
		  Ext.applyIf(this,defConfig);
        
		  Ext.ux.GMapPanel.superclass.initComponent.call(this);        

	 },
	 // private
	 afterRender : function()
	 {
        
		  var wh = this.ownerCt.getSize();
		  Ext.applyIf(this, wh);
        
		  Ext.ux.GMapPanel.superclass.afterRender.call(this);    
        
		  if (this.gmapType === 'map'){
			   this.gmap = new GMap2(this.body.dom);
			   this.mapDefined = true;
			   this.mapDefinedGMap = true;
		  }
        
		  if (this.gmapType === 'panorama'){
			   this.gmap = new GStreetviewPanorama(this.body.dom);
			   this.mapDefined = true;
		  }

		  if (!this.mapDefined && this.gmapType){
			   this.gmap = new GMap2(this.body.dom);
			   this.gmap.setMapType(this.gmapType);
			   this.mapDefined = true;
			   this.mapDefinedGMap = true;
		  }
        
		  GEvent.bind(this.getMap(), 'load', this, this.onMapReady);
        
		  if (typeof this.setCenter === 'object') {
			   if (typeof this.setCenter.geoCodeAddr === 'string'){
					this.geoCodeLookup(this.setCenter.geoCodeAddr, this.setCenter.marker, false, true, this.setCenter.listeners);
			   }else{
					if (this.gmapType === 'map'){
						 var point = this.fixLatLng(new GLatLng(this.setCenter.lat,this.setCenter.lng));
						 this.getMap().setCenter(point, this.zoomLevel);    
					}
					if (typeof this.setCenter.marker === 'object' && typeof point === 'object') {
						 this.addMarker(point, this.setCenter.marker, this.setCenter.marker.clear);
					}
			   }
			   if (this.gmapType === 'panorama'){
					this.getMap().setLocationAndPOV(new GLatLng(this.setCenter.lat,this.setCenter.lng), {yaw: this.yaw, pitch: this.pitch, zoom: this.zoomLevel});
			   }
		  }

	 },
	 // private
	 onMapReady : function()
	 {
        
		  this.addMapControls();
		  this.addOptions();
        
		  this.addMarkers(this.markers);
		  this.addKMLOverlay(this.autoLoadKML);
        
	 },
	 // private
	 onResize : function(w, h)
	 {
        
		  // check for the existance of the google map in case the onResize fires too early
		  if (typeof this.getMap() == 'object') {
			   this.getMap().checkResize();
		  }
        
		  Ext.ux.GMapPanel.superclass.onResize.call(this, w, h);

	 },
	 // private
	 setSize : function(width, height, animate)
	 {
        
		  // check for the existance of the google map in case setSize is called too early
		  if (typeof this.getMap() == 'object') {
			   this.getMap().checkResize();
		  }
        
		  Ext.ux.GMapPanel.superclass.setSize.call(this, width, height, animate);
        
	 },
	 /**
     * Returns the current google map
     * @return {GMap} this
     */
	 getMap : function()
	 {
		  return this.gmap;
	 },
	 /**
     * Returns the maps center as a GLatLng object
     * @return {GLatLng} this
     */
	 getCenter : function()
	 {
		  return this.fixLatLng(this.getMap().getCenter());
	 },
	 /**
     * Returns the maps center as a simple object
     * @return {Object} this has lat and lng properties only
     */
	 getCenterLatLng : function()
	 {
		  var ll = this.getCenter();
		  return {lat: ll.lat(), lng: ll.lng()};
	 },
	 /**
     * Creates markers from the array that is passed in. Each marker must consist of at least lat and lng properties.
     * @param {Array} markers an array of marker objects
     */
	 addMarkers : function(markers) 
	 {
        
		  if (Ext.isArray(markers)){
			   for (var i = 0; i < markers.length; i++) {
					if (typeof markers[i].geoCodeAddr == 'string') {
						 this.geoCodeLookup(markers[i].geoCodeAddr, markers[i].marker, false, markers[i].setCenter, markers[i].listeners);
					}else{
						 var mkr_point = this.fixLatLng(new GLatLng(markers[i].lat, markers[i].lng));
						 this.addMarker(mkr_point, markers[i].marker, false, markers[i].setCenter, markers[i].listeners);
					}
			   }
		  }
        
	 },
	 /**
     * Creates a single marker.
     * @param {Object} point a GLatLng point
     * @param {Object} marker a marker object consisting of at least lat and lng
     * @param {Boolean} clear clear other markers before creating this marker
     * @param {Boolean} center true to center the map on this marker
     * @param {Object} listeners a listeners config
     */
	 addMarker : function(point, marker, clear, center, listeners)
	 {
		  Ext.applyIf(marker,G_DEFAULT_ICON);

		  if (clear === true){
			   this.getMap().clearOverlays();
		  }
		  if (center === true) {
			   this.getMap().setCenter(point, this.zoomLevel);
		  }

		  var mark = new GMarker(point,marker);
		  if (typeof listeners === 'object'){
			   for (evt in listeners) {
					GEvent.bind(mark, evt, this, listeners[evt]);
			   }
		  }
		  this.getMap().addOverlay(mark);

	 },
	 // private
	 addMapControls : function()
	 {
		  if (this.gmapType === 'map') {
			   if (Ext.isArray(this.mapControls)) {
					for(i=0;i<this.mapControls.length;i++){
						 this.addMapControl(this.mapControls[i]);
					}
			   }else if(typeof this.mapControls === 'string'){
					this.addMapControl(this.mapControls);
			   }else if(typeof this.mapControls === 'object'){
					this.getMap().addControl(this.mapControls);
			   }
		  }
        
	 },
	 /**
     * Adds a GMap control to the map.
     * @param {String} mc a string representation of the control to be instantiated.
     */
	 addMapControl : function(mc)
	 {
		  var mcf = window[mc];
		  if (typeof mcf === 'function') {
			   this.getMap().addControl(new mcf());
		  }    
        
	 },
	 // private
	 addOptions : function()
	 {
        
		  if (Ext.isArray(this.mapConfOpts)) {
			   var mc;
			   for(i=0;i<this.mapConfOpts.length;i++){
					this.addOption(this.mapConfOpts[i]);
			   }
		  }else if(typeof this.mapConfOpts === 'string'){
			   this.addOption(this.mapConfOpts);
		  }        
        
	 },
	 /**
     * Adds a GMap option to the map.
     * @param {String} mo a string representation of the option to be instantiated.
     */
	 addOption : function(mo)
	 {
        
		  var mof = this.getMap()[mo];
		  if (typeof mof === 'function') {
			   this.getMap()[mo]();
		  }    
        
	 },
	 /**
     * Loads a KML file into the map.
     * @param {String} kmlfile a string URL to the KML file.
     */
	 addKMLOverlay : function(kmlfile)
	 {
        
		  if (typeof kmlfile === 'string' && kmlfile !== '') {
			   var geoXml = new GGeoXml(kmlfile);
			   this.getMap().addOverlay(geoXml);
		  }
        
	 },
	 /**
     * Adds a marker to the map based on an address string (ie: "123 Fake Street, Springfield, NA, 12345, USA") or center the map on the address.
     * @param {String} addr the address to lookup.
     * @param {Object} marker the marker to add (optional).
     * @param {Boolean} clear clear other markers before creating this marker
     * @param {Boolean} center true to set this point as the center of the map.
     * @param {Object} listeners a listeners config
     */
	 geoCodeLookup : function(addr, marker, clear, center, listeners) 
	 {
        
		  if (!this.geocoder) {
			   this.geocoder = new GClientGeocoder();
		  }
		  this.geocoder.getLocations(addr, this.addAddressToMap.createDelegate(this, [addr, marker, clear, center, listeners], true));
        
	 },
	 // private
	 addAddressToMap : function(response, addr, marker, clear, center, listeners)
	 {
		  if (!response || response.Status.code != 200) {
			   this.respErrorMsg(response.Status.code);
		  }else{
			   place = response.Placemark[0];
			   addressinfo = place.AddressDetails;
			   accuracy = addressinfo.Accuracy;
			   if (accuracy === 0) {
					this.geoErrorMsg(this.geoErrorTitle, this.geoErrorMsgUnable);
			   }else{
					if (accuracy < this.minGeoAccuracy) {
						 // console.debug(addr + ' - Accuracy Warning: ' + accuracy);
						 this.geoErrorMsg(this.geoErrorTitle, String.format(this.geoErrorMsgAccuracy, accuracy));
					}else{
						 point = this.fixLatLng(new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]));
						 if (center){
							  this.getMap().setCenter(point, this.zoomLevel);
						 }
						 if (typeof marker === 'object') {
							  if (!marker.title){
								   marker.title = place.address;
							  }
							  Ext.applyIf(marker, G_DEFAULT_ICON);
							  this.addMarker(point, marker, clear, false, listeners);
						 }
					}
			   }
		  }
        
	 },

	 // private
	 geoErrorMsg : function(title,msg)
	 {
		  if (this.displayGeoErrors) {
			   Ext.MessageBox.alert(title,msg);
		  }
	 },
	 // private
	 respErrorMsg : function(code)
	 {
		  Ext.each(this.respErrors, 
				   function(obj)
				   {
						if (code == obj.code)
						{
							 Ext.MessageBox.alert(this.respErrorTitle, obj.msg);
						}
				   }, this);
	 },
	 // private
	 // used to inverse the lat/lng coordinates to correct locations on the sky map
	 fixLatLng : function(llo)
	 {
		  if (this.getMap().getCurrentMapType().QO == 'visible'){
			   llo.lat(180 - llo.lat());
			   llo.lng(180 - llo.lng());
		  }
		  return llo;
	 }
});

Ext.reg('gmappanel',Ext.ux.GMapPanel); 
;
/*
 * Ext Map Window
 * Copyright(c) 2008, David Davis
 * 
 */
/**
 * @author David Davis
 */

var houseIcon = new GIcon();
houseIcon.image = absolute_url + 'images/flag_house.png';
houseIcon.shadow = absolute_url + 'images/flag_house_shadow.png';
houseIcon.iconSize = new GSize(32, 32);
houseIcon.shadowSize = new GSize(59, 32);
houseIcon.iconAnchor = new GPoint(0, 0);
houseIcon.infoWindowAnchor = new GPoint(9, 2);
houseIcon.infoShadowAnchor = new GPoint(18, 25);

Ext.namespace('Ext.ux');

Ext.ux.GMapWindow = Ext.extend(
	 Ext.Window, {
		  initComponent: function() 
		  {

			   this.mapPanel = new Ext.ux.GMapPanel({
					xtype: 'gmappanel',
					region: 'center',
					zoomLevel: this.zoomLevel || 12,
					gmapType: this.gmapType || 'map',
					mapConfOpts: this.mapConfOpts || [
						 'enableScrollWheelZoom',
						 'enableDoubleClickZoom',
						 'enableDragging'
					],
					mapControls: this.mapControls || ['GSmallMapControl'],
					mapTypes: this.mapTypes || [G_NORMAL_MAP,G_SATELLITE_MAP,G_HYBRID_MAP,G_PHYSICAL_MAP],
					setCenter: this.setCenter || {
						 geoCodeAddr: 'USA',
						 marker: {title: 'USA'}
					},
					markers: this.markers || []
			   });
        
			   this.mapMenu = new Ext.menu.Menu({
					id: 'mainmenu',
					items: [],
					listeners: {
						 beforeshow: this.buildTypeMenu.createDelegate(this),
						 itemclick: this.onItemCheck.createDelegate(this)
					}
			   });

			   var defConfig = {
					layout: 'fit',
					title: 'Google Map',
					maximizable: true,
					width: 400,
					height: 400,
					minheight: 140,
					minwidth: 200,
					items: [ this.mapPanel ],
					bbar: new Ext.ux.StatusBar({
						 defaultText: '',
						 id: 'statusbar',
						 items: [{ text: 'View', menu: this.mapMenu }, ' ', ' ']
					})
			   };

			   Ext.applyIf(this,defConfig);
        
			   Ext.ux.GMapWindow.superclass.initComponent.call(this);        
		  },

		  buildTypeMenu: function() {
			   var map = this.mapPanel.getMap();
			   var t = map.getMapTypes();
			   this.mapMenu.removeAll();
			   var curType = map.getCurrentMapType();
			   for ( var i = 0, len = t.length; i < len; i++ ) {
					var name = t[i].getName();
					this.mapMenu.addMenuItem({
						 text: name,
						 checked: ( ( t[i] == curType ) ? true : false ),
						 group: 'maptype'
					});
			   }
		  },

		  onItemCheck: function(item, checked) {
			   if ( checked ) {
					var map = this.mapPanel.getMap();
					var t = map.getMapTypes();
					for ( var i = 0, len = t.length; i < len; i++ )
						 if ( t[i].getName() == item.text )
							  map.setMapType(t[i]);
			   }
		  },
		  showRestaurant: function(restid)
		  {
			   var ds = Ext.StoreMgr.get('location-store');
			   restaurantIdx = ds.find('restaurantid', restid);
			   var restaurant = ds.getAt(restaurantIdx);
			   var restLoc = new GLatLng(restaurant.get('latitude'),
										 restaurant.get('longitude'));
			   this.setTitle(restaurant.get('restaurantname'));
			   marker = {title:restaurant.get('address1'),
						 icon:houseIcon};
			   this.mapPanel.addMarker(restLoc, marker, true, true);
			   this.show();
		  }
	 });

Ext.reg('gmapwindow',Ext.ux.GMapWindow);
;
// $Rev: 4803 $

Ext.BLANK_IMAGE_URL = "/mp/include/ExtJS/images/default/s.gif";
Ext.SSL_SECURE_URL='themes/olive/images/olive/s.gif';

Ext.QuickTips.init();

function fpRedirect(url)
{
	 window.top.location = url;
};

Ext.override(Ext.form.Field, {
   setLabel: function(text){
      var r = this.getEl().up('div.x-form-item');
      r.dom.firstChild.firstChild.nodeValue = String.format('{0}', text);
   }
}); 

Ext.override(Ext.form.DateField,{
    onTriggerClick : function()
	{
		if(this.disabled)
		{
			return;
		}
		if(this.menu == null){
			this.menu = new Ext.menu.DateMenu({
				hideOnClick: false,
				focusOnSelect: false
			});
		}
		this.onFocus();
		Ext.apply(this.menu.picker,  {
			minDate : this.minValue,
			maxDate : this.maxValue,
			disabledDatesRE : this.disabledDatesRE,
			disabledDatesText : this.disabledDatesText,
			disabledDays : this.disabledDays,
			disabledDaysText : this.disabledDaysText,
			format : this.format,
			showToday : this.showToday,
			minText : String.format(this.minText, this.formatDate(this.minValue)),
			maxText : String.format(this.maxText, this.formatDate(this.maxValue))
		});
		this.menu.picker.setValue(this.getValue() || new Date());
		this.menu.show(this.el, "tr-br?");
		this.menuEvents('on');
	}
});


Ext.override(Ext.form.Field, {
	hide: function(mode)
	{
		if (mode == 'row')
			this.getEl().up('div.x-form-item').setDisplayed('none');
		else if (mode == 'label')
			this.getEl().up('div.x-form-element').prev('label.x-form-item-label').hide();
         
		Ext.form.Field.superclass.hide.call(this);
	},
   
	show: function(mode)
	{
		if (mode == 'row')
			this.getEl().up('div.x-form-item').setDisplayed('block');
		else if (mode == 'label')
			this.getEl().up('div.x-form-element').prev('label.x-form-item-label').show();
         
		Ext.form.Field.superclass.show.call(this);
	}
});

hideGroupOrderingCheckBox=document.getElementById('change_order')!=null;
Ext.namespace('Ext.NovaDine');

var GroupText = [
	 '<div class="fpAboutText">'+
	 '<h3>'+
	 translate('Group Ordering')+
	 '</h3>' +
	 '<p>' +
	 translate('Group ordering is an easy way for a group to order food ')+
	 translate('together, where every participant can choose their own food, from ')+
	 translate('their own desk/PC. If you are placing an order for a group and you ')+
	 translate('will be choosing the items for everyone in the group, you can just ')+
	 translate('place a normal order through the Order Food link.')+
	 '</p><p>'+

	 translate('Group ordering is great because it allows everyone in the group order ')+
	 translate('to choose, customize, and if required, pay for their portion of the ')+
	 translate('order while sitting at their desk! When you start a group order, ')+
	 translate('everyone you invite is sent an e-mail with a link to directly join the order.')+
	 '</p>'+
	 
	 '<h3>'+
	 translate('A group order is placed by completing these simple steps:')+
	 '</h3>'+
	 '<ol class="fpGroupPoints">'+
	 '<li>'+
	 translate('Specify the delivery or pick up time.')+
	 '</li>'+
//	 '<li>'+
//	 translate('Specify the cut-off time for the order. This is the time the entire order will be sent to the restaurant.')+
//	 '</li>'+
	 '<li>'+
	 translate("Specify whether you are paying for everyone's food, or if everyone will pay for their own.") +
	 '</li>'+
	 '<li>'+
	 translate('Specify the people you are inviting by entering their Email addresses, or selecting them from your previously entered groups.')+
	 '</li>'+
	 '</ol>'+
	 '<p>'+
	 translate('That is all there is to it!')+
	 '</p>'+
	 '</div>'];
	

timeAtLocation = function(offset) // offset comes in seconds...
{
	 var d = new Date();
	 var utc = d.getTime() + (d.getTimezoneOffset() * 60000);
	 var nd = new Date(utc + (1000 * offset));
	 return(nd);
};

var mapWindow = null;

Ext.NovaDine.SearchInterface = function() {
	var allTimes = [];
	var checkForLogin = null;
	var browseMenu = null;
	var enableGuest = null;


	var timeStore = new Ext.data.SimpleStore({
		fields: ['value', 'text'],
		data : []
	});

	var submitOrderButton = new Ext.Button({
		id:'submitOrderButton',
		text:translate('Start an Order'),
		disabled:true,
		handler:function(button, event){checkForLogin(button, event);}
	});

	var browseMenuButton = new Ext.Button({
		id:'browseMenuButton',
		text:translate('Browse Menu'),
		style:'padding-top:2px',
		handler:function(button, event){browseMenu();}
	});
	 
	var showGroupOrderText = function()
	{
		  
		Ext.Msg.show({title:translate('Group Ordering'), msg:GroupText,
					  minWidth:600, modal:true,
					  buttons:Ext.Msg.OK,
					  height:310, maxHeight:320,
					  width:600});
	};

	var groupOrderButton = new Ext.Button({
		id:'groupOrderButton',
		text:translate('Tell me about Group Ordering'),
		handler:showGroupOrderText
	});
	 
	var setGroupDefaults = function()
	{
		var records = dataView.getSelectedRecords();
		var record = records[0];

		var dt = Ext.getCmp('datePicker');
		var dtVal = dt.getValue();
		if(!dtVal)
		{
			var newDate = getToday(record);
			dt.setValue(newDate);
			dt.fireEvent('change', dt, newDate, null);
		}
		  
		var tc = Ext.getCmp('timeCombo');
		var tcVal = tc.getValue();

		if(!tc.store.getTotalCount())
		{
			;
		}
		else
		{
			if(tcVal == translate('Select a time'))

			{
				tcVal = '';
			}

			if(!tcVal)
			{
				var val = tc.store.getAt(0);
				if(val)
				{
					tc.setValue(val.get('value'));
				}
				tc.fireEvent('select', tc, val, null);
			}
		}
	};

	var locationSelected = function(dv, recordNum, node, event)
	{
		var records = dv.getSelectedRecords();
		var record = records[0];

		var res = Ext.getCmp('loc-display-form');
		var f = res.getForm();

		if(!record)
		{
			return;
		}

		f.loadRecord(record);

		if (record.get('disableGroupOrders')) {
			var fieldset = Ext.getCmp('group-order-fieldset');
			fieldset.hide();
		}

		updating = record.get('updating');

		var dow = record.get('weekday');
		var schedule = record.get('schedToday');

		if(updating && record.get('setDate') && record.get('active'))
		{
			var orderDate = record.get('setDate');
			dow = Date.parseDate(orderDate,'Y-m-d').format('w') + 1;
			schedule = record.get('schedule')[dow];
		}

		var times = [];
		  
		if(schedule.length)
		{

			var times = fixTimes(schedule, record, !updating);
		}

		timeStore.loadData(times);
		  
		dt = Ext.getCmp('datePicker');
		dt.reset();
		dt.minValue = getToday(record);
		dt.maxValue = dt.parseDate(dt.minValue.add(Date.MONTH, 3));
		dt.disabledDays = record.get('baddays');

		if(updating && record.get('setDate') && record.get('active'))
		{
			newDate = dt.parseDate(record.get('setDate'), 'Y-m-d');
			dt.setValue(newDate);
			dt.fireEvent('change', dt, newDate, null);
		}
		  
		if(dt.menu)
		{
			dt.menu.destroy();
		}
		dt.menu = null;

		orderType = record.get('ordermode');

		if (orderType == 1)
		{
			if(!updating)
			{
				submitOrderButton.setText(translate("Start Delivery Order"));					
			}
			else
			{
				submitOrderButton.setText(translate("Update Delivery Order"));
			}
			var details = Ext.getCmp('delivery-charge-panel');
			deliveryDetailTemplate.overwrite(details.body, record.data);
			var ot = Ext.getCmp('edelivery-field');
			ot.show('row');
			ot = Ext.getCmp('epickup-field');
			ot.hide('row');
			details.show();
		}
		else
		{
			var details = Ext.getCmp('delivery-charge-panel');
			details.hide();
			if(!updating)
			{
				submitOrderButton.setText(translate("Start Pick Up Order"));
				if(!addressWidget.loggedIn)
				{
					enableGuest = true;
				}
			}
			else
			{
				submitOrderButton.setText(translate("Update Pick Up Order"));
			}
			var ot = Ext.getCmp('edelivery-field');
			ot.hide('row');
			ot = Ext.getCmp('epickup-field');
			ot.show('row');
		}
		tc = Ext.getCmp('timeCombo');
		tc.enable();
		tc.clearInvalid();

		if(record.get('active'))
		{
			browseMenuButton.enable();
		}
		else
		{
			browseMenuButton.disable();
		}

		if(times.length && record.get('active'))
		{
			if(!updating)
			{
				tc.emptyText = translate("ASAP");
			}
			else
			{
				tc.emptyText = translate("Select a time");
			}
			submitOrderButton.enable();

			if(updating && record.get('setTime'))
			{
				tc.setValue(Date.parseDate(record.get('setTime'),'I:m'));
			}
		}
		else
		{
			submitOrderButton.disable();
			tc.emptyText = translate("No Times Available");
			tc.disable();
		}
		tc.reset();

		dp = Ext.getCmp('datePanel');

		if(record.get('active'))
		{
			dp.enable();
			dp.show();
			if(res.collapsed)
			{
				res.expand(true);
			}
			Ext.get('panel3_title').addClass('yc-active');
			Ext.get('panel1_title').removeClass('yc-active');
			Ext.get('panel2_title').removeClass('yc-active');

		}
		else
		{
			dp.disable();
			dp.hide();
			res.collapse(true);
		}
		f.getEl().highlight('c0ffc0', {duration:1});
		trackALFEvent('/ALF/Search/Select/' + record.get('storeid'));		  
	};

	var ds = new Ext.data.Store({
		storeId:'location-store',
		id:'location-store',
		proxy: new Ext.data.HttpProxy({
			url: 'doLocSearch'
		}),
		reader: new Ext.data.JsonReader({
			root: 'rows',
			totalProperty: 'count',
			id: 'storeid',
			fields: [
			'restaurantid',
			'restaurantname', 'address1', 'city',
			'phone', 'fax', 'active', 'isopen',
			'epickup', 'edeliver', 'weekday',
			'schedule', 'schedToday', 'today', 'baddays', 'storeid',
			'businesshours', 'localtime', 
			'deliveryavailable', 'pickupavailable', 'servicehours', 
			'ordermodename', 'setDate', 'setTime', 'grpDate', 'grpTime',
			'rulename',
			{name: 'max_endtime',mapping:'max_endtime',type: 'int'},
			{name: 'updating',   mapping:'updating',   type:'bool'},
			{name: 'preptime',   mapping:'preptime',   type:'int'},
			{name: 'ordermode',  mapping:'ordermode',  type:'int'},
			{name: 'tzoffset',   mapping:'tzoffset',   type:'int'},
			{name: 'client_lat', mapping:'client_lat', type:'float'},
			{name: 'client_lon', mapping:'client_lon', type:'float'},
			{name: 'latitude',   mapping:'latitude',   type:'float'},
			{name: 'longitude',  mapping:'longitude',  type:'float'},
			{name: 'distance',   mapping:'distance',   type:'float'},
			{name: 'minsubtotalcents', mapping:'minsubtotalcents', type:'int'},
			{name: 'deliverychargecents', mapping:'deliverychargecents', type:'int'},
			{name: 'disableGroupOrders',   mapping: 'disableGroupOrders',   type: 'bool'}
			]
		}),
		baseParams: {json: true, limit:6}
	});

	var doDeliverySearch = function(form, callback)
	{
		Ext.get('panel2_title').addClass('yc-active');
		Ext.get('panel1_title').removeClass('yc-active');
		Ext.get('panel3_title').removeClass('yc-active');

		trackALFEvent('/ALF/Search/Delivery');
		if(form.isValid())
		{
			ds.baseParams = ds.baseParams || {};
			ds.baseParams['query'] = null;
			params = form.getValues();
			params['start'] = 0;
			ds.reload({params:params, callback:callback});
		}
	};

	mapWindow = new Ext.ux.GMapWindow({
		maximizable: false,
		collapsible: true,
		closeAction: 'hide',
		x: 120,
		y: 10,
		constrain:true,
		width:350,
		height:350,
		zoomLevel:14,
		mapConfOpts: [
			'enableScrollWheelZoom',
			'enableDoubleClickZoom',
			'enableDragging'
		],
		mapControls: ['GLargeMapControl']
	});
	mapWindow.show();
	mapWindow.hide();

	var centsToDollars = function(cents)
	{
		realCents = (cents % 100);
		if(realCents < 10)
		{
			realCents = "0" + realCents;
		}
		return '$' + parseInt(cents/100) + '.' + realCents;
	};
	 
	// Custom rendering Template for the View
	var resultTpl = new Ext.XTemplate(
		'<tpl for=".">',
		'<div class="search-item">',
		'<tpl if="active"><span class="online">',
		translate('Online Ordering'),
		'</span></tpl>',
		'<tpl if="!active"><span class="offline">',
		translate('Please Call To Order'),
		'</span></tpl>',
		'<h3>{restaurantname}</h3>',
		'<tpl if="!active">',
		'<span class="details">{address1}, {city} - {phone}',
		'</tpl>',
		'<tpl if="active">',
		'<span class="details">',
		'{ordermodename} ',
		translate('Hours Today'),
		': {servicehours}',
		'</span>',
		'</tpl>',
		'<tpl if="hasGoogleKey">',
		'<tpl if="ordermode==2">',
		'<tpl if="longitude">',
		' <a href="#" onClick="mapWindow.showRestaurant({restaurantid});">',
		translate('Show Map'),
		'</a>',
		'</tpl>',
		'</tpl>',
		'</tpl>',
		'</div></tpl>',
		{
			dollars: function(cents) {
				return centsToDollars(cents);
			}
		}
	).compile();

	var resultTplLong = new Ext.XTemplate(
		'<tpl for=".">',
		'<div class="search-item">',
		'<tpl if="active"><span class="online">',
		translate('Online Ordering'),
		'</span></tpl>',
		'<tpl if="!active"><span class="offline">',
		translate('Please Call To Order'),
		'</span></tpl>',
		'<h3>{restaurantname}</h3>',
		'<tpl if="active">',
		'<span class="details">',
		'<tpl if="ordermode == 1">',
		'<tpl if="rulename">',
		'{rulename} - ',
		'</tpl>',
		'<tpl if="minsubtotalcents">',
		'&nbsp;',
		translate('Minimum Order:'),
		' {[this.dollars(values.minsubtotalcents)]} ',
		'</tpl>',
		'<tpl if="deliverychargecents">',
		translate('Delivery Charge:'),
		' {[this.dollars(values.deliverychargecents)]} ',
		'</tpl>',
		'</tpl>',
		'<br>{ordermodename} ',
		translate('Hours Today:'),
		' {servicehours}',
		'</span><br/>',
		'</tpl>',
		'<span class="details">{address1}, {city} - {phone}',
		'<tpl if="active">',
		'<tpl if="distance"> - ({distance} ',
		translate('miles'),
		')</tpl><br/>',
		'<tpl if="deliveryavailable">',
		translate('Delivery Available'),
		' </tpl>',
		'<tpl if="pickupavailable">',
		translate('Pick Up Available'),
		' </tpl><br>',
		translate('Open Right Now'),
		': {isopen}',
		'</tpl>',
		'</span>',
		'</div></tpl>',
		{
			dollars: function(cents) {
				return centsToDollars(cents);
			}
		}
	).compile();

	var deliveryDetailTemplate = new Ext.XTemplate(
		'<span class="details red-highlight">',
		'<tpl if="ordermode == 1">',
		'{rulename}<br/>',
		'<tpl if="minsubtotalcents">',
		'&nbsp;',
		translate('Minimum Order:'),
		' {[this.dollars(values.minsubtotalcents)]} ',
		'</tpl>',
		'<tpl if="deliverychargecents">',
		translate('Delivery Charge:'),
		' {[this.dollars(values.deliverychargecents)]} ',
		'</tpl>',
		'</tpl>',
		{
			dollars: function(cents) {
				return centsToDollars(cents);
			}
		}
	).compile();

	 
	var dataView = new Ext.DataView({
		id:'search-results',
		tpl: resultTpl,
		store: ds,
		itemSelector: 'div.search-item',
		singleSelect: true,
		loadingText: translate("Searching please wait..."),
		emptyText: translate("No matching locations. Please search again."),
		overClass:'x-view-hover'
	});
	 
	dataView.on('click', locationSelected);
	ds.on(
		'load', 
		function()
		{
			Ext.get('panel2_title').addClass('yc-active');
			Ext.get('panel1_title').removeClass('yc-active');
			Ext.get('panel3_title').removeClass('yc-active');
			// Ext.getCmp('loc-display-form').collapse();

			if(!this.getCount())
			{
				trackALFEvent('/ALF/Search/NoResults');
			}
			else
			{
				trackALFEvent('/ALF/Search/Results/' + this.getCount());
			}

			Ext.getCmp('search-results').getEl().highlight('C0FFC0', {duration:1});
		}
	);

	browseMenu = function()
	{
		var records = dataView.getSelectedRecords();
		var record = records[0];
		var restid = record.get('restaurantid');
		fpRedirect('/mp/pub/menu?restid='+restid);
	};

	var groupOrderRequested = function()
	{
		var tdf = Ext.getCmp('loc-display-form').getForm();
		var params = tdf.getValues();
		var isGroupOrder = params.groupOrdering || false;
		return isGroupOrder;
	};

	var doStartOrder = function(button, event) 
	{
		var records = dataView.getSelectedRecords();
		var record = records[0];
		var tdf = Ext.getCmp('loc-display-form').getForm();
		var params = tdf.getValues();

		var isGroupOrder = params.groupOrdering || false;

		var restid = record.get('restaurantid');
		var orderMode = record.get('ordermode');
		var cl_id = Ext.getCmp('customerAddressCombo').getValue();

//		  if(isGroupOrder && !tdf.isValid())
		if(!tdf.isValid())
		{
			Ext.Msg.alert(translate('Incomplete'), 
						  translate('Please complete all required fields.'));
			return;
		}

		if(true)
		{
			if(!params.time || 
			   params.time == translate('Select a time'))
			{
				Ext.Msg.alert(translate('Incomplete'), 
							  translate('Please select a time.'));
				return;
			}
			if(params.time == translate('No Times Available'))
			{
				Ext.Msg.alert(translate('Closed'), 
							  translate('The restaurant is closed for the rest of the day, please choose another date, or another available location.'));
				return;
			}
			if(params.time == translate('ASAP'))
			{
				var tal = timeAtLocation(record.get('tzoffset'));
				var tc = Ext.getCmp('timeCombo').store;
				var t = tc.getAt(tc.getCount()-1);
				var dal = tal.format("Y-m-d");
				var cto = new Date.parseDate(dal, "Y-m-d").add(Date.MINUTE, t.get('value'));
				if(cto <= tal)
				{
					Ext.Msg.alert(translate('Closed'), 
								  translate('This location has now closed, please choose another'));
					return;
				}
			}
			else if(timeIndexSelected >= 0)
			{
				var tc = Ext.getCmp('timeCombo').store;
				var t = tc.getAt(timeIndexSelected);
				params.time = t.get('value');
			}
		}

		params.restid = restid;
		params.servicetype = orderMode;
		params.isgrouporder = isGroupOrder;
		params.customerlocid = cl_id || -1;
		params.json = 1;

		var checkTimeReader = new Ext.data.JsonReader({
			root: 'rows',
			totalProperty: 'count',
			id: 'id'
		}, [
			'success', 'message'
		]);
		
		var stp = new Ext.data.ScriptTagProxy({
			url:absolute_url + 'checkTime',
			timeout:25000,
			api:{
				'read':absolute_url + 'checkTime'
			}
		});

		stp.doRequest(
			'read', null, params, 
			checkTimeReader, 
			function(result, params, success)
			{
				if(!result || !success)
				{
					Ext.Msg.alert(translate('Problem'),
								  translate("Could not confirm order time, please try again"));
					return;
				}
				
				var record = result.records[0];
				if(!record.get('success'))
				{
					Ext.Msg.alert(translate('Problem'),
								  record.get('message'));
					return;
				}

				if(params.servicetype == 1)
				{
					trackALFEvent('/ALF/StartOrder/Delivery');
				}
				else
				{
					trackALFEvent('/ALF/StartOrder/PickUp');
				}
				
				var qString = Ext.urlEncode(params);
				fpRedirect(absolute_url + 'ordernow' + '?' + qString);
			}, this, params
		);
	};

	var timeIndexSelected = -1;

	var timeSelected = function(timePicker, timeRecord, timeIndex)
	{
		timeIndexSelected = timeIndex;
	};

	var getToday = function(record)
	{
		var today;
		today = dt.parseDate(record.get('today'), 'm/d/Y');


		if(record.get('max_endtime') > 1440)
		{
			var timeOff = eval(
				timeAtLocation(
					record.get('tzoffset')).format('H * 60 + i;'));
			var o = record.get('max_endtime');
			if(o > 1440)
			{
				var z = o - 1440;
				if(timeOff < z)
				{
					today = today.add(Date.DAY, -1);
				}
			}
		}
		return(today);
	};

	var fixTimes = function(times, record, isToday)
	{
		var minVal = 36 * 60;
		var newTimes = [];

		var sid = record.get('ordermode');
		var prep = record.get('preptime');

		if(isToday)
		{
			minVal = eval(timeAtLocation(
							  record.get('tzoffset')).add(Date.MINUTE, prep).format('H * 60 + i;'));
		}

		if(sid == 1)
		{
			if(isToday && record.get('edeliver') != 'N/A')
			{
				minVal = eval(Date.parseDate(record.get('edeliver'), 'h:i A').format('H * 60 + i;'));
			}
			else if(!isToday)
			{
				minVal = eval(Date.parseDate(times[0][1], 'H:i A').format('H * 60 + i;'));
			}
			else
			{
				times = [];
			}
		}
		else
		{
			if(isToday && record.get('epickup') != 'N/A')
			{
				minVal = eval(Date.parseDate(record.get('epickup'), 'h:i A').format('H * 60 + i'));
			}
			else if(!isToday)
			{
				minVal = eval(Date.parseDate(times[0][1], 'H:i A').format('H * 60 + i;'));
			}
			else
			{
				times = [];
			}
		}
		
		if(isToday)
		{
			var o = record.get('max_endtime');
			if(o > 1440)
			{
				var z = o - 1440;
				if(minVal < z)
				{
					minVal += 1440;
				}
			}
		}
		  
		for(i = 0; i < times.length; i++)
		{
			var t = times[i][0];
			if(t >= minVal)
			{
				newTimes.push(times[i]);
			}
		}
		return newTimes;
	};

	var _fixTimes = function(times, record, isToday)
	{
		var minVal = '23:59';
		var newTimes = [];

		var sid = record.get('ordermode');
		var prep = record.get('preptime');
		var active = record.get('active');

		if(!active)
		{
			return [];
		}

		minVal = timeAtLocation(record.get('tzoffset')).add(Date.MINUTE, prep).format('H:i');

		if(sid == 1)
		{
			if(isToday && record.get('edeliver') != 'N/A')
			{
				minVal = Date.parseDate(record.get('edeliver'), 'H:i A').format('H:i');
			}
			else if(!isToday)
			{
				minVal = Date.parseDate(times[0][1], 'H:i A').format('H:i');
			}
			else
			{
				times = [];
			}
		}
		else
		{
			if(isToday && (record.get('epickup')||'N/A') != 'N/A')
			{
				minVal = Date.parseDate(record.get('epickup'), 'H:i A').format('H:i');
			}
			else if(!isToday)
			{
				minVal = Date.parseDate(times[0][1], 'H:i A').format('H:i');
			}
			else
			{
				times = [];
			}
		}
		for(i = 0; i < times.length; i++)
		{
			var t = Date.parseDate(times[i][1], 'H:i A').format('H:i');
			if(t >= minVal)
			{
				newTimes.push(times[i]);
			}
		}
		return newTimes;
	};

	var dateSelected = function(datePicker, newDate, oldDate)
	{
		var records = dataView.getSelectedRecords();
		var record = records[0];

		schedule = record.get('schedule');
		if(newDate)
		{
			dow = newDate.format('w') + 1;

		}
		else
		{
			dow = record.get('weekday');
		}
		times = schedule[dow];

		today = getToday(record);

		if(!newDate || today.between(newDate, newDate))
		{
			times = record.get('schedToday');
			if(times.length)
			{
				times = fixTimes(times, record, true);
			}
		}
		else
		{
			if(times.length)
			{
				times = fixTimes(times, record, false);
			}
		}

		timeStore.loadData(times);

		if(record.get('active'))
		{
			browseMenuButton.enable();
		}
		else
		{
			browseMenuButton.disable();
		}

		if(times.length && record.get('active'))
		{
			submitOrderButton.enable();
		}
		else
		{
			submitOrderButton.disable();
		}		  

		var tc = Ext.getCmp('timeCombo');
		tc.enable();
		tc.clearInvalid();
		if(newDate)
		{
			tc.reset();
			tc.allowBlank = false;
			tc.emptyText = translate("Select a time");
		}
		else
		{
			tc.emptyText = translate("ASAP");
			tc.allowBlank = true;
			tc.reset();
		}

		tc.reset();

		if(!times.length)
		{
			tc.emptyText = translate("No Times Available");
			tc.disable();
			tc.reset();
		}

		timeIndexSelected = -1;
	};

	var resultPanel = new Ext.Panel( {
		id:'loc-results-panel',
		//iconCls:'search-panel-title',
		//title:'Search Results (click to select)',
		height:273,
		width:362,
		autoScroll:true,
		renderTo:'zip-panel',
		items: dataView,
		tbar: [
			'<b>'+translate('Search Results') + '</b>', '->',
			{
				pressed:false,
				iconCls:'details-button',
				enableToggle:true,
				text:translate('Show Details'),
				toggleHandler:function(button, state)
				{
					if(state)
					{
						dataView.tpl = resultTplLong;
						button.setText(translate("Hide Details"));
					}
					else
					{
						dataView.tpl = resultTpl;
						button.setText(translate("Show Details"));
					}
					var indices = dataView.getSelectedIndexes();
					dataView.refresh();
					dataView.select(indices[0]);
				}
			}
		],
		bbar: new Ext.PagingToolbar({
			store: ds,
			pageSize: 6,
			displayInfo: true,
			displayMsg: translate('Locations') + ' {0} - {1} ' + translate('of') +' {2}',
			emptyMsg: translate("No Locations to display")
		})
	});
	
	var zipPanel = new Ext.NovaDine.ZipCode(ds);
	 
	var addressWidget = new Ext.NovaDine.Address(doDeliverySearch);

	var loginOrRegister = function(buttonId)
	{
		if(buttonId == 'yes') // Login
		{
			addressWidget.doLogin();
			return;
		}
		else if(buttonId == 'no') // Register
		{
			addressWidget.doRegister();
			return;
		}
		else if(buttonId == 'ok') // Guest
		{
			addressWidget.doGuestRegister();
		}
		return;
	};

	// empty defined above;
	checkForLogin = function(button, event)
	{
		if(addressWidget.loggedIn)
		{
			doStartOrder(button, event);
			return;
		}
		var buttons = {yes:translate('Login'), 
					   no:translate('Register'), 
					   cancel:translate('Cancel')}
		
		var message = ( 
			translate('You must be logged in to start an order.') +
			'<br>'+ 
			translate('If you have an account, press Login now and you will be logged in and your order started.')+
			'<br>'+
			translate('If you need to register, press Register now and we will collect some information from you, save it, and then start your order at the selected location.')
		);
		if(groupOrderRequested())
		{
			enableGuest = false;
		}

		if(enableGuest)
		{
			buttons.ok = translate('Guest');
			message = message + ('<br>' + 
								 translate('If you do not wish to register at this time you can place your order in guest mode'));
		}

		Ext.Msg.show({
			fn:loginOrRegister,
			buttons:buttons,
			modal:true,
			msg:message,
			title:translate('Login or Register')});
	};
	 
	var tabs = new Ext.TabPanel( {
		id:'main-tab-panel',
		enableTabScroll:true,
		renderTo: 'locationSearch',
		width:194,
		height:273,
		activeTab: 1,
		frame:false,
		footer:false,
		defaults:{autoHeight: true, autoWidth: true},
		items: [
			zipPanel,
			addressWidget.addressForm
		]
	});

	var displayForm = new Ext.form.FormPanel({
		id:'loc-display-form',
		collapsed:true,
		labelWidth: 90,
		width: 244,
		height:273,
		defaultType: 'textfield',
		defaults: {
			width:'auto'
		},
		layoutConfig: {
			labelSeparator: ':'
		},
		items:[{ 
			name:'restaurantname',
			hideLabel: true,				   
			readOnly:true,
			width:238,
			cls:'display-only-title'
		}, { 
			fieldLabel:translate('Earliest Delivery Today'),
			name:'edeliver',
			readOnly:true,
			width:76,
			cls:'display-only',
			labelWidth:140,
			labelStyle:'width:140px;',
			id:'edelivery-field'
		}, {
			fieldLabel:translate('Earliest Pick Up Today'),
			name:'epickup',
			readOnly:true,
			width:76,
			cls:'display-only',
			labelWidth:140,
			labelStyle:'width:140px;',
			id:'epickup-field'
		}, { 
			xtype:'fieldset',
			height:'auto',
			width:238,
			layout:'form',
			id:'datePanel',
			style:'padding:2px;',
			defaults:{anchor:'98%'},
			labelWidth:100,
			items:[{ 
				fieldLabel: translate('Date'), 
				name: 'date', 
				xtype:'datefield', 
				emptyText:translate('Today'), 
				minValue:new Date(), 
				id:'datePicker', 
				tabIndex:20,  
				disabledDaysText:translate('Closed'), 
				width:80
			},{ 
				fieldLabel: translate('Time'), 
				name: 'time', 
				triggerAction:'all',
				mode:'local',
				xtype:'combo', 
				emptyText:translate('ASAP'), 
				store:timeStore, 
				id:'timeCombo', 
				valueField:'value', 
				displayField:'text', 
				forceSelection:true, 
				tabIndex:21 , 
				width:80, 
				editable:false
			}]
		}, { 
			id:'group-order-fieldset',
			xtype:'fieldset',
			height:'auto',
			width:238,
			layout:'form',
			hidden:hideGroupOrderingCheckBox,
			items:[{
				hideLabel: true,
				name:'groupOrdering',
				boxLabel: translate('Invite others by email - Group Order'),
				xtype:'checkbox'
			}, groupOrderButton ]
		}, {
			xtype:'panel',
			layout:'fit',
			id:'delivery-charge-panel',
			hidden:true,
			border:false
		}, submitOrderButton ],
		bbar:[ '->', browseMenuButton  ]
	});

	tt = Ext.getCmp('timeCombo');
	tt.on('select', timeSelected);

	dt = Ext.getCmp('datePicker');
	dt.on('change', dateSelected);

	var SelectorLayout = new Ext.Panel({
		el:'bigSelector',
		layout: 'border',
		width:820,
		height:332,
		tbar:addressWidget.userTBar,
		items: [ {
			title:'<span class="yc" id="panel1_title">&nbsp;&nbsp;&nbsp;1 '+ translate('Find a') + ' ' + top.document.title.split('--')[0] + '</span>',
			contentEl:'west',
			id:'west-panel',
			width:200,
			region:'west',
			collapsible: false,
			items:[tabs]
		}, {
			title:'<span class="yc" id="panel3_title">&nbsp;&nbsp;&nbsp;3 '+translate('Start Your Order') + '</span>',
			contentEl:'east',
			collapsible:false,
			id:'east-panel',
			region:'east',
			width:250,
			items:[displayForm]
		}, {
			title:'<span class="yc" id="panel2_title">&nbsp;&nbsp;&nbsp;2 '+ translate('Choose a Location') + '</span>',
			el:'center',
			collapsible:false,
			region:'center',
			width:370,
			items:[resultPanel]
		}]
	});
	 
	dp = Ext.getCmp('datePanel');
	dp.hide();
	Ext.get('loading').remove();
	Ext.get('loading-mask').fadeOut({remove:true});
	SelectorLayout.render();

	Ext.get('panel1_title').addClass('yc-active');

	if(!addressWidget.loggedIn)
	{
		if(popLoginForm||false)
		{
			addressWidget.doLogin();
		}
		else if(forcePopLogin||false)
		{
			var FLD = new Ext.NovaDine.ForceLogin();
			fld_proxyPopUp(FLD);			   
		}
//		  if(popRegisterForm||false)
//		  {
	//			   addressWidget.doRegister();
//		  }
	}
};
	 
var SearchInterface;
Ext.onReady(function(){SearchInterface = new Ext.NovaDine.SearchInterface();});

