3 * xChatty: xCally Shuttle WebChat Client
7 * @link http://www.xcally.com
13 websiteId: {{websiteId}},
14 signedUp: {{signedUp}},
15 windowFocused: {{windowFocused}},
16 isNewPage: {{isNewPage}},
17 processingSignUp: {{processingSignUp}},
18 processingEnquiry: {{processingEnquiry}},
19 processingSend: {{processingSend}},
20 processingRating: {{processingRating}},
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}},
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}}"
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({
93 complete: function() {
94 if (xChatty.config.restoreOpenState) {
95 xChatty.config.isNewPage = true;
96 jQuery(".xc_chat_head").trigger("click");
100 xChatty.initAnimateHover();
101 jQuery(window).focus(function() {
102 xChatty.config.windowFocused = true;
104 jQuery(window).blur(function() {
105 xChatty.config.windowFocused = false;
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('');
129 }).bind('blur', function() {
130 if (jQuery(this).val() === '') {
131 jQuery(this).val(jQuery(this).attr('placeholder')).css('color', '#ccc');
134 window.onbeforeunload = xChatty.handleDocumentUnload;
135 xChatty.readMessages();
137 handleDocumentUnload: function() {
138 if (!xChatty.processingSignUp) {
140 url: xChatty.config.rootPath + xChatty.config.websiteId + "/abandon",
143 complete: function() {
150 initAnimateHover: function() {
151 if (xChatty.config.animateHover !== true)
153 jQuery(".xc_chat_container").animate({
159 jQuery(".xc_chat_container").hover(function() {
160 jQuery(this).animate({
167 if (!jQuery(this).hasClass("xc_box_open"))
168 jQuery(this).animate({
175 jQuery(".xc_chat_container").bind("chatOpen", function(e, isOpen) {
177 jQuery(this).animate({
184 jQuery(this).animate({
193 // enquiryClick: function(e) {
194 // e.preventDefault();
195 // jQuery(".xc_form_enquiry").submit();
197 btnExitChatClick: function(e) {
199 jQuery(".xc_exit_chat_confirmation_wrapper").show();
202 btnExitChatConfirmClick: function(e) {
204 clearTimeout(xChatty.config.timerReadMessages);
205 clearTimeout(xChatty.config.timerCheckStatus);
206 var formData = jQuery(this).serializeArray();
208 name: 'data[sign_out]',
212 url: xChatty.config.rootPath + xChatty.config.websiteId + "/signout",
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 = {
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();
232 complete: function() {
233 // xChatty.checkStatus(true);
237 btnExitChatCancelClick: function(e) {
239 jQuery(".xc_exit_chat_confirmation_wrapper").hide();
240 jQuery(".xc_btn_exit_chat").show();
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>');
246 resetDefaultState: function() {
247 xChatty.config.signedUp = false;
248 xChatty.config.visitor = {
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");
260 skipRatingSubmit: function (e) {
262 if (xChatty.config.processingRating)
264 xChatty.config.processingRating = true;
267 name: 'data[Rating][room_id]',
268 value: xChatty.config.roomId
271 url: xChatty.config.rootPath + "rating",
274 success: function(result) {
275 xChatty.config.processingRating = false;
276 xChatty.resetDefaultState();
278 error: function(err) {
280 'message': 'Service temporarily unavailable. We back as soon as possible!'
282 xChatty.renderErrors(error, true);
283 // xChatty.config.timerSendMessages = setTimeout(function() {
284 // xChatty.handleAjaxSubmitCall(formData, enquiryForm);
289 ratingSubmit: function (e) {
291 if (xChatty.config.processingRating)
293 xChatty.config.processingRating = true;
294 var formData = jQuery(this).serializeArray();
296 name: 'data[Rating][room_id]',
297 value: xChatty.config.roomId
300 url: xChatty.config.rootPath + "rating",
303 success: function(result) {
304 xChatty.config.processingRating = false;
305 xChatty.resetDefaultState();
307 error: function(err) {
309 'message': 'Service temporarily unavailable. We back as soon as possible!'
311 xChatty.renderErrors(error, true);
312 // xChatty.config.timerSendMessages = setTimeout(function() {
313 // xChatty.handleAjaxSubmitCall(formData, enquiryForm);
318 enquirySubmit: function(e) {
320 if (xChatty.config.processingEnquiry)
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')) {
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')];
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];
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];
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];
342 // if (validationErrors.hasOwnProperty("fullname") || validationErrors.hasOwnProperty("email") || validationErrors.hasOwnProperty("message")) {
343 // xChatty.renderNotifications(validationErrors, true);
346 if (Object.keys(validationErrors).length > 0) {
347 xChatty.renderNotifications(validationErrors,true);
350 xChatty.config.processingEnquiry = true;
351 var enquiryForm = jQuery(this);
352 enquiryForm.addClass("xc_enquiry_sending");
353 var formData = jQuery(this).serializeArray();
355 name: 'data[Enquiry][websiteId]',
356 value: xChatty.config.websiteId
359 name: 'data[Enquiry][current_page]',
360 value: encodeURIComponent(encodeURIComponent(document.URL))
362 xChatty.handleAjaxSubmitCall(formData, enquiryForm);
365 handleAjaxSubmitCall: function(formData, enquiryForm) {
367 url: xChatty.config.rootPath + "submit",
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]
379 xChatty.renderNotifications(notifications, false);
381 xChatty.renderNotifications(result.errors, true);
383 xChatty.config.processingEnquiry = false;
384 enquiryForm.removeClass("xc_enquiry_sending");
385 jQuery(".xc_chat_container input, .xc_chat_container textarea").trigger("blur");
387 error: function(err) {
389 'message': 'Service temporarily unavailable. We back as soon as possible!'
391 xChatty.renderErrors(error, true);
392 xChatty.config.timerSendMessages = setTimeout(function() {
393 xChatty.handleAjaxSubmitCall(formData, enquiryForm);
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"))
404 if (xChatty.config.processingSend)
406 var messageForm = jQuery(this);
407 messageForm.addClass("xc_message_sending");
408 xChatty.config.processingSend = true;
409 var formData = jQuery(".xc_form_reply").serializeArray();
411 name: 'data[Message][current_page]',
412 value: encodeURIComponent(encodeURIComponent(document.URL))
415 name: 'data[last_id]',
416 value: xChatty.getMaxId()
419 name: 'data[is_new_page]',
420 value: xChatty.config.isNewPage
422 xChatty.config.isNewPage = false;
423 jQuery(".xc_input_message").val("");
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, {
433 xChatty.scrollBottom(false);
434 xChatty.handleAjaxSendCall(formData, tmpMessage, messageForm);
437 handleAjaxSendCall: function(formData, tmpMessage, messageForm) {
439 url: xChatty.config.rootPath + xChatty.config.websiteId + "/send",
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]);
452 if (result.messages.length > 0)
453 xChatty.scrollBottom(true);
454 xChatty.config.processingSend = false;
455 messageForm.removeClass("xc_message_sending");
457 jQuery("[data-id=" + tmpMessage.id + "]").css('border', '1px dashed #f00');
460 error: function(err) {
462 'message': 'Service temporarily unavailable. We back as soon as possible!'
464 xChatty.renderErrors(error, true);
465 xChatty.config.timerSendMessages = setTimeout(function() {
466 xChatty.handleAjaxSendCall(formData, tmpMessage, messageForm);
471 headerClick: function(e) {
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();
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();
485 jQuery(".xc_enquiry_wrapper").show();
486 jQuery(".xc_signup_wrapper").hide();
487 jQuery(".xc_conversation").hide();
490 jQuery(".xc_enquiry_wrapper").hide();
491 jQuery(".xc_signup_wrapper").hide();
492 jQuery(".xc_conversation").show();
494 var wasClosed = jQuery(".xc_chat_toggle_container").is(":visible");
495 jQuery(".xc_chat_toggle_container").slideToggle("fast", function() {
496 xChatty.scrollBottom(true);
498 jQuery(".xc_chat_container").addClass("xc_box_open");
499 jQuery(".xc_chat_container").trigger("chatOpen", true);
503 jQuery(".xc_chat_container").addClass("xc_chat_closing");
504 jQuery(".xc_chat_container").animate({
509 complete: function() {
510 jQuery(".xc_chat_container").animate({
515 complete: function() {}
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);
523 jQuery(".xc_input_message").focus();
525 if (e.originalEvent !== undefined) {
526 xChatty.readMessages();
528 xChatty.checkStatus(true);
530 // signUpClick: function(e) {
531 // e.preventDefault();
532 // jQuery(".xc_form_signup").submit();
534 signUpSubmit: function(e) {
536 if (xChatty.config.processingSignUp)
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')) {
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')];
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];
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];
556 // if (validationErrors.hasOwnProperty("fullname") || validationErrors.hasOwnProperty("email")) {
557 // xChatty.renderNotifications(validationErrors, true);
560 if (Object.keys(validationErrors).length > 0) {
561 xChatty.renderNotifications(validationErrors,true);
562 xChatty.config.processingSignUp = false;
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();
570 name: 'chatWebsiteId' ,
571 value: xChatty.config.websiteId
573 if (xChatty.config.hideEmail) {
575 name: 'data[Discussion][email]',
576 value: 'not.provided@example.com'
580 url: xChatty.config.rootPath + xChatty.config.websiteId + "/signup",
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();
597 // xChatty.handleNoAgentResponse();
599 // xChatty.readMessages();
600 // jQuery(".xc_signup_wrapper").hide();
601 // jQuery(".xc_conversation").show();
602 // xChatty.scrollBottom(false);
604 xChatty.renderNotifications(result.errors, true);
607 error: function(err) {
608 xChatty.config.processingSignUp = false;
610 'message': 'Service temporarily unavailable. We back as soon as possible!'
612 xChatty.renderErrors(error, true);
614 complete: function() {
615 // xChatty.config.processingSignUp = false;
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);
627 jQuery(".xc_chat_head-title").html(xChatty.Lang.HeaderOffline);
629 handleSnippetOpen: function () {
630 if (!jQuery(".xc_chat_toggle_container").is(":visible")) {
631 jQuery(".xc_chat_head").trigger("click");
634 getProactiveActions: function () {
636 url: xChatty.config.rootPath + xChatty.config.websiteId + '/proactive',
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) {
646 if (proAction.hasOwnProperty('selector') && proAction.selector) {
647 jQuery(document).on("mouseover", proAction.selector, xChatty.handleSnippetOpen);
651 if (proAction.hasOwnProperty('timeout') && proAction.timeout > 0) {
652 setTimeout(function () {
653 xChatty.handleSnippetOpen();
654 }, proAction.timeout * 1000);
658 console.log('Event type not supported');
666 getHTMLTemplate: function() {
668 url: xChatty.config.rootPath + xChatty.config.websiteId + '/html',
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]);
676 jQuery('body').append(data);
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);
686 if(xChatty.config.downloadTranscript) {
687 jQuery(".xc_download_transcript_container").show();
689 jQuery(".xc_download_transcript_container").hide();
691 xChatty.getProactiveActions();
692 xChatty.checkStatus();
696 checkStatus: function(async) {
697 clearTimeout(xChatty.config.timerCheckStatus);
699 if (xChatty.config.isInitialStatusCheck)
701 name: 'data[referer]',
702 value: encodeURIComponent(encodeURIComponent(document.referrer))
706 name: 'data[open_state]',
707 value: (jQuery(".xc_chat_toggle_container").is(":visible") && !jQuery(".xc_chat_container").hasClass("xc_chat_closing"))
710 url: xChatty.config.rootPath + xChatty.config.websiteId + "/status",
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();
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;
736 if (result.success && result.signed_up === false && xChatty.config.signedUp) {
737 xChatty.resetDefaultState();
739 if (xChatty.config.isOnline) {
740 jQuery(".xc_chat_container").addClass("xc_state_online").removeClass("xc_state_offline").fadeIn();
742 jQuery(".xc_chat_container").removeClass("xc_state_online").addClass("xc_state_offline");
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();
750 jQuery(".xc_enquiry_wrapper").show();
751 jQuery(".xc_signup_wrapper").hide();
752 jQuery(".xc_conversation").hide();
755 if (xChatty.config.isOnline) {
756 xChatty.clearNotifications();
758 var notifications = {
759 offline: [xChatty.Lang.OperatorOfflineMessage]
761 xChatty.renderNotifications(notifications, true);
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();
770 if (result.open_state === true) {
771 xChatty.config.restoreOpenState = true;
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();
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();
787 if (!wasSignedUp && xChatty.config.processingSignUp && result.is_unserved) {
788 xChatty.config.processingSignUp = false;
790 'message': xChatty.Lang.MessageAgentsBusy
792 xChatty.renderErrors(error, true);
793 xChatty.setHeaderText();
794 xChatty.disableSignUpForm('xc_form_signup',false);
797 jQuery('.xc_rating_wrapper').hide();
798 jQuery('.xc_form_rating')[0].reset();
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);
809 error: function(err) {
811 'message': 'Service temporarily unavailable. We back as soon as possible!'
813 xChatty.renderErrors(error, true);
815 complete: function() {
816 xChatty.setHeaderText();
817 var duration = xChatty.calculateStatusTimeOutDuration();
818 xChatty.config.timerCheckStatus = setTimeout(function() {
819 xChatty.checkStatus(true);
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("");
833 timerNotifications: null,
834 renderNotifications: function(errorMessages, isError) {
836 jQuery(".xc_notifications_wrapper").removeClass("xc_notification_success");
837 jQuery(".xc_notifications_wrapper").addClass("xc_notification_error");
839 jQuery(".xc_notifications_wrapper").addClass("xc_notification_success");
840 jQuery(".xc_notifications_wrapper").removeClass("xc_notification_error");
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>"));
847 jQuery(".xc_notifications_wrapper").slideDown();
848 clearTimeout(xChatty.timerNotifications);
849 xChatty.timerNotifications = setTimeout(function() {
850 jQuery(".xc_notifications_wrapper").slideUp();
853 renderErrors: function(error, isError) {
855 jQuery(".xc_notifications_wrapper").removeClass("xc_notification_success");
856 jQuery(".xc_notifications_wrapper").addClass("xc_notification_error");
858 jQuery(".xc_notifications_wrapper").addClass("xc_notification_success");
859 jQuery(".xc_notifications_wrapper").removeClass("xc_notification_error");
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();
869 clearNotifications: function() {
870 jQuery(".xc_notifications_wrapper").hide();
871 jQuery(".xc_notifications_wrapper ul.xc_errorlist").html("");
873 btnNotificationsCloseClick: function(e) {
875 jQuery(".xc_notifications_wrapper").slideUp();
877 messageKeyUp: function(e) {
880 if (e.keyCode === 13 && !jQuery(this).hasClass("xc_input_enquiry_message")) {
881 jQuery(this).parents('form').submit();
884 messageKeyDownWait: false,
885 messageKeyDown: function(e) {
886 if (xChatty.messageKeyDownWait === true) {
889 xChatty.messageKeyDownWait = true;
890 setTimeout(function() {
891 xChatty.messageKeyDownWait = false;
895 // url: xChatty.config.rootPath + "discussions/composing",
896 // dataType: "jsonp",
897 // jsonpCallback: xChatty.getJsonpCallbackName(),
898 // success: function(result) {},
899 // complete: function() {}
902 sendClick: function(e) {
904 jQuery('form.xc_form_reply').submit();
906 addMessageToChat: function(message, options) {
907 var isConfirmed = "";
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) {
915 fullname = message.User.fullname;
917 if (message.ChatVisitor) {
918 fullname = message.ChatVisitor.fullname;
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"));
934 }).appendTo('.xc_conversation_container');
937 prepareMessageText: function(text) {
940 s: [' :-D ', ' :D '],
944 s: [' :-S ', ' :S '],
952 s: [' ;-( ', ' ;( '],
980 s: [' :-| ', ' :| '],
988 s: [' :-P ', ' :P '],
1000 s: [' :-( ', ' :( '],
1004 s: [' :-) ', ' :) '],
1008 s: [' :-O ', ' :O '],
1024 s: [' ;-) ', ' ;) '],
1028 text = " " + text + " ";
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);
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");
1045 jQuery(this).addClass("xc_link_internal");
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 />');
1052 escapeRegExp: function(str) {
1053 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
1055 loadMore: function() {
1056 xChatty.readMessages(true);
1058 readMessages: function(loadMore) {
1060 // clearTimeout(xChatty.config.timerReadMessages);
1061 if (!xChatty.config.signedUp) {
1064 if (xChatty.config.isNewPage) {}
1065 var requestData = [];
1066 if (loadMore === true) {
1068 name: 'data[first_id]',
1069 value: xChatty.getMinId()
1072 name: 'data[load_more]',
1077 name: 'data[last_id]',
1078 value: xChatty.getMaxId()
1081 name: 'data[is_new_page]',
1082 value: xChatty.config.isNewPage
1087 url: xChatty.config.rootPath + xChatty.config.websiteId + "/read",
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]);
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);
1103 if (result.composing === true && result.messages.length === 0) {
1104 jQuery(".xc_composing_container").html(xChatty.Lang.OperatorComposing.replace("{fullname}", result.composing_fullname)).slideDown();
1106 jQuery(".xc_composing_container").slideUp();
1108 if (result.messages.length > 0) {
1109 jQuery(".xc_composing_container").slideUp();
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({
1121 jQuery(".xc_chat_container").animate({
1123 }, 100, function() {
1124 jQuery(this).animate({
1126 }, 100, function() {
1127 jQuery(this).animate({
1129 }, 100, function() {
1130 jQuery(this).animate({
1132 }, 200, function() {});
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');
1141 } else if (loadMore) {
1142 xChatty.scrollToElement(scrollToElem);
1144 if (result.messages.length === 0)
1145 xChatty.config.decayHistory++;
1147 xChatty.config.decayHistory = 0;
1148 // var duration = xChatty.calculateTimeOutDuration();
1150 // xChatty.config.timerReadMessages = setTimeout(function() {
1151 // xChatty.readMessages(false);
1154 } else if (result.success === false) {
1155 xChatty.checkStatus(true);
1157 xChatty.config.isNewPage = false;
1159 error: function(err) {
1161 'message': 'Service temporarily unavailable. We back as soon as possible!'
1163 xChatty.renderErrors(error, true);
1165 complete: function() {
1166 var duration = xChatty.calculateTimeOutDuration();
1168 xChatty.config.timerReadMessages = setTimeout(function() {
1169 xChatty.readMessages(false);
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;
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');
1186 calculateTimeOutDuration: function() {
1187 if (!jQuery(".xc_conversation_container").is(":visible"))
1189 var calcTimeOut = (parseFloat(xChatty.config.decayHistory / 10) * 1000);
1190 if (calcTimeOut > 10000)
1192 if (calcTimeOut > xChatty.config.defaultTimeout) {
1195 return xChatty.config.defaultTimeout;
1197 calculateStatusTimeOutDuration: function() {
1198 if (jQuery(".xc_signup_wrapper").is(":visible") && xChatty.config.processingSignUp)
1199 return xChatty.config.defaultTimeout;
1202 getMaxId: function() {
1203 if (jQuery(".xc_chatrow").length === 0)
1205 var numbers = jQuery(".xc_chatrow").map(function() {
1206 return parseFloat(this.getAttribute('data-id')) || -Infinity;
1208 return Math.max.apply(Math, numbers);
1210 getMinId: function() {
1211 if (jQuery(".xc_chatrow").length === 0)
1213 var numbers = jQuery(".xc_chatrow").map(function() {
1214 return parseFloat(this.getAttribute('data-id')) || -Infinity;
1216 return Math.min.apply(Math, numbers);
1218 scrollBottom: function(animate) {
1220 jQuery(".xc_conversation_container").scrollTop(jQuery(".xc_conversation_container")[0].scrollHeight);
1222 jQuery(".xc_conversation_container").animate({
1223 scrollTop: jQuery(".xc_conversation_container")[0].scrollHeight
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({
1232 disableSignUpForm: function(form, enable)Â {
1233 jQuery("." + form + " :input").attr("disabled", enable);
1234 jQuery("." + form + " :button").prop("disabled", enable);
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 = {
1244 'Firefox': isFirefox,
1249 return browserValue[test];
1251 testStyle: function(property) {
1252 return property in document.documentElement.style;
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));
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;
1271 script.onload = function() {
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);
1281 if (typeof jQuery == 'undefined') {
1282 xcLoadJS(function() {
1284 jQuery(document).ready(function() {
1285 xChatty.getHTMLTemplate();
1291 jQuery(document).ready(function() {
1292 xChatty.getHTMLTemplate();
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.
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
1309 var CryptoJS = CryptoJS || function(s, p) {
1314 extend: function(b) {
1318 h.hasOwnProperty("init") || (h.init = function() {
1319 h.$super.init.apply(this, arguments)
1321 h.init.prototype = h;
1325 create: function() {
1326 var b = this.extend();
1327 b.init.apply(b, arguments);
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)
1336 return this.init.prototype.extend(this)
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
1344 toString: function(b) {
1345 return (b || t).stringify(this)
1347 concat: function(b) {
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);
1364 b[h >>> 2] &= 4294967295 << 32 - 8 * (h % 4);
1365 b.length = s.ceil(h / 4)
1368 var b = r.clone.call(this);
1369 b.words = this.words.slice(0);
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)
1379 stringify: function(b) {
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))
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)
1395 stringify: function(b) {
1398 for (var g = [], j = 0; j < b; j++) g.push(String.fromCharCode(a[j >>> 2] >>> 24 - 8 * (j % 4) & 255));
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)
1407 stringify: function(b) {
1409 return decodeURIComponent(escape(a.stringify(b)))
1411 throw Error("Malformed UTF-8 data");
1414 parse: function(b) {
1415 return a.parse(unescape(encodeURIComponent(b)))
1418 g = l.BufferedBlockAlgorithm = r.extend({
1420 this._data = new q.init;
1421 this._nDataBytes = 0
1423 _append: function(b) {
1424 "string" == typeof b && (b = u.parse(b));
1425 this._data.concat(b);
1426 this._nDataBytes += b.sigBytes
1428 _process: function(b) {
1434 m = b ? s.ceil(m) : s.max((m | 0) - this._minBufferSize, 0);
1436 j = s.min(4 * b, j);
1438 for (var l = 0; l < b; l += k) this._doProcessBlock(g, l);
1442 return new q.init(l, j)
1445 var b = r.clone.call(this);
1446 b._data = this._data.clone();
1451 l.Hasher = g.extend({
1454 this.cfg = this.cfg.extend(b);
1461 update: function(b) {
1466 finalize: function(b) {
1467 b && this._append(b);
1468 return this._doFinalize()
1471 _createHelper: function(b) {
1472 return function(a, g) {
1473 return (new b.init(g)).finalize(a)
1476 _createHmacHelper: function(b) {
1477 return function(a, g) {
1478 return (new k.HMAC.init(b, g)).finalize(a)
1482 var k = m.algo = {};
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
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
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
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
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])
1510 _doProcessBlock: function(g, k) {
1511 for (var b = 0; 16 > b; b++) {
1514 g[h] = (w << 8 | w >>> 24) & 16711935 | (w << 24 | w >>> 8) & 4278255360
1516 var b = this._hash.words,
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;
1606 _doFinalize: function() {
1609 b = 8 * this._nDataBytes,
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);
1619 for (b = 0; 4 > b; b++) h = k[b], k[b] = (h << 8 | h >>> 24) & 16711935 | (h << 24 | h >>> 8) & 4278255360;
1623 var a = t.clone.call(this);
1624 a._hash = this._hash.clone();
1628 r.MD5 = t._createHelper(q);
1629 r.HmacMD5 = t._createHmacHelper(q)