/**** /js/moikrug/ui/GrowingTextarea.js ****/
Lang.module('moikrug.ui.GrowingTextarea');

Lang.include('Widget');

moikrug.ui.GrowingTextarea = Lang.createClass(Widget, {
	init: function(node, options) {
		this.baseConstructor(node);
        this.heightSaved = false;
        this.saveHeightTimeout = 0;
	},
    
    parse: function() {
        this.saveHeight();
        this.node.style.overflowY = "hidden";
        this._updateHeight();
        return this;
    },
    
    onHeightUpdate: function(){},
	
	bindEvents: function() {
        Event.observe(this.node, "keyup", this._updateHeight.bind(this));
        return this;
	},
    
    saveHeight: function() {
        this.saveHeightTimeout = window.setInterval((function() {
            if (this.node.offsetHeight) {
                this.originalOffsetHeight = this.node.offsetHeight;
                this.originalStyleHeight = this.node.getStyle('height');
                this.heightSaved = true;
                window.clearInterval(this.saveHeightTimeout);
            }
        }).bind(this), 50);
    },
    
    _getEmSize: function() {
        if (!this.emSize) {
            var textarea = document.createElement("textarea");
            textarea.style.border = "0";
            textarea.style.height = "2em";
            textarea.style.padding = "0";
            textarea.style.visibility = "hidden";
            this.node.parentNode.appendChild(textarea);
            var height = textarea.offsetHeight;
            textarea.parentNode.removeChild(textarea);
            this.emSize = height / 2;
        }
        return this.emSize;
    },
    
    _updateHeight: function() {
        if (!this.heightSaved) {
            window.setTimeout(this._updateHeight.bind(this), 100);
            return;
        }
        if (this.needWidthUpdate && this.node.offsetWidth) {
            var div = this._getContainer();
            div.style.width = this.node.offsetWidth - this.additional + "px";
            this.needWidthUpdate = false;
        }
        var newHeight = this._getTextHeight();
        if (newHeight > this.originalOffsetHeight + 5) {
            this.node.style.height = newHeight + 'px';
        } else {
            if (Prototype.Browser.Opera) {
                this.node.style.height = this.originalOffsetHeight + "px";
            } else {
                this.node.style.height = this.originalStyleHeight;
            }
        }
    },
    
    _getTextHeight: function() {
        if (Prototype.Browser.IE) {
            return this.node.scrollHeight + 2 * this._getEmSize();
        } else {
            var div = this._getContainer();
            var value = this.node.value;
            if (this.previousValue) {
                var newNewLinesRegexp = value.match(/\n+$/);
                var newNewLines = newNewLinesRegexp ? newNewLinesRegexp[0].length : 0;
                var oldNewLinesRegexp = this.previousValue.match(/\n+$/);
                var oldNewLines = oldNewLinesRegexp ? oldNewLinesRegexp[0].length : 0;
                if (newNewLines - oldNewLines == 2) {
                    value = value.substr(0, value.length - 1);
                }
            }
            if (Prototype.Browser.WebKit) {
                this.previousValue = value;
            }
            div.innerHTML = value.replace(/</g, '&lt;').replace(/ {2}/g, ' &nbsp;').replace(/\n/g, '<br/>t') + "<br/>t<br/>t";
            return div.offsetHeight;
        }
    },
    
    _getContainer: function() {
        if (!this._container) {
            this._container = document.createElement("div");
            this._container.style.position = "absolute";
            this._container.style.left = "-9999px";
            
            this._syncStyles(this.node, this._container);
            this.node.parentNode.appendChild(this._container);
        }
        this._container.innerHTML = '';
        return this._container;
    },
    
    _syncStyles: function(src, target) {
        if (Prototype.Browser.Opera) {
            src.style["lineHeight"] = src.getStyle("lineHeight");
            this.needWidthUpdate = true;
        }
        $w('fontFamily fontSize lineHeight ' +
           'paddingLeft paddingRight paddingTop paddingBottom ' +
           'borderLeftWidth borderRightWidth borderTopWidth borderBottomWidth ' + 
           'borderLeftStyle borderRightStyle borderTopStyle borderBottomStyle ' +
           'lineHeight width').each(function(s) {
            target.style[s] = src.getStyle(s);
        });
        if (Prototype.Browser.Opera) {
            this.additional = 20;
        }
        if (Prototype.Browser.Gecko) {
            this.additional = 10;
        }
        if (Prototype.Browser.WebKit) {
            this.additional = 4;
        }
        if (this.additional) {
            target.style.width = parseFloat(target.style.width) - this.additional + "px";
        }
    }
});
;

/**** /js/moikrug/ui/MessageForm.js ****/
Lang.module('moikrug.ui.MessageForm');
Lang.include('common.FormUtils');

moikrug.ui.MessageForm = Lang.createClass(moikrug.Widget, {
    init: function(node, options, name) {
        this.baseConstructor(node, options, name);
    },
    
    parse: function() {
        this.textInput = this.node.down('.message_message');
        this.textInputWidget = WidgetRegistry.get(this.textInput);
        this.textLabel = this.textInput.up().down("label");
        
        this.showControl = this.node.down(".message_form_show");
        this.hideControl = this.node.down(".message_form_hide");
        
        this.hasControls = !!this.showControl;
        this.form = this.node.down("div") || this.node.down("form");
        this.formShown = !this.form.hasClassName("hidden");

        this.recipientListShow = this.node.down(".message_form_recipients_show");
        this.recipientList = this.node.down(".message_form_recipients");
        return this;
    },
    
    getControlls: function() {
        return { show: this.showControl, hide : this.hideControl };
    },
    
    toggleForm: function() {
        this.formShown = !this.formShown;
        if (this.formShown) {
            this.showForm();
        } else {
            this.hideForm();
        }
    },
    
    showForm: function() {
        this.form.removeClassName("hidden");
        this.form.style.zoom = 1;
        if (this.hasControls) {
            this.showControl.addClassName("hidden");
            this.hideControl.removeClassName("hidden");
        }
        this.textInput.focus();
    },
    
    hideForm: function() {
        this.form.addClassName("hidden");
        if (this.hasControls) {
            this.hideControl.addClassName("hidden");
            this.showControl.removeClassName("hidden");
        }
    },

    bindEvents: function() {
        common.FormUtils.placeholder(this.textInput, this.textLabel);
        if (this.recipientListShow) {
            Event.observe(this.recipientListShow, "click", (function(e) {
                e.stop();
                this.recipientListShow.addClassName("hidden");
                this.recipientList.removeClassName("hidden");
                var wList  = WidgetRegistry.get(this.recipientList.down());
                if (wList) {
                    wList.setFocus();
                }
            }).bindAsEventListener(this));
        }
        if (this.hasControls) {
            Event.observe(this.showControl, "click", this.toggleForm.bind(this));
            Event.observe(this.hideControl, "click", this.toggleForm.bind(this));
        }
        return this;
    },

    setRecipientPerson: function(person_id) {
        $('recipients_persons').value = person_id;
    }
});

;

/**** /js/form/Form.js ****/
Lang.module('form.Form');

Lang.include('moikrug.widget.Clonable');

form.Form = Lang.createClass(moikrug.widget.Clonable, {
    init: function(node, options, name, className) {
        this.baseConstructor(node, options, name, className);
        this.controlSubmit = {};
    },

    parse: function() {
        var tmp = this.node.down('input[type="submit"]') || this.node.down('button[type="submit"]');
        this.controlSubmit = Widget.getInstance(tmp) || tmp;
    },

    setDisabled: function(state) {
        if(this.controlSubmit.setDisabled) {
        	this.controlSubmit.setDisabled(state);
        } else {
        	this.controlSubmit.disabled = state;
        }
    },

    isDisabled: function() {
        return this.controlSubmit.disabled;
    },

    bindEvents: function() {
        Event.observe(this.node, 'submit', this.onFormSubmit.bindAsEventListener(this));
    },

    onFormSubmit: function(event) {
        this.onSubmit();
    },

    onSubmit: function() {
    }
});

form.Form.getInstance = function(node) {
    return Widget.getInstance(node) || Widget.registerInstance(node, new form.Form(node));
};

;

/**** /js/form/SubmitableForm.js ****/
Lang.module('form.SubmitableForm');

Lang.include('form.Form');

form.SubmitableForm = Lang.createClass(form.Form, {
    init: function(node, options, name, className) {
        this.baseConstructor(node, options, name, className);
    },

    parse: function() {
        this.textareas = this.node.select('textarea');
        return this;
    },
    
    bindEvents: function() {
        for (var i=0; i < this.textareas.length; i++) {
	        Event.observe(this.textareas[i], 'keydown', this.submitForm.bindAsEventListener(this));
	    }
	    return this;
    },
	
    submitForm: function(event) {
        if (
            (event.ctrlKey || event.metaKey) 
            && event.keyCode == Event.KEY_RETURN
        ) {
            this.node.submit();
        }
    }
	
});

;

/**** /js/common/FormUtils.js ****/
Lang.module('common.FormUtils');

common.FormUtils = {
    
    placeholder: function(node, textOrLabel, options) {
         this.options = options || {};
         
         this.isSpanHeightRequired = this.options.hasOwnProperty("isSpanHeightRequired") ? this.options.isSpanHeightRequired : true;
         
         if (!$(node)) {
             return;
         }
         if (!textOrLabel && $(node + '_label')) { 
            this._placeholderLabel($(node), $(node + '_label'));
        } else if ($(textOrLabel)) {
            this._placeholderLabel($(node), $(textOrLabel));
        } else if (textOrLabel) {
            this._placeholderText($(node), textOrLabel);
        }
    },

    getLabel: function(input) {
        for (var i=0,I=this._inputs.length;i<I;i++) {
            if (this._inputs[i] == input) {
                return this._labels[i];
            }
        }
        return null;
    },
    
    _inputs: [],
    _labels: [],
    _cleanerLaunched: false,
    
    _cleaner: function() {
        for (var i=0,I=this._inputs.length; i<I; i++) {
            //noinspection BadExpressionStatementJS
            if (this._inputs[i] && !!this._inputs[i].value.length) {
                this._labels[i].style.display = "none";
            }
        }
    },
    
    _placeholderLabel: function(node, label)
    {
        this._inputs[this._inputs.length] = node;
        this._labels[this._labels.length] = label;
        Event.observe(node, "focus", function() {
             label.style.display = "none";
        });
        Event.observe(node, "blur", function() {
            if (node.value.strip() === "") {
                label.style.display = "block";
            }
        });
        Event.observe(label, "click", function() {
            node.focus();
        });
        if (!this._cleanerLaunched) {
            this._cleanerLaunched = true;
            window.setInterval(this._cleaner.bind(this), 100);
        }
    },
    
    _placeholderText: function(node, text) {
        Element.wrap(node, 'span').setStyle({
            position: 'relative',
            top: '0', 
            left: '0', 
            display: 'block', 
            height: this.isSpanHeightRequired ? "1%" : ""
        });
        
        var label = new Element('label', {'for': node.id});
        label.innerHTML = text;
        label.setStyle({
            position: 'absolute',
            top: this.options.top || '1px', 
            left: '4px',
            display: 'block',
            lineHeight: '1.4em',
            cursor: 'text',
            color: '#999',
            zIndex: '2',
            whiteSpace: 'nowrap'
        });
        node.insert({before: label});
        this._placeholderLabel(node, label);
    }
};

;

/**** /js/moikrug/ChatNotificationManager.js ****/
Lang.module("moikrug.ChatNofiticationManager");

moikrug.ChatNotificationManager = Lang.createClass(Widget, {

	frameSize: null,
	msgCount: null,
	widgets: [],
	queen: null,
	msgContainer: null,

	closeNode: null,
	CLOSE_COOKIE: 'ChatNotificationManager_closed',

    init: function(node, options, limit, count) {
        this.baseConstructor(node, options);
        this.frameSize = limit;
        this.msgCount = count;
    },

    parse: function() {
        this.widgets = [];
        
        // Save sample (prototype) node and remove it from the container.
        this.queen = WidgetRegistry.get(this.node.down('.chat_notifier_item.hidden'));
        this.msgContainer = this.queen.node.parentNode;
        this.msgContainer.removeChild(this.queen.node);
        
        this.node.select('.chat_notifier_item').each((function(item) {
            this.widgets.push(WidgetRegistry.get(item));
        }).bind(this));
        
        this.closeNode = this.node.down('.chat_notifier_close');
        if (!this.isClosed()) {
        	this.setClosed(false);
        }

        this.limitFrame();
        return this;
    },

    bindEvents: function() {
        var markReadAndMaybeHide = (function(notification) {
            moikrug.Multiplexor.removeKey("Message", notification.getMessageId());
        }).bind(this);

        this.widgets.each((function(notification) {
            notification.observe("textClick", markReadAndMaybeHide.curry(notification));
        }).bind(this));
        
        Event.observe(this.closeNode, "click", (function(e) {
            e.stop();
            this.setClosed(true);
        }).bindAsEventListener(this));

        moikrug.Multiplexor.subscribe("Message", (function(messageData) {
            if (moikrug.ThreadPage && moikrug.ThreadPage.instance.threadId == messageData.threadId) {
                moikrug.Multiplexor.removeKey("Message", messageData.messageId);
                return;
            }
            var newNotification = this.queen.cloneCurrent();
            if (this.msgContainer.firstChild) {
		        this.msgContainer.insertBefore(newNotification.node, this.msgContainer.firstChild);
            } else {
		        this.msgContainer.appendChild(newNotification.node);
            }
            newNotification.setMessageId(messageData.messageId);
            newNotification.setPersonName(messageData.personName, messageData.personNameFull);
            newNotification.setPersonLink(messageData.personLink);
            newNotification.setMessageText(messageData.inlineText);
            newNotification.setMessageLink(messageData.url);
            newNotification.node.removeClassName("hidden");

            newNotification.observe("close", markReadAndMaybeHide.curry(newNotification));
            newNotification.observe("textClick", markReadAndMaybeHide.curry(newNotification));
            this.widgets.push(newNotification);
            this.msgCount++;
            this.limitFrame();

            this.setClosed(false);
            newNotification.blink();
            moikrug.TitleNotification.startBlink(messageData.personName + ' - ' + DIC.new_message_from);
            
        }).bind(this));
        return this;
    },
    
    limitFrame: function() {
		var f = $(this.msgContainer.parentNode).select('.chat_notifier_f')[0];
		var items = $(this.msgContainer).select('.chat_notifier_item');
		var nShown = 0;
		for (var i = 0; i < items.length; i++) {
			var item = items[i];
			var widget = WidgetRegistry.get(item);
			if (nShown < this.frameSize) {
	        	item.removeClassName("hidden");
				nShown++;
			} else {
	        	item.addClassName("hidden");
			}
        }
        if (this.msgCount <= nShown) {
        	f.style.display = 'none';
        } else {
        	f.style.display = '';
			$(f).select('a')[0].innerHTML = common.TextUtils.formatNumberTemplate(
				this.msgCount - nShown,
				DIC.chat_notifier_n_new_messages
			);
        }
    },
    
    setClosed: function(flag) {
        Cookie.set(this.CLOSE_COOKIE, flag? 1 : 0, null, "/");
        var allHidden = this.widgets.all(function(widget) {return widget.node.hasClassName("hidden");});
        if (!flag && !allHidden) {
        	this.node.removeClassName("hidden");
        } else {
        	this.node.addClassName("hidden");
        }
    },
    
    isClosed: function() {
        return parseInt(Cookie.get(this.CLOSE_COOKIE), 10);
    }
});
;

/**** /js/moikrug/TitleNotification.js ****/
Lang.module("moikrug.TitleNotification");

moikrug.TitleNotification = {

    focusStatus: false,
    blinkStatus: false,
    oldTitle: false,
    timeout: null,
    
    bindEvents: function() {
        if (Prototype.Browser.IE) {
            document.observe('focusin', this._setFocus.bindAsEventListener(this));
            document.observe('focusout', this._clearFocus.bindAsEventListener(this));
        } else {
	        document.observe('focus', this._setFocus.bindAsEventListener(this));
	        document.observe('blur', this._clearFocus.bindAsEventListener(this));
        }
        return this;
    },
    
    _setFocus: function() {
        this.focusStatus = true;
    },
    
    _clearFocus: function() {
        this.focusStatus = false;
    },
    
    startBlink: function(msg) {
        this.oldTitle = document.title;
        msg = msg.stripTags();
        msg = msg.replace(/\&.*?;/,'');
        this._blinkTitle(msg);
    },
    
    stopBlink: function() {
        this._clearFocus();
    },
    
    _blinkTitle: function(msg) {
        
        if (this.blinkStatus) {
            document.title = msg;
        } else {
            document.title = this.oldTitle;
        }
        this.blinkStatus = !this.blinkStatus;
        if (!this.focusStatus) {
            this.timeout = setTimeout(function() { this._blinkTitle(msg); }.bind(this), 1500);
        } else {
            document.title = this.oldTitle;
        }
        
    }
    
};
moikrug.TitleNotification.bindEvents();

;

/**** /js/moikrug/ui/messaging/ChatNotification.js ****/
Lang.module('moikrug.ui.messaging.ChatNotification');

Lang.include('moikrug.widget.Clonable');

moikrug.ui.messaging.ChatNotification = Lang.createClass(moikrug.widget.Clonable, {
    init: function(node, options, name, className) {
        this.baseConstructor(node, options, name, className || "ChatNotification");
    },

    _createClonedWidget: function(node, options, name, className) {
        return new moikrug.ui.messaging.ChatNotification(node, options, name, className).parse().bindEvents();
    },
    
    parse: function() {
        this.personNameNode = this.node.down(".chat_notifier_person");
        this.messageTextNode = this.node.down(".chat_notifier_text");
        return this;
    },
    
    bindEvents: function() {
        Event.observe(this.node, "click", (function() {
            this.onTextClick();
        }).bind(this));
        return this;
    },

    blink: function() {
        var node = this.node;
        var delay = 400;
        node.addClassName("chat_notifier_item_dark");
        window.setTimeout(function() {node.removeClassName("chat_notifier_item_dark");}, delay);
        window.setTimeout(function() {node.addClassName("chat_notifier_item_dark");}, delay*2);
        window.setTimeout(function() {node.removeClassName("chat_notifier_item_dark");}, delay*3);
        window.setTimeout(function() {node.addClassName("chat_notifier_item_dark");}, delay*4);
        window.setTimeout(function() {node.removeClassName("chat_notifier_item_dark");}, delay*5);
        window.setTimeout(function() {node.addClassName("chat_notifier_item_dark");}, delay*6);
        window.setTimeout(function() {node.removeClassName("chat_notifier_item_dark");}, delay*7);
    },

    close: function() {
        this.node.addClassName("hidden");
    },

    getMessageId: function() {
        return this.options.messageId;
    },

    setMessageId: function(id) {
        this.options.messageId = id; 
    },

    /**
     * Setters
     */
    setPersonName: function(name, fullName) {
        this.personNameNode.title = fullName;
        this.personNameNode.innerHTML = common.TextUtils.highlightFirstLetterInName(name);
    },

    setPersonLink: function(link) {
        // No separated link for a person. 
        //this.personNameNode.href = link;
    },

    setMessageLink: function(link) {
    	// Note that yo CANNOT do up('a'), because this.messageTextNode
    	// is not in DOMDocument yet at this time. :-(
    	node = $(this.messageTextNode).up(); 
        node.href = link;
    },

    setMessageText: function(text) {
        this.messageTextNode.down("span").innerHTML = text;
    },

    /**
     * Events
     */
    onClose: function(){},
    onTextClick: function(){}

});
;

/**** /js/moikrug/widget/Messaging/NewMessageButton.js ****/
Lang.module('moikrug.widget.Messaging.NewMessageButton');
moikrug.widget.Messaging.NewMessageButton = Lang.createClass(moikrug.Widget, {
    init: function(node, options, name) {
        this.baseConstructor(node, options, name);
    },
    
    
    bindEvents: function() {
    	this.messageForm = WidgetRegistry.getByName('message');
    	var formControlls = this.messageForm.getControlls();
    	
    	this.node.observe('click', this.showForm.bind(this));
    	if (formControlls.show) {
            formControlls.show.observe('click', this.showForm.bind(this));
    	}
    	
    	if (formControlls.hide) {
            formControlls.hide.observe('click', this.hideForm.bind(this));
        }
    	return this;
    },
    
    showForm: function() {
    	this.messageForm.showForm();
    	this.node.addClassName('hidden');
    },
    
    hideForm: function() {
        this.messageForm.hideForm();
        this.node.removeClassName('hidden');
    }
    
});
;

/**** /js/moikrug/ui/GrowingInput.js ****/
Lang.module('moikrug.ui.GrowingInput');

Lang.include('Widget');

moikrug.ui.GrowingInput = Lang.createClass(Widget, {
	init: function(node, options) {
		this.baseConstructor(node, options);
        this.interval = 0;
	},
    
    bindEvents: function() {
        Event.observe(this.node, "keyup", this._onKeyUp.bind(this));
        //Event.observe(this.node, "keydown", this._onKeyDown.bind(this));
        return this;
	},
    
    _onKeyUp: function() {
        this._updateWidth();
    },
    
    _updateWidth: function() {
        var newWidth = this._getTextWidth();
        this.node.style.width = newWidth + 'px';
    },
    
    _getTextWidth: function() {
        var span = this._getContainer();
        var value = this.node.value;
        span.innerHTML = this._updateText(value.replace(/ {2}/g, ' &nbsp;'));
        return span.offsetWidth;
    },

    _updateText: function(text) {
        return text + "m";
    },
    
    _getContainer: function() {
        if (!this._container) {
            this._container = document.createElement("span");
            this._container.style.position = "absolute";
            this._container.style.left = "-9999px";
            
            this._syncStyles(this.node, this._container);
            this.node.parentNode.appendChild(this._container);
        }
        this._container.innerHTML = '';
        return this._container;
    },
    
    _syncStyles: function(src, target) {
        $w('fontFamily fontSize ' +
           'paddingLeft paddingRight ' +
           'borderLeftWidth borderRightWidth ' + 
           'borderLeftStyle borderRightStyle').each(function(s) {
            target.style[s] = src.getStyle(s);
        });
    }
});
;

/**** /js/moikrug/ui/Suggest.js ****/
Lang.module("moikrug.ui.Suggest");

Lang.include("moikrug.widget.Clonable");

moikrug.ui.Suggest = Lang.createClass(moikrug.widget.Clonable, {

/**
 * @author akoval
 * 
 * Options:
 *    invitation:                  text in suggest when there's no user input
 *    requestParams:               additional params for ajax request
 *    serverTarget:                url part after /widgets/ajax/
 *    selectedClassName:           css class name for selected item
 *    hoverClassName:              css class name for hover interaction
 *    additionalListClassName:     optional css class name for the list of suggestons
 *    updateInputOnLoopingThru:    flag indicating if input field value should be replaced or not
 *                                 with value of current(highlighted) one during looping
 *                                 through the list of suggestions
 *    showInvitationOnBlur:        flag indicating if invitation container can be displayed after occuring onBlur event on input field
 *    showInvitation:              flag indicating if invitation container should be displayed
 *    showLoadingIndicator:        flag indicating if loading indicator should be displayed
 *
 * @param options see options description
 */
    init: function(node, options, name, className) {
        this.baseConstructor(node, options, name, className || '');
        if (!options.invitation && window.DIC) {
            Object.extend({
                invitation: DIC.dropdown_invitation
            }, this.options);
        }
        if (this.options.requestParams) {
            this.requestParams = this.options.requestParams;
        }
        this.preSelectedElementIndex = null;
        this.defaults = {
            selectedClassName:           "selected",
            hoverClassName:              "hover",
            additionalListClassName:     "",
            updateInputOnLoopingThru:    true,
            showInvitationOnBlur:        false,
            showInvitation:              true,
            showLoadingIndicator:        true
        };
        
        this.overrideOptions();
        
        this.list = this.createList();
        this.listAttached = false;

        this.indicator = this.createIndicator();
        this.indicatorAttached = false;
        
        this.invitation = this.options.invitation;
        this.node.setAttribute("autocomplete", "off");
        this.form = this.node.form;
    },

    _createClonedWidget: function(node, options, name, className) {
        return new moikrug.ui.Suggest(node, options, name, className).bindEvents();
    },
    
    overrideOptions: function() {
        for(var i in this.defaults) {
            if(!this.options.hasOwnProperty(i)) {
                this.options[i] = this.defaults[i];
            }
        }
    },

/**
 * Creates a <ul> list that will contain suggest items
 */
    createList: function() {
        var list = document.createElement("ul");
        list.className = "newDropDownList suggest-list " + this.options.additionalListClassName;
        list.style.display = "none";
        return list;
    },

/**
 * Attaches list to DOM. Should be called after <tt>onload</tt>
 * due to problems in IE
 */
    attachList: function() {
        this.listAttached = true;
        var div = document.createElement("div");
        div.className = "form";
        div.appendChild(this.list);
        document.body.appendChild(div);
    },

/**
 * Updates width of the list so that it's the same as of input
 */
    updateListWidth: function() {
        if (this.node.offsetWidth) {
            var newWidth = this.node.offsetWidth - 2;
            newWidth = Math.max(this.options.minWidth || 0, newWidth);
            this.list.style.width = newWidth + 'px';
        }
    },

/**
 * Updates position of the list, so that it's just below the input
 * Currently the position is bottom-input-border to top-list-border
 */
    updateListPosition: function() {
        var offset = $(this.node.parentNode).cumulativeOffset();
        this.list.style.left = offset[0] + "px";
        this.list.style.top = offset[1] + this.node.offsetHeight + "px";
    },

    updateListAppearance: function() {
        this.updateListWidth();
        this.updateListPosition();
    },

    showList: function() {
        if (!this.listAttached) {
            this.attachList();
        }
        if (this.list.firstChild) {
            this.preSelectedElementIndex = null;
            this.updateListAppearance();
            this.list.style.display = "block";
        }
        if (window.WCH) {
            window.WCH.Apply(this.list, this.list.parentNode, true);
        }
    },

    hideList: function() {
        this.clearList();
        this.list.style.display = "none";
        if (window.WCH) {
            window.WCH.Discard(this.list, this.list.parentNode, true);
        }
    },

/**
 * Creates an indicator to show that AJAX request is sent
 */
    createIndicator: function() {
        var indicator = document.createElement("img");
        indicator.style.position = "absolute";
        indicator.src = "/images/icon_updating.gif";
        return indicator;
    },

/**
 * Attaches indicator to DOM. Should be called after <tt>onload</tt>
 * due to problems in IE
 */
    attachIndicator: function() {
        this.indicatorAttached = true;
        document.body.appendChild(this.indicator);
    },

    updateIndicatorPosition: function() {
        var offset = Position.cumulativeOffset(this.options.updateIconOffsetNode || this.node.parentNode);
        var leftOffset = 0;
        if (this.options.rightIndicator) {
            leftOffset = 5 + this.node.getWidth();
        } else {
            leftOffset = -24;
        }
        this.indicator.style.left = offset[0] + leftOffset + 'px';
        this.indicator.style.top = offset[1] + 5 + 'px';
        this.indicator.style.zIndex = 100;
    },
    
    /**
     * Displays loading indicator
     * 
     * In the case showInvitation flag is set to FALSE
     * we have an opportunity to show invitation on demand
     * by passing optional parameter
     * 
     * @param {Boolean} showOnDemand
     */
    showIndicator: function(showOnDemand) {
        if (this.options.showLoadingIndicator || !!showOnDemand) {
               if (!this.indicatorAttached) {
                this.attachIndicator();
            }
            this.updateIndicatorPosition();
            this.indicator.style.visibility = "visible";
        }
    },

    hideIndicator: function() {
        this.indicator.style.visibility = "hidden";
    },
    
    _getServerUrl: function() {
        if (/^\w+$/.test(this.options.serverTarget)) {
            return window.location.protocol + '//' + window.location.host + '/widgets/ajax/' + this.options.serverTarget;
        } else {
            return this.options.serverTarget;
        }
    },

    requestList: function() {
        if (this.node.value.length === 0) {
            this.hideList();
            this.hideIndicator();
            this.showInvitation();
            JsHttpRequest.clearTimeout(this.timeout);
            return;
        }
        this.oldReqValue = this.node.value;
        this.JsHttpRequest = new JsHttpRequest();
        this.JsHttpRequest.onreadystatechange = (function() {
            if (this.JsHttpRequest.readyState != 4) {
                return;
            }
            this.hideList();
            this.fillList(this.JsHttpRequest.responseJS.result);
            this.showList();
            this.hideIndicator();
        }).bind(this);
        this.JsHttpRequest.caching = true;
        this.JsHttpRequest.open('GET', this._getServerUrl(), true);
        JsHttpRequest.clearTimeout(this.timeout);
        this.timeout = JsHttpRequest.setTimeout((function() {
            var request = this.options.requestParams || {};
            request.q = this.node.value;
            if (request.q.length > 0) {
                this.showIndicator();
                this.JsHttpRequest.send(request);
                this.onRequestSent();
            } else {
                this.showInvitation();
            }
        }).bind(this), 300);
    },

    bindEvents: function() {
        this.boundOnFocus = this.onNodeFocus.bind(this);
        this.boundOnBlur = this.onNodeBlur.bind(this);

        Event.observe(this.node, "focus", this.boundOnFocus);
        Event.observe(this.node, "blur", this.boundOnBlur);
        Event.observe(window, "resize", this.updateListPosition.bindAsEventListener(this));
        
        var event;
        if (Prototype.Browser.Gecko || Prototype.Browser.Opera) {
            event = "keypress";
        } else {
            event = "keydown";
        }
        Event.observe(this.node, event, this.onNodeKeyDown.bindAsEventListener(this));
        Event.observe(this.node, "keyup", this.onNodeKeyUp.bindAsEventListener(this));
        return this;
    },

    onNodeFocus: function() {
        this.nodeBlurred = false;
        if (this.node.value.length === 0) {
            this.showInvitation();
        }
        this.onFocus();
    },

    onNodeBlur: function() {
        this.nodeBlurred = true;
        var th = this;
        JsHttpRequest.setTimeout(function() {
            if (th.nodeBlurred) {
                th.onBlur();
            }
        }, 200);
    },

    onNodeKeyDown: function(e) {
        this.waitingForKeyPress = false;
        var code = e.keyCode;

        switch (code) {
            case Event.KEY_BACKSPACE:
                if (this.onNodeBackspaceKey(e)) {
                    return;
                }
                break;
            case Event.KEY_ESC:
                if (this.onNodeEscapeKey(e)) {
                    return;
                }
                break;
            case Event.KEY_UP:
                if (this.onNodeUpKey(e)) {
                    return;
                }
                break;
            case Event.KEY_DOWN:
                if (this.onNodeDownKey(e)) {
                    return;
                }
                break;
            case Event.KEY_RETURN:
                if (this.onNodeEnterKey(e)) {
                    return;
                }
                break;
            case Event.KEY_TAB:
                if (this.onNodeTabKey(e)) {
                    return;
                }
                break;
        }
        this.waitingForKeyPress = true;
    },

    onNodeBackspaceKey: function() {
        this.hideList();
    },

    onNodeEscapeKey: function(e) {
        this.hideList();
        Event.stop(e);
        return true;
    },

    onNodeUpKey: function(e) {
        if (this.list.childNodes.length > 0 && this.list.firstChild.className != "invitation") {

            this.resetSelection();

            switch (this.preSelectedElementIndex) {
                case null:
                    this.preSelectedElementIndex = this.list.childNodes.length - 1;
                    break;
                case 0:
                    this.preSelectedElementIndex = null;
                    this.node.value = this.oldReqValue;
                    break;
                default:
                    this.preSelectedElementIndex--;
                    break;
            }

            if (this.preSelectedElementIndex !== null) {
                $(this.list.childNodes[this.preSelectedElementIndex]).addClassName(this.options.selectedClassName);
                if (this.options.updateInputOnLoopingThru) {
                    this.node.value = this.list.childNodes[this.preSelectedElementIndex].title;
                }
                this.node.dic_id = this.list.childNodes[this.preSelectedElementIndex].dic_id;
                this.selectedItem = this.list.childNodes[this.preSelectedElementIndex];
            }
            Event.stop(e);
            return true;
        }
    },

    onNodeDownKey: function(e) {
        if (this.list.childNodes.length > 0 && this.list.firstChild.className != "invitation") {
            
            this.resetSelection();

            switch (this.preSelectedElementIndex) {
                case null:
                    this.preSelectedElementIndex = 0;
                    break;
                case this.list.childNodes.length - 1:
                    this.preSelectedElementIndex = null;
                    this.node.value = this.oldReqValue;
                    break;
                default:
                    this.preSelectedElementIndex++;
                    break;
            }

            if (this.preSelectedElementIndex !== null) {
                this.list.childNodes[this.preSelectedElementIndex].addClassName(this.options.selectedClassName);
                if (this.options.updateInputOnLoopingThru) {
                    this.node.value = this.list.childNodes[this.preSelectedElementIndex].title;
                }
                this.node.dic_id = this.list.childNodes[this.preSelectedElementIndex].dic_id;
                this.selectedItem = this.list.childNodes[this.preSelectedElementIndex];
            }
            Event.stop(e);
            return true;
        }
    },

    onNodeEnterKey: function(e) {
        Event.stop(e);
        this.onEnterKey();
        if (this.selectedItem) {
            this.selectItem(this.selectedItem);
        }
        return true;
    },

    onEnterKey: function() {

    },

    onNodeTabKey: function(e) {
        if (this.preSelectedElementIndex !== null && this.list.childNodes.length > 0 && this.node.value == this.list.childNodes[this.preSelectedElementIndex].title) {
            if (this.selectedItem) {
                this.selectItem(this.selectedItem);
            }
            return true;
        } else {
            this.hideList();
            return true;
        }
    },

    onNodeKeyUp: function() {
        if (this.waitingForKeyPress) {
            this.requestList();
        }
    },

    onRequestSent: function() {

    },
    
    onFocus: function() {
    },

    onBlur: function() {
        if (this.JsHttpRequest) {
            this.JsHttpRequest.onreadystatechange = null;
        }
        this.hideIndicator();
        if (!this.options.showInvitationOnBlur) {
            this.hideList();
        }
    },

    fillList: function(jsList) {
        this.clearList();
        if (jsList.length) {
            var search = this.node.value;
            for (var idx = 0,I = jsList.length; idx < I; idx++) {
                if (jsList[idx].size && jsList[idx].size > 0) {
                    this.addListItem(jsList[idx], search);
                }
            }
        }
    },

    addListItem: function(rawListItem, search) {
        var li = document.createElement('li');
        var highlightedName = this.getHighlightedValue(rawListItem, search);
        /*
        var sizeSpan = '<span class="count">' + rawListItem.size + '</span>';
        if (this.options.countless) {
            sizeSpan = '<span class="count">&nbsp;</span>';
        }
        */
        li.innerHTML = highlightedName;
        li.title = rawListItem.name;
        li.dic_id = rawListItem.id;
        this.list.appendChild(li);
        this.initListItem(li);
    },
    
    initListItem: function(listItem) {
        var that = this;
        Event.observe(listItem, 'click', ((function(e) {
            this.selectItem(listItem);
        }).bindAsEventListener(this)));
        listItem.onmouseover = (function() {
            this.resetSelection();
            listItem.addClassName(this.options.hoverClassName);
        }).bind(this);
        listItem.onmouseout = function() { this.removeClassName(that.options.hoverClassName); };
    },
    
    resetSelection: function (){
        if (this.list.childNodes.length > 0){
            for (var i=0,l=this.list.childNodes.length;i<l;i++) {
                if (this.list.childNodes[i].className){
                    this.list.childNodes[i].removeClassName(this.options.hoverClassName);
                    this.list.childNodes[i].removeClassName(this.options.selectedClassName);
                }
            }
        }
    },

    getHighlightedValue: function(value, searchSubstr) {
        var name = value.name;
        var substrIdx = name.toLowerCase().indexOf(searchSubstr.toLowerCase());
        var highlightedName;
        if (substrIdx > -1) {
            highlightedName = name.substr(0, substrIdx);
            highlightedName += "<span class=\"highlight\">" + name.substr(substrIdx, searchSubstr.length).escapeHTML() + "</span>";
            highlightedName += name.substr(substrIdx + searchSubstr.length).escapeHTML();
        } else {
            highlightedName = name;
        }
        return highlightedName;
    },

    clearList: function() {
        while (this.list.childNodes.length > 0) {
            this.list.removeChild(this.list.firstChild);
        }
        this.selectedItem = null;
    },
    
    /**
     * Displays invitation
     * 
     * In the case showInvitation flag is set to FALSE
     * we have an opportunity to show invitation on demand
     * by passing optional parameter
     * 
     * @param {Boolean} showOnDemand
     */
    showInvitation: function(showOnDemand) {
        if (this.options.showInvitation || !!showOnDemand) {
               this.clearList();
            var li = document.createElement('li');
            $(li).addClassName("invitation");
            li.appendChild(document.createTextNode(this.invitation));
            this.list.appendChild(li);
            this.showList();
        }
    },

    selectItem: function(listItem) {
        this.selectedItem = listItem;
        this.node.value = listItem.title;
        this.node.dic_id = listItem.dic_id;
        this.node.focus();
        this.hideList();
        this.onItemSelected();
    },

    onItemSelected: function() {
    }

});
;

/**** /js/moikrug/ui/messaging/PersonSuggest.js ****/
Lang.module("moikrug.ui.messaging.PersonSuggest");

Lang.include("common.TextUtils");
Lang.include("moikrug.ui.Suggest");

moikrug.ui.messaging.PersonSuggest = Lang.createClass(moikrug.ui.Suggest, {

    init: function(node, options, name, className) {
        this.baseConstructor(node, options, name, className);
        this._template = new Template(
            '<div class="person person_middle"><div class="avatar">' + 
            '<div class="person_photo_container person_photo_container_middle profilePreview">' +
            '<img src="#{photo}" class="person_photo">' + '<div class="person_border"></div>' +
            '#{online}' + 
            '</div></div><div class="info"><div class="name">' +
            '#{name}</div>' +
            '<div class="slogan">#{motto}</div>' +
            '</div><div class="wrap"></div></div>'
        );
        this._onlineStatus = '<div class="person_border_online"></div>';
    },

    createList: function() {
        var list = document.createElement("ul");
        list.className = "suggest-list PersonSuggestList";
        list.style.display = "none";
        return list;
    },
    
    fillList: function(jsList) {
        this.clearList();
        if (jsList.length) {
            var search = this.node.value;
            for (var idx = 0,I = jsList.length; idx < I; idx++) {
                this.addListItem(jsList[idx], search);
            }
        }
    },

    updateListWidth: function(){},

    onNodeUpKey: function(e) {
        if (this.list.childNodes.length > 0 && this.list.firstChild.className != "invitation") {

            this.resetSelection();

            switch (this.preSelectedElementIndex) {
                case null:
                    this.preSelectedElementIndex = this.list.childNodes.length - 1;
                    break;
                case 0:
                    this.preSelectedElementIndex = null;
                    this.node.value = this.oldReqValue;
                    break;
                default:
                    this.preSelectedElementIndex--;
                    break;
            }

            if (this.preSelectedElementIndex !== null) {
                $(this.list.childNodes[this.preSelectedElementIndex]).addClassName("selected");
				this.selectedItem = this.list.childNodes[this.preSelectedElementIndex];
            }
            Event.stop(e);
            return true;
        }
    },

    onNodeDownKey: function(e) {
        if (this.list.childNodes.length > 0 && this.list.firstChild.className != "invitation") {

            this.resetSelection();

            switch (this.preSelectedElementIndex) {
                case null:
                    this.preSelectedElementIndex = 0;
                    break;
                case this.list.childNodes.length - 1:
                    this.preSelectedElementIndex = null;
                    this.node.value = this.oldReqValue;
                    break;
                default:
                    this.preSelectedElementIndex++;
                    break;
            }

            if (this.preSelectedElementIndex !== null) {
                this.list.childNodes[this.preSelectedElementIndex].addClassName("selected");
				this.selectedItem = this.list.childNodes[this.preSelectedElementIndex];
            }
            Event.stop(e);
            return true;
        }
    },

    requestList: function() {
		if (this.node.value.length === 0) {
            this.hideList();
            this.hideIndicator();
            this.showInvitation();
            JsHttpRequest.clearTimeout(this.timeout);
            return;
        }
        this.oldReqValue = this.node.value;
        this.JsHttpRequest = new JsHttpRequest();
        this.JsHttpRequest.onreadystatechange = (function() {
            if (this.JsHttpRequest.readyState != 4) {
                return;
            }
            this.hideList();
            this.fillList(this.JsHttpRequest.responseJS);
            this.showList();
            this.hideIndicator();
        }).bind(this);
        this.JsHttpRequest.caching = true;
        this.JsHttpRequest.open('GET', this._getServerUrl(), true);
        JsHttpRequest.clearTimeout(this.timeout);
        this.timeout = JsHttpRequest.setTimeout((function() {
            var request = this.options.requestParams || {};
            request.request = this.node.value;
            if (request.request.length > 0) {
                this.showIndicator();
                this.JsHttpRequest.send(request);
                this.onRequestSent();
            } else {
                this.showInvitation();
            }
        }).bind(this), 300);
	},
    
    _getListItemHtml: function(dataItem, searchString) {
        var templateData = {};
        templateData.photo = dataItem.photo || "/images/blank_photo/blank_photo_30px.png";
        templateData.motto = dataItem.resume_headline;
        templateData.online = dataItem.is_online ? this._onlineStatus : "";
        templateData.name = common.TextUtils.highlightFirstLetterInName(
            common.TextUtils.highlightSearchString(dataItem.displayname, searchString)
        );
        return this._template.evaluate(templateData);
    },

    addListItem: function(dataItem, searchString) {
        if (this.options.validate && !this.options.validate(dataItem)) {
            return;
        }
        var html = this._getListItemHtml(dataItem, searchString);
        var li = document.createElement('li');

        li.innerHTML = html;
        li.title = dataItem.displayname;
        li.dic_id = dataItem.id;
        this.list.appendChild(li);
        Event.observe(li, 'click', ((function(e) {
            this.selectItem(li);
        }).bindAsEventListener(this)));
        li.onmouseover = (function() {
            this.resetSelection();
            li.addClassName("hover");
        }).bind(this);
        li.onmouseout = function() { this.removeClassName("hover"); };
    },

    selectItem: function(listItem)  {
        this.node.focus();
        this.hideList();
        this.onItemSelected(listItem);
    },
    
    _createClonedWidget: function(node, options, widgetName, widgetClassName) {
        return new moikrug.ui.PersonSuggest(node, options, widgetName, widgetClassName);
    }

});
;

/**** /js/moikrug/ui/messaging/RecipientsList.js ****/
Lang.module('moikrug.ui.messaging.RecipientsList');

Lang.include('moikrug.ui.GrowingInput');
Lang.include('moikrug.ui.messaging.PersonSuggest');

moikrug.ui.messaging.RecipientsList = Lang.createClass(Widget, {
    init: function(node, options) {
        this.baseConstructor(node, options);
        this.people = [];
        this.selectedPerson = null;
    },

    parse: function() {
        var person = this.node.down(".RecipientsList_person_dummy");
        person.down(".RecipientsList_name").innerHTML = "";
        person.removeClassName(".RecipientsList_person_dummy");
        this.personTemplate = $(person.cloneNode(true));
        this.personTemplate.removeClassName("hidden");
        person.remove();
        
        var people = this.node.select(".RecipientsList_person");
        for (var i=0,l=people.length;i<l;i++) {
            var _person = people[i];
            this._addEventsForPerson(_person);
            this.people.push(_person);
        }
        
        this.input = this.node.down(".RecipientsList_input");
        var suggest = new moikrug.ui.messaging.RecipientsList.MyPersonSuggest(this.input, {
            serverTarget: "messagerecipients",
            invitation: this.options.invitation,
            alignNode: this.node,
            validate: (function(dataItem) {
                var id = dataItem.id;
                for (var i = 0,l = this.people.length; i < l; i++) {
                    if (this.people[i].down("input").value == id) {
                        return false;
                    }
                }
                return true;
            }).bind(this)
        }, this.widgetName + "_person").parse().bindEvents();
        suggest._updateWidth();
        suggest.observe("itemSelected", this.addPerson.bind(this));
        suggest.observe("blur", (function() {
            this.input.value = "";
        }).bind(this));
        suggest.observe("focus", (function() {
            this._resetSelection();
        }).bind(this));
        this._wrap = this.node.down(".wrap");
        this._focus = this.node.down(".RecipientsList_focus"); 
        return this;
    },

    bindEvents: function() {
        Event.observe(this.node, "click", (function() {
            this._resetSelection();
            this.input.focus();
        }).bind(this));
        var event;
        if (Prototype.Browser.Gecko || Prototype.Browser.Opera) {
            event = "keypress";
        } else {
            event = "keydown";
        }
        Event.observe(this.node, event, this._onNodeKeyDown.bindAsEventListener(this));
        return this;
    },

    addPerson: function(listItem) {
        var name = listItem.title;
        var id = listItem.dic_id;

        var person = $(this.personTemplate.cloneNode(true));
        person.down(".RecipientsList_name").innerHTML = common.TextUtils.highlightFirstLetterInName(name);
        person.down("input").value = id;
        this._addEventsForPerson(person);
        
        this.people.push(person);
        this.node.insertBefore(person, this.input);
        this.input.value = "";
        this.input.focus();
    },
    
    _addEventsForPerson: function(person) {
        Event.observe(person, "click", (function(e) {
            Event.stop(e);
        }).bindAsEventListener(this, person));
        Event.observe(person.down(".RecipientsList_name"), "focus", (function(e, man) {
            this.selectPerson(man);
            Event.stop(e);
        }).bindAsEventListener(this, person));
        Event.observe(person.down(".RecipientsList_close"), "click", (function(e, man) {
            this.removePerson(man);
            Event.stop(e);
        }).bindAsEventListener(this, person));
    },

    removePerson: function(person) {
        this.people = this.people.without(person);
        if (person == this.selectedPerson) {
            this.selectedPerson = null;
        }
        person.remove();
    },

    _onLeftKey: function(e) {
        var el = e.element();
        if (el == this.input && this.input.value !== "") {
            return;
        }
        this._selectPrevPerson();
    },

    _onRightKey: function(e) {
        var el = e.element();
        if (el == this.input && this.input.value !== "") {
            return;
        }
        var selected = this.selectedPerson;
        this._selectNextPerson();
        if (this.selectedPerson == selected) {
            this._resetSelection();
            this.input.focus();
            e.stop();
        }
    },

    _onBackspaceKey: function(e) {
        var el = e.element();
        if (el == this.input && this.input.value !== "") {
            return;
        }
        if (this.selectedPerson) {
            var prev = this._getPrevPerson();
            if (!prev) {
                prev = this._getNextPerson();
            }
            this.removePerson(this.selectedPerson);
            if (prev) {
                this.selectPerson(prev);
            } else {
                this.input.focus();
            }
        } else {
            this._selectPrevPerson();
        }
        e.stop();
    },

    _onDeleteKey: function(e) {
        var el = e.element();
        if (el == this.input && this.input.value !== "") {
            return;
        }
        if (this.selectedPerson) {
            var next = this._getNextPerson();
            if (!next) {
                next = this._getPrevPerson();
            }
            this.removePerson(this.selectedPerson);
            if (next) {
                this.selectPerson(next);
            } else {
                this.input.focus();
            }
        } else {
            this._selectPrevPerson();
        }
        e.stop();
    },

    _onNodeKeyDown: function(e) {
        switch (e.keyCode) {
            case Event.KEY_LEFT:
                this._onLeftKey(e);
                break;
            case Event.KEY_RIGHT:
                this._onRightKey(e);
                break;
            case Event.KEY_BACKSPACE:
                this._onBackspaceKey(e);
                break;
            case Event.KEY_DELETE:
                this._onDeleteKey(e);
                break;
        }
    },

    _resetSelection: function() {
        this.selectedPerson = null;
        this.node.select(".RecipientsList_person").each(function(person) {
            person.removeClassName("RecipientsList_person-selected");
        });
    },

    _getNextPerson: function(person) {
        person = person || this.selectedPerson;
        var index = this.people.indexOf(person);
        if (index == -1 || index == this.people.size() - 1) {
        	return null;
        }
        return this.people[index + 1];
    },

    _getPrevPerson: function(person) {
        person = person || this.selectedPerson;
        var index = this.people.indexOf(person);
        if (index <= 0) {
        	return null;
        }
        return this.people[index - 1];
    },

    _selectPrevPerson: function() {
        if (!this.selectedPerson) {
            if (this.people.size() > 0) {
                this.input.blur();
                this.selectPerson(this.people.last());
            }
            return;
        }
        var prev = this._getPrevPerson();
        if (prev !== null) {
            this.selectPerson(prev);
        }
    },

    _selectNextPerson: function() {
        if (!this.selectedPerson) {
        	return;
        }
        var next = this._getNextPerson();
        if (next !== null) {
            this.selectPerson(next);
        }
    },

    selectPerson: function(person) {
        this._resetSelection();
        this.selectedPerson = person;
        person.addClassName("RecipientsList_person-selected");
        this._focus.focus();
    },
    
    setFocus: function() {
        this.input.focus();
    }
    
});

moikrug.ui.messaging.RecipientsList.MyPersonSuggest = Lang.createClass(
    [moikrug.ui.messaging.PersonSuggest, moikrug.ui.GrowingInput], {

    init: function(node, options, name, className) {
        this.baseConstructor(node, options, name, className);
        this.alignNode = options.alignNode || this.node;
    },

    parse: function() {
        moikrug.ui.messaging.PersonSuggest.prototype.parse.apply(this);
        moikrug.ui.GrowingInput.prototype.parse.apply(this);
        return this;
    },

    bindEvents: function() {
        moikrug.ui.messaging.PersonSuggest.prototype.bindEvents.apply(this);
        moikrug.ui.GrowingInput.prototype.bindEvents.apply(this);
        return this;
    },

    updateListWidth: function() {
        if (this.alignNode.offsetWidth) {
            var newWidth = this.alignNode.offsetWidth - 2 + 'px';
            this.list.style.width = newWidth;
        }
    },

    updateListPosition: function() {
        var offset = this.alignNode.cumulativeOffset();
        this.list.style.left = offset[0] + "px";
        this.list.style.top = offset[1] + this.alignNode.offsetHeight - 1 + "px";
    },
    
    updateIndicatorPosition: function() {
        var offset = Position.cumulativeOffset(this.alignNode);
        this.indicator.style.left = offset[0] + this.alignNode.offsetWidth + 4 + 'px';
        this.indicator.style.top = offset[1] + 'px';
    },

    _updateText: function(text) {
        return text + "mm";
    }
});
;
