Built motion from commit eeb7beacd.|1.0.21
[motion.git] / server / components / xchatty / xchatty.js
1 /**
2  *
3  * xChatty: xCally Shuttle WebChat Client
4  * Powered by Xenialab
5  *
6  * @author          Xenialab
7  * @link            http://www.xcally.com
8  * @since           xChatty v 2.0
9  *
10  */
11 var xChatty = {
12     config: {
13         websiteId: {{websiteId}},
14         signedUp: {{signedUp}},
15         windowFocused: {{windowFocused}},
16         isNewPage: {{isNewPage}},
17         processingSignUp: {{processingSignUp}},
18         processingEnquiry: {{processingEnquiry}},
19         processingSend: {{processingSend}},
20         processingRating: {{processingRating}},
21         visitor: {
22             fullname: '',
23             avatar: ''
24         },
25         timerReadMessages: {{timerReadMessages}},
26         timerCheckStatus: {{timerCheckStatus}},
27         timerSendMessages: '',
28         timerSignupResponse: '',
29         isOnline: {{isOnline}},
30         decayHistory: {{decayHistory}},
31         defaultTimeout: {{defaultTimeout}},
32         isInitialStatusCheck: {{isInitialStatusCheck}},
33         muteNotificationSoundOnce: {{muteNotificationSoundOnce}},
34         assetBase: '{{& assetBase}}',
35         rootPath: '{{& rootPath}}',
36         hasSessionSaf: {{hasSessionSaf}},
37         restoreOpenState: {{restoreOpenState}},
38         animateHover: {{animateHover}},
39         hideEmail: {{hideEmail}},
40         hideOffline: {{hideOffline}},
41         headerShape: '{{headerShape}}',
42         downloadTranscript: {{downloadTranscript}},
43         roomId: 0
44     },
45     Lang: {
46         "HeaderCurrentlyChatting": "Live Chat",
47         "HeaderOnline": '{{HeaderOnline}}',
48         "HeaderOffline": "{{HeaderOffline}}",
49         "OperatorOfflineMessage": "It appears as if all operators are currently offline.",
50         "OfflineMessage": "{{& OfflineMessage}}",
51         "OnlineMessage": '{{& OnlineMessage}}',
52         "UsernamePlaceholder": '{{UsernamePlaceholder}}',
53         "EmailPlaceholder": '{{EmailPlaceholder}}',
54         "EnquiryMessagePlaceholder": "{{EnquiryMessagePlaceholder}}",
55         "EnquiryButtonText": "{{EnquiryButtonText}}",
56         "EnquirySubmitSuccess": "Your message was sucessfully submitted - we will contact you as soon as possible.",
57         "StartChatButtonText": '{{StartChatButtonText}}',
58         "OperatorComposing": "{fullname} is typing...",
59         "FirstMessageText": "",
60         "ExitChatButtonText": "Exit Chat",
61         "ExitChatQuestionText": "Are you sure?",
62         "ExitChatButtonConfirmText": "Yes",
63         "ExitChatButtonCancelText": "No",
64         "MessagePlaceholderText": "Your message...",
65         "MessageSendButtonText": "Send",
66         "ValidationEmailRequired": "Please enter your email address",
67         "ValidationEmailInvalid": "Please enter a valid email address",
68         "ValidationEmailMaxLength": "The email address may not exceed 85 characters",
69         "ValidationUsernameRequired": "Please enter your name",
70         "ValidationUsernameMaxLength": "The name may not exceed 45 characters",
71         "ValidationEnquiryRequired": "Please enter your enquiry",
72         "ValidationEnquiryMaxLength": "The enquiry may not exceed 1500 characters",
73         "ValidationMessageRequired": "Please enter your message",
74         "ValidationMessageMaxLength": "The message may not exceed 750 characters",
75         "DownloadTranscript": "Download Transcript",
76         "RatingMessage": "{{& RatingMessage}}",
77         "RatingSendText": "{{RatingSend}}",
78         "RatingSkipText": "{{RatingSkip}}",
79         "MessageAgentsBusy": "{{& MessageAgentsBusy}}",
80         "EmailTitle": "{{EmailTitle}}",
81         "NameTitle": "{{NameTitle}}",
82         "MessageTitle": "{{MessageTitle}}"
83     },
84     init: function() {
85         jQuery(".xc_chat_container").css('margin-bottom', '-50px');
86         if (!xChatty.config.hideOffline)
87             jQuery(".xc_chat_container").show();
88         jQuery(".xc_chat_container").animate({
89             marginBottom: 0
90         }, {
91             duration: 500,
92             queue: true,
93             complete: function() {
94                 if (xChatty.config.restoreOpenState) {
95                     xChatty.config.isNewPage = true;
96                     jQuery(".xc_chat_head").trigger("click");
97                 }
98             }
99         });
100         xChatty.initAnimateHover();
101         jQuery(window).focus(function() {
102             xChatty.config.windowFocused = true;
103         });
104         jQuery(window).blur(function() {
105             xChatty.config.windowFocused = false;
106         });
107         jQuery(document).on("click", ".xc_chat_head", xChatty.headerClick);
108         // jQuery(document).on("click", ".xc_btn_enquiry", xChatty.enquiryClick);
109         jQuery(document).on("submit", ".xc_form_enquiry", xChatty.enquirySubmit);
110         // jQuery(document).on("click", ".xc_btn_signup", xChatty.signUpClick);
111         jQuery(document).on("submit", ".xc_form_signup", xChatty.signUpSubmit);
112         jQuery(document).on("click", ".xc_btn_send", xChatty.sendClick);
113         jQuery(document).on("submit", ".xc_form_reply", xChatty.onSendSubmit);
114         jQuery(document).on("click", ".xc_btn_exit_chat", xChatty.btnExitChatClick);
115         jQuery(document).on("click", ".xc_btn_exit_chat_confirm", xChatty.btnExitChatConfirmClick);
116         jQuery(document).on("click", ".xc_btn_exit_chat_cancel", xChatty.btnExitChatCancelClick);
117         jQuery(document).on("click", ".xc_btn_notifications_close", xChatty.btnNotificationsCloseClick);
118         jQuery(document).on("keyup", ".xc_chat_container textarea, .xc_chat_container input", xChatty.messageKeyUp);
119         jQuery(document).on("keydown", ".xc_input_message", xChatty.messageKeyDown);
120         jQuery(document).on("submit", ".xc_form_rating", xChatty.ratingSubmit);
121         jQuery(document).on("click", ".xc_button_skip_rating", xChatty.skipRatingSubmit);
122         jQuery('[placeholder]').each(function() {
123             jQuery(this).css('color', '#ccc').val(jQuery(this).attr('placeholder'));
124         }).bind('focus', function() {
125             jQuery(this).css('color', 'inherit');
126             if (jQuery(this).val() === jQuery(this).attr('placeholder')) {
127                 jQuery(this).val('');
128             }
129         }).bind('blur', function() {
130             if (jQuery(this).val() === '') {
131                 jQuery(this).val(jQuery(this).attr('placeholder')).css('color', '#ccc');
132             }
133         });
134         window.onbeforeunload = xChatty.handleDocumentUnload;
135         xChatty.readMessages();
136     },
137     handleDocumentUnload: function() {
138       if (!xChatty.processingSignUp) {
139         jQuery.ajax({
140           url: xChatty.config.rootPath + xChatty.config.websiteId + "/abandon",
141           data: [],
142           dataType: "jsonp",
143           complete: function() {
144             return null;
145           }
146         });
147       }
148       return null;
149     },
150     initAnimateHover: function() {
151         if (xChatty.config.animateHover !== true)
152             return;
153         jQuery(".xc_chat_container").animate({
154             opacity: 0.7
155         }, {
156             duration: 0,
157             queue: false
158         });
159         jQuery(".xc_chat_container").hover(function() {
160             jQuery(this).animate({
161                 opacity: 1
162             }, {
163                 duration: 200,
164                 queue: false
165             });
166         }, function() {
167             if (!jQuery(this).hasClass("xc_box_open"))
168                 jQuery(this).animate({
169                     opacity: 0.7
170                 }, {
171                     duration: 200,
172                     queue: false
173                 });
174         });
175         jQuery(".xc_chat_container").bind("chatOpen", function(e, isOpen) {
176             if (isOpen) {
177                 jQuery(this).animate({
178                     opacity: 1
179                 }, {
180                     duration: 200,
181                     queue: false
182                 });
183             } else {
184                 jQuery(this).animate({
185                     opacity: 0.7
186                 }, {
187                     duration: 200,
188                     queue: false
189                 });
190             }
191         });
192     },
193     // enquiryClick: function(e) {
194     //     e.preventDefault();
195     //     jQuery(".xc_form_enquiry").submit();
196     // },
197     btnExitChatClick: function(e) {
198         e.preventDefault();
199         jQuery(".xc_exit_chat_confirmation_wrapper").show();
200         jQuery(this).hide();
201     },
202     btnExitChatConfirmClick: function(e) {
203         e.preventDefault();
204         clearTimeout(xChatty.config.timerReadMessages);
205         clearTimeout(xChatty.config.timerCheckStatus);
206         var formData = jQuery(this).serializeArray();
207         formData.push({
208             name: 'data[sign_out]',
209             value: true
210         });
211         jQuery.ajax({
212             url: xChatty.config.rootPath + xChatty.config.websiteId + "/signout",
213             data: formData,
214             dataType: "jsonp",
215             jsonpCallback: xChatty.getJsonpCallbackName(),
216             success: function(result) {
217                 if (result.success === true) {
218                     // xChatty.resetDefaultState();
219                     xChatty.config.signedUp = false;
220                     xChatty.config.visitor = {
221                         fullname: "",
222                         avatar: ""
223                     };
224                     jQuery(".xc_conversation_container").empty();
225                     jQuery(".xc_conversation_container").html('<p class="xc_message_intro" data-id="-10">' + xChatty.Lang.FirstMessageText + '</p>');
226                     jQuery(".xc_exit_chat_confirmation_wrapper").hide();
227                     jQuery(".xc_btn_exit_chat").show();
228                     jQuery(".xc_conversation").hide();
229                     jQuery('.xc_rating_wrapper').show();
230                 } else {}
231             },
232             complete: function() {
233                 // xChatty.checkStatus(true);
234             }
235         });
236     },
237     btnExitChatCancelClick: function(e) {
238         e.preventDefault();
239         jQuery(".xc_exit_chat_confirmation_wrapper").hide();
240         jQuery(".xc_btn_exit_chat").show();
241     },
242     removeOldMessages: function () {
243       jQuery(".xc_conversation_container").empty();
244       jQuery(".xc_conversation_container").html('<p class="xc_message_intro" data-id="-10">' + xChatty.Lang.FirstMessageText + '</p>');
245     },
246     resetDefaultState: function() {
247         xChatty.config.signedUp = false;
248         xChatty.config.visitor = {
249             fullname: "",
250             avatar: ""
251         };
252         jQuery(".xc_conversation_container").empty();
253         jQuery(".xc_conversation_container").html('<p class="xc_message_intro" data-id="-10">' + xChatty.Lang.FirstMessageText + '</p>');
254         jQuery(".xc_exit_chat_confirmation_wrapper").hide();
255         jQuery(".xc_btn_exit_chat").show();
256         jQuery('.xc_rating_wrapper').hide();
257         jQuery('.xc_form_rating')[0].reset();
258         jQuery(".xc_chat_head").trigger("click");
259     },
260     skipRatingSubmit: function (e) {
261       e.preventDefault();
262       if (xChatty.config.processingRating)
263         return false;
264       xChatty.config.processingRating = true;
265       var formData = [];
266       formData.push({
267           name: 'data[Rating][room_id]',
268           value: xChatty.config.roomId
269       });
270       jQuery.ajax({
271           url: xChatty.config.rootPath + "rating",
272           data: formData,
273           dataType: "jsonp",
274           success: function(result) {
275               xChatty.config.processingRating = false;
276               xChatty.resetDefaultState();
277           },
278           error: function(err) {
279             var error = {
280               'message': 'Service temporarily unavailable. We back as soon as possible!'
281             };
282             xChatty.renderErrors(error, true);
283             // xChatty.config.timerSendMessages = setTimeout(function() {
284             //   xChatty.handleAjaxSubmitCall(formData, enquiryForm);
285             // }, 5000);
286           }
287       });
288     },
289     ratingSubmit: function (e) {
290       e.preventDefault();
291       if (xChatty.config.processingRating)
292         return false;
293       xChatty.config.processingRating = true;
294       var formData = jQuery(this).serializeArray();
295       formData.push({
296           name: 'data[Rating][room_id]',
297           value: xChatty.config.roomId
298       });
299       jQuery.ajax({
300           url: xChatty.config.rootPath + "rating",
301           data: formData,
302           dataType: "jsonp",
303           success: function(result) {
304               xChatty.config.processingRating = false;
305               xChatty.resetDefaultState();
306           },
307           error: function(err) {
308             var error = {
309               'message': 'Service temporarily unavailable. We back as soon as possible!'
310             };
311             xChatty.renderErrors(error, true);
312             // xChatty.config.timerSendMessages = setTimeout(function() {
313             //   xChatty.handleAjaxSubmitCall(formData, enquiryForm);
314             // }, 5000);
315           }
316       });
317     },
318     enquirySubmit: function(e) {
319         e.preventDefault();
320         if (xChatty.config.processingEnquiry)
321             return false;
322         var validationErrors = {};
323         var signupForm = jQuery(".xc_form_enquiry");
324         jQuery('.xc_form_enquiry :input').each(function () {
325           var el = jQuery(this);
326           if (el.val() === el.attr('placeholder')) {
327             el.val('');
328           }
329           if ((jQuery.trim(el.val()) === '' || el.val() === el.attr('placeholder')) && el.attr('required') === 'required' ) {
330             validationErrors[el.attr('id')] = ['Please enter the field ' + el.attr('data-label')];
331           }
332         });
333         // if (jQuery.trim(jQuery(".xc_input_enquiry_fullname").val()) === '' || jQuery(".xc_input_enquiry_fullname").val() === jQuery(".xc_input_enquiry_fullname").attr("placeholder")) {
334         //     validationErrors["fullname"] = [xChatty.Lang.ValidationUsernameRequired];
335         // }
336         // if (jQuery.trim(jQuery(".xc_input_enquiry_email").val()) === '' || jQuery(".xc_input_enquiry_email").val() === jQuery(".xc_input_enquiry_email").attr("placeholder")) {
337         //     validationErrors["email"] = [xChatty.Lang.ValidationEmailRequired];
338         // }
339         // if (jQuery.trim(jQuery(".xc_input_enquiry_message").val()) === '' || jQuery(".xc_input_enquiry_message").val() === jQuery(".xc_input_enquiry_message").attr("placeholder")) {
340         //     validationErrors["message"] = [xChatty.Lang.ValidationEnquiryRequired];
341         // }
342         // if (validationErrors.hasOwnProperty("fullname") || validationErrors.hasOwnProperty("email") || validationErrors.hasOwnProperty("message")) {
343         //     xChatty.renderNotifications(validationErrors, true);
344         //     return;
345         // }
346         if (Object.keys(validationErrors).length > 0) {
347           xChatty.renderNotifications(validationErrors,true);
348           return;
349         }
350         xChatty.config.processingEnquiry = true;
351         var enquiryForm = jQuery(this);
352         enquiryForm.addClass("xc_enquiry_sending");
353         var formData = jQuery(this).serializeArray();
354         formData.push({
355             name: 'data[Enquiry][websiteId]',
356             value: xChatty.config.websiteId
357         });
358         formData.push({
359             name: 'data[Enquiry][current_page]',
360             value: encodeURIComponent(encodeURIComponent(document.URL))
361         });
362         xChatty.handleAjaxSubmitCall(formData, enquiryForm);
363         return false;
364     },
365     handleAjaxSubmitCall: function(formData, enquiryForm) {
366       jQuery.ajax({
367           url: xChatty.config.rootPath + "submit",
368           data: formData,
369           dataType: "jsonp",
370           jsonpCallback: xChatty.getJsonpCallbackName(),
371           success: function(result) {
372               if (result.success === true) {
373                   jQuery(".xc_notifications_wrapper").slideUp();
374                   xChatty.clearNotifications();
375                   jQuery(".xc_form_enquiry")[0].reset();
376                   var notifications = {
377                       success: [xChatty.Lang.EnquirySubmitSuccess]
378                   };
379                   xChatty.renderNotifications(notifications, false);
380               } else {
381                   xChatty.renderNotifications(result.errors, true);
382               }
383               xChatty.config.processingEnquiry = false;
384               enquiryForm.removeClass("xc_enquiry_sending");
385               jQuery(".xc_chat_container input, .xc_chat_container textarea").trigger("blur");
386           },
387           error: function(err) {
388             var error = {
389               'message': 'Service temporarily unavailable. We back as soon as possible!'
390             };
391             xChatty.renderErrors(error, true);
392             xChatty.config.timerSendMessages = setTimeout(function() {
393               xChatty.handleAjaxSubmitCall(formData, enquiryForm);
394             }, 5000);
395           }
396       });
397     },
398     onSendSubmit: function() {
399         var message = jQuery.trim(jQuery(".xc_input_message").val());
400         message = jQuery('<p>' + message + '</p>').text();
401         jQuery(".xc_input_message").val(message);
402         if (message === "" || jQuery(".xc_input_message").val() === jQuery(".xc_input_message").attr("placeholder"))
403             return false;
404         if (xChatty.config.processingSend)
405             return false;
406         var messageForm = jQuery(this);
407         messageForm.addClass("xc_message_sending");
408         xChatty.config.processingSend = true;
409         var formData = jQuery(".xc_form_reply").serializeArray();
410         formData.push({
411             name: 'data[Message][current_page]',
412             value: encodeURIComponent(encodeURIComponent(document.URL))
413         });
414         formData.push({
415             name: 'data[last_id]',
416             value: xChatty.getMaxId()
417         });
418         formData.push({
419             name: 'data[is_new_page]',
420             value: xChatty.config.isNewPage
421         });
422         xChatty.config.isNewPage = false;
423         jQuery(".xc_input_message").val("");
424
425         var tmpMessage = {};
426         tmpMessage.id = xChatty.getMaxId() + 999;
427         tmpMessage.fullname = xChatty.config.visitor.fullname;
428         tmpMessage.body = message;
429         tmpMessage.createdAt = new Date();
430         xChatty.addMessageToChat(tmpMessage, {
431             confirmed: false
432         });
433         xChatty.scrollBottom(false);
434         xChatty.handleAjaxSendCall(formData, tmpMessage, messageForm);
435         return false;
436     },
437     handleAjaxSendCall: function(formData, tmpMessage, messageForm) {
438       jQuery.ajax({
439           url: xChatty.config.rootPath + xChatty.config.websiteId + "/send",
440           data: formData,
441           dataType: "jsonp",
442           jsonpCallback: xChatty.getJsonpCallbackName(),
443           success: function(result) {
444               if (result.success === true) {
445                   jQuery(".xc_notifications_wrapper").slideUp();
446                   jQuery("[data-id=" + tmpMessage.id + "]").remove();
447                   // xChatty.addMessageToChat(result.data);
448                   xChatty.addMessageToChat(result.messages[0]);
449                   for (var k = 0; k < result.messages.length; k++) {
450                       xChatty.addMessageToChat(result.messages[k]);
451                   }
452                   if (result.messages.length > 0)
453                       xChatty.scrollBottom(true);
454                   xChatty.config.processingSend = false;
455                   messageForm.removeClass("xc_message_sending");
456               } else {
457                   jQuery("[data-id=" + tmpMessage.id + "]").css('border', '1px dashed #f00');
458               }
459           },
460           error: function(err) {
461             var error = {
462               'message': 'Service temporarily unavailable. We back as soon as possible!'
463             };
464             xChatty.renderErrors(error, true);
465             xChatty.config.timerSendMessages = setTimeout(function() {
466               xChatty.handleAjaxSendCall(formData, tmpMessage, messageForm);
467             }, 5000);
468           }
469       });
470     },
471     headerClick: function(e) {
472         e.preventDefault();
473         // if (!xChatty.config.signedUp && (e.originalEvent !== undefined) && !jQuery(".xc_chat_toggle_container").is(":visible") && xChatty.config.hasSession !== true) {
474         //     jQuery('<form method="post" action="' + xChatty.config.rootPath + 'discussions/session_redir"><input type="hidden" name="data[referer]" value="' + window.location + '" /></form>').submit();
475         // }
476         jQuery(".xc_notification_badge_number").fadeOut();
477         jQuery(".xc_notification_badge_number").html('');
478         jQuery(".xc_chat_container").removeClass('xc_has_unread_messages');
479         if (!xChatty.config.signedUp) {
480             if (xChatty.config.isOnline) {
481                 jQuery(".xc_signup_wrapper").show();
482                 jQuery(".xc_conversation").hide();
483                 jQuery(".xc_enquiry_wrapper").hide();
484             } else {
485                 jQuery(".xc_enquiry_wrapper").show();
486                 jQuery(".xc_signup_wrapper").hide();
487                 jQuery(".xc_conversation").hide();
488             }
489         } else {
490             jQuery(".xc_enquiry_wrapper").hide();
491             jQuery(".xc_signup_wrapper").hide();
492             jQuery(".xc_conversation").show();
493         }
494         var wasClosed = jQuery(".xc_chat_toggle_container").is(":visible");
495         jQuery(".xc_chat_toggle_container").slideToggle("fast", function() {
496             xChatty.scrollBottom(true);
497             if (!wasClosed) {
498                 jQuery(".xc_chat_container").addClass("xc_box_open");
499                 jQuery(".xc_chat_container").trigger("chatOpen", true);
500             }
501         });
502         if (wasClosed) {
503             jQuery(".xc_chat_container").addClass("xc_chat_closing");
504             jQuery(".xc_chat_container").animate({
505                 marginBottom: -50
506             }, {
507                 duration: 200,
508                 queue: true,
509                 complete: function() {
510                     jQuery(".xc_chat_container").animate({
511                         marginBottom: 0
512                     }, {
513                         duration: 500,
514                         queue: true,
515                         complete: function() {}
516                     });
517                     jQuery(".xc_chat_container").removeClass("xc_box_open");
518                     jQuery(".xc_chat_container").removeClass("xc_chat_closing");
519                     jQuery(".xc_chat_container").trigger("chatOpen", false);
520                 }
521             });
522         } else {
523             jQuery(".xc_input_message").focus();
524         }
525         if (e.originalEvent !== undefined) {
526             xChatty.readMessages();
527         }
528         xChatty.checkStatus(true);
529     },
530     // signUpClick: function(e) {
531     //     e.preventDefault();
532     //     jQuery(".xc_form_signup").submit();
533     // },
534     signUpSubmit: function(e) {
535         e.preventDefault();
536         if (xChatty.config.processingSignUp)
537             return false;
538         xChatty.config.processingSignUp = true;
539         var validationErrors = {};
540         var signupForm = jQuery(".xc_form_signup");
541         jQuery('.xc_form_signup :input').each(function () {
542           var el = jQuery(this);
543           if (el.val() === el.attr('placeholder')) {
544             el.val('');
545           }
546           if ((jQuery.trim(el.val()) === '' || el.val() === el.attr('placeholder')) && el.attr('required') === 'required' ) {
547             validationErrors[el.attr('id')] = ['Please enter the field ' + el.attr('data-label')];
548           }
549         });
550         // if (jQuery.trim(jQuery(".xc_input_fullname").val()) === '' || jQuery(".xc_input_fullname").val() === jQuery(".xc_input_fullname").attr("placeholder")) {
551         //     validationErrors["fullname"] = [xChatty.Lang.ValidationUsernameRequired];
552         // }
553         // if (!xChatty.config.hideEmail && (jQuery.trim(jQuery(".xc_input_email").val()) === '' || jQuery(".xc_input_email").val() === jQuery(".xc_input_email").attr("placeholder"))) {
554         //     validationErrors["email"] = [xChatty.Lang.ValidationEmailRequired];
555         // }
556         // if (validationErrors.hasOwnProperty("fullname") || validationErrors.hasOwnProperty("email")) {
557         //     xChatty.renderNotifications(validationErrors, true);
558         //     return;
559         // }
560         if (Object.keys(validationErrors).length > 0) {
561           xChatty.renderNotifications(validationErrors,true);
562           xChatty.config.processingSignUp = false;
563           return;
564         }
565         var now = new Date();
566         var dateStr = now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
567         jQuery(".xc_input_visitor_time").val(dateStr);
568         var formData = jQuery(".xc_form_signup").serializeArray();
569         formData.push({
570           name: 'chatWebsiteId' ,
571           value: xChatty.config.websiteId
572         });
573         if (xChatty.config.hideEmail) {
574             formData.push({
575                 name: 'data[Discussion][email]',
576                 value: 'not.provided@example.com'
577             });
578         }
579         jQuery.ajax({
580             url: xChatty.config.rootPath + xChatty.config.websiteId + "/signup",
581             data: formData,
582             dataType: "jsonp",
583             jsonpCallback: xChatty.getJsonpCallbackName(),
584             success: function(result) {
585                 if (result.success === true) {
586                     jQuery(".xc_notifications_wrapper").slideUp();
587                     xChatty.config.processingSignUp = true;
588                     xChatty.config.visitor.fullname = jQuery(".xc_input_fullname").val();
589                     xChatty.config.visitor.avatar = CryptoJS.MD5(jQuery.trim(jQuery(".xc_input_email").val()).toLowerCase());
590                     xChatty.clearNotifications();
591                     // xChatty.config.signedUp = true;
592                     xChatty.setHeaderText();
593                     xChatty.disableSignUpForm('xc_form_signup',true);
594                     xChatty.removeOldMessages();
595                     xChatty.checkStatus();
596
597                     // xChatty.handleNoAgentResponse();
598
599                     // xChatty.readMessages();
600                     // jQuery(".xc_signup_wrapper").hide();
601                     // jQuery(".xc_conversation").show();
602                     // xChatty.scrollBottom(false);
603                 } else {
604                     xChatty.renderNotifications(result.errors, true);
605                 }
606             },
607             error: function(err) {
608               xChatty.config.processingSignUp = false;
609               var error = {
610                 'message': 'Service temporarily unavailable. We back as soon as possible!'
611               };
612               xChatty.renderErrors(error, true);
613             },
614             complete: function() {
615                 // xChatty.config.processingSignUp = false;
616             }
617         });
618     },
619     setHeaderText: function() {
620         if (xChatty.config.signedUp === true)
621             jQuery(".xc_chat_head-title").html(xChatty.Lang.HeaderCurrentlyChatting);
622         else if (xChatty.config.signedUp === false && xChatty.config.processingSignUp === true)
623             jQuery(".xc_chat_head-title").html('Waiting for connection...');
624         else if (xChatty.config.isOnline === true)
625             jQuery(".xc_chat_head-title").html(xChatty.Lang.HeaderOnline);
626         else
627             jQuery(".xc_chat_head-title").html(xChatty.Lang.HeaderOffline);
628     },
629     handleSnippetOpen: function () {
630       if (!jQuery(".xc_chat_toggle_container").is(":visible")) {
631         jQuery(".xc_chat_head").trigger("click");
632       }
633     },
634     getProactiveActions: function () {
635       jQuery.ajax({
636           url: xChatty.config.rootPath + xChatty.config.websiteId + '/proactive',
637           dataType: 'jsonp',
638           crossDomain: true,
639           success: function (data) {
640             if (data.length > 0) {
641               for (var i in data) {
642                 if (data.hasOwnProperty(i)) {
643                   var proAction = data[i];
644                   switch (proAction.type) {
645                     case 'mouseOver':
646                       if (proAction.hasOwnProperty('selector') && proAction.selector) {
647                         jQuery(document).on("mouseover", proAction.selector, xChatty.handleSnippetOpen);
648                       }
649                       break;
650                     case 'timeout':
651                       if (proAction.hasOwnProperty('timeout') && proAction.timeout > 0) {
652                         setTimeout(function () {
653                           xChatty.handleSnippetOpen();
654                         }, proAction.timeout * 1000);
655                       }
656                       break;
657                     default:
658                       console.log('Event type not supported');
659                   }
660                 }
661               }
662             }
663           }
664         });
665     },
666     getHTMLTemplate: function() {
667       jQuery.ajax({
668           url: xChatty.config.rootPath + xChatty.config.websiteId + '/html',
669           dataType: 'jsonp',
670           crossDomain: true,
671           success: function (data) {
672             if (jQuery(".xc_chat_container").length === 0) {
673               for (var i in xChatty.Lang) {
674                 data = data.replace(new RegExp("{" + i + "}", "gm"), xChatty.Lang[i]);
675               }
676               jQuery('body').append(data);
677             }
678             if (jQuery("#xc_stylesheet").length === 0) {
679                 var xcCss = document.createElement('link');
680                 xcCss.setAttribute('rel', 'stylesheet');
681                 xcCss.type = 'text/css';
682                 xcCss.id = 'xc_stylesheet';
683                 xcCss.href = xChatty.config.rootPath + xChatty.config.websiteId + "/styles";
684                 document.body.appendChild(xcCss);
685             }
686             if(xChatty.config.downloadTranscript) {
687               jQuery(".xc_download_transcript_container").show();
688             } else {
689               jQuery(".xc_download_transcript_container").hide();
690             }
691             xChatty.getProactiveActions();
692             xChatty.checkStatus();
693           }
694         });
695     },
696     checkStatus: function(async) {
697         clearTimeout(xChatty.config.timerCheckStatus);
698         var formData = [];
699         if (xChatty.config.isInitialStatusCheck)
700             formData.push({
701                 name: 'data[referer]',
702                 value: encodeURIComponent(encodeURIComponent(document.referrer))
703             });
704         else
705             formData.push({
706                 name: 'data[open_state]',
707                 value: (jQuery(".xc_chat_toggle_container").is(":visible") && !jQuery(".xc_chat_container").hasClass("xc_chat_closing"))
708             });
709         jQuery.ajax({
710             url: xChatty.config.rootPath + xChatty.config.websiteId + "/status",
711             dataType: "jsonp",
712             data: formData,
713             async: async,
714             success: function(result) {
715                 jQuery(".xc_notifications_wrapper").slideUp();
716                 var wasSignedUp = xChatty.config.signedUp;
717                 if (wasSignedUp && result.signed_up === false) {
718                   clearTimeout(xChatty.config.timerReadMessages);
719                   clearTimeout(xChatty.config.timerCheckStatus);
720                   jQuery(".xc_conversation_container").empty();
721                   jQuery(".xc_conversation_container").html('<p class="xc_message_intro" data-id="-10">' + xChatty.Lang.FirstMessageText + '</p>');
722                   jQuery(".xc_exit_chat_confirmation_wrapper").hide();
723                   jQuery(".xc_btn_exit_chat").show();
724                   jQuery(".xc_conversation").hide();
725                   jQuery('.xc_rating_wrapper').show();
726                   return;
727                 }
728                 if (result.success) {
729                     xChatty.config.visitor.fullname = result.fullname;
730                     xChatty.config.visitor.avatar = result.avatar;
731                     xChatty.config.signedUp = result.signed_up;
732                     xChatty.config.isOnline = result.online;
733                     xChatty.config.hasSessionSaf = result.has_session_saf;
734                     xChatty.config.roomId = result.room_id;
735                 }
736                 if (result.success && result.signed_up === false && xChatty.config.signedUp) {
737                     xChatty.resetDefaultState();
738                 }
739                 if (xChatty.config.isOnline) {
740                     jQuery(".xc_chat_container").addClass("xc_state_online").removeClass("xc_state_offline").fadeIn();
741                 } else {
742                     jQuery(".xc_chat_container").removeClass("xc_state_online").addClass("xc_state_offline");
743                 }
744                 if (!xChatty.config.signedUp) {
745                     if (xChatty.config.isOnline) {
746                         jQuery(".xc_signup_wrapper").show();
747                         jQuery(".xc_conversation").hide();
748                         jQuery(".xc_enquiry_wrapper").hide();
749                     } else {
750                         jQuery(".xc_enquiry_wrapper").show();
751                         jQuery(".xc_signup_wrapper").hide();
752                         jQuery(".xc_conversation").hide();
753                     }
754                 } else {
755                     if (xChatty.config.isOnline) {
756                         xChatty.clearNotifications();
757                     } else {
758                         var notifications = {
759                             offline: [xChatty.Lang.OperatorOfflineMessage]
760                         };
761                         xChatty.renderNotifications(notifications, true);
762                     }
763                 }
764                 var wasInitialStatusCheck = xChatty.config.isInitialStatusCheck;
765                 if (xChatty.config.isInitialStatusCheck === true) {
766                     xChatty.config.isInitialStatusCheck = false;
767                     xChatty.config.muteNotificationSoundOnce = true;
768                     xChatty.setHeaderText();
769                     xChatty.init();
770                     if (result.open_state === true) {
771                         xChatty.config.restoreOpenState = true;
772                     }
773                 }
774                 if (result.success && result.signed_up === true && wasSignedUp === false && wasInitialStatusCheck === false) {
775                     jQuery(".xc_enquiry_wrapper").hide();
776                     jQuery(".xc_signup_wrapper").hide();
777                     jQuery(".xc_conversation").show();
778                     xChatty.readMessages();
779                 }
780
781                 if(!wasSignedUp && result.signed_up === true && xChatty.config.processingSignUp) {
782                   xChatty.config.processingSignUp = false;
783                   xChatty.disableSignUpForm('xc_form_signup',false);
784                   xChatty.setHeaderText();
785                 }
786
787                 if (!wasSignedUp && xChatty.config.processingSignUp && result.is_unserved) {
788                   xChatty.config.processingSignUp = false;
789                   var error = {
790                     'message': xChatty.Lang.MessageAgentsBusy
791                   };
792                   xChatty.renderErrors(error, true);
793                   xChatty.setHeaderText();
794                   xChatty.disableSignUpForm('xc_form_signup',false);
795                 }
796
797                 jQuery('.xc_rating_wrapper').hide();
798                 jQuery('.xc_form_rating')[0].reset();
799
800                 // if(wasSignedUp && result.signed_up === true) {
801                 //   xChatty.readMessages(false);
802                 //   // var duration = xChatty.calculateTimeOutDuration();
803                 //   // xChatty.config.timerReadMessages = setTimeout(function() {
804                 //   //   xChatty.readMessages(false);
805                 //   // }, duration);
806                 // }
807
808             },
809             error: function(err) {
810               var error = {
811                 'message': 'Service temporarily unavailable. We back as soon as possible!'
812               };
813               xChatty.renderErrors(error, true);
814             },
815             complete: function() {
816                 xChatty.setHeaderText();
817                 var duration = xChatty.calculateStatusTimeOutDuration();
818                 xChatty.config.timerCheckStatus = setTimeout(function() {
819                     xChatty.checkStatus(true);
820                 }, duration);
821             }
822         });
823     },
824     getJsonpCallbackName: function() {
825         var callback = 'xChatty_';
826         var cStr = parseInt(new Date().getTime() / 1000).toString().substring(5) + (Math.random() + ' ').substring(5, 10);
827         var mult = parseInt(cStr.charAt(Math.floor(Math.random() * cStr.length)));
828         mult = (mult === 0 || mult === 1) ? mult + 2 : mult;
829         cStr = mult.toString() + cStr.toString() + (cStr * mult).toString();
830         callback += cStr.toString().split("").reverse().join("");
831         return callback;
832     },
833     timerNotifications: null,
834     renderNotifications: function(errorMessages, isError) {
835         if (isError) {
836             jQuery(".xc_notifications_wrapper").removeClass("xc_notification_success");
837             jQuery(".xc_notifications_wrapper").addClass("xc_notification_error");
838         } else {
839             jQuery(".xc_notifications_wrapper").addClass("xc_notification_success");
840             jQuery(".xc_notifications_wrapper").removeClass("xc_notification_error");
841         }
842         jQuery(".xc_notifications_wrapper ul.xc_errorlist").html("");
843         for (var k in errorMessages) {
844             for (var l = 0; l < errorMessages[k].length; l++)
845                 jQuery(".xc_notifications_wrapper ul.xc_errorlist").append(jQuery("<li>" + errorMessages[k][l] + "</li>"));
846         }
847         jQuery(".xc_notifications_wrapper").slideDown();
848         clearTimeout(xChatty.timerNotifications);
849         xChatty.timerNotifications = setTimeout(function() {
850             jQuery(".xc_notifications_wrapper").slideUp();
851         }, 10000);
852     },
853     renderErrors: function(error, isError) {
854         if (isError) {
855             jQuery(".xc_notifications_wrapper").removeClass("xc_notification_success");
856             jQuery(".xc_notifications_wrapper").addClass("xc_notification_error");
857         } else {
858             jQuery(".xc_notifications_wrapper").addClass("xc_notification_success");
859             jQuery(".xc_notifications_wrapper").removeClass("xc_notification_error");
860         }
861         jQuery(".xc_notifications_wrapper ul.xc_errorlist").html("");
862         jQuery(".xc_notifications_wrapper ul.xc_errorlist").append(jQuery("<li>" + error.message + "</li>"));
863         jQuery(".xc_notifications_wrapper").slideDown();
864         // clearTimeout(xChatty.timerNotifications);
865         // xChatty.timerNotifications = setTimeout(function() {
866         //     jQuery(".xc_notifications_wrapper").slideUp();
867         // }, 10000);
868     },
869     clearNotifications: function() {
870         jQuery(".xc_notifications_wrapper").hide();
871         jQuery(".xc_notifications_wrapper ul.xc_errorlist").html("");
872     },
873     btnNotificationsCloseClick: function(e) {
874         e.preventDefault();
875         jQuery(".xc_notifications_wrapper").slideUp();
876     },
877     messageKeyUp: function(e) {
878         if (e.shiftKey)
879             return;
880         if (e.keyCode === 13 && !jQuery(this).hasClass("xc_input_enquiry_message")) {
881             jQuery(this).parents('form').submit();
882         }
883     },
884     messageKeyDownWait: false,
885     messageKeyDown: function(e) {
886         if (xChatty.messageKeyDownWait === true) {
887             return;
888         } else {
889             xChatty.messageKeyDownWait = true;
890             setTimeout(function() {
891                 xChatty.messageKeyDownWait = false;
892             }, 1000);
893         }
894         // jQuery.ajax({
895         //     url: xChatty.config.rootPath + "discussions/composing",
896         //     dataType: "jsonp",
897         //     jsonpCallback: xChatty.getJsonpCallbackName(),
898         //     success: function(result) {},
899         //     complete: function() {}
900         // });
901     },
902     sendClick: function(e) {
903         e.preventDefault();
904         jQuery('form.xc_form_reply').submit();
905     },
906     addMessageToChat: function(message, options) {
907         var isConfirmed = "";
908         var fullname = "";
909         if ((typeof options !== 'undefined' && options.confirmed === false) && xChatty.config.visitor.fullname === message.fullname)
910             isConfirmed = " xc_submission_pending";
911         else if (typeof options === 'undefined' && xChatty.config.visitor.fullname === message.fullname)
912             isConfirmed = " xc_submission_confirmed";
913         if (jQuery(".xc_conversation_container [data-id=" + message.id + "]").length === 0) {
914           if (message.User) {
915             fullname = message.User.fullname;
916           }
917           if (message.ChatVisitor) {
918             fullname = message.ChatVisitor.fullname;
919           }
920
921             jQuery(".xc_conversation_container .xc_message_intro").remove();
922             var mTime = ('0' + new Date(message.createdAt).getHours()).slice(-2) + ":" + ('0' + new Date(message.createdAt).getMinutes()).slice(-2);
923             var newMessage = jQuery("<div style=\"clear: both\" class=\"xc_chatrow" + "\" data-id=\"" + message.id + "\"><div class=\"xc_time" + isConfirmed + "\">" + mTime + "</div><p><i style=\"background-image: url(http://www.gravatar.com/avatar/" + message.email + "?s=40&d=identicon);\" class=\"xc_avatar\"></i><span class=\"xc_fullname\">" + fullname + "</span> " + xChatty.prepareMessageText(message.body) + "</p></div>");
924             jQuery(".xc_conversation_container").append(newMessage);
925             jQuery('.xc_conversation_container').children().sort(function(a, b) {
926                 var aF = parseInt(jQuery(a).attr("data-id"));
927                 var bF = parseInt(jQuery(b).attr("data-id"));
928                 if (aF > bF)
929                     return 1;
930                 else if (aF < bF)
931                     return -1;
932                 else
933                     return 0;
934             }).appendTo('.xc_conversation_container');
935         }
936     },
937     prepareMessageText: function(text) {
938         var smilies = [
939           {
940               s: [' :-D ', ' :D '],
941               r: "biggrin"
942           },
943           {
944               s: [' :-S ', ' :S '],
945               r: "confused"
946           },
947           // {
948           //     s: [],
949           //     r: "cool"
950           // },
951           {
952               s: [' ;-( ', ' ;( '],
953               r: "cry"
954           },
955           {
956               s: [' OO '],
957               r: "eek"
958           },
959           // {
960           //     s: [],
961           //     r: "evil"
962           // },
963           {
964               s: [' <3 '],
965               r: "like"
966           },
967           {
968               s: [' ^^ '],
969               r: "lol"
970           },
971           // {
972           //     s: [],
973           //     r: "mad"
974           // },
975           // {
976           //     s: [],
977           //     r: "mrgreen"
978           // },
979           {
980               s: [' :-| ', ' :| '],
981               r: "neutral"
982           },
983           // {
984           //     s: [],
985           //     r: "question"
986           // },
987           {
988               s: [' :-P ', ' :P '],
989               r: "razz"
990           },
991           // {
992           //     s: [],
993           //     r: "redface"
994           // },
995           // {
996           //     s: [],
997           //     r: "rolleyes"
998           // },
999           {
1000               s: [' :-( ', ' :( '],
1001               r: "sad"
1002           },
1003           {
1004               s: [' :-) ', ' :) '],
1005               r: "smile"
1006           },
1007           {
1008               s: [' :-O ', ' :O '],
1009               r: "surprised"
1010           },
1011           // {
1012           //     s: [],
1013           //     r: "thumbdown"
1014           // },
1015           // {
1016           //     s: [],
1017           //     r: "thumbup"
1018           // },
1019           // {
1020           //     s: [],
1021           //     r: "twisted"
1022           // },
1023           {
1024               s: [' ;-) ', ' ;) '],
1025               r: "wink"
1026           }
1027         ];
1028         text = " " + text + " ";
1029         var regex;
1030         for (var i = 0; i < smilies.length; i++) {
1031             for (var j = 0; j < smilies[i].s.length; j++) {
1032                 var smilie = ' <i style="background-image: url(' + ('{XC_REP}' + '?resource=smilies/' + smilies[i].r + '.png') + ');" class="xc_smilie" >' + jQuery.trim(smilies[i].s[j].toString()) + '</i> ';
1033                 regex = new RegExp(xChatty.escapeRegExp(smilies[i].s[j]), 'g');
1034                 text = text.replace(regex, smilie);
1035             }
1036         }
1037         var wAddress = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
1038         var eAddress = /\w+@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6})+/gim;
1039         text = text.replace(wAddress, '<a href="$&">$&</a>').replace(eAddress, '<a href="mailto:$&">$&</a>');
1040         var tmp = jQuery("<div>" + text + "<div>");
1041         tmp.find("a").each(function() {
1042             if (jQuery(this).attr("href").indexOf(document.domain) === -1) {
1043                 jQuery(this).attr("target", "_blank").addClass("xc_link_external");
1044             } else {
1045                 jQuery(this).addClass("xc_link_internal");
1046             }
1047         });
1048         regex = new RegExp(xChatty.escapeRegExp("{XC_REP}"), 'g');
1049         text = jQuery(tmp).html().replace(regex, xChatty.config.assetBase);
1050         return jQuery.trim(text).replace(/\n/g, '<br />');
1051     },
1052     escapeRegExp: function(str) {
1053         return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
1054     },
1055     loadMore: function() {
1056         xChatty.readMessages(true);
1057     },
1058     readMessages: function(loadMore) {
1059         // if (!loadMore)
1060         //     clearTimeout(xChatty.config.timerReadMessages);
1061         if (!xChatty.config.signedUp) {
1062             return;
1063         }
1064         if (xChatty.config.isNewPage) {}
1065         var requestData = [];
1066         if (loadMore === true) {
1067             requestData.push({
1068                 name: 'data[first_id]',
1069                 value: xChatty.getMinId()
1070             });
1071             requestData.push({
1072                 name: 'data[load_more]',
1073                 value: true
1074             });
1075         } else {
1076             requestData.push({
1077                 name: 'data[last_id]',
1078                 value: xChatty.getMaxId()
1079             });
1080             requestData.push({
1081                 name: 'data[is_new_page]',
1082                 value: xChatty.config.isNewPage
1083             });
1084         }
1085         jQuery.ajax({
1086             data: requestData,
1087             url: xChatty.config.rootPath + xChatty.config.websiteId + "/read",
1088             dataType: "jsonp",
1089             jsonpCallback: xChatty.getJsonpCallbackName(),
1090             success: function(result) {
1091                 if (result.success === true) {
1092                     jQuery(".xc_notifications_wrapper").slideUp();
1093                     var scrollToElem = jQuery("[data-id=" + xChatty.getMinId() + "]");
1094                     for (var i = 0; i < result.messages.length; i++) {
1095                         xChatty.addMessageToChat(result.messages[i]);
1096                     }
1097                     if (loadMore)
1098                         jQuery(".xc_btn_load_more").remove();
1099                     // if (result.messages.length >= 20 && jQuery(".xc_btn_load_more").length === 0) {
1100                     //     jQuery(".xc_conversation_container").prepend(jQuery("<a href=\"#\" data-id=\"-10\" class=\"xc_btn_load_more xc_btn_style\">Load More</a>"));
1101                     //     jQuery(".xc_btn_load_more").on("click", xChatty.loadMore);
1102                     // }
1103                     if (result.composing === true && result.messages.length === 0) {
1104                         jQuery(".xc_composing_container").html(xChatty.Lang.OperatorComposing.replace("{fullname}", result.composing_fullname)).slideDown();
1105                     } else {
1106                         jQuery(".xc_composing_container").slideUp();
1107                     }
1108                     if (result.messages.length > 0) {
1109                         jQuery(".xc_composing_container").slideUp();
1110                     }
1111                     if (!loadMore && result.messages.length > 0) {
1112                         xChatty.playNotificationSound();
1113                         xChatty.scrollBottom(true);
1114                         if (!xChatty.config.isNewPage && !jQuery(".xc_conversation_container").is(":visible")) {
1115                             jQuery(".xc_chat_container").animate({
1116                                 opacity: 1
1117                             }, {
1118                                 duration: 200,
1119                                 queue: false
1120                             });
1121                             jQuery(".xc_chat_container").animate({
1122                                 'margin-bottom': -7
1123                             }, 100, function() {
1124                                 jQuery(this).animate({
1125                                     'margin-bottom': 0
1126                                 }, 100, function() {
1127                                     jQuery(this).animate({
1128                                         'margin-bottom': -5
1129                                     }, 100, function() {
1130                                         jQuery(this).animate({
1131                                             'margin-bottom': 0
1132                                         }, 200, function() {});
1133                                     });
1134                                 });
1135                             });
1136                             jQuery(".xc_notification_badge_number").fadeIn();
1137                             var newVal = (isNaN(parseInt(jQuery(".xc_notification_badge_number").html())) ? 0 : parseInt(jQuery(".xc_notification_badge_number").html())) + result.messages.length;
1138                             jQuery(".xc_notification_badge_number").html(newVal);
1139                             jQuery(".xc_chat_container").addClass('xc_has_unread_messages');
1140                         }
1141                     } else if (loadMore) {
1142                         xChatty.scrollToElement(scrollToElem);
1143                     }
1144                     if (result.messages.length === 0)
1145                         xChatty.config.decayHistory++;
1146                     else
1147                         xChatty.config.decayHistory = 0;
1148                     // var duration = xChatty.calculateTimeOutDuration();
1149                     // if (!loadMore) {
1150                     //     xChatty.config.timerReadMessages = setTimeout(function() {
1151                     //         xChatty.readMessages(false);
1152                     //     }, duration);
1153                     // }
1154                 } else if (result.success === false) {
1155                     xChatty.checkStatus(true);
1156                 } else {}
1157                 xChatty.config.isNewPage = false;
1158             },
1159             error: function(err) {
1160               var error = {
1161                 'message': 'Service temporarily unavailable. We back as soon as possible!'
1162               };
1163               xChatty.renderErrors(error, true);
1164             },
1165             complete: function() {
1166               var duration = xChatty.calculateTimeOutDuration();
1167               if (!loadMore) {
1168                   xChatty.config.timerReadMessages = setTimeout(function() {
1169                       xChatty.readMessages(false);
1170                   }, duration);
1171               }
1172             }
1173         });
1174     },
1175     playNotificationSound: function() {
1176         if (xChatty.config.isNewPage || (xChatty.config.windowFocused && jQuery(".xc_conversation_container").is(":visible")) || xChatty.config.muteNotificationSoundOnce) {
1177             xChatty.config.muteNotificationSoundOnce = false;
1178             return;
1179         }
1180         jQuery("#xc_auto_tag").remove();
1181         var soundWav = xChatty.config.assetBase + "?resource=notification/xc_blubb.wav";
1182         var soundMp3 = xChatty.config.assetBase + "?resource=notification/xc_blubb.mp3";
1183         var soundOgg = xChatty.config.assetBase + "?resource=notification/xc_blubb.ogg";
1184         jQuery('<audio id="xc_auto_tag" autoplay="autoplay">').append(jQuery('<source>').attr('src', soundWav)).append(jQuery('<source>').attr('src', soundMp3)).append(jQuery('<source>').attr('src', soundOgg)).appendTo('body');
1185     },
1186     calculateTimeOutDuration: function() {
1187         if (!jQuery(".xc_conversation_container").is(":visible"))
1188             return 10000;
1189         var calcTimeOut = (parseFloat(xChatty.config.decayHistory / 10) * 1000);
1190         if (calcTimeOut > 10000)
1191             return 10000;
1192         if (calcTimeOut > xChatty.config.defaultTimeout) {
1193             return calcTimeOut;
1194         }
1195         return xChatty.config.defaultTimeout;
1196     },
1197     calculateStatusTimeOutDuration: function() {
1198         if (jQuery(".xc_signup_wrapper").is(":visible") && xChatty.config.processingSignUp)
1199           return xChatty.config.defaultTimeout;
1200         return 15000;
1201     },
1202     getMaxId: function() {
1203         if (jQuery(".xc_chatrow").length === 0)
1204             return 0;
1205         var numbers = jQuery(".xc_chatrow").map(function() {
1206             return parseFloat(this.getAttribute('data-id')) || -Infinity;
1207         }).toArray();
1208         return Math.max.apply(Math, numbers);
1209     },
1210     getMinId: function() {
1211         if (jQuery(".xc_chatrow").length === 0)
1212             return 0;
1213         var numbers = jQuery(".xc_chatrow").map(function() {
1214             return parseFloat(this.getAttribute('data-id')) || -Infinity;
1215         }).toArray();
1216         return Math.min.apply(Math, numbers);
1217     },
1218     scrollBottom: function(animate) {
1219         if (!animate)
1220             jQuery(".xc_conversation_container").scrollTop(jQuery(".xc_conversation_container")[0].scrollHeight);
1221         else
1222             jQuery(".xc_conversation_container").animate({
1223                 scrollTop: jQuery(".xc_conversation_container")[0].scrollHeight
1224             }, 800);
1225     },
1226     scrollToElement: function(elem) {
1227         var offset = jQuery(elem).offset().top + (jQuery(elem).height() * 2) - jQuery(".xc_conversation_container").height();
1228         jQuery(".xc_conversation_container").animate({
1229             scrollTop: offset
1230         }, 800);
1231     },
1232     disableSignUpForm: function(form, enable) {
1233       jQuery("." + form + " :input").attr("disabled", enable);
1234       jQuery("." + form + " :button").prop("disabled", enable);
1235     },
1236     browserTest: function(test) {
1237         var isOpera = !!(window.opera && window.opera.version);
1238         var isFirefox = xChatty.testStyle('MozBoxSizing');
1239         var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
1240         var isChrome = !isSafari && xChatty.testStyle('WebkitTransform');
1241         var isIE = false || xChatty.testStyle('msTransform');
1242         var browserValue = {
1243             'Opera': isOpera,
1244             'Firefox': isFirefox,
1245             'Safari': isSafari,
1246             'Chrome': isChrome,
1247             'IE': isIE
1248         };
1249         return browserValue[test];
1250     },
1251     testStyle: function(property) {
1252         return property in document.documentElement.style;
1253     },
1254     checkIfMobileDevice: function() {
1255         var n = (navigator.userAgent || navigator.vendor || window.opera);
1256         return /android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge|maemo|midp|mmp|netfront|opera m(ob|in)i|palm(os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows(ce|phone)|xda|xiino/i.test(n) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(n.substr(0, 4));
1257     }
1258 };
1259
1260 function xcLoadJS(xcCallback) {
1261     var script = document.createElement("script")
1262     script.type = "text/javascript";
1263     if (script.readyState) {
1264         script.onreadystatechange = function() {
1265             if (script.readyState == "loaded" || script.readyState == "complete") {
1266                 script.onreadystatechange = null;
1267                 xcCallback();
1268             }
1269         };
1270     } else {
1271         script.onload = function() {
1272             xcCallback();
1273         };
1274     }
1275     script.src = "http://code.jquery.com/jquery-2.1.4.min.js";
1276     var ph = document.getElementsByTagName('script')[0];
1277     ph.parentNode.insertBefore(script, ph);
1278 }
1279
1280 if (true) {
1281     if (typeof jQuery == 'undefined') {
1282         xcLoadJS(function() {
1283             (function($) {
1284                 jQuery(document).ready(function() {
1285                     xChatty.getHTMLTemplate();
1286                 });
1287             })(jQuery);
1288         });
1289     } else {
1290         (function($) {
1291             jQuery(document).ready(function() {
1292                 xChatty.getHTMLTemplate();
1293             });
1294         })(jQuery);
1295     }
1296 }
1297
1298 /**
1299  * The code below this is not covered by the CodeCanyon Regular License.
1300  * Feel free to re-use the code below as per your requirements whilst following
1301  * the respective licensing terms.
1302  */
1303 /*
1304 CryptoJS v3.1.2
1305 code.google.com/p/crypto-js
1306 (c) 2009-2013 by Jeff Mott. All rights reserved.
1307 code.google.com/p/crypto-js/wiki/License
1308 */
1309 var CryptoJS = CryptoJS || function(s, p) {
1310     var m = {},
1311         l = m.lib = {},
1312         n = function() {},
1313         r = l.Base = {
1314             extend: function(b) {
1315                 n.prototype = this;
1316                 var h = new n;
1317                 b && h.mixIn(b);
1318                 h.hasOwnProperty("init") || (h.init = function() {
1319                     h.$super.init.apply(this, arguments)
1320                 });
1321                 h.init.prototype = h;
1322                 h.$super = this;
1323                 return h
1324             },
1325             create: function() {
1326                 var b = this.extend();
1327                 b.init.apply(b, arguments);
1328                 return b
1329             },
1330             init: function() {},
1331             mixIn: function(b) {
1332                 for (var h in b) b.hasOwnProperty(h) && (this[h] = b[h]);
1333                 b.hasOwnProperty("toString") && (this.toString = b.toString)
1334             },
1335             clone: function() {
1336                 return this.init.prototype.extend(this)
1337             }
1338         },
1339         q = l.WordArray = r.extend({
1340             init: function(b, h) {
1341                 b = this.words = b || [];
1342                 this.sigBytes = h != p ? h : 4 * b.length
1343             },
1344             toString: function(b) {
1345                 return (b || t).stringify(this)
1346             },
1347             concat: function(b) {
1348                 var h = this.words,
1349                     a = b.words,
1350                     j = this.sigBytes;
1351                 b = b.sigBytes;
1352                 this.clamp();
1353                 if (j % 4)
1354                     for (var g = 0; g < b; g++) h[j + g >>> 2] |= (a[g >>> 2] >>> 24 - 8 * (g % 4) & 255) << 24 - 8 * ((j + g) % 4);
1355                 else if (65535 < a.length)
1356                     for (g = 0; g < b; g += 4) h[j + g >>> 2] = a[g >>> 2];
1357                 else h.push.apply(h, a);
1358                 this.sigBytes += b;
1359                 return this
1360             },
1361             clamp: function() {
1362                 var b = this.words,
1363                     h = this.sigBytes;
1364                 b[h >>> 2] &= 4294967295 << 32 - 8 * (h % 4);
1365                 b.length = s.ceil(h / 4)
1366             },
1367             clone: function() {
1368                 var b = r.clone.call(this);
1369                 b.words = this.words.slice(0);
1370                 return b
1371             },
1372             random: function(b) {
1373                 for (var h = [], a = 0; a < b; a += 4) h.push(4294967296 * s.random() | 0);
1374                 return new q.init(h, b)
1375             }
1376         }),
1377         v = m.enc = {},
1378         t = v.Hex = {
1379             stringify: function(b) {
1380                 var a = b.words;
1381                 b = b.sigBytes;
1382                 for (var g = [], j = 0; j < b; j++) {
1383                     var k = a[j >>> 2] >>> 24 - 8 * (j % 4) & 255;
1384                     g.push((k >>> 4).toString(16));
1385                     g.push((k & 15).toString(16))
1386                 }
1387                 return g.join("")
1388             },
1389             parse: function(b) {
1390                 for (var a = b.length, g = [], j = 0; j < a; j += 2) g[j >>> 3] |= parseInt(b.substr(j, 2), 16) << 24 - 4 * (j % 8);
1391                 return new q.init(g, a / 2)
1392             }
1393         },
1394         a = v.Latin1 = {
1395             stringify: function(b) {
1396                 var a = b.words;
1397                 b = b.sigBytes;
1398                 for (var g = [], j = 0; j < b; j++) g.push(String.fromCharCode(a[j >>> 2] >>> 24 - 8 * (j % 4) & 255));
1399                 return g.join("")
1400             },
1401             parse: function(b) {
1402                 for (var a = b.length, g = [], j = 0; j < a; j++) g[j >>> 2] |= (b.charCodeAt(j) & 255) << 24 - 8 * (j % 4);
1403                 return new q.init(g, a)
1404             }
1405         },
1406         u = v.Utf8 = {
1407             stringify: function(b) {
1408                 try {
1409                     return decodeURIComponent(escape(a.stringify(b)))
1410                 } catch (g) {
1411                     throw Error("Malformed UTF-8 data");
1412                 }
1413             },
1414             parse: function(b) {
1415                 return a.parse(unescape(encodeURIComponent(b)))
1416             }
1417         },
1418         g = l.BufferedBlockAlgorithm = r.extend({
1419             reset: function() {
1420                 this._data = new q.init;
1421                 this._nDataBytes = 0
1422             },
1423             _append: function(b) {
1424                 "string" == typeof b && (b = u.parse(b));
1425                 this._data.concat(b);
1426                 this._nDataBytes += b.sigBytes
1427             },
1428             _process: function(b) {
1429                 var a = this._data,
1430                     g = a.words,
1431                     j = a.sigBytes,
1432                     k = this.blockSize,
1433                     m = j / (4 * k),
1434                     m = b ? s.ceil(m) : s.max((m | 0) - this._minBufferSize, 0);
1435                 b = m * k;
1436                 j = s.min(4 * b, j);
1437                 if (b) {
1438                     for (var l = 0; l < b; l += k) this._doProcessBlock(g, l);
1439                     l = g.splice(0, b);
1440                     a.sigBytes -= j
1441                 }
1442                 return new q.init(l, j)
1443             },
1444             clone: function() {
1445                 var b = r.clone.call(this);
1446                 b._data = this._data.clone();
1447                 return b
1448             },
1449             _minBufferSize: 0
1450         });
1451     l.Hasher = g.extend({
1452         cfg: r.extend(),
1453         init: function(b) {
1454             this.cfg = this.cfg.extend(b);
1455             this.reset()
1456         },
1457         reset: function() {
1458             g.reset.call(this);
1459             this._doReset()
1460         },
1461         update: function(b) {
1462             this._append(b);
1463             this._process();
1464             return this
1465         },
1466         finalize: function(b) {
1467             b && this._append(b);
1468             return this._doFinalize()
1469         },
1470         blockSize: 16,
1471         _createHelper: function(b) {
1472             return function(a, g) {
1473                 return (new b.init(g)).finalize(a)
1474             }
1475         },
1476         _createHmacHelper: function(b) {
1477             return function(a, g) {
1478                 return (new k.HMAC.init(b, g)).finalize(a)
1479             }
1480         }
1481     });
1482     var k = m.algo = {};
1483     return m
1484 }(Math);
1485 (function(s) {
1486     function p(a, k, b, h, l, j, m) {
1487         a = a + (k & b | ~k & h) + l + m;
1488         return (a << j | a >>> 32 - j) + k
1489     }
1490
1491     function m(a, k, b, h, l, j, m) {
1492         a = a + (k & h | b & ~h) + l + m;
1493         return (a << j | a >>> 32 - j) + k
1494     }
1495
1496     function l(a, k, b, h, l, j, m) {
1497         a = a + (k ^ b ^ h) + l + m;
1498         return (a << j | a >>> 32 - j) + k
1499     }
1500
1501     function n(a, k, b, h, l, j, m) {
1502         a = a + (b ^ (k | ~h)) + l + m;
1503         return (a << j | a >>> 32 - j) + k
1504     }
1505     for (var r = CryptoJS, q = r.lib, v = q.WordArray, t = q.Hasher, q = r.algo, a = [], u = 0; 64 > u; u++) a[u] = 4294967296 * s.abs(s.sin(u + 1)) | 0;
1506     q = q.MD5 = t.extend({
1507         _doReset: function() {
1508             this._hash = new v.init([1422584193, 4023233417, 2562383102, 271423878])
1509         },
1510         _doProcessBlock: function(g, k) {
1511             for (var b = 0; 16 > b; b++) {
1512                 var h = k + b,
1513                     w = g[h];
1514                 g[h] = (w << 8 | w >>> 24) & 16711935 | (w << 24 | w >>> 8) & 4278255360
1515             }
1516             var b = this._hash.words,
1517                 h = g[k + 0],
1518                 w = g[k + 1],
1519                 j = g[k + 2],
1520                 q = g[k + 3],
1521                 r = g[k + 4],
1522                 s = g[k + 5],
1523                 t = g[k + 6],
1524                 u = g[k + 7],
1525                 v = g[k + 8],
1526                 x = g[k + 9],
1527                 y = g[k + 10],
1528                 z = g[k + 11],
1529                 A = g[k + 12],
1530                 B = g[k + 13],
1531                 C = g[k + 14],
1532                 D = g[k + 15],
1533                 c = b[0],
1534                 d = b[1],
1535                 e = b[2],
1536                 f = b[3],
1537                 c = p(c, d, e, f, h, 7, a[0]),
1538                 f = p(f, c, d, e, w, 12, a[1]),
1539                 e = p(e, f, c, d, j, 17, a[2]),
1540                 d = p(d, e, f, c, q, 22, a[3]),
1541                 c = p(c, d, e, f, r, 7, a[4]),
1542                 f = p(f, c, d, e, s, 12, a[5]),
1543                 e = p(e, f, c, d, t, 17, a[6]),
1544                 d = p(d, e, f, c, u, 22, a[7]),
1545                 c = p(c, d, e, f, v, 7, a[8]),
1546                 f = p(f, c, d, e, x, 12, a[9]),
1547                 e = p(e, f, c, d, y, 17, a[10]),
1548                 d = p(d, e, f, c, z, 22, a[11]),
1549                 c = p(c, d, e, f, A, 7, a[12]),
1550                 f = p(f, c, d, e, B, 12, a[13]),
1551                 e = p(e, f, c, d, C, 17, a[14]),
1552                 d = p(d, e, f, c, D, 22, a[15]),
1553                 c = m(c, d, e, f, w, 5, a[16]),
1554                 f = m(f, c, d, e, t, 9, a[17]),
1555                 e = m(e, f, c, d, z, 14, a[18]),
1556                 d = m(d, e, f, c, h, 20, a[19]),
1557                 c = m(c, d, e, f, s, 5, a[20]),
1558                 f = m(f, c, d, e, y, 9, a[21]),
1559                 e = m(e, f, c, d, D, 14, a[22]),
1560                 d = m(d, e, f, c, r, 20, a[23]),
1561                 c = m(c, d, e, f, x, 5, a[24]),
1562                 f = m(f, c, d, e, C, 9, a[25]),
1563                 e = m(e, f, c, d, q, 14, a[26]),
1564                 d = m(d, e, f, c, v, 20, a[27]),
1565                 c = m(c, d, e, f, B, 5, a[28]),
1566                 f = m(f, c, d, e, j, 9, a[29]),
1567                 e = m(e, f, c, d, u, 14, a[30]),
1568                 d = m(d, e, f, c, A, 20, a[31]),
1569                 c = l(c, d, e, f, s, 4, a[32]),
1570                 f = l(f, c, d, e, v, 11, a[33]),
1571                 e = l(e, f, c, d, z, 16, a[34]),
1572                 d = l(d, e, f, c, C, 23, a[35]),
1573                 c = l(c, d, e, f, w, 4, a[36]),
1574                 f = l(f, c, d, e, r, 11, a[37]),
1575                 e = l(e, f, c, d, u, 16, a[38]),
1576                 d = l(d, e, f, c, y, 23, a[39]),
1577                 c = l(c, d, e, f, B, 4, a[40]),
1578                 f = l(f, c, d, e, h, 11, a[41]),
1579                 e = l(e, f, c, d, q, 16, a[42]),
1580                 d = l(d, e, f, c, t, 23, a[43]),
1581                 c = l(c, d, e, f, x, 4, a[44]),
1582                 f = l(f, c, d, e, A, 11, a[45]),
1583                 e = l(e, f, c, d, D, 16, a[46]),
1584                 d = l(d, e, f, c, j, 23, a[47]),
1585                 c = n(c, d, e, f, h, 6, a[48]),
1586                 f = n(f, c, d, e, u, 10, a[49]),
1587                 e = n(e, f, c, d, C, 15, a[50]),
1588                 d = n(d, e, f, c, s, 21, a[51]),
1589                 c = n(c, d, e, f, A, 6, a[52]),
1590                 f = n(f, c, d, e, q, 10, a[53]),
1591                 e = n(e, f, c, d, y, 15, a[54]),
1592                 d = n(d, e, f, c, w, 21, a[55]),
1593                 c = n(c, d, e, f, v, 6, a[56]),
1594                 f = n(f, c, d, e, D, 10, a[57]),
1595                 e = n(e, f, c, d, t, 15, a[58]),
1596                 d = n(d, e, f, c, B, 21, a[59]),
1597                 c = n(c, d, e, f, r, 6, a[60]),
1598                 f = n(f, c, d, e, z, 10, a[61]),
1599                 e = n(e, f, c, d, j, 15, a[62]),
1600                 d = n(d, e, f, c, x, 21, a[63]);
1601             b[0] = b[0] + c | 0;
1602             b[1] = b[1] + d | 0;
1603             b[2] = b[2] + e | 0;
1604             b[3] = b[3] + f | 0
1605         },
1606         _doFinalize: function() {
1607             var a = this._data,
1608                 k = a.words,
1609                 b = 8 * this._nDataBytes,
1610                 h = 8 * a.sigBytes;
1611             k[h >>> 5] |= 128 << 24 - h % 32;
1612             var l = s.floor(b / 4294967296);
1613             k[(h + 64 >>> 9 << 4) + 15] = (l << 8 | l >>> 24) & 16711935 | (l << 24 | l >>> 8) & 4278255360;
1614             k[(h + 64 >>> 9 << 4) + 14] = (b << 8 | b >>> 24) & 16711935 | (b << 24 | b >>> 8) & 4278255360;
1615             a.sigBytes = 4 * (k.length + 1);
1616             this._process();
1617             a = this._hash;
1618             k = a.words;
1619             for (b = 0; 4 > b; b++) h = k[b], k[b] = (h << 8 | h >>> 24) & 16711935 | (h << 24 | h >>> 8) & 4278255360;
1620             return a
1621         },
1622         clone: function() {
1623             var a = t.clone.call(this);
1624             a._hash = this._hash.clone();
1625             return a
1626         }
1627     });
1628     r.MD5 = t._createHelper(q);
1629     r.HmacMD5 = t._createHmacHelper(q)
1630 })(Math);