GIF89a; Mini Shell

Mini Shell

Direktori : /home/serb/www/livechat/js/app/view/
Upload File :
Current File : /home/serb/www/livechat/js/app/view/WidgetView.js

//==============================================================================
//
//  Widget view
//
//==============================================================================

(function(app, $, config)
{
    var WidgetView = app.WidgetView = Backbone.View.extend({
    
        events : {
        
            // Login form
            
            'click #customer-chat-login-start'                : 'login',
            'keydown #customer-chat-content-login-form input' : 'loginOnEnter',
            
            // Chat box
            
            'click #customer-chat-button-toggle'                : 'toggle',
            'click #customer-chat-button-close'                 : 'close',
            'click #customer-chat-button-settings'              : 'toggleSettings',
            'click .customer-chat-content-message-emots-button' : 'toggleEmoticons',
            'click .customer-chat-toggle-sound'                 : 'toggleSetting',
            'click .customer-chat-toggle-scroll'                : 'toggleSetting',
            'click .customer-chat-toggle-emots'                 : 'toggleSetting',
            'click .customer-chat-toggle-show'                  : 'toggleSetting',
            'click #customer-chat-toggle-fs'                    : 'toggleFullscreen',
            'click #customer-chat-action-end-chat'              : 'endChat',
            'click #customer-chat-action-end-chat-confirm'      : 'endChatConfirm',
            'click #customer-chat-action-end-chat-cancel'       : 'endChatCancel',
            'click .customer-chat-emoticon'                     : 'addEmoticon',
            'keydown #customer-chat-message-input'              : 'messageTyping',
            'click   #chat-send-button'                         : 'sendMessage',
            
            // Contact form
            
            'click #customer-chat-contact-send' : 'sendContactMessage',
            
            // Information
            
            'click #customer-chat-info-back' : 'showPrevState'
        },
        
        initialized        : false,
        visible            : false,
        state              : '',
        prevState          : '',
        titleBlinking      : false,
        typingInfoBlinking : false,
        emotsVisible       : false,
        
        initialize : function()
        {
            // Initialize models
            
            this.settings = app.model.settings;
            
            // Create sub views
            
            this.loginForm    = new app.LoginFormView         ({ el : this.$('#customer-chat-content-login-form')   });
            this.chatBox      = new app.ChatBoxView           ({ el : this.$('.customer-chat-content-messages')     });
            this.contactForm  = new app.ContactFormView       ({ el : this.$('#customer-chat-content-contact-form') });
            this.selectAvatar = new app.SelectAvatarInlineView({ el : this.$('#customer-chat-select-avatar'), model : config.defaultAvatars });
            
            // Cache view components
            
            this.$window              = $(window);
            this.$html                = $('html');
            this.$header              = this.$('.customer-chat-header');
            this.$title               = this.$('.customer-chat-header-title');
            this.$mobileTitle         = $('#mobile-widget i');
            this.$toggleBtn           = this.$('#customer-chat-button-toggle');
            this.$settingsBtn         = this.$('#customer-chat-button-settings');
            this.$settings            = this.$('.customer-chat-header-menu');
            this.$typingInfo          = this.$('.typing-indicator');
            this.$emoticons           = this.$('.customer-chat-emots-menu');
            this.$input               = this.$('#customer-chat-message-input');
            this.$contactName         = this.$('#customer-chat-contact-name');
            this.$contactMail         = this.$('#customer-chat-contact-mail');
            this.$contactMessage      = this.$('#customer-chat-contact-message');
            this.$loginName           = this.$('#customer-chat-login-name');
            this.$loginMail           = this.$('#customer-chat-login-mail');
            this.$info                = this.$('#customer-chat-info-text');
            this.$toggleSound         = this.$('.customer-chat-toggle-sound');
            this.$toggleScroll        = this.$('.customer-chat-toggle-scroll');
            this.$toggleEmots         = this.$('.customer-chat-toggle-emots');
            this.$toggleShow          = this.$('.customer-chat-toggle-show');
            this.$endChat             = this.$('#customer-chat-action-end-chat');
            this.$endChatConfirmation = this.$('#customer-chat-action-end-chat-confirmation');
            this.$endChatConfirm      = this.$('#customer-chat-action-end-chat-confirm');
            
            // Set the initial state
            
            this.showLoading();
            
            // Check if operators are on-line/off-line
            
            this.model.once('operators:online',  this.autoLogin,   this);
            this.model.once('operators:offline', this.showContact, this);
            
            // Handle on-line/off-line visibility
            
            this.model.once('operators:online', function()
            {
                this.postMessage('show');
                
                this.initialized = true;
                
            }, this);
            
            this.model.once('operators:offline', function()
            {
                if(!this.initialized && config.ui.hideWhenOffline === 'true')
                {
                    this.postMessage('hide');
                }
                else
                {
                    this.postMessage('show');
                }
            
            }, this);
            
            // Disable default link elements functionality for buttons
            
            this.$('a[href="#"]').click(function(e) { e.preventDefault(); });
            
            // Handle logging in / out
            
            this.model.on('login:success',  this.showChat,        this);
            this.model.on('login:login',    this.showLogin,       this);
            this.model.on('login:error',    this.showLoginError,  this);
            this.model.on('logout:init',    this.onLogout,        this);
            this.model.on('logout:success', this.onLogoutSuccess, this);
            this.model.on('logout:error',   this.onLogoutError,   this);
            
            // Handle last & new messages
            
            this.model.once('messages:last', this.handleLastMessages, this);
            this.model.on  ('messages:new',  this.handleMessages,     this);
            
            // Handle typing status
            
            this.model.on('operator:typing', this.handleOperatorTyping, this);
            
            // Handle settings
            
            this.settings.on('change', this.renderSettings, this);
            
            this.renderSettings();
            
            // Handle frames communication
            
            this.initFramesCommunication();
            
            // Start up
            
            this.model.checkOperators();
            
            // Store widget's properties
            
            this.storeProperties();
            
            // Show if it's the mobile version
            
            if(config.mobile) this.toggle();
        },
        
        setState : function(state)
        {
            // Return if it's the current state
            
            if(this.state == state)
            {
                return;
            }
            
            // Store the new state
            
            this.state = state;
            
            // Show appropriate view
            
            this.$el.removeClass('login-form chat-box contact-form loading-screen info-screen');
            
            switch(state)
            {
                case 'loading':
                    this.$el.addClass('loading-screen');
                    this.$title.html(config.ui.loadingLabel);
                break;
                
                case 'chat':
                    this.$el.addClass('chat-box');
                    this.$title.html(config.ui.chatHeader);
                    
                    // Add last messages to the chat
                    
                    for(var i = 0; i < this.model.lastMessages.length; i++)
                    {
                        var msgData = this.model.lastMessages[i];
                        
                        var message = new app.MessageModel({
                        
                            authorType : msgData.authorType,
                            author     : msgData.authorType === 'guest' ? msgData.author : this.model.getOperatorName(msgData.from_id),
                            body       : msgData.body,
                            time       : new Date(msgData.datetime)
                        });
                        
                        // Add message to the chat box
                        
                        this.chatBox.addMessage(message, true);
                    }
                    
                    this.prevState = state;
                break;
                
                case 'login':
                    this.$el.addClass('login-form');
                    this.$title.html(config.ui.chatHeader);
                    this.fullscreenOff();
                    
                    this.prevState = state;
                break;
                
                case 'contact':
                    this.$el.addClass('contact-form');
                    this.$title.html(config.ui.contactHeader);
                    this.fullscreenOff();
                    
                    this.prevState = state;
                break;
                
                case 'info':
                    this.$el.addClass('info-screen');
                break;
            }
        },
        
        toggle : function()
        {
            var bottom;
            
            if(this.visible) // Hide
            {
                // Store widget's properties
                
                this.storeProperties();
                this.prevFullscreen = this.fullscreen;
                
                // Exit fullscreen mode
                
                this.fullscreenOff();
                
                // -----
                
                this.$el.removeClass('customer-chat-visible');
                
                // Hide menus
                
                this.$settings.hide();
                this.$emoticons.hide();
                
                // -----
                
                bottom = this.headerHeight - this.frameHeight;
            }
            else // Show
            {
                this.$el.addClass('customer-chat-visible');
                this.stopTitleBlink();
                
                bottom = 0;
                
                // Go fullscreen if it was the previous state
                
                if(this.prevFullscreen) this.fullscreenOn();
            }
            
            this.postMessage('animate|bottom=' + bottom + '');
            
            this.visible = !this.visible;
        },
        
        toggleFullscreen : function()
        {
            if(this.fullscreen) this.fullscreenOff();
            else                this.fullscreenOn();
        },
        
        fullscreenOn : function()
        {
            this.storeProperties();
            
            this.$html.addClass('fs');
            this.postMessage('animate|width=100%,height=100%,right=0');
            
            this.fullscreen = true;
        },
        
        fullscreenOff : function()
        {
            this.$html.removeClass('fs');
            this.postMessage('animate|width=' + this.frameWidth + 'px,height=' + this.frameHeight + 'px,right=' + this.frameOffset, 'px');
            
            this.fullscreen = false;
        },
        
        close : function()
        {
            if(history.length > 1) history.back();
            else
            {
                window.open('', '_self');
                window.close();
            }
        },
        
        autoLogin : function()
        {
            // Show loading screen
            
            this.showLoading();
            
            // Check if user is already logged in
            
            this.model.autoLogin();
        },
        
        login : function()
        {
            this.manualLogin = true;
            
            // Get the input
            
            var input = {
            
                name  : this.$loginName.val(),
                mail  : this.$loginMail.val(),
                image : this.selectAvatar.selected
            };
            
            // Return if form is not valid
            
            if(!this.loginForm.isValid())
            {
                return;
            }
            
            // Show loading screen
            
            this.showLoading();
            
            // Send the login request
            
            this.model.login(input);
        },
        
        loginOnEnter : function(e)
        {
            if(e.which === 13) // ENTER
            {
                this.login();
            }
        },
        
        toggleSettings : function()
        {
            // Disable if hidden
            
            if(!this.visible)
            {
                return;
            }
            
            // Toggle menu
            
            if(this.$settings.is(':visible'))
            {
                this.$settings.fadeOut('fast');
                
                // Hide logout confirmation

                this.$endChatConfirmation.hide();
                this.$endChat.show();
            }
            else
            {
                this.$settings.fadeIn('fast');
            }
        },
        
        toggleEmoticons : function()
        {
            if(this.emotsVisible) this.hideEmoticons();
            else                  this.showEmoticons();
        },
        
        showEmoticons : function()
        {
            // Hide settings menu
            
            this.$settings.fadeOut('fast');
            
            this.emotsVisible = true;
            
            this.$emoticons.fadeIn('fast');
            
            var _this = this;
            
            setTimeout(function()
            {
                $('html, body').bind('click.hideemots', $.proxy(_this.hideEmoticons, _this));
            }, 10);
        },
        
        hideEmoticons : function()
        {
            this.emotsVisible = false;
            
            $('html, body').unbind('.hideemots');
            
            this.$emoticons.fadeOut('fast');
        },
        
        toggleSetting : function(evt)
        {
            var $option = $(evt.currentTarget);
            
            // Get setting's name
            
            var settingName = $option.attr('id').split('customer-chat-setting-toggle-')[1];
            
            // Update the setting
            
            this.settings.set(settingName, !this.settings.get(settingName));
        },
        
        endChat : function()
        {
            // Show confirmation
            
            this.$endChat.hide();
            this.$endChatConfirmation.show();
        },
        
        endChatCancel: function()
        {
            // Hide confirmation
            
            this.$endChatConfirmation.hide();
            this.$endChat.show();
        },
        
        endChatConfirm : function()
        {
            // Hide confirmation
            
            this.$endChatConfirmation.hide();
            this.$endChat.show();
            
            // Hide the menu
            
            this.$settings.hide();
            
            // Clear the chatbox & login form
            
            this.chatBox.clear();
            
            this.$loginName.val('');
            this.$loginMail.val('');
            
            // Logout
            
            this.model.logout();
        },
        
        renderSettings : function()
        {
            // Update view according to the model
            
            this.settings.get('sound')  ? this.$toggleSound .removeClass('customer-chat-disabled') : this.$toggleSound .addClass('customer-chat-disabled');
            this.settings.get('scroll') ? this.$toggleScroll.removeClass('customer-chat-disabled') : this.$toggleScroll.addClass('customer-chat-disabled');
            this.settings.get('emots')  ? this.$toggleEmots .removeClass('customer-chat-disabled') : this.$toggleEmots .addClass('customer-chat-disabled');
            this.settings.get('show')   ? this.$toggleShow  .removeClass('customer-chat-disabled') : this.$toggleShow  .addClass('customer-chat-disabled');
        },
        
        addEmoticon : function(evt)
        {
            var $emot = $(evt.currentTarget);
            
            this.$input.val(this.$input.val() + ' ' + $emot.data('emot') + ' ');
            
            // Set focus on the input
            
            if(!config.mobile) this.$input.focus();
            
            // Hide emoticons menu
            
            this.$emoticons.fadeOut('fast');
        },
        
        handleMessages : function(messages)
        {
            // Add messages to the chat
            
            for(var i = 0; i < messages.length; i++)
            {
                var msgData = messages[i];
                
                msgData.authorType = 'operator';
                msgData.author     = this.model.getOperatorName(msgData.from_id);
                
                var message = new app.MessageModel(msgData);
                
                message.fromUser = msgData.from_user_info;
                
                // Add message to the chat box
                
                this.chatBox.addMessage(message);
            }
            
            // Play notification sound
            
            if(this.settings.get('sound')) app.service.soundPlayer.play('message');
            
            // Show the widget and notify visually
            
            if(!this.visible)
            {
                if(this.settings.get('show')) this.toggle();
                else                          this.startTitleBlink();
            }
            
            if(this.$mobileTitle.is(':visible'))
            {
                this.stopTitleBlink();
                this.startTitleBlink();
            }
            
            // Hide typing indicator
            
            setTimeout($.proxy(this.stopTypingInfoBlink, this), 1);
        },
        
        handleLastMessages : function(messages)
        {
            // Add last messages to the chat
            
            for(var i = 0; i < messages.length; i++)
            {
                var message = new app.MessageModel(messages[i]);

                // Add message to the chat box
                
                this.chatBox.addMessage(message, true);
            }
        },
        
        messageTyping : function(evt)
        {
            // Handle typing status
            
            this.handleTyping();
            
            // React only to the ENTER key
            
            if(evt.keyCode !== 13 || evt.shiftKey)
            {
                return;
            }
            
            this.sendMessage();
        },
        
        sendMessage : function()
        {
            var body = $.trim(this.$input.val());
            
            // Do nothing if there's no input
            
            if(body.length == 0)
            {
                return;
            }
            
            var message = new app.MessageModel({
            
                author     : this.model.get('name'),
                authorType : 'guest',
                body       : body,
                time       : new Date(),
                
                from_user_info : { image : this.model.get('image') }
            },
            {
                localMessage : true
            });
            
            // Send the message
            
            this.model.sendMessage(message);
            
            // Add message to the chat box
            
            this.chatBox.addMessage(message, true);
            
            // Clear the input field
            
            this.$input.val('');
        },
        
        handleTyping : function()
        {
            this.model.updateTypingStatus();
        },
        
        handleOperatorTyping : function()
        {
            this.startTypingInfoBlink();
            
            // Hide automatically later
            
            if(this.stopTypingBlinkTimer) clearTimeout(this.stopTypingBlinkTimer);
            
            this.stopTypingBlinkTimer = setTimeout($.proxy(this.stopTypingInfoBlink, this), WidgetView.TYPING_STATUS_TIME);
        },
        
        sendContactMessage : function()
        {
            // Get the input
            
            var input = {
            
                name     : this.$contactName.val(),
                mail     : this.$contactMail.val(),
                question : this.$contactMessage.val()
            };
            
            // Return if form is not valid
            
            if(!this.contactForm.isValid())
            {
                return;
            }
            
            // Send question from the contact form
            
            var _this = this;
            
            $.post(config.contactPath, input, function(data)
            {
                if(data.success)
                {
                    // Clear the form fields
                    
                    _this.contactForm.reset();
                    
                    _this.showInfo(config.ui.contactSuccessMessage, config.ui.contactSuccessHeader);
                }
                else
                {
                    _this.showInfo(config.ui.contactErrorMessage, config.ui.contactErrorHeader)
                }
            });
            
            this.showLoading();
        },
        
        startTitleBlink : function()
        {
            this.titleBlinking = true;
            
            this.blinkTitle();
        },
        
        blinkTitle : function()
        {
            if(!this.titleBlinking)
            {
                return;
            }
            
            var _this = this;
            
            this.$mobileTitle.fadeOut('slow');
            this.$title.fadeOut('slow', function()
            {
                _this.$mobileTitle.fadeIn('slow');
                _this.$title.fadeIn('slow', function()
                {
                    _this.blinkTitle();
                });
            });
        },
        
        stopTitleBlink : function()
        {
            this.titleBlinking = false;
        },
        
        startTypingInfoBlink : function()
        {
            if(!this.typingInfoBlinking)
            {
                this.typingInfoBlinking = true;
                this.blinkTypingInfo();
            }
        },
        
        blinkTypingInfo : function()
        {
            if(!this.typingInfoBlinking)
            {
                return;
            }
            
            var _this = this;
            
            this.$typingInfo.fadeIn('slow', function()
            {
                _this.$typingInfo.fadeOut('slow', function()
                {
                    _this.blinkTypingInfo();
                });
            });
        },
        
        stopTypingInfoBlink : function()
        {
            this.typingInfoBlinking = false;
        },
        
        showLogin : function()
        {
            this.setState('login');
            
            // Handle welcome message (only after initial login)
            
            this.model.once('login:success', this.showWelcomeMessage, this);
        },
        
        showLoginError : function()
        {
            this.showInfo(config.ui.loginError);
        },
        
        onLogout : function()
        {
            // Wait for success response
            
            this.showLoading();
        },
        
        onLogoutSuccess : function()
        {
            // Initialize the chat again
            
            this.showLogin();
            this.model.checkOperators();
        },
        
        onLogoutError : function()
        {
            // Initialize the chat again
            
            this.showLogin();
            this.model.checkOperators();
        },
        
        showWelcomeMessage : function()
        {
            // Create the message
            
            var message = new app.MessageModel({

                authorType : 'operator',
                author     : config.ui.initMessageAuthor,
                body       : config.ui.initMessageBody,
                time       : new Date()
            });
            
            // Add message to the chat box

            this.chatBox.addMessage(message);
        },
        
        showChat : function()
        {
            this.setState('chat');
            
            // For mobile devices, refresh the page
            
            if(this.manualLogin && config.mobile) window.location.reload();
        },
        
        showContact : function()
        {
            this.setState('contact');
        },
        
        showLoading : function()
        {
            this.setState('loading');
        },
        
        showInfo : function(text, title)
        {
            this.$info.html(text);
            this.$title.html(title);
            
            this.setState('info');
        },
        
        showPrevState : function()
        {
            this.setState(this.prevState);
        },
        
        storeProperties : function()
        {
            if(!this.fullscreen)
            {
                this.headerHeight = this.$header.height();
                
                var _this = this;
                
                this.postMessage('get.properties', function(data)
                {
                    var p = data.split(',');
                    
                    _this.frameWidth  = parseInt(p[0]);
                    _this.frameHeight = parseInt(p[1]);
                    _this.frameOffset = parseInt(p[2]);
                    
                });
            }
        },
        
        postMessage : function(data, callback)
        {
            window.parent.postMessage(data, '*');
            
            if(callback)
            {
                var $window = $(window);
                var id      = Math.floor(new Date().getTime() * Math.random());
                
                $window.bind('message.' + id, function(evt)
                {
                    var parts = evt.originalEvent.data.split(':');
                    
                    if(parts[0] === data) callback(parts[1]);
                    
                    $window.unbind('message.' + id);
                });
            }
        },
        
        initFramesCommunication : function()
        {
            var _this = this;
            
            this.$window.bind('message', function(evt)
            {
                if(!evt.originalEvent.data) return;
                
                var parts = evt.originalEvent.data.split(':');
                
                if     (parts[0] === 'state.mobile')  _this.$html.addClass   ('mobile-widget');
                else if(parts[0] === 'state.desktop') _this.$html.removeClass('mobile-widget');
            });
        }
    },
    {
        TYPING_STATUS_TIME : 2000,
        ANIMATION_TIME     :  400
    });

})(window.Application, jQuery, window.chatConfig);

./BlackJoker Mini Shell 1.0