GIF89a;
Direktori : /home/serb/www/livechat/js/app/view/ |
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);