Built motion from commit 344422e17.|1.0.22
[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.config.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                   for (var k = 0; k < result.messages.length; k++) {
449                       xChatty.addMessageToChat(result.messages[k]);
450                   }
451                   if (result.messages.length > 0)
452                       xChatty.scrollBottom(true);
453                   xChatty.config.processingSend = false;
454                   messageForm.removeClass("xc_message_sending");
455               } else {
456                   jQuery("[data-id=" + tmpMessage.id + "]").css('border', '1px dashed #f00');
457               }
458           },
459           error: function(err) {
460             var error = {
461               'message': 'Service temporarily unavailable. We back as soon as possible!'
462             };
463             xChatty.renderErrors(error, true);
464             xChatty.config.timerSendMessages = setTimeout(function() {
465               xChatty.handleAjaxSendCall(formData, tmpMessage, messageForm);
466             }, 5000);
467           }
468       });
469     },
470     headerClick: function(e) {
471         e.preventDefault();
472         // if (!xChatty.config.signedUp && (e.originalEvent !== undefined) && !jQuery(".xc_chat_toggle_container").is(":visible") && xChatty.config.hasSession !== true) {
473         //     jQuery('<form method="post" action="' + xChatty.config.rootPath + 'discussions/session_redir"><input type="hidden" name="data[referer]" value="' + window.location + '" /></form>').submit();
474         // }
475         jQuery(".xc_notification_badge_number").fadeOut();
476         jQuery(".xc_notification_badge_number").html('');
477         jQuery(".xc_chat_container").removeClass('xc_has_unread_messages');
478         if (!xChatty.config.signedUp) {
479             if (xChatty.config.isOnline) {
480                 jQuery(".xc_signup_wrapper").show();
481                 jQuery(".xc_conversation").hide();
482                 jQuery(".xc_enquiry_wrapper").hide();
483             } else {
484                 jQuery(".xc_enquiry_wrapper").show();
485                 jQuery(".xc_signup_wrapper").hide();
486                 jQuery(".xc_conversation").hide();
487             }
488         } else {
489             jQuery(".xc_enquiry_wrapper").hide();
490             jQuery(".xc_signup_wrapper").hide();
491             jQuery(".xc_conversation").show();
492         }
493         var wasClosed = jQuery(".xc_chat_toggle_container").is(":visible");
494         jQuery(".xc_chat_toggle_container").slideToggle("fast", function() {
495             xChatty.scrollBottom(true);
496             if (!wasClosed) {
497                 jQuery(".xc_chat_container").addClass("xc_box_open");
498                 jQuery(".xc_chat_container").trigger("chatOpen", true);
499             }
500         });
501         if (wasClosed) {
502             jQuery(".xc_chat_container").addClass("xc_chat_closing");
503             jQuery(".xc_chat_container").animate({
504                 marginBottom: -50
505             }, {
506                 duration: 200,
507                 queue: true,
508                 complete: function() {
509                     jQuery(".xc_chat_container").animate({
510                         marginBottom: 0
511                     }, {
512                         duration: 500,
513                         queue: true,
514                         complete: function() {}
515                     });
516                     jQuery(".xc_chat_container").removeClass("xc_box_open");
517                     jQuery(".xc_chat_container").removeClass("xc_chat_closing");
518                     jQuery(".xc_chat_container").trigger("chatOpen", false);
519                 }
520             });
521         } else {
522             jQuery(".xc_input_message").focus();
523         }
524         if (e.originalEvent !== undefined) {
525             xChatty.readMessages();
526         }
527         xChatty.checkStatus(true);
528     },
529     // signUpClick: function(e) {
530     //     e.preventDefault();
531     //     jQuery(".xc_form_signup").submit();
532     // },
533     signUpSubmit: function(e) {
534         e.preventDefault();
535         if (xChatty.config.processingSignUp)
536             return false;
537         xChatty.config.processingSignUp = true;
538         var validationErrors = {};
539         var signupForm = jQuery(".xc_form_signup");
540         jQuery('.xc_form_signup :input').each(function () {
541           var el = jQuery(this);
542           if (el.val() === el.attr('placeholder')) {
543             el.val('');
544           }
545           if ((jQuery.trim(el.val()) === '' || el.val() === el.attr('placeholder')) && el.attr('required') === 'required' ) {
546             validationErrors[el.attr('id')] = ['Please enter the field ' + el.attr('data-label')];
547           }
548         });
549         // if (jQuery.trim(jQuery(".xc_input_fullname").val()) === '' || jQuery(".xc_input_fullname").val() === jQuery(".xc_input_fullname").attr("placeholder")) {
550         //     validationErrors["fullname"] = [xChatty.Lang.ValidationUsernameRequired];
551         // }
552         // if (!xChatty.config.hideEmail && (jQuery.trim(jQuery(".xc_input_email").val()) === '' || jQuery(".xc_input_email").val() === jQuery(".xc_input_email").attr("placeholder"))) {
553         //     validationErrors["email"] = [xChatty.Lang.ValidationEmailRequired];
554         // }
555         // if (validationErrors.hasOwnProperty("fullname") || validationErrors.hasOwnProperty("email")) {
556         //     xChatty.renderNotifications(validationErrors, true);
557         //     return;
558         // }
559         if (Object.keys(validationErrors).length > 0) {
560           xChatty.renderNotifications(validationErrors,true);
561           xChatty.config.processingSignUp = false;
562           return;
563         }
564         var now = new Date();
565         var dateStr = now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
566         jQuery(".xc_input_visitor_time").val(dateStr);
567         var formData = jQuery(".xc_form_signup").serializeArray();
568         formData.push({
569           name: 'chatWebsiteId' ,
570           value: xChatty.config.websiteId
571         });
572         if (xChatty.config.hideEmail) {
573             formData.push({
574                 name: 'data[Discussion][email]',
575                 value: 'not.provided@example.com'
576             });
577         }
578         jQuery.ajax({
579             url: xChatty.config.rootPath + xChatty.config.websiteId + "/signup",
580             data: formData,
581             dataType: "jsonp",
582             //jsonpCallback: xChatty.getJsonpCallbackName(),
583             success: function(result) {
584                 if (result.success === true) {
585                     jQuery(".xc_notifications_wrapper").slideUp();
586                     xChatty.config.processingSignUp = true;
587                     xChatty.config.visitor.fullname = jQuery(".xc_input_fullname").val();
588                     xChatty.config.visitor.avatar = CryptoJS.MD5(jQuery.trim(jQuery(".xc_input_email").val()).toLowerCase());
589                     xChatty.clearNotifications();
590                     // xChatty.config.signedUp = true;
591                     xChatty.setHeaderText();
592                     xChatty.disableSignUpForm('xc_form_signup',true);
593                     xChatty.removeOldMessages();
594                     xChatty.checkStatus();
595
596                     // xChatty.handleNoAgentResponse();
597
598                     // xChatty.readMessages();
599                     // jQuery(".xc_signup_wrapper").hide();
600                     // jQuery(".xc_conversation").show();
601                     // xChatty.scrollBottom(false);
602                 } else {
603                     xChatty.renderNotifications(result.errors, true);
604                 }
605             },
606             error: function(err) {
607               xChatty.config.processingSignUp = false;
608               var error = {
609                 'message': 'Service temporarily unavailable. We back as soon as possible!'
610               };
611               xChatty.renderErrors(error, true);
612             },
613             complete: function() {
614                 // xChatty.config.processingSignUp = false;
615             }
616         });
617     },
618     setHeaderText: function() {
619         if (xChatty.config.signedUp === true)
620             jQuery(".xc_chat_head-title").html(xChatty.Lang.HeaderCurrentlyChatting);
621         else if (xChatty.config.signedUp === false && xChatty.config.processingSignUp === true)
622             jQuery(".xc_chat_head-title").html('Waiting for connection...');
623         else if (xChatty.config.isOnline === true)
624             jQuery(".xc_chat_head-title").html(xChatty.Lang.HeaderOnline);
625         else
626             jQuery(".xc_chat_head-title").html(xChatty.Lang.HeaderOffline);
627     },
628     handleSnippetOpen: function () {
629       if (!jQuery(".xc_chat_toggle_container").is(":visible")) {
630         jQuery(".xc_chat_head").trigger("click");
631       }
632     },
633     getProactiveActions: function () {
634       jQuery.ajax({
635           url: xChatty.config.rootPath + xChatty.config.websiteId + '/proactive',
636           dataType: 'jsonp',
637           crossDomain: true,
638           success: function (data) {
639             if (data.length > 0) {
640               for (var i in data) {
641                 if (data.hasOwnProperty(i)) {
642                   var proAction = data[i];
643                   switch (proAction.type) {
644                     case 'mouseOver':
645                       if (proAction.hasOwnProperty('selector') && proAction.selector) {
646                         jQuery(document).on("mouseover", proAction.selector, xChatty.handleSnippetOpen);
647                       }
648                       break;
649                     case 'timeout':
650                       if (proAction.hasOwnProperty('timeout') && proAction.timeout > 0) {
651                         setTimeout(function () {
652                           xChatty.handleSnippetOpen();
653                         }, proAction.timeout * 1000);
654                       }
655                       break;
656                     default:
657                       console.log('Event type not supported');
658                   }
659                 }
660               }
661             }
662           }
663         });
664     },
665     getHTMLTemplate: function() {
666       jQuery.ajax({
667           url: xChatty.config.rootPath + xChatty.config.websiteId + '/html',
668           dataType: 'jsonp',
669           crossDomain: true,
670           success: function (data) {
671             if (jQuery(".xc_chat_container").length === 0) {
672               for (var i in xChatty.Lang) {
673                 data = data.replace(new RegExp("{" + i + "}", "gm"), xChatty.Lang[i]);
674               }
675               jQuery('body').append(data);
676             }
677             if (jQuery("#xc_stylesheet").length === 0) {
678                 var xcCss = document.createElement('link');
679                 xcCss.setAttribute('rel', 'stylesheet');
680                 xcCss.type = 'text/css';
681                 xcCss.id = 'xc_stylesheet';
682                 xcCss.href = xChatty.config.rootPath + xChatty.config.websiteId + "/styles";
683                 document.body.appendChild(xcCss);
684             }
685             if(xChatty.config.downloadTranscript) {
686               jQuery(".xc_download_transcript_container").show();
687             } else {
688               jQuery(".xc_download_transcript_container").hide();
689             }
690             xChatty.getProactiveActions();
691             xChatty.checkStatus();
692           }
693         });
694     },
695     checkStatus: function(async) {
696         clearTimeout(xChatty.config.timerCheckStatus);
697         var formData = [];
698         if (xChatty.config.isInitialStatusCheck)
699             formData.push({
700                 name: 'data[referer]',
701                 value: encodeURIComponent(encodeURIComponent(document.referrer))
702             });
703         else
704             formData.push({
705                 name: 'data[open_state]',
706                 value: (jQuery(".xc_chat_toggle_container").is(":visible") && !jQuery(".xc_chat_container").hasClass("xc_chat_closing"))
707             });
708         jQuery.ajax({
709             url: xChatty.config.rootPath + xChatty.config.websiteId + "/status",
710             dataType: "jsonp",
711             data: formData,
712             async: async,
713             success: function(result) {
714                 jQuery(".xc_notifications_wrapper").slideUp();
715                 var wasSignedUp = xChatty.config.signedUp;
716                 if (wasSignedUp && result.signed_up === false) {
717                   clearTimeout(xChatty.config.timerReadMessages);
718                   clearTimeout(xChatty.config.timerCheckStatus);
719                   jQuery(".xc_conversation_container").empty();
720                   jQuery(".xc_conversation_container").html('<p class="xc_message_intro" data-id="-10">' + xChatty.Lang.FirstMessageText + '</p>');
721                   jQuery(".xc_exit_chat_confirmation_wrapper").hide();
722                   jQuery(".xc_btn_exit_chat").show();
723                   jQuery(".xc_conversation").hide();
724                   jQuery('.xc_rating_wrapper').show();
725                   return;
726                 }
727                 if (result.success) {
728                     xChatty.config.visitor.fullname = result.fullname;
729                     xChatty.config.visitor.avatar = result.avatar;
730                     xChatty.config.signedUp = result.signed_up;
731                     xChatty.config.isOnline = result.online;
732                     xChatty.config.hasSessionSaf = result.has_session_saf;
733                     xChatty.config.roomId = result.room_id;
734                 }
735                 if (result.success && result.signed_up === false && xChatty.config.signedUp) {
736                     xChatty.resetDefaultState();
737                 }
738                 if (xChatty.config.isOnline) {
739                     jQuery(".xc_chat_container").addClass("xc_state_online").removeClass("xc_state_offline").fadeIn();
740                 } else {
741                     jQuery(".xc_chat_container").removeClass("xc_state_online").addClass("xc_state_offline");
742                 }
743                 if (!xChatty.config.signedUp) {
744                     if (xChatty.config.isOnline) {
745                         jQuery(".xc_signup_wrapper").show();
746                         jQuery(".xc_conversation").hide();
747                         jQuery(".xc_enquiry_wrapper").hide();
748                     } else {
749                         jQuery(".xc_enquiry_wrapper").show();
750                         jQuery(".xc_signup_wrapper").hide();
751                         jQuery(".xc_conversation").hide();
752                     }
753                 } else {
754                     if (xChatty.config.isOnline) {
755                         xChatty.clearNotifications();
756                     } else {
757                         var notifications = {
758                             offline: [xChatty.Lang.OperatorOfflineMessage]
759                         };
760                         xChatty.renderNotifications(notifications, true);
761                     }
762                 }
763                 var wasInitialStatusCheck = xChatty.config.isInitialStatusCheck;
764                 if (xChatty.config.isInitialStatusCheck === true) {
765                     xChatty.config.isInitialStatusCheck = false;
766                     xChatty.config.muteNotificationSoundOnce = true;
767                     xChatty.setHeaderText();
768                     xChatty.init();
769                     if (result.open_state === true) {
770                         xChatty.config.restoreOpenState = true;
771                     }
772                 }
773                 if (result.success && result.signed_up === true && wasSignedUp === false && wasInitialStatusCheck === false) {
774                     jQuery(".xc_enquiry_wrapper").hide();
775                     jQuery(".xc_signup_wrapper").hide();
776                     jQuery(".xc_conversation").show();
777                     xChatty.readMessages();
778                 }
779
780                 if(!wasSignedUp && result.signed_up === true && xChatty.config.processingSignUp) {
781                   xChatty.config.processingSignUp = false;
782                   xChatty.disableSignUpForm('xc_form_signup',false);
783                   xChatty.setHeaderText();
784                 }
785
786                 if (!wasSignedUp && xChatty.config.processingSignUp && result.is_unserved) {
787                   xChatty.config.processingSignUp = false;
788                   var error = {
789                     'message': xChatty.Lang.MessageAgentsBusy
790                   };
791                   xChatty.renderErrors(error, true);
792                   xChatty.setHeaderText();
793                   xChatty.disableSignUpForm('xc_form_signup',false);
794                 }
795
796                 jQuery('.xc_rating_wrapper').hide();
797                 jQuery('.xc_form_rating')[0].reset();
798
799                 // if(wasSignedUp && result.signed_up === true) {
800                 //   xChatty.readMessages(false);
801                 //   // var duration = xChatty.calculateTimeOutDuration();
802                 //   // xChatty.config.timerReadMessages = setTimeout(function() {
803                 //   //   xChatty.readMessages(false);
804                 //   // }, duration);
805                 // }
806
807             },
808             error: function(err) {
809               var error = {
810                 'message': 'Service temporarily unavailable. We back as soon as possible!'
811               };
812               xChatty.renderErrors(error, true);
813             },
814             complete: function() {
815                 xChatty.setHeaderText();
816                 var duration = xChatty.calculateStatusTimeOutDuration();
817                 xChatty.config.timerCheckStatus = setTimeout(function() {
818                     xChatty.checkStatus(true);
819                 }, duration);
820             }
821         });
822     },
823     getJsonpCallbackName: function() {
824         var callback = 'xChatty_';
825         var cStr = parseInt(new Date().getTime() / 1000).toString().substring(5) + (Math.random() + ' ').substring(5, 10);
826         var mult = parseInt(cStr.charAt(Math.floor(Math.random() * cStr.length)));
827         mult = (mult === 0 || mult === 1) ? mult + 2 : mult;
828         cStr = mult.toString() + cStr.toString() + (cStr * mult).toString();
829         callback += cStr.toString().split("").reverse().join("");
830         return callback;
831     },
832     timerNotifications: null,
833     renderNotifications: function(errorMessages, isError) {
834         if (isError) {
835             jQuery(".xc_notifications_wrapper").removeClass("xc_notification_success");
836             jQuery(".xc_notifications_wrapper").addClass("xc_notification_error");
837         } else {
838             jQuery(".xc_notifications_wrapper").addClass("xc_notification_success");
839             jQuery(".xc_notifications_wrapper").removeClass("xc_notification_error");
840         }
841         jQuery(".xc_notifications_wrapper ul.xc_errorlist").html("");
842         for (var k in errorMessages) {
843             for (var l = 0; l < errorMessages[k].length; l++)
844                 jQuery(".xc_notifications_wrapper ul.xc_errorlist").append(jQuery("<li>" + errorMessages[k][l] + "</li>"));
845         }
846         jQuery(".xc_notifications_wrapper").slideDown();
847         clearTimeout(xChatty.timerNotifications);
848         xChatty.timerNotifications = setTimeout(function() {
849             jQuery(".xc_notifications_wrapper").slideUp();
850         }, 10000);
851     },
852     renderErrors: function(error, isError) {
853         if (isError) {
854             jQuery(".xc_notifications_wrapper").removeClass("xc_notification_success");
855             jQuery(".xc_notifications_wrapper").addClass("xc_notification_error");
856         } else {
857             jQuery(".xc_notifications_wrapper").addClass("xc_notification_success");
858             jQuery(".xc_notifications_wrapper").removeClass("xc_notification_error");
859         }
860         jQuery(".xc_notifications_wrapper ul.xc_errorlist").html("");
861         jQuery(".xc_notifications_wrapper ul.xc_errorlist").append(jQuery("<li>" + error.message + "</li>"));
862         jQuery(".xc_notifications_wrapper").slideDown();
863         // clearTimeout(xChatty.timerNotifications);
864         // xChatty.timerNotifications = setTimeout(function() {
865         //     jQuery(".xc_notifications_wrapper").slideUp();
866         // }, 10000);
867     },
868     clearNotifications: function() {
869         jQuery(".xc_notifications_wrapper").hide();
870         jQuery(".xc_notifications_wrapper ul.xc_errorlist").html("");
871     },
872     btnNotificationsCloseClick: function(e) {
873         e.preventDefault();
874         jQuery(".xc_notifications_wrapper").slideUp();
875     },
876     messageKeyUp: function(e) {
877         if (e.shiftKey)
878             return;
879         if (e.keyCode === 13 && !jQuery(this).hasClass("xc_input_enquiry_message")) {
880             jQuery(this).parents('form').submit();
881         }
882     },
883     messageKeyDownWait: false,
884     messageKeyDown: function(e) {
885         if (xChatty.messageKeyDownWait === true) {
886             return;
887         } else {
888             xChatty.messageKeyDownWait = true;
889             setTimeout(function() {
890                 xChatty.messageKeyDownWait = false;
891             }, 1000);
892         }
893         // jQuery.ajax({
894         //     url: xChatty.config.rootPath + "discussions/composing",
895         //     dataType: "jsonp",
896         //     jsonpCallback: xChatty.getJsonpCallbackName(),
897         //     success: function(result) {},
898         //     complete: function() {}
899         // });
900     },
901     sendClick: function(e) {
902         e.preventDefault();
903         jQuery('form.xc_form_reply').submit();
904     },
905     addMessageToChat: function(message, options) {
906         var isConfirmed = "";
907         var fullname = message.fullname;
908         if ((typeof options !== 'undefined' && options.confirmed === false) && xChatty.config.visitor.fullname === message.fullname)
909             isConfirmed = " xc_submission_pending";
910         else if (typeof options === 'undefined' && xChatty.config.visitor.fullname === message.fullname)
911             isConfirmed = " xc_submission_confirmed";
912         if (jQuery(".xc_conversation_container [data-id=" + message.id + "]").length === 0) {
913           if (message.User) {
914             fullname = message.User.fullname;
915           }
916           if (message.ChatVisitor) {
917             fullname = message.ChatVisitor.fullname;
918           }
919
920             jQuery(".xc_conversation_container .xc_message_intro").remove();
921             var mTime = ('0' + new Date(message.createdAt).getHours()).slice(-2) + ":" + ('0' + new Date(message.createdAt).getMinutes()).slice(-2);
922             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>");
923             jQuery(".xc_conversation_container").append(newMessage);
924             jQuery('.xc_conversation_container').children().sort(function(a, b) {
925                 var aF = parseInt(jQuery(a).attr("data-id"));
926                 var bF = parseInt(jQuery(b).attr("data-id"));
927                 if (aF > bF)
928                     return 1;
929                 else if (aF < bF)
930                     return -1;
931                 else
932                     return 0;
933             }).appendTo('.xc_conversation_container');
934         }
935     },
936     prepareMessageText: function(text) {
937         var smilies = [
938           {
939               s: [' :-D ', ' :D '],
940               r: "biggrin"
941           },
942           {
943               s: [' :-S ', ' :S '],
944               r: "confused"
945           },
946           // {
947           //     s: [],
948           //     r: "cool"
949           // },
950           {
951               s: [' ;-( ', ' ;( '],
952               r: "cry"
953           },
954           {
955               s: [' OO '],
956               r: "eek"
957           },
958           // {
959           //     s: [],
960           //     r: "evil"
961           // },
962           {
963               s: [' <3 '],
964               r: "like"
965           },
966           {
967               s: [' ^^ '],
968               r: "lol"
969           },
970           // {
971           //     s: [],
972           //     r: "mad"
973           // },
974           // {
975           //     s: [],
976           //     r: "mrgreen"
977           // },
978           {
979               s: [' :-| ', ' :| '],
980               r: "neutral"
981           },
982           // {
983           //     s: [],
984           //     r: "question"
985           // },
986           {
987               s: [' :-P ', ' :P '],
988               r: "razz"
989           },
990           // {
991           //     s: [],
992           //     r: "redface"
993           // },
994           // {
995           //     s: [],
996           //     r: "rolleyes"
997           // },
998           {
999               s: [' :-( ', ' :( '],
1000               r: "sad"
1001           },
1002           {
1003               s: [' :-) ', ' :) '],
1004               r: "smile"
1005           },
1006           {
1007               s: [' :-O ', ' :O '],
1008               r: "surprised"
1009           },
1010           // {
1011           //     s: [],
1012           //     r: "thumbdown"
1013           // },
1014           // {
1015           //     s: [],
1016           //     r: "thumbup"
1017           // },
1018           // {
1019           //     s: [],
1020           //     r: "twisted"
1021           // },
1022           {
1023               s: [' ;-) ', ' ;) '],
1024               r: "wink"
1025           }
1026         ];
1027         text = " " + text + " ";
1028         var regex;
1029         for (var i = 0; i < smilies.length; i++) {
1030             for (var j = 0; j < smilies[i].s.length; j++) {
1031                 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> ';
1032                 regex = new RegExp(xChatty.escapeRegExp(smilies[i].s[j]), 'g');
1033                 text = text.replace(regex, smilie);
1034             }
1035         }
1036         var wAddress = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
1037         var eAddress = /\w+@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6})+/gim;
1038         text = text.replace(wAddress, '<a href="$&">$&</a>').replace(eAddress, '<a href="mailto:$&">$&</a>');
1039         var tmp = jQuery("<div>" + text + "<div>");
1040         tmp.find("a").each(function() {
1041             if (jQuery(this).attr("href").indexOf(document.domain) === -1) {
1042                 jQuery(this).attr("target", "_blank").addClass("xc_link_external");
1043             } else {
1044                 jQuery(this).addClass("xc_link_internal");
1045             }
1046         });
1047         regex = new RegExp(xChatty.escapeRegExp("{XC_REP}"), 'g');
1048         text = jQuery(tmp).html().replace(regex, xChatty.config.assetBase);
1049         return jQuery.trim(text).replace(/\n/g, '<br />');
1050     },
1051     escapeRegExp: function(str) {
1052         return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
1053     },
1054     loadMore: function() {
1055         xChatty.readMessages(true);
1056     },
1057     readMessages: function(loadMore) {
1058         // if (!loadMore)
1059         //     clearTimeout(xChatty.config.timerReadMessages);
1060         if (!xChatty.config.signedUp) {
1061             return;
1062         }
1063         if (xChatty.config.isNewPage) {}
1064         var requestData = [];
1065         if (loadMore === true) {
1066             requestData.push({
1067                 name: 'data[first_id]',
1068                 value: xChatty.getMinId()
1069             });
1070             requestData.push({
1071                 name: 'data[load_more]',
1072                 value: true
1073             });
1074         } else {
1075             requestData.push({
1076                 name: 'data[last_id]',
1077                 value: xChatty.getMaxId()
1078             });
1079             requestData.push({
1080                 name: 'data[is_new_page]',
1081                 value: xChatty.config.isNewPage
1082             });
1083         }
1084         jQuery.ajax({
1085             data: requestData,
1086             url: xChatty.config.rootPath + xChatty.config.websiteId + "/read",
1087             dataType: "jsonp",
1088             //jsonpCallback: xChatty.getJsonpCallbackName(),
1089             success: function(result) {
1090                 if (result.success === true) {
1091                     jQuery(".xc_notifications_wrapper").slideUp();
1092                     var scrollToElem = jQuery("[data-id=" + xChatty.getMinId() + "]");
1093                     for (var i = 0; i < result.messages.length; i++) {
1094                         xChatty.addMessageToChat(result.messages[i]);
1095                     }
1096                     if (loadMore)
1097                         jQuery(".xc_btn_load_more").remove();
1098                     // if (result.messages.length >= 20 && jQuery(".xc_btn_load_more").length === 0) {
1099                     //     jQuery(".xc_conversation_container").prepend(jQuery("<a href=\"#\" data-id=\"-10\" class=\"xc_btn_load_more xc_btn_style\">Load More</a>"));
1100                     //     jQuery(".xc_btn_load_more").on("click", xChatty.loadMore);
1101                     // }
1102                     if (result.composing === true && result.messages.length === 0) {
1103                         jQuery(".xc_composing_container").html(xChatty.Lang.OperatorComposing.replace("{fullname}", result.composing_fullname)).slideDown();
1104                     } else {
1105                         jQuery(".xc_composing_container").slideUp();
1106                     }
1107                     if (result.messages.length > 0) {
1108                         jQuery(".xc_composing_container").slideUp();
1109                     }
1110                     if (!loadMore && result.messages.length > 0) {
1111                         xChatty.playNotificationSound();
1112                         xChatty.scrollBottom(true);
1113                         if (!xChatty.config.isNewPage && !jQuery(".xc_conversation_container").is(":visible")) {
1114                             jQuery(".xc_chat_container").animate({
1115                                 opacity: 1
1116                             }, {
1117                                 duration: 200,
1118                                 queue: false
1119                             });
1120                             jQuery(".xc_chat_container").animate({
1121                                 'margin-bottom': -7
1122                             }, 100, function() {
1123                                 jQuery(this).animate({
1124                                     'margin-bottom': 0
1125                                 }, 100, function() {
1126                                     jQuery(this).animate({
1127                                         'margin-bottom': -5
1128                                     }, 100, function() {
1129                                         jQuery(this).animate({
1130                                             'margin-bottom': 0
1131                                         }, 200, function() {});
1132                                     });
1133                                 });
1134                             });
1135                             jQuery(".xc_notification_badge_number").fadeIn();
1136                             var newVal = (isNaN(parseInt(jQuery(".xc_notification_badge_number").html())) ? 0 : parseInt(jQuery(".xc_notification_badge_number").html())) + result.messages.length;
1137                             jQuery(".xc_notification_badge_number").html(newVal);
1138                             jQuery(".xc_chat_container").addClass('xc_has_unread_messages');
1139                         }
1140                     } else if (loadMore) {
1141                         xChatty.scrollToElement(scrollToElem);
1142                     }
1143                     if (result.messages.length === 0)
1144                         xChatty.config.decayHistory++;
1145                     else
1146                         xChatty.config.decayHistory = 0;
1147                     // var duration = xChatty.calculateTimeOutDuration();
1148                     // if (!loadMore) {
1149                     //     xChatty.config.timerReadMessages = setTimeout(function() {
1150                     //         xChatty.readMessages(false);
1151                     //     }, duration);
1152                     // }
1153                 } else if (result.success === false) {
1154                     xChatty.checkStatus(true);
1155                 } else {}
1156                 xChatty.config.isNewPage = false;
1157             },
1158             error: function(err) {
1159               var error = {
1160                 'message': 'Service temporarily unavailable. We back as soon as possible!'
1161               };
1162               xChatty.renderErrors(error, true);
1163             },
1164             complete: function() {
1165               var duration = xChatty.calculateTimeOutDuration();
1166               if (!loadMore) {
1167                   xChatty.config.timerReadMessages = setTimeout(function() {
1168                       xChatty.readMessages(false);
1169                   }, duration);
1170               }
1171             }
1172         });
1173     },
1174     playNotificationSound: function() {
1175         if (xChatty.config.isNewPage || (xChatty.config.windowFocused && jQuery(".xc_conversation_container").is(":visible")) || xChatty.config.muteNotificationSoundOnce) {
1176             xChatty.config.muteNotificationSoundOnce = false;
1177             return;
1178         }
1179         jQuery("#xc_auto_tag").remove();
1180         var soundWav = xChatty.config.assetBase + "?resource=notification/xc_blubb.wav";
1181         var soundMp3 = xChatty.config.assetBase + "?resource=notification/xc_blubb.mp3";
1182         var soundOgg = xChatty.config.assetBase + "?resource=notification/xc_blubb.ogg";
1183         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');
1184     },
1185     calculateTimeOutDuration: function() {
1186         if (!jQuery(".xc_conversation_container").is(":visible"))
1187             return 10000;
1188         var calcTimeOut = (parseFloat(xChatty.config.decayHistory / 10) * 1000);
1189         if (calcTimeOut > 10000)
1190             return 10000;
1191         if (calcTimeOut > xChatty.config.defaultTimeout) {
1192             return calcTimeOut;
1193         }
1194         return xChatty.config.defaultTimeout;
1195     },
1196     calculateStatusTimeOutDuration: function() {
1197         if (jQuery(".xc_signup_wrapper").is(":visible") && xChatty.config.processingSignUp)
1198           return xChatty.config.defaultTimeout;
1199         return 15000;
1200     },
1201     getMaxId: function() {
1202         if (jQuery(".xc_chatrow").length === 0)
1203             return 0;
1204         var numbers = jQuery(".xc_chatrow").map(function() {
1205             return parseFloat(this.getAttribute('data-id')) || -Infinity;
1206         }).toArray();
1207         return Math.max.apply(Math, numbers);
1208     },
1209     getMinId: function() {
1210         if (jQuery(".xc_chatrow").length === 0)
1211             return 0;
1212         var numbers = jQuery(".xc_chatrow").map(function() {
1213             return parseFloat(this.getAttribute('data-id')) || -Infinity;
1214         }).toArray();
1215         return Math.min.apply(Math, numbers);
1216     },
1217     scrollBottom: function(animate) {
1218         if (!animate)
1219             jQuery(".xc_conversation_container").scrollTop(jQuery(".xc_conversation_container")[0].scrollHeight);
1220         else
1221             jQuery(".xc_conversation_container").animate({
1222                 scrollTop: jQuery(".xc_conversation_container")[0].scrollHeight
1223             }, 800);
1224     },
1225     scrollToElement: function(elem) {
1226         var offset = jQuery(elem).offset().top + (jQuery(elem).height() * 2) - jQuery(".xc_conversation_container").height();
1227         jQuery(".xc_conversation_container").animate({
1228             scrollTop: offset
1229         }, 800);
1230     },
1231     disableSignUpForm: function(form, enable) {
1232       jQuery("." + form + " :input").attr("disabled", enable);
1233       jQuery("." + form + " :button").prop("disabled", enable);
1234     },
1235     browserTest: function(test) {
1236         var isOpera = !!(window.opera && window.opera.version);
1237         var isFirefox = xChatty.testStyle('MozBoxSizing');
1238         var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
1239         var isChrome = !isSafari && xChatty.testStyle('WebkitTransform');
1240         var isIE = false || xChatty.testStyle('msTransform');
1241         var browserValue = {
1242             'Opera': isOpera,
1243             'Firefox': isFirefox,
1244             'Safari': isSafari,
1245             'Chrome': isChrome,
1246             'IE': isIE
1247         };
1248         return browserValue[test];
1249     },
1250     testStyle: function(property) {
1251         return property in document.documentElement.style;
1252     },
1253     checkIfMobileDevice: function() {
1254         var n = (navigator.userAgent || navigator.vendor || window.opera);
1255         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));
1256     }
1257 };
1258
1259 function xcLoadJS(xcCallback) {
1260     var script = document.createElement("script")
1261     script.type = "text/javascript";
1262     if (script.readyState) {
1263         script.onreadystatechange = function() {
1264             if (script.readyState == "loaded" || script.readyState == "complete") {
1265                 script.onreadystatechange = null;
1266                 xcCallback();
1267             }
1268         };
1269     } else {
1270         script.onload = function() {
1271             xcCallback();
1272         };
1273     }
1274     script.src = "http://code.jquery.com/jquery-2.1.4.min.js";
1275     var ph = document.getElementsByTagName('script')[0];
1276     ph.parentNode.insertBefore(script, ph);
1277 }
1278
1279 if (true) {
1280     if (typeof jQuery == 'undefined') {
1281         xcLoadJS(function() {
1282             (function($) {
1283                 jQuery(document).ready(function() {
1284                     xChatty.getHTMLTemplate();
1285                 });
1286             })(jQuery);
1287         });
1288     } else {
1289         (function($) {
1290             jQuery(document).ready(function() {
1291                 xChatty.getHTMLTemplate();
1292             });
1293         })(jQuery);
1294     }
1295 }
1296
1297 /**
1298  * The code below this is not covered by the CodeCanyon Regular License.
1299  * Feel free to re-use the code below as per your requirements whilst following
1300  * the respective licensing terms.
1301  */
1302 /*
1303 CryptoJS v3.1.2
1304 code.google.com/p/crypto-js
1305 (c) 2009-2013 by Jeff Mott. All rights reserved.
1306 code.google.com/p/crypto-js/wiki/License
1307 */
1308 var CryptoJS = CryptoJS || function(s, p) {
1309     var m = {},
1310         l = m.lib = {},
1311         n = function() {},
1312         r = l.Base = {
1313             extend: function(b) {
1314                 n.prototype = this;
1315                 var h = new n;
1316                 b && h.mixIn(b);
1317                 h.hasOwnProperty("init") || (h.init = function() {
1318                     h.$super.init.apply(this, arguments)
1319                 });
1320                 h.init.prototype = h;
1321                 h.$super = this;
1322                 return h
1323             },
1324             create: function() {
1325                 var b = this.extend();
1326                 b.init.apply(b, arguments);
1327                 return b
1328             },
1329             init: function() {},
1330             mixIn: function(b) {
1331                 for (var h in b) b.hasOwnProperty(h) && (this[h] = b[h]);
1332                 b.hasOwnProperty("toString") && (this.toString = b.toString)
1333             },
1334             clone: function() {
1335                 return this.init.prototype.extend(this)
1336             }
1337         },
1338         q = l.WordArray = r.extend({
1339             init: function(b, h) {
1340                 b = this.words = b || [];
1341                 this.sigBytes = h != p ? h : 4 * b.length
1342             },
1343             toString: function(b) {
1344                 return (b || t).stringify(this)
1345             },
1346             concat: function(b) {
1347                 var h = this.words,
1348                     a = b.words,
1349                     j = this.sigBytes;
1350                 b = b.sigBytes;
1351                 this.clamp();
1352                 if (j % 4)
1353                     for (var g = 0; g < b; g++) h[j + g >>> 2] |= (a[g >>> 2] >>> 24 - 8 * (g % 4) & 255) << 24 - 8 * ((j + g) % 4);
1354                 else if (65535 < a.length)
1355                     for (g = 0; g < b; g += 4) h[j + g >>> 2] = a[g >>> 2];
1356                 else h.push.apply(h, a);
1357                 this.sigBytes += b;
1358                 return this
1359             },
1360             clamp: function() {
1361                 var b = this.words,
1362                     h = this.sigBytes;
1363                 b[h >>> 2] &= 4294967295 << 32 - 8 * (h % 4);
1364                 b.length = s.ceil(h / 4)
1365             },
1366             clone: function() {
1367                 var b = r.clone.call(this);
1368                 b.words = this.words.slice(0);
1369                 return b
1370             },
1371             random: function(b) {
1372                 for (var h = [], a = 0; a < b; a += 4) h.push(4294967296 * s.random() | 0);
1373                 return new q.init(h, b)
1374             }
1375         }),
1376         v = m.enc = {},
1377         t = v.Hex = {
1378             stringify: function(b) {
1379                 var a = b.words;
1380                 b = b.sigBytes;
1381                 for (var g = [], j = 0; j < b; j++) {
1382                     var k = a[j >>> 2] >>> 24 - 8 * (j % 4) & 255;
1383                     g.push((k >>> 4).toString(16));
1384                     g.push((k & 15).toString(16))
1385                 }
1386                 return g.join("")
1387             },
1388             parse: function(b) {
1389                 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);
1390                 return new q.init(g, a / 2)
1391             }
1392         },
1393         a = v.Latin1 = {
1394             stringify: function(b) {
1395                 var a = b.words;
1396                 b = b.sigBytes;
1397                 for (var g = [], j = 0; j < b; j++) g.push(String.fromCharCode(a[j >>> 2] >>> 24 - 8 * (j % 4) & 255));
1398                 return g.join("")
1399             },
1400             parse: function(b) {
1401                 for (var a = b.length, g = [], j = 0; j < a; j++) g[j >>> 2] |= (b.charCodeAt(j) & 255) << 24 - 8 * (j % 4);
1402                 return new q.init(g, a)
1403             }
1404         },
1405         u = v.Utf8 = {
1406             stringify: function(b) {
1407                 try {
1408                     return decodeURIComponent(escape(a.stringify(b)))
1409                 } catch (g) {
1410                     throw Error("Malformed UTF-8 data");
1411                 }
1412             },
1413             parse: function(b) {
1414                 return a.parse(unescape(encodeURIComponent(b)))
1415             }
1416         },
1417         g = l.BufferedBlockAlgorithm = r.extend({
1418             reset: function() {
1419                 this._data = new q.init;
1420                 this._nDataBytes = 0
1421             },
1422             _append: function(b) {
1423                 "string" == typeof b && (b = u.parse(b));
1424                 this._data.concat(b);
1425                 this._nDataBytes += b.sigBytes
1426             },
1427             _process: function(b) {
1428                 var a = this._data,
1429                     g = a.words,
1430                     j = a.sigBytes,
1431                     k = this.blockSize,
1432                     m = j / (4 * k),
1433                     m = b ? s.ceil(m) : s.max((m | 0) - this._minBufferSize, 0);
1434                 b = m * k;
1435                 j = s.min(4 * b, j);
1436                 if (b) {
1437                     for (var l = 0; l < b; l += k) this._doProcessBlock(g, l);
1438                     l = g.splice(0, b);
1439                     a.sigBytes -= j
1440                 }
1441                 return new q.init(l, j)
1442             },
1443             clone: function() {
1444                 var b = r.clone.call(this);
1445                 b._data = this._data.clone();
1446                 return b
1447             },
1448             _minBufferSize: 0
1449         });
1450     l.Hasher = g.extend({
1451         cfg: r.extend(),
1452         init: function(b) {
1453             this.cfg = this.cfg.extend(b);
1454             this.reset()
1455         },
1456         reset: function() {
1457             g.reset.call(this);
1458             this._doReset()
1459         },
1460         update: function(b) {
1461             this._append(b);
1462             this._process();
1463             return this
1464         },
1465         finalize: function(b) {
1466             b && this._append(b);
1467             return this._doFinalize()
1468         },
1469         blockSize: 16,
1470         _createHelper: function(b) {
1471             return function(a, g) {
1472                 return (new b.init(g)).finalize(a)
1473             }
1474         },
1475         _createHmacHelper: function(b) {
1476             return function(a, g) {
1477                 return (new k.HMAC.init(b, g)).finalize(a)
1478             }
1479         }
1480     });
1481     var k = m.algo = {};
1482     return m
1483 }(Math);
1484 (function(s) {
1485     function p(a, k, b, h, l, j, m) {
1486         a = a + (k & b | ~k & h) + l + m;
1487         return (a << j | a >>> 32 - j) + k
1488     }
1489
1490     function m(a, k, b, h, l, j, m) {
1491         a = a + (k & h | b & ~h) + l + m;
1492         return (a << j | a >>> 32 - j) + k
1493     }
1494
1495     function l(a, k, b, h, l, j, m) {
1496         a = a + (k ^ b ^ h) + l + m;
1497         return (a << j | a >>> 32 - j) + k
1498     }
1499
1500     function n(a, k, b, h, l, j, m) {
1501         a = a + (b ^ (k | ~h)) + l + m;
1502         return (a << j | a >>> 32 - j) + k
1503     }
1504     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;
1505     q = q.MD5 = t.extend({
1506         _doReset: function() {
1507             this._hash = new v.init([1422584193, 4023233417, 2562383102, 271423878])
1508         },
1509         _doProcessBlock: function(g, k) {
1510             for (var b = 0; 16 > b; b++) {
1511                 var h = k + b,
1512                     w = g[h];
1513                 g[h] = (w << 8 | w >>> 24) & 16711935 | (w << 24 | w >>> 8) & 4278255360
1514             }
1515             var b = this._hash.words,
1516                 h = g[k + 0],
1517                 w = g[k + 1],
1518                 j = g[k + 2],
1519                 q = g[k + 3],
1520                 r = g[k + 4],
1521                 s = g[k + 5],
1522                 t = g[k + 6],
1523                 u = g[k + 7],
1524                 v = g[k + 8],
1525                 x = g[k + 9],
1526                 y = g[k + 10],
1527                 z = g[k + 11],
1528                 A = g[k + 12],
1529                 B = g[k + 13],
1530                 C = g[k + 14],
1531                 D = g[k + 15],
1532                 c = b[0],
1533                 d = b[1],
1534                 e = b[2],
1535                 f = b[3],
1536                 c = p(c, d, e, f, h, 7, a[0]),
1537                 f = p(f, c, d, e, w, 12, a[1]),
1538                 e = p(e, f, c, d, j, 17, a[2]),
1539                 d = p(d, e, f, c, q, 22, a[3]),
1540                 c = p(c, d, e, f, r, 7, a[4]),
1541                 f = p(f, c, d, e, s, 12, a[5]),
1542                 e = p(e, f, c, d, t, 17, a[6]),
1543                 d = p(d, e, f, c, u, 22, a[7]),
1544                 c = p(c, d, e, f, v, 7, a[8]),
1545                 f = p(f, c, d, e, x, 12, a[9]),
1546                 e = p(e, f, c, d, y, 17, a[10]),
1547                 d = p(d, e, f, c, z, 22, a[11]),
1548                 c = p(c, d, e, f, A, 7, a[12]),
1549                 f = p(f, c, d, e, B, 12, a[13]),
1550                 e = p(e, f, c, d, C, 17, a[14]),
1551                 d = p(d, e, f, c, D, 22, a[15]),
1552                 c = m(c, d, e, f, w, 5, a[16]),
1553                 f = m(f, c, d, e, t, 9, a[17]),
1554                 e = m(e, f, c, d, z, 14, a[18]),
1555                 d = m(d, e, f, c, h, 20, a[19]),
1556                 c = m(c, d, e, f, s, 5, a[20]),
1557                 f = m(f, c, d, e, y, 9, a[21]),
1558                 e = m(e, f, c, d, D, 14, a[22]),
1559                 d = m(d, e, f, c, r, 20, a[23]),
1560                 c = m(c, d, e, f, x, 5, a[24]),
1561                 f = m(f, c, d, e, C, 9, a[25]),
1562                 e = m(e, f, c, d, q, 14, a[26]),
1563                 d = m(d, e, f, c, v, 20, a[27]),
1564                 c = m(c, d, e, f, B, 5, a[28]),
1565                 f = m(f, c, d, e, j, 9, a[29]),
1566                 e = m(e, f, c, d, u, 14, a[30]),
1567                 d = m(d, e, f, c, A, 20, a[31]),
1568                 c = l(c, d, e, f, s, 4, a[32]),
1569                 f = l(f, c, d, e, v, 11, a[33]),
1570                 e = l(e, f, c, d, z, 16, a[34]),
1571                 d = l(d, e, f, c, C, 23, a[35]),
1572                 c = l(c, d, e, f, w, 4, a[36]),
1573                 f = l(f, c, d, e, r, 11, a[37]),
1574                 e = l(e, f, c, d, u, 16, a[38]),
1575                 d = l(d, e, f, c, y, 23, a[39]),
1576                 c = l(c, d, e, f, B, 4, a[40]),
1577                 f = l(f, c, d, e, h, 11, a[41]),
1578                 e = l(e, f, c, d, q, 16, a[42]),
1579                 d = l(d, e, f, c, t, 23, a[43]),
1580                 c = l(c, d, e, f, x, 4, a[44]),
1581                 f = l(f, c, d, e, A, 11, a[45]),
1582                 e = l(e, f, c, d, D, 16, a[46]),
1583                 d = l(d, e, f, c, j, 23, a[47]),
1584                 c = n(c, d, e, f, h, 6, a[48]),
1585                 f = n(f, c, d, e, u, 10, a[49]),
1586                 e = n(e, f, c, d, C, 15, a[50]),
1587                 d = n(d, e, f, c, s, 21, a[51]),
1588                 c = n(c, d, e, f, A, 6, a[52]),
1589                 f = n(f, c, d, e, q, 10, a[53]),
1590                 e = n(e, f, c, d, y, 15, a[54]),
1591                 d = n(d, e, f, c, w, 21, a[55]),
1592                 c = n(c, d, e, f, v, 6, a[56]),
1593                 f = n(f, c, d, e, D, 10, a[57]),
1594                 e = n(e, f, c, d, t, 15, a[58]),
1595                 d = n(d, e, f, c, B, 21, a[59]),
1596                 c = n(c, d, e, f, r, 6, a[60]),
1597                 f = n(f, c, d, e, z, 10, a[61]),
1598                 e = n(e, f, c, d, j, 15, a[62]),
1599                 d = n(d, e, f, c, x, 21, a[63]);
1600             b[0] = b[0] + c | 0;
1601             b[1] = b[1] + d | 0;
1602             b[2] = b[2] + e | 0;
1603             b[3] = b[3] + f | 0
1604         },
1605         _doFinalize: function() {
1606             var a = this._data,
1607                 k = a.words,
1608                 b = 8 * this._nDataBytes,
1609                 h = 8 * a.sigBytes;
1610             k[h >>> 5] |= 128 << 24 - h % 32;
1611             var l = s.floor(b / 4294967296);
1612             k[(h + 64 >>> 9 << 4) + 15] = (l << 8 | l >>> 24) & 16711935 | (l << 24 | l >>> 8) & 4278255360;
1613             k[(h + 64 >>> 9 << 4) + 14] = (b << 8 | b >>> 24) & 16711935 | (b << 24 | b >>> 8) & 4278255360;
1614             a.sigBytes = 4 * (k.length + 1);
1615             this._process();
1616             a = this._hash;
1617             k = a.words;
1618             for (b = 0; 4 > b; b++) h = k[b], k[b] = (h << 8 | h >>> 24) & 16711935 | (h << 24 | h >>> 8) & 4278255360;
1619             return a
1620         },
1621         clone: function() {
1622             var a = t.clone.call(this);
1623             a._hash = this._hash.clone();
1624             return a
1625         }
1626     });
1627     r.MD5 = t._createHelper(q);
1628     r.HmacMD5 = t._createHmacHelper(q)
1629 })(Math);