define(['angular', 'lib/json-formatter'], function (angular) { var Chat = angular.module('chat', ['jsonFormatter']) Chat.controller('Chat', ['$scope', '$http', '$rootScope', '$timeout', '$interval', '$anchorScroll', function ($scope, $http, $rootScope, $timeout, $interval, $anchorScroll) { if (window._CallmeReason) { if ($scope.Callmeback) { $scope.Callmeback.Reason = _CallmeReason; } else { $scope.Callmeback = { Reason: _CallmeReason } } } $scope.showSmallChatForm = false; $scope.showSmallCallBackForm = false $scope.today = new Date(); $scope.today = new Date($scope.today.getFullYear(), $scope.today.getMonth(), $scope.today.getDate()); $scope.CallbackSchedule = false; $scope.showCallBackSideForm = function () { $scope.callback = true; $scope.chat = false; } //If the mobi callback element exits scroll to it. $scope.scrollToMobiCallBack = function (offset) { if (document.getElementById("call-me-back-mobi-top") != null) { $location.hash('call-me-back-mobi-top'); $anchorScroll.yOffset = offset; $anchorScroll(); } else { $scope.callMobiBackOverride = true; $scope.chat = false; } } $scope.callbackDate; $scope.callbackTimeslot; var _callbackMinDate = convertDatesServerToClientRecursive(callbackMinDate); var _CallbackMaxDate = convertDatesServerToClientRecursive(callbackMinDate); var _callbackPublicHolidays = convertDatesServerToClientRecursive(callbackPublicHolidays); var TodaysDate = new Date().getDateOnly(); $scope.minEffectiveDate = TodaysDate; $scope.maxEffectiveDate = TodaysDate.addDays(45); // Public holiday list $scope.publicHolidays = []; // Update scheduled datetime $scope.updateSchedule = function () { try { var now = new Date(); var selectedDate = new Date(Date.parse($scope.callbackDate)); $scope.ContactUsData.CallbackDateTime = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate(), $scope.callbackTimeslot.start); if (selectedDate.getTime() == $scope.today.getTime() && $scope.callbackTimeslot.start <= now.getHours() && $scope.callbackTimeslot.end >= now.getHours()) { $scope.ContactUsData.CallbackDateTime = now; } } catch (err) { } } // Remove past time slots if in past for today $scope.showTimeslot = function (timeslot) { var selectedDate = new Date(Date.parse($scope.callbackDate)); if (selectedDate.getTime() != $scope.today.getTime()) return true; var mustShowTimeslot = true; var hour = new Date().getHours(); if (hour >= timeslot.end) { mustShowTimeslot = false; $scope.callbackTimeslot = null; } return mustShowTimeslot; }; // Get timeslots for days.. haha "for days" :P $scope.setCallbackTimeslots = function (date) { if (!date) return; var day = date.getDay(); // Public Holiday for (var i = 0; i < $scope.publicHolidays.length; i++) { if (date.getTime() == $scope.publicHolidays[i].getTime()) { $scope.CallbackTimeSlots = $scope.callbackTimeslots.Holiday; $scope.callbackTimeslot = null; return; } } // Monday - Saturday if (day >= 0 && day < 5) $scope.CallbackTimeSlots = $scope.callbackTimeslots.MonToThu; else if (day == 5) $scope.CallbackTimeSlots = $scope.callbackTimeslots.Fri; else if (day == 6) $scope.CallbackTimeSlots = $scope.callbackTimeslots.Sat; $scope.callbackTimeslot = null; }; $scope.$watch("callbackDate", function (nv, ov) { $scope.validTime = null; if (!nv && !ov) return; nv = new Date(Date.parse(nv)); $scope.setCallbackTimeslots(nv); $scope.CurrentCallbackTimeSlots = $scope.CallbackTimeSlots.filter(function (timeslot) { return $scope.showTimeslot(timeslot); }); $scope.updateSchedule(); }); $scope.validTime = null; $scope.$watch("callbackTimeslot", function (nv, ov) { if (nv == ov) return; $scope.validTime = true; $scope.updateSchedule(); }); // Disable sundays disableCallbackSundays = function (date) { if (date.getDay() == 0) return [false, '']; return [true, '']; }; $scope.NextCallMeBack = function () { if ($scope.Callmeback && $scope.Callmeback.Reason != "ShortTerm") { $scope.SubmitCallMeBack(); } else { $scope.Submitted = true; $scope.CallbackSchedule = false; } } $scope.callbackTimeslots = { MonToThu: [{ value: 0, name: "Morning (08h00 - 12h00)", start: 8, end: 12 }, { value: 1, name: "Lunchtime (12h00 - 14h00)", start: 12, end: 14 }, { value: 2, name: "Afternoon (14h00- 17h00)", start: 14, end: 17 }, { value: 3, name: "After work (17h00 - 20h00)", start: 17, end: 20 }], Fri: [{ value: 0, name: "Morning (08h00 - 12h00)", start: 8, end: 12 }, { value: 1, name: "Lunchtime (12h00 - 14h00)", start: 12, end: 14 }, { value: 2, name: "Afternoon (14h00- 17h00)", start: 14, end: 17 }, { value: 3, name: "After work (17h00 - 18h00)", start: 17, end: 18 }], Sat: [{ value: 0, name: "Morning (08h00 - 12h00)", start: 8, end: 12 }, { value: 1, name: "Lunchtime (12h00 - 13h00)", start: 12, end: 13 }], Holiday: [{ value: 0, name: "Morning (08h00 - 12h00)", start: 8, end: 12 }, { value: 1, name: "Lunchtime (12h00 - 13h00)", start: 12, end: 13 }] }; if (_callbackPublicHolidays && _callbackPublicHolidays.length) for (var i = 0; i < _callbackPublicHolidays.length; i++) { if (typeof (_callbackPublicHolidays[i]) == "string") { var ms = parseInt(_callbackPublicHolidays[i].match(/\d+/g)[0]); _callbackPublicHolidays[i] = new Date(ms); } $scope.publicHolidays = _callbackPublicHolidays; } $scope.setCallbackTimeslots(_callbackMinDate); $scope.callbackTimeslot = null; $scope.updateSchedule(); //Update minDate if past callcenter hours on load if today if (_callbackMinDate.getTime() == $scope.today.getTime() && new Date().getHours() >= $scope.CallbackTimeSlots[$scope.CallbackTimeSlots.length - 1].end) { _callbackMinDate.setDate(_callbackMinDate.getDate() + 1); if (_callbackMinDate.getDay() == 0) _callbackMinDate.setDate(_callbackMinDate.getDate() + 1); if (angular.element(document.querySelector('#txtCallBackDate'))) $scope.minEffectiveDate = _callbackMinDate; $scope.callbackDate = _callbackMinDate; $scope.setCallbackTimeslots(_callbackMinDate); $scope.updateSchedule(); } $scope.LoadInfo = function () { var gChatTimeOutCheck; //All the chatme info $scope.chatmeControl = { events: $scope.events, unreadMessages: 0, SecondsSinceTypingStopped: 0, ChatMe: { name: $scope.name, email: $scope.email, status: true, message: "", participantID: $scope.participantId, isFriendTyping: false, userIsTyping: false, userStoppedTyping: false, userTimeOut: 180, userTimeOutWarning: 60, timeOutCheckStarted: false, timedOutWarning: false }, //Call the intil for chat Type: function () { $scope.chatmeControl.SecondsSinceTypingStopped = 0; $scope.chatmeControl.ChatMe.userIsTyping = true; $scope.chatmeControl.ChatMe.userStoppedTyping = false; $scope.chatmeControl.resetTimeouts(); }, startTimeOutCheck: function () { if ($scope.chatmeControl.ChatMe.timeOutCheckStarted == false) { $scope.chatmeControl.ChatMe.timeOutCheckStarted = true; //Implement the Timeout function. Remove it if in the event it existed if (!angular.isDefined) { $interval.cancel(gChatTimeOutCheck); gChatTimeOutCheck = undefined; } if (!angular.isDefined(gChatTimeOutCheck)) { gChatTimeOutCheck = $interval(function () { $scope.chatmeControl.ChatMe.userTimeOut -= 1; $scope.chatmeControl.ChatMe.userTimeOutWarning -= 1; if ($scope.chatmeControl.ChatMe.userTimeOutWarning <= 0) { if (!$scope.chatmeControl.ChatMe.timedOutWarning && !$scope.chat) $rootScope.toggleSmallChatForm(); $scope.chatmeControl.ChatMe.timedOutWarning = true; } else { $scope.chatmeControl.ChatMe.timedOutWarning = false; } if ($scope.chatmeControl.ChatMe.userTimeOut <= 0) { $scope.chatmeControl.timeOut(); } else { $scope.chatmeControl.ChatMe.timedOut = false; } }, 1000); $scope.$on('$destroy', function () { // Make sure that the interval is destroyed too $scope.chatmeControl.endTimeOutCheck(); }); } } }, timeOut: function () { $scope.chatmeControl.ChatMe.timedOut = true; $scope.chatmeControl.Exit(); //End the chat session $scope.notificationCounter = 0; }, endTimeOutCheck: function () { if ($scope.chatmeControl.ChatMe.timeOutCheckStarted == true) { $scope.chatmeControl.ChatMe.timeOutCheckStarted = false; //Stop counting down if (angular.isDefined(gChatTimeOutCheck)) { $interval.cancel(gChatTimeOutCheck); gChatTimeOutCheck = undefined; } } }, resetTimeouts: function () { $scope.chatmeControl.ChatMe.userTimeOut = 180; $scope.chatmeControl.ChatMe.userTimeOutWarning = 60; }, startchat: function () { $scope.loadingNext = true; if ($scope.email == null || $scope.email.length == 0) { $scope.email = $scope.chatmeControl.ChatMe.email; } // TO USE TEST DATA COMMENT OUT HERE $http({ method: 'POST', url: '/Chat/StartChat', data: { name: this.ChatMe.name, referenceNumber: $scope.referenceNumber, idNumber: $scope.idNumber, email: $scope.email, contactNumber: $scope.contactNumber } }).success(function (data) { $scope.notificationCounter = 0; $scope.onStartChat = false; $scope.onChatting = true; // TO USE TEST DATA UNCOMMENT THIS //data = { "PollWaitSuggestion": 2000, "CfgVer": 1, "ParticipantID": "48a6a93f-27a8-4626-8c2f-4b208c161a92", "DateFormat": "M/d/yyyy", "TimeFormat": "h:mm:ss tt", "ChatID": "62b45107-00c3-4863-966a-e36e8647ca5e", "Status": { "type": "success", "reason": null } }; //END TEST DATA $scope.loadingNext = false; $scope.chatmeControl.ChatMe.status = true; $scope.chatmeControl.chatstartresult = data; $scope.chatmeControl.ChatMe.participantID = $scope.chatmeControl.chatstartresult.ParticipantID; $scope.chatmeControl.runpoll(); localStorage.setItem("name", $scope.chatmeControl.ChatMe.name); localStorage.setItem("email", $scope.email); localStorage.setItem("ParticipantID", $scope.chatmeControl.chatstartresult.ParticipantID); //TO USE TEST DATA COMMENT OUT HERE }).error(function (data, status, headers, config) { $scope.loadingNext = false; }); }, //poll the CIC for events while user is still on chat runpoll: function () { if ($scope.chatmeControl.ChatMe.status) $timeout(function () { $scope.$apply(function () { if ($scope.chatmeControl.ChatMe.status) { $scope.chatmeControl.poll(); $scope.chatmeControl.SecondsSinceTypingStopped = $scope.chatmeControl.SecondsSinceTypingStopped + 2; } $scope.chatmeControl.runpoll(); }) }, 2000); }, poll: function () { //TO USE TEST DATA COMMENT OUT HERE var eventCount = this.events.length; $http({ method: 'POST', url: '/Chat/Poll', data: { participantId: $scope.chatmeControl.ChatMe.participantID, userIsTyping: $scope.chatmeControl.ChatMe.userIsTyping, userStoppedTyping: $scope.chatmeControl.ChatMe.userStoppedTyping } }).success(function (data) { $scope.chat ? $scope.notificationCounter = 0 : $scope.notificationCounter = $scope.notificationCounter; // END COMMETNING //UNCOMMENT TO DO SOME TESTING (Not Required) //if (localStorage.count) { // localStorage.count = Number(localStorage.count) + 1; //} else { // localStorage.count = 1; //} //var events = [{ "type": "participantStateChanged", "participantID": "5a9ded82-fd4a-451a-bcfe-9d4ca5cc2b12", "sequenceNumber": 0, "state": "active", "participantName": "Test", "participantType": "WebUser", "conversationSequenceNumber": 0, "value": null, "displayName": null, "contentType": null }, { "type": "text", "participantID": "00000000-0000-0000-0000-000000000000", "sequenceNumber": 1, "state": null, "participantName": null, "participantType": "System", "conversationSequenceNumber": 0, "value": "Text" + localStorage.count.toString(), "displayName": "IC" + localStorage.count.toString(), "contentType": "text/plain" }, { "type": "participantStateChanged", "participantID": "5a9ded82-fd4a-451a-bcfe-9d4ca5cc2b12", "sequenceNumber": 3, "state": "disconnected", "participantName": "Test", "participantType": "WebUser", "conversationSequenceNumber": 0, "value": null, "displayName": null, "contentType": null }]; //var data = { participantId: $scope.chatmeControl.ChatMe.participantID, userIsTyping: $scope.chatmeControl.ChatMe.userIsTyping, userStoppedTyping: $scope.chatmeControl.ChatMe.userStoppedTyping, status: true, events }; //END COMMENT $scope.chatmeControl.ChatMe.userStoppedTyping = false; if (data.status) { if (data.status.type != 'failure') { if (data.events && data.events.length > 0) { //Loop though events and see if we need to start checking for timeouts or start doing so for (var i = 0; i < data.events.length; i++) { var curEvent = data.events[i]; $scope.notificationCounter++ //CIC Angent sent a message if (curEvent.participantID != $scope.chatmeControl.ChatMe.participantID && curEvent.type == 'text' && curEvent.participantType != 'System') { $scope.chatmeControl.startTimeOutCheck(); } //User sent a messsage if (curEvent.participantID == $scope.chatmeControl.ChatMe.participantID && curEvent.type == 'text') { $scope.chatmeControl.endTimeOutCheck(); } } // get local storage var localToConcat = localStorage.getItem('ChatEventHistory'); // convert JSON string to object var localToConcatObject = JSON.parse(localToConcat); // Concat the local object if its not null var localObject = localToConcatObject != null ? localToConcatObject.concat(data.events) : $scope.chatmeControl.events.concat(data.events); // Put the object into storage localStorage.setItem('ChatEventHistory', JSON.stringify(localObject)); // Retrieve the object from storage var retrievedObject = localStorage.getItem('ChatEventHistory'); $scope.chatmeControl.events = JSON.parse(retrievedObject); if ($scope.chatMinimised) $scope.chatmeControl.unreadMessages = data.events.length; } } else { $scope.chatmeControl.ChatMe.status = false; } angular.forEach(data.events, function (item) { if (item.type == 'typingIndicator') { var isTyping = false; if (item.value.toLowerCase() == "true") isTyping = true; $scope.chatmeControl.ChatMe.isFriendTyping = isTyping; } }); } // TO USE TEST DATA COMMENT OUT HERE }).error(function (data) { }); // END COMMENTING }, //create a chat message sendMessage: function () { $scope.chatmeControl.ChatMe.userStoppedTyping = true; $scope.chatmeControl.ChatMe.userIsTyping = false; $scope.loadingNext = true; $http({ method: 'POST', url: '/Chat/SendMessage', data: this.ChatMe }).success(function (data) { $scope.chatmeControl.poll(); $scope.chatmeControl.ChatMe.message = ""; $scope.loadingNext = false; }).error(function (data) { // Not sure what to do on error $scope.loadingNext = false; }); $scope.chatmeControl.poll(); }, Exit: function () { //You are exiting chat. Stop checking for timeouts $scope.chatmeControl.endTimeOutCheck(); if ($scope.chatmeControl.ChatMe.participantID) { // build up the conversation object var messages = []; angular.forEach($scope.chatmeControl.events, function (value, key) { if (value.type && value.type == "text" || value.type == "url") { var msg = { name: value.displayName, text: value.value } messages.push(msg); } }); $http({ method: 'POST', url: '/Chat/ExitChat', data: { participantId: $scope.chatmeControl.ChatMe.participantID, conversation: messages, email: localStorage.getItem("email") == null ? $scope.chatmeControl.ChatMe.email : localStorage.getItem("email"), name: $scope.chatmeControl.ChatMe.name } }).success(function (data) { $scope.chatmeControl.clearChatData(); localStorage.clear(); $scope.notificationCounter = 0; }).error(function (data) { $scope.chatmeControl.clearChatData(); localStorage.clear(); }); } else { $scope.chatmeControl.clearChatData(); localStorage.clear(); } }, clearChatData: function () { chatstartresult = null, $scope.chatmeControl.ChatMe = { name: $scope.name, email: $scope.email, status: false, message: "", participantID: "", isFriendTyping: false, userIsTyping: false, userStoppedTyping: false, userTimeOut: 180, userTimeOutWarning: 60, timeOutCheckStarted: false, timedOutWarning: false }, $scope.chatmeControl.events = []; } } } $scope.$watch('chatmeControl.events', function () { setTimeout(function () { var objDiv = document.getElementById("scroll"); if (objDiv) objDiv.scrollTop = objDiv.scrollHeight; }, 200); }); if (typeof _ShowChat !== "undefined" && _ShowChat) // If the chat is off, there is no need to execute chat Initialize { $http({ method: 'POST', url: '/Chat/Initialize' }).success(function (data) { $scope.name = localStorage.getItem("name") == null ? data.Name || "" : localStorage.getItem("name"); $scope.email = localStorage.getItem("email") == null ? data.Email || "" : localStorage.getItem("email"); $scope.contactNumber = data.ContactNumber; $scope.referenceNumber = $scope.Quote && $scope.Quote.ReferenceNumber ? $scope.Quote.ReferenceNumber : ""; $scope.idNumber = data.IdNumber; $scope.participantId = localStorage.getItem("ParticipantID") == null ? data.ParticipantId || "" : localStorage.getItem("ParticipantID"); $scope.events = data.Events || []; $scope.IsCICOnline = data.IsCICOnline; $scope.LoadInfo(); //Open the chat if we currently have an active session going if ($scope.chatmeControl.ChatMe.participantID.length > 0) { $rootScope.toggleSmallChatForm(); $scope.chatmeControl.runpoll(); $scope.chatmeControl.startTimeOutCheck(); } }); } $scope.CloseOnlineChat = function () { localStorage.clear(); $scope.chatmeControl.Exit(); $scope.chatmeControl.ChatMe.participantID = ""; $scope.notificationCounter = 0; } $scope.toggleSmallChatForm = function () { if (!$scope.showSmallChatForm) { $scope.showSmallChatForm = true $scope.notificationCounter = 0; if ($scope.showSmallCallBackForm) $scope.showSmallCallBackForm = false; } else $scope.showSmallChatForm = false; } $scope.toggleSmallCallBackForm = function () { $scope.callback = false; $scope.chat = false; } $rootScope.setSmallCallMeBackForm = function () { $scope.chatMenu.expanded = true; $scope.chat = false; $scope.callback = true; } //Call Back $scope.Submitted = false; $scope.CallMeLoading = false; $scope.excludeSundays = function (date) { var day = date.getDay(); if (day !== 0) return day; } if (typeof _ContactNumber !== "undefined" && typeof _FullName !== "undefined") { $scope.Callmeback = { ContactNumber: _ContactNumber, Fullname: _FullName } } $scope.SubmitCallMeBack = function () { $scope.CallMeLoading = true; $http({ method: 'POST', url: '/CallMeBack/CallMeBack', data: { Name: $scope.Callmeback.Fullname, ContactNumber: $scope.Callmeback.ContactNumber, Reason: $scope.Callmeback.Reason, Date: $scope.callbackDate ? $scope.callbackDate.toString() : $scope.today.toString(), Time: $scope.callbackTimeslot } }).success(function (data) { $scope.Submitted = true; $scope.CallbackSchedule = true; $scope.CallMeLoading = false; }); } $scope.ThankYou = function () { $scope.Submitted = false; $scope.CallbackSchedule = false; $scope.toggleSmallCallBackForm(); } $rootScope.toggleSmallChatForm = function () { $scope.chat = !$scope.chat; $scope.callback = false; $scope.notificationCounter = 0; } //ie var ie10Styles = [ 'msTouchAction', 'msWrapFlow', 'msWrapMargin', 'msWrapThrough', 'msOverflowStyle', 'msScrollChaining', 'msScrollLimit', 'msScrollLimitXMin', 'msScrollLimitYMin', 'msScrollLimitXMax', 'msScrollLimitYMax', 'msScrollRails', 'msScrollSnapPointsX', 'msScrollSnapPointsY', 'msScrollSnapType', 'msScrollSnapX', 'msScrollSnapY', 'msScrollTranslation', 'msFlexbox', 'msFlex', 'msFlexOrder']; var ie11Styles = [ 'msTextCombineHorizontal']; /* * Test all IE only CSS properties */ var d = document; var b = d.body; var s = b.style; var ieVersion = null; var property; $scope.isIE = false; // Test IE10 properties for (var i = 0; i < ie10Styles.length; i++) { property = ie10Styles[i]; if (s[property] != undefined) { $scope.isIE = true; } } // Test IE11 properties for (var i = 0; i < ie11Styles.length; i++) { property = ie11Styles[i]; if (s[property] != undefined) { $scope.isIE = true; } } }]); return Chat; });