diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index d4aac5b0ae..d1a60b5683 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -192,9 +192,8 @@ class CourseFields(object): }}, scope=Scope.content) show_calculator = Boolean(help="Whether to show the calculator in this course", default=False, scope=Scope.settings) - display_name = String( - help="Display name for this module", default="Empty", - display_name="Display Name", scope=Scope.settings) + display_name = String(help="Display name for this module", default="Empty", display_name="Display Name", scope=Scope.settings) + show_chat = Boolean(help="Whether to show the chat widget in this course", default=False, scope=Scope.settings) tabs = List(help="List of tabs to enable in this course", scope=Scope.settings) end_of_course_survey_url = String(help="Url for the end-of-course survey", scope=Scope.settings) discussion_blackouts = List(help="List of pairs of start/end dates for discussion blackouts", scope=Scope.settings) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index a5efe744a8..07be74c98e 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -6,6 +6,7 @@ from django.http import Http404 from django.test.utils import override_settings from django.contrib.auth.models import User from django.test.client import RequestFactory +from django.conf import settings from student.models import CourseEnrollment from xmodule.modulestore.django import modulestore @@ -124,3 +125,26 @@ class ViewsTestCase(TestCase): self.assertContains(result, expected_end_text) else: self.assertNotContains(result, "Classes End") + + def test_chat_settings(self): + mock_user = MagicMock() + mock_user.username = "johndoe" + + mock_course = MagicMock() + mock_course.id = "a/b/c" + + # Stub this out in the case that it's not in the settings + domain = "jabber.edx.org" + settings.JABBER_DOMAIN = domain + + chat_settings = views.chat_settings(mock_course, mock_user) + + # Test the proper format of all chat settings + self.assertEquals(chat_settings['domain'], domain) + self.assertEquals(chat_settings['room'], "a-b-c_class") + self.assertEquals(chat_settings['username'], "johndoe@%s" % domain) + + # TODO: this needs to be changed once we figure out how to + # generate/store a real password. + self.assertEquals(chat_settings['password'], "johndoe@%s" % domain) + diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index e6e062c494..f1e1f7660c 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -40,7 +40,6 @@ log = logging.getLogger("mitx.courseware") template_imports = {'urllib': urllib} - def user_groups(user): """ TODO (vshnayder): This is not used. When we have a new plan for groups, adjust appropriately. @@ -236,6 +235,36 @@ def update_timelimit_module(user, course_id, model_data_cache, timelimit_descrip return context +def chat_settings(course, user): + """ + Returns a dict containing the settings required to connect to a + Jabber chat server and room. + """ + domain = getattr(settings, "JABBER_DOMAIN", None) + if domain is None: + log.warning('You must set JABBER_DOMAIN in the settings to ' + 'enable the chat widget') + return None + + return { + 'domain': domain, + + # Jabber doesn't like slashes, so replace with dashes + 'room': "{ID}_class".format(ID=course.id.replace('/', '-')), + + 'username': "{USER}@{DOMAIN}".format( + USER=user.username, DOMAIN=domain + ), + + # TODO: clearly this needs to be something other than the username + # should also be something that's not necessarily tied to a + # particular course + 'password': "{USER}@{DOMAIN}".format( + USER=user.username, DOMAIN=domain + ), + } + + @login_required @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) @@ -300,6 +329,18 @@ def index(request, course_id, chapter=None, section=None, 'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://xqa:server@content-qa.mitx.mit.edu/xqa') } + # Only show the chat if it's enabled by the course and in the + # settings. + show_chat = course.show_chat and settings.MITX_FEATURES['ENABLE_CHAT'] + if show_chat: + context['chat'] = chat_settings(course, user) + # If we couldn't load the chat settings, then don't show + # the widget in the courseware. + if context['chat'] is None: + show_chat = False + + context['show_chat'] = show_chat + chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter) if chapter_descriptor is not None: save_child_position(course_module, chapter) diff --git a/lms/envs/common.py b/lms/envs/common.py index 0859dbc3f2..7dee15a8c8 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -144,6 +144,10 @@ MITX_FEATURES = { # Allow use of the hint managment instructor view. 'ENABLE_HINTER_INSTRUCTOR_VIEW': False, + + # Toggle to enable chat availability (configured on a per-course + # basis in Studio) + 'ENABLE_CHAT': False } # Used for A/B testing diff --git a/lms/static/candy_res/audioplayer.swf b/lms/static/candy_res/audioplayer.swf new file mode 100644 index 0000000000..72390d4157 Binary files /dev/null and b/lms/static/candy_res/audioplayer.swf differ diff --git a/lms/static/candy_res/candy_full.css b/lms/static/candy_res/candy_full.css new file mode 100644 index 0000000000..c934881754 --- /dev/null +++ b/lms/static/candy_res/candy_full.css @@ -0,0 +1,606 @@ +/** + * Chat CSS + * + * @author Michael + * @author Patrick + * @copyright 2011 Amiado Group AG, All rights reserved. + */ +html, body { + margin: 0; + padding: 0; + font-family: Arial, Helvetica, sans-serif; +} + +#candy { + margin: 0; + padding: 0; + position: absolute; + top: 0; + bottom: 0; + right: 0; + width: 100%; + background-color: #bdb7a1; + color: #333; + overflow: hidden; + border: 1px solid #bdb7a1; + border-top-right-radius: 10px; + box-sizing: border-box; +} +#candy.poppedOut { + border-top-left-radius: 0 !important; +} + +#chatPopin { + position: absolute; + bottom: 5px; + right: 5px; + font-size: 24px; + height: 18px !important; + width: 22px; + color: #666; +} +#chatPopin:hover { + color: #333; + text-decoration: none; +} + +a { + color: #333; + text-decoration: none; +} +ul { + list-style: none; + padding: 0; + margin: 0; +} + +#chat-tabs { + margin: 0 0 0 28px; + padding: 0; + overflow: auto; + border-left: 1px solid #bdb7a1; +} + +#chat-pane.collapsed-message-pane #chat-tabs { + height: 100%; + width: 29px; + border-left: 0; + margin: 30px 0 0 0; +} + +#chat-tabs #chat-expand-arrow { + position: absolute; + top: 0; + left: 0; + width: 27px; + height: 15px; + padding: 5px 0; + cursor: pointer; +} +#chat-tabs #chat-expand-arrow em { + font-size: 18px; + padding: 0 10px; +} + +#chat-tabs li { + margin: 0; + float: left; + position: relative; + white-space: nowrap; +} + +#chat-tabs li a { + background-color: #e9e6df; + padding: 6px 20px 4px 1px; + display: inline-block; + color: #999; + height: 19px; + font-size: 22px; + -webkit-font-smoothing: antialiased; +} + +#chat-tabs li a.label { + border-right: 1px solid #bdb7a1; + border-bottom: 1px solid #bdb7a1; +} + +#chat-pane.collapsed-message-pane #chat-tabs li a.label { + border-bottom: 0; + margin-bottom: 1px; +} + +#chat-tabs li.active a { + color: #333; + font-weight: bold; +} + +#chat-tabs li.active a.label { + border-bottom: 1px solid white; + background-color: white; +} + +#chat-tabs li a.transition { + display: none; /* JRBL */ +} + +#chat-tabs li a.close { + background-color: transparent; + position: absolute; + top: 2px; + right: 7px; + height: auto; + padding: 0; + margin: 0; + color: #999; +} +#chat-tabs li a.close:hover, #chat-tabs li.active a.close:hover { + color: #333; +} + +#chat-tabs li .unread { + color: white; + background-color: #8C1515; + padding: 1px 2px; + font-weight: normal; + font-size: 10px; + position: absolute; + top: 12px; + right: 30px; + border-radius: 5px; +} + +#chat-tabs li.offline a.label { + text-decoration: line-through; +} + +#chat-toolbar { + /* + position: fixed; + bottom: 0; + right: 0; + font-size: 11px; + color: #666; + width: 200px; + height: 24px; + padding-top: 7px; + border-top: 1px solid #e9e6df; + background-color: #d3cec0; + */ + display: none !important; +} +#chat-toolbar li { + width: 16px; + height: 16px; + margin-left: 5px; + float: left; + display: inline-block; + cursor: pointer; + background-position: top left; + background-repeat: no-repeat; +} +#chat-toolbar #emoticons-icon { + background-image: url(img/action/emoticons.png); +} +#chat-toolbar .context { + background-image: url(img/action/settings.png); + display: none; +} +.role-moderator #chat-toolbar .context, .affiliation-owner #chat-toolbar .context { + display: inline-block; +} +#chat-sound-control { + background-image: url(img/action/sound-off.png); +} +#chat-sound-control.checked { + background-image: url(img/action/sound-on.png); +} +#chat-autoscroll-control { + background-image: url(img/action/autoscroll-off.png); +} +#chat-autoscroll-control.checked { + background-image: url(img/action/autoscroll-on.png); +} +#chat-statusmessage-control { + background: url(img/action/statusmessage-off.png); +} +#chat-statusmessage-control.checked { + background: url(img/action/statusmessage-on.png); +} +#chat-toolbar .usercount { + background-image: url(img/action/usercount.png); + cursor: default; + padding-left: 20px; + width: auto; + margin-right: 5px; + float: right; +} +.usercount span { + display: inline-block; + padding: 1px 3px; + background-color: #ccc; + font-weight: bold; + border-radius: 3px; +} + +.room-pane { + /* display: none; */ +} +.roster-pane { + position: absolute; + overflow: auto; + top: 30px; + right: 0; + bottom: 30px; + width: 198px; + margin: 0; +} +.roster-pane .user { + cursor: pointer; + width: 90%; + padding: 6px 5%; + font-size: 14px; + margin: 0; + /* display: none; */ + color: #666; + float: left; + clear: both; + height: 17px; + background-color: #d3cec0; + border-bottom: 1px solid #bdb7a1; +} +.roster-pane .user.me { + font-weight: bold; + cursor: default; +} +.roster-pane .user:hover, +.roster-pane .user.me:hover { + background-color: #e9e6df; +} +.roster-pane .user.status-ignored { + cursor: default; + color: #999; + opacity: .5 !important; +} +.roster-pane .label { + float: left; + width: 125px; + overflow: hidden; + white-space: nowrap; +} +.roster-pane li { + width: 16px; + height: 16px; + float: right; + display: block; + margin-left: 3px; + background-repeat: no-repeat; + background-position: center; +} +.roster-pane li.role { + cursor: default; + display: none; +} +.roster-pane li.role-moderator { + background-image: url(img/roster/role-moderator.png); + display: block; +} +.roster-pane li.affiliation-owner { + background-image: url(img/roster/affiliation-owner.png); + display: block; +} +.roster-pane li.ignore { + background-image: url(img/roster/ignore.png); + display: none; +} +.roster-pane .status-ignored li.ignore { + display: block; +} +.roster-pane .me li.context { + display: none; +} +.roster-pane li.context { + background-image: url(img/action/menu.png); + cursor: pointer; +} +.roster-pane li.context:hover { + background-color: #ccc; + border-radius: 4px; +} + +.message-pane-wrapper { + clear: both; + overflow: auto; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: auto; + width: auto; + margin: 30px 199px 32px 0; + background-color: white; + font-size: 13px; +} +.message-pane { + margin: 0; + padding: 5px 10px 2px 10px; +} +.message-pane dt { + width: 55px; + float: left; + color: #888; + font-size: 10px; + text-align: right; + padding-top: 4px; +} + +.message-pane dd { + overflow: auto; + padding: 2px 0 1px 100px; + margin: 0 0 2px 0; + white-space: -o-pre-wrap; /* Opera */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +.message-pane dd .label { + font-weight: bold; + white-space: nowrap; + display: block; + margin-left: -90px; + width: 90px; + float: left; + overflow: hidden; +} + +.message-pane .subject { + color: #a00; + font-weight: bold; +} + +.message-pane .adminmessage { + color: #a00; + font-weight: bold; +} + +.message-pane .infomessage { + color: #888; + font-style: italic; + padding-left: 5px; +} + +.message-pane .emoticon { + vertical-align: text-bottom; + height: 15px; + width: 15px; +} + +.message-form-wrapper { + position: absolute; + bottom: 1px; + left: 0; + right: 0; + width: auto; + margin-right: 199px; + background-color: #e9e6df; + height: 30px; +} + +.message-form { + position: absolute; + bottom: 1px; + left: 0; + right: 0; + margin: 0 199px 0 0; + padding: 0; + height: 30px; +} + +.message-form input { + border: 0 none; + font-size: 14px; + width: 100%; + height: 100%; + display: block; + outline-width: 0; + padding: 0 50px 0 5px; + background-color: transparent; +} +.message-form input:focus { + background-color: white; +} + +.message-form input.submit { + cursor: pointer; + background-color: #333; + color: #e9e6df; + position: absolute; + bottom: 0; + right: 0; + margin: 3px; + padding: 5px; + width: 40px; + font-size: 12px; + line-height: 12px; + height: 24px; + font-weight: bold; +} + +#tooltip { + position: absolute; + z-index: 10; + display: none; + margin: 18px -18px 2px -2px; + color: white; + font-size: 11px; + padding: 5px 0; + background: url(img/tooltip-arrows.gif) no-repeat left bottom; +} + +#tooltip div { + background-color: black; + padding: 2px 5px; + zoom: 1; +} + +#context-menu { + position: absolute; + z-index: 10; + display: none; + padding: 15px 10px; + margin: 8px -28px -8px -12px; + background: url(img/context-arrows.gif) no-repeat left bottom; +} + +#context-menu ul { + background-color: black; + color: white; + font-size: 12px; + padding: 2px; + zoom: 1; +} + +#context-menu li { + padding: 3px 5px 3px 20px; + line-height: 12px; + cursor: pointer; + margin-bottom: 2px; + background: 1px no-repeat; + white-space: nowrap; +} + +#context-menu li:hover { + background-color: #666; +} + +#context-menu li:last-child { + margin-bottom: 0; +} + +#context-menu .private { + background-image: url(img/action/private.png); +} + +#context-menu .ignore { + background-image: url(img/action/ignore.png); +} + +#context-menu .unignore { + background-image: url(img/action/unignore.png); +} + +#context-menu .kick { + background-image: url(img/action/kick.png); +} + +#context-menu .ban { + background-image: url(img/action/ban.png); +} + +#context-menu .subject { + background-image: url(img/action/subject.png); +} + +#context-menu .emoticons { + padding-left: 5px; + width: 85px; + white-space: normal; +} + +#context-menu .emoticons:hover { + background-color: transparent; +} + +#context-menu .emoticons img { + cursor: pointer; + margin: 3px; + height: 15px; + width: 15px; +} + +#chat-modal { + background: url(img/modal-bg.png); + width: 300px; + padding: 20px 5px; + color: white; + font-size: 16px; + position: absolute; + left: 50%; + top: 50%; + margin-left: -155px; + margin-top: -45px; + text-align: center; + display: none; + z-index: 100; + border-radius: 5px; +} + +#chat-modal-overlay { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + z-index: 90; + background-image: url(img/overlay.png); + border-top-left-radius: 8px; +} + +#chat-modal.modal-login { + display: block; + margin-top: -100px; +} + +#chat-modal-spinner { + display: none; + margin-left: 15px; +} + +#chat-modal form { + margin: 15px 0; +} + +#chat-modal label, #chat-modal input, #chat-modal select { + display: block; + float: left; + line-height: 26px; + font-size: 16px; + margin: 5px 0; +} + +#chat-modal input, #chat-modal select { + padding: 2px; + line-height: 16px; + width: 150px; +} + +#chat-modal label { + text-align: right; + padding-right: 1em; + clear: both; + width: 100px; +} + +#chat-modal input.button { + float: none; + display: block; + margin: 5px auto; + clear: both; + position: relative; + top: 10px; + /* width: 200px; */ + width: 120px; /* JRBL */ +} + +#chat-modal .close { + position: absolute; + right: 0; + display: none; + padding: 0 5px; + margin: -17px 3px 0 0; + color: white; + border-radius: 3px; +} + +#chat-modal .close:hover { + background-color: #333; +} diff --git a/lms/static/candy_res/img/action/autoscroll-off.png b/lms/static/candy_res/img/action/autoscroll-off.png new file mode 100644 index 0000000000..a0b8aa6940 Binary files /dev/null and b/lms/static/candy_res/img/action/autoscroll-off.png differ diff --git a/lms/static/candy_res/img/action/autoscroll-on.png b/lms/static/candy_res/img/action/autoscroll-on.png new file mode 100644 index 0000000000..3f55052b0f Binary files /dev/null and b/lms/static/candy_res/img/action/autoscroll-on.png differ diff --git a/lms/static/candy_res/img/action/ban.png b/lms/static/candy_res/img/action/ban.png new file mode 100644 index 0000000000..b335cb11c4 Binary files /dev/null and b/lms/static/candy_res/img/action/ban.png differ diff --git a/lms/static/candy_res/img/action/emoticons.png b/lms/static/candy_res/img/action/emoticons.png new file mode 100755 index 0000000000..ade431851b Binary files /dev/null and b/lms/static/candy_res/img/action/emoticons.png differ diff --git a/lms/static/candy_res/img/action/ignore.png b/lms/static/candy_res/img/action/ignore.png new file mode 100644 index 0000000000..08f249365a Binary files /dev/null and b/lms/static/candy_res/img/action/ignore.png differ diff --git a/lms/static/candy_res/img/action/kick.png b/lms/static/candy_res/img/action/kick.png new file mode 100644 index 0000000000..bce1c97686 Binary files /dev/null and b/lms/static/candy_res/img/action/kick.png differ diff --git a/lms/static/candy_res/img/action/menu.png b/lms/static/candy_res/img/action/menu.png new file mode 100644 index 0000000000..be4540c436 Binary files /dev/null and b/lms/static/candy_res/img/action/menu.png differ diff --git a/lms/static/candy_res/img/action/private.png b/lms/static/candy_res/img/action/private.png new file mode 100644 index 0000000000..39433cf78a Binary files /dev/null and b/lms/static/candy_res/img/action/private.png differ diff --git a/lms/static/candy_res/img/action/settings.png b/lms/static/candy_res/img/action/settings.png new file mode 100755 index 0000000000..327fdf4963 Binary files /dev/null and b/lms/static/candy_res/img/action/settings.png differ diff --git a/lms/static/candy_res/img/action/sound-off.png b/lms/static/candy_res/img/action/sound-off.png new file mode 100644 index 0000000000..7ba81fefa5 Binary files /dev/null and b/lms/static/candy_res/img/action/sound-off.png differ diff --git a/lms/static/candy_res/img/action/sound-on.png b/lms/static/candy_res/img/action/sound-on.png new file mode 100644 index 0000000000..b4351604a7 Binary files /dev/null and b/lms/static/candy_res/img/action/sound-on.png differ diff --git a/lms/static/candy_res/img/action/statusmessage-off.png b/lms/static/candy_res/img/action/statusmessage-off.png new file mode 100644 index 0000000000..03eb01d771 Binary files /dev/null and b/lms/static/candy_res/img/action/statusmessage-off.png differ diff --git a/lms/static/candy_res/img/action/statusmessage-on.png b/lms/static/candy_res/img/action/statusmessage-on.png new file mode 100644 index 0000000000..063e8dc3fe Binary files /dev/null and b/lms/static/candy_res/img/action/statusmessage-on.png differ diff --git a/lms/static/candy_res/img/action/subject.png b/lms/static/candy_res/img/action/subject.png new file mode 100644 index 0000000000..7bc9233ea6 Binary files /dev/null and b/lms/static/candy_res/img/action/subject.png differ diff --git a/lms/static/candy_res/img/action/unignore.png b/lms/static/candy_res/img/action/unignore.png new file mode 100644 index 0000000000..89c8129a49 Binary files /dev/null and b/lms/static/candy_res/img/action/unignore.png differ diff --git a/lms/static/candy_res/img/action/usercount.png b/lms/static/candy_res/img/action/usercount.png new file mode 100755 index 0000000000..7fb4e1f1e1 Binary files /dev/null and b/lms/static/candy_res/img/action/usercount.png differ diff --git a/lms/static/candy_res/img/context-arrows.gif b/lms/static/candy_res/img/context-arrows.gif new file mode 100644 index 0000000000..d02df8c43f Binary files /dev/null and b/lms/static/candy_res/img/context-arrows.gif differ diff --git a/lms/static/candy_res/img/emoticons/Angel.png b/lms/static/candy_res/img/emoticons/Angel.png new file mode 100755 index 0000000000..0cf707b7de Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Angel.png differ diff --git a/lms/static/candy_res/img/emoticons/Angry.png b/lms/static/candy_res/img/emoticons/Angry.png new file mode 100755 index 0000000000..9ae5d1822f Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Angry.png differ diff --git a/lms/static/candy_res/img/emoticons/Aww.png b/lms/static/candy_res/img/emoticons/Aww.png new file mode 100755 index 0000000000..3512863987 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Aww.png differ diff --git a/lms/static/candy_res/img/emoticons/Aww_2.png b/lms/static/candy_res/img/emoticons/Aww_2.png new file mode 100755 index 0000000000..60510bb23d Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Aww_2.png differ diff --git a/lms/static/candy_res/img/emoticons/Blushing.png b/lms/static/candy_res/img/emoticons/Blushing.png new file mode 100755 index 0000000000..ab03ee8c5d Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Blushing.png differ diff --git a/lms/static/candy_res/img/emoticons/Childish.png b/lms/static/candy_res/img/emoticons/Childish.png new file mode 100755 index 0000000000..1a31c5068e Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Childish.png differ diff --git a/lms/static/candy_res/img/emoticons/Confused.png b/lms/static/candy_res/img/emoticons/Confused.png new file mode 100755 index 0000000000..08ba7d3f10 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Confused.png differ diff --git a/lms/static/candy_res/img/emoticons/Creepy.png b/lms/static/candy_res/img/emoticons/Creepy.png new file mode 100755 index 0000000000..561505895f Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Creepy.png differ diff --git a/lms/static/candy_res/img/emoticons/Crying.png b/lms/static/candy_res/img/emoticons/Crying.png new file mode 100755 index 0000000000..2532976871 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Crying.png differ diff --git a/lms/static/candy_res/img/emoticons/Cthulhu.png b/lms/static/candy_res/img/emoticons/Cthulhu.png new file mode 100755 index 0000000000..fafc4b3eb8 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Cthulhu.png differ diff --git a/lms/static/candy_res/img/emoticons/Cute.png b/lms/static/candy_res/img/emoticons/Cute.png new file mode 100755 index 0000000000..a883ac321b Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Cute.png differ diff --git a/lms/static/candy_res/img/emoticons/Cute_Winking.png b/lms/static/candy_res/img/emoticons/Cute_Winking.png new file mode 100755 index 0000000000..ad3383df51 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Cute_Winking.png differ diff --git a/lms/static/candy_res/img/emoticons/Devil.png b/lms/static/candy_res/img/emoticons/Devil.png new file mode 100755 index 0000000000..afc5c2cde5 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Devil.png differ diff --git a/lms/static/candy_res/img/emoticons/Gah.png b/lms/static/candy_res/img/emoticons/Gah.png new file mode 100755 index 0000000000..b03ee1b163 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Gah.png differ diff --git a/lms/static/candy_res/img/emoticons/Gah_2.png b/lms/static/candy_res/img/emoticons/Gah_2.png new file mode 100755 index 0000000000..b682458ece Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Gah_2.png differ diff --git a/lms/static/candy_res/img/emoticons/Gasping.png b/lms/static/candy_res/img/emoticons/Gasping.png new file mode 100755 index 0000000000..b6655ced50 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Gasping.png differ diff --git a/lms/static/candy_res/img/emoticons/Greedy.png b/lms/static/candy_res/img/emoticons/Greedy.png new file mode 100755 index 0000000000..a179638dde Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Greedy.png differ diff --git a/lms/static/candy_res/img/emoticons/Grinning.png b/lms/static/candy_res/img/emoticons/Grinning.png new file mode 100755 index 0000000000..85ff9154cb Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Grinning.png differ diff --git a/lms/static/candy_res/img/emoticons/Grinning_Winking.png b/lms/static/candy_res/img/emoticons/Grinning_Winking.png new file mode 100755 index 0000000000..5b1d5b71b9 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Grinning_Winking.png differ diff --git a/lms/static/candy_res/img/emoticons/Happy.png b/lms/static/candy_res/img/emoticons/Happy.png new file mode 100755 index 0000000000..51cf1a2331 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Happy.png differ diff --git a/lms/static/candy_res/img/emoticons/Happy_2.png b/lms/static/candy_res/img/emoticons/Happy_2.png new file mode 100755 index 0000000000..13326863b5 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Happy_2.png differ diff --git a/lms/static/candy_res/img/emoticons/Happy_3.png b/lms/static/candy_res/img/emoticons/Happy_3.png new file mode 100755 index 0000000000..be79df0823 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Happy_3.png differ diff --git a/lms/static/candy_res/img/emoticons/Heart.png b/lms/static/candy_res/img/emoticons/Heart.png new file mode 100755 index 0000000000..dcd28b9655 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Heart.png differ diff --git a/lms/static/candy_res/img/emoticons/Huh.png b/lms/static/candy_res/img/emoticons/Huh.png new file mode 100755 index 0000000000..241f50f4f7 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Huh.png differ diff --git a/lms/static/candy_res/img/emoticons/Huh_2.png b/lms/static/candy_res/img/emoticons/Huh_2.png new file mode 100755 index 0000000000..a1a54e4b1a Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Huh_2.png differ diff --git a/lms/static/candy_res/img/emoticons/Laughing.png b/lms/static/candy_res/img/emoticons/Laughing.png new file mode 100755 index 0000000000..edefc957a6 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Laughing.png differ diff --git a/lms/static/candy_res/img/emoticons/Lips_Sealed.png b/lms/static/candy_res/img/emoticons/Lips_Sealed.png new file mode 100755 index 0000000000..46e470179b Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Lips_Sealed.png differ diff --git a/lms/static/candy_res/img/emoticons/Madness.png b/lms/static/candy_res/img/emoticons/Madness.png new file mode 100755 index 0000000000..1c0946c3e8 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Madness.png differ diff --git a/lms/static/candy_res/img/emoticons/Malicious.png b/lms/static/candy_res/img/emoticons/Malicious.png new file mode 100755 index 0000000000..23f25792f1 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Malicious.png differ diff --git a/lms/static/candy_res/img/emoticons/README b/lms/static/candy_res/img/emoticons/README new file mode 100644 index 0000000000..208db2c2f0 --- /dev/null +++ b/lms/static/candy_res/img/emoticons/README @@ -0,0 +1,2 @@ +Simple Smileys is a set of 49 clean, free as in freedom, Public Domain smileys. +For more packages or older versions, visit http://simplesmileys.org diff --git a/lms/static/candy_res/img/emoticons/Sick.png b/lms/static/candy_res/img/emoticons/Sick.png new file mode 100755 index 0000000000..6f73e2f096 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Sick.png differ diff --git a/lms/static/candy_res/img/emoticons/Smiling.png b/lms/static/candy_res/img/emoticons/Smiling.png new file mode 100755 index 0000000000..725eef526d Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Smiling.png differ diff --git a/lms/static/candy_res/img/emoticons/Speechless.png b/lms/static/candy_res/img/emoticons/Speechless.png new file mode 100755 index 0000000000..4fc424602e Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Speechless.png differ diff --git a/lms/static/candy_res/img/emoticons/Spiteful.png b/lms/static/candy_res/img/emoticons/Spiteful.png new file mode 100755 index 0000000000..195ced852f Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Spiteful.png differ diff --git a/lms/static/candy_res/img/emoticons/Stupid.png b/lms/static/candy_res/img/emoticons/Stupid.png new file mode 100755 index 0000000000..3fcea491a5 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Stupid.png differ diff --git a/lms/static/candy_res/img/emoticons/Sunglasses.png b/lms/static/candy_res/img/emoticons/Sunglasses.png new file mode 100755 index 0000000000..cad8379742 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Sunglasses.png differ diff --git a/lms/static/candy_res/img/emoticons/Terrified.png b/lms/static/candy_res/img/emoticons/Terrified.png new file mode 100755 index 0000000000..fad2e06524 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Terrified.png differ diff --git a/lms/static/candy_res/img/emoticons/Thumb_Down.png b/lms/static/candy_res/img/emoticons/Thumb_Down.png new file mode 100755 index 0000000000..4f70696dd8 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Thumb_Down.png differ diff --git a/lms/static/candy_res/img/emoticons/Thumb_Up.png b/lms/static/candy_res/img/emoticons/Thumb_Up.png new file mode 100755 index 0000000000..2ca0e0d087 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Thumb_Up.png differ diff --git a/lms/static/candy_res/img/emoticons/Tired.png b/lms/static/candy_res/img/emoticons/Tired.png new file mode 100755 index 0000000000..13f7d1207a Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Tired.png differ diff --git a/lms/static/candy_res/img/emoticons/Tongue_Out.png b/lms/static/candy_res/img/emoticons/Tongue_Out.png new file mode 100755 index 0000000000..3d154f9081 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Tongue_Out.png differ diff --git a/lms/static/candy_res/img/emoticons/Tongue_Out_Laughing.png b/lms/static/candy_res/img/emoticons/Tongue_Out_Laughing.png new file mode 100755 index 0000000000..fba5d75148 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Tongue_Out_Laughing.png differ diff --git a/lms/static/candy_res/img/emoticons/Tongue_Out_Left.png b/lms/static/candy_res/img/emoticons/Tongue_Out_Left.png new file mode 100755 index 0000000000..8015de7f12 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Tongue_Out_Left.png differ diff --git a/lms/static/candy_res/img/emoticons/Tongue_Out_Up.png b/lms/static/candy_res/img/emoticons/Tongue_Out_Up.png new file mode 100755 index 0000000000..46328fbbee Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Tongue_Out_Up.png differ diff --git a/lms/static/candy_res/img/emoticons/Tongue_Out_Up_Left.png b/lms/static/candy_res/img/emoticons/Tongue_Out_Up_Left.png new file mode 100755 index 0000000000..b67b69fb7a Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Tongue_Out_Up_Left.png differ diff --git a/lms/static/candy_res/img/emoticons/Tongue_Out_Winking.png b/lms/static/candy_res/img/emoticons/Tongue_Out_Winking.png new file mode 100755 index 0000000000..2a22cf6a9f Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Tongue_Out_Winking.png differ diff --git a/lms/static/candy_res/img/emoticons/Uncertain.png b/lms/static/candy_res/img/emoticons/Uncertain.png new file mode 100755 index 0000000000..717685684f Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Uncertain.png differ diff --git a/lms/static/candy_res/img/emoticons/Uncertain_2.png b/lms/static/candy_res/img/emoticons/Uncertain_2.png new file mode 100755 index 0000000000..a7f5370d2c Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Uncertain_2.png differ diff --git a/lms/static/candy_res/img/emoticons/Unhappy.png b/lms/static/candy_res/img/emoticons/Unhappy.png new file mode 100755 index 0000000000..79fc0c00ff Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Unhappy.png differ diff --git a/lms/static/candy_res/img/emoticons/Winking.png b/lms/static/candy_res/img/emoticons/Winking.png new file mode 100755 index 0000000000..1e01f943e6 Binary files /dev/null and b/lms/static/candy_res/img/emoticons/Winking.png differ diff --git a/lms/static/candy_res/img/favicon.png b/lms/static/candy_res/img/favicon.png new file mode 100644 index 0000000000..d384cc4b22 Binary files /dev/null and b/lms/static/candy_res/img/favicon.png differ diff --git a/lms/static/candy_res/img/modal-bg.png b/lms/static/candy_res/img/modal-bg.png new file mode 100644 index 0000000000..9fef73a742 Binary files /dev/null and b/lms/static/candy_res/img/modal-bg.png differ diff --git a/lms/static/candy_res/img/modal-spinner.gif b/lms/static/candy_res/img/modal-spinner.gif new file mode 100644 index 0000000000..f8593d57bf Binary files /dev/null and b/lms/static/candy_res/img/modal-spinner.gif differ diff --git a/lms/static/candy_res/img/overlay.png b/lms/static/candy_res/img/overlay.png new file mode 100644 index 0000000000..0593fcf0b6 Binary files /dev/null and b/lms/static/candy_res/img/overlay.png differ diff --git a/lms/static/candy_res/img/roster/affiliation-owner.png b/lms/static/candy_res/img/roster/affiliation-owner.png new file mode 100644 index 0000000000..b88c857895 Binary files /dev/null and b/lms/static/candy_res/img/roster/affiliation-owner.png differ diff --git a/lms/static/candy_res/img/roster/ignore.png b/lms/static/candy_res/img/roster/ignore.png new file mode 100644 index 0000000000..08f249365a Binary files /dev/null and b/lms/static/candy_res/img/roster/ignore.png differ diff --git a/lms/static/candy_res/img/roster/role-moderator.png b/lms/static/candy_res/img/roster/role-moderator.png new file mode 100644 index 0000000000..0d064d1140 Binary files /dev/null and b/lms/static/candy_res/img/roster/role-moderator.png differ diff --git a/lms/static/candy_res/img/tab-transitions.png b/lms/static/candy_res/img/tab-transitions.png new file mode 100644 index 0000000000..1a361e4d47 Binary files /dev/null and b/lms/static/candy_res/img/tab-transitions.png differ diff --git a/lms/static/candy_res/img/tooltip-arrows.gif b/lms/static/candy_res/img/tooltip-arrows.gif new file mode 100644 index 0000000000..ef4b05c6ff Binary files /dev/null and b/lms/static/candy_res/img/tooltip-arrows.gif differ diff --git a/lms/static/candy_res/notify.mp3 b/lms/static/candy_res/notify.mp3 new file mode 100644 index 0000000000..c00d997622 Binary files /dev/null and b/lms/static/candy_res/notify.mp3 differ diff --git a/lms/static/js/vendor/candy.min.js b/lms/static/js/vendor/candy.min.js new file mode 100644 index 0000000000..91923ccf68 --- /dev/null +++ b/lms/static/js/vendor/candy.min.js @@ -0,0 +1 @@ +var Candy=(function(a,b){a.about={name:"Candy",version:"1.0.9"};a.init=function(c,d){a.View.init(b("#candy"),d.view);a.Core.init(c,d.core)};return a}(Candy||{},jQuery));Candy.Core=(function(l,e,f){var d=null,j=null,a=null,g={},c=false,k={autojoin:true,debug:false},b=function(m,n){e.addNamespace(m,n)},h=function(){b("PRIVATE","jabber:iq:private");b("BOOKMARKS","storage:bookmarks");b("PRIVACY","jabber:iq:privacy");b("DELAY","jabber:x:delay")},i=function(){l.addHandler(l.Event.Jabber.Version,e.NS.VERSION,"iq");l.addHandler(l.Event.Jabber.Presence,null,"presence");l.addHandler(l.Event.Jabber.Message,null,"message");l.addHandler(l.Event.Jabber.Bookmarks,e.NS.PRIVATE,"iq");l.addHandler(l.Event.Jabber.Room.Disco,e.NS.DISCO_INFO,"iq");l.addHandler(l.Event.Jabber.PrivacyList,e.NS.PRIVACY,"iq","result");l.addHandler(l.Event.Jabber.PrivacyListError,e.NS.PRIVACY,"iq","error")};l.init=function(m,n){j=m;f.extend(true,k,n);if(k.debug){l.log=function(p){try{if(typeof window.console!==undefined&&typeof window.console.log!==undefined){console.log(p)}}catch(o){}};l.log("[Init] Debugging enabled")}h();d=new e.Connection(j);d.rawInput=l.rawInput.bind(l);d.rawOutput=l.rawOutput.bind(l);window.onbeforeunload=l.onWindowUnload;if(f.browser.mozilla){f(document).keydown(function(o){if(o.which===27){o.preventDefault()}})}};l.connect=function(o,n,m){d.reset();i();c=!c?o&&o.indexOf("@")<0:true;if(o&&n){d.connect(_getEscapedJidFromJid(o)+"/"+Candy.about.name,n,Candy.Core.Event.Strophe.Connect);a=new l.ChatUser(o,e.getNodeFromJid(o))}else{if(o&&m){d.connect(_getEscapedJidFromJid(o)+"/"+Candy.about.name,null,Candy.Core.Event.Strophe.Connect);a=new l.ChatUser(null,m)}else{if(o){Candy.Core.Event.Login(o)}else{Candy.Core.Event.Login()}}}};_getEscapedJidFromJid=function(m){var n=e.getNodeFromJid(m),o=e.getDomainFromJid(m);return n?e.escapeNode(n)+"@"+o:o};l.attach=function(n,m,o){a=new l.ChatUser(n,e.getNodeFromJid(n));i();d.attach(n,m,o,Candy.Core.Event.Strophe.Connect)};l.disconnect=function(){if(d.connected){f.each(l.getRooms(),function(){Candy.Core.Action.Jabber.Room.Leave(this.getJid())});d.disconnect()}};l.addHandler=function(q,p,n,o,s,r,m){return d.addHandler(q,p,n,o,s,r,m)};l.getUser=function(){return a};l.setUser=function(m){a=m};l.getConnection=function(){return d};l.getRooms=function(){return g};l.isAnonymousConnection=function(){return c};l.getOptions=function(){return k};l.getRoom=function(m){if(g[m]){return g[m]}return null};l.onWindowUnload=function(){d.sync=true;l.disconnect();d.flush()};l.rawInput=function(m){this.log("RECV: "+m)};l.rawOutput=function(m){this.log("SENT: "+m)};l.log=function(){};return l}(Candy.Core||{},Strophe,jQuery));Candy.View=(function(i,b){var d={container:null,roomJid:null},h={language:"en",resources:"res/",messages:{limit:2000,remove:500},crop:{message:{nickname:15,body:1000},roster:{nickname:15}}},a=function(j){b.i18n.setDictionary(i.Translation[j])},g=function(){Candy.Core.Event.addObserver(Candy.Core.Event.KEYS.CHAT,i.Observer.Chat);Candy.Core.Event.addObserver(Candy.Core.Event.KEYS.PRESENCE,i.Observer.Presence);Candy.Core.Event.addObserver(Candy.Core.Event.KEYS.PRESENCE_ERROR,i.Observer.PresenceError);Candy.Core.Event.addObserver(Candy.Core.Event.KEYS.MESSAGE,i.Observer.Message);Candy.Core.Event.addObserver(Candy.Core.Event.KEYS.LOGIN,i.Observer.Login)},e=function(){if(b.browser.msie&&!b.browser.version.match("^9")){b(document).focusin(Candy.View.Pane.Window.onFocus).focusout(Candy.View.Pane.Window.onBlur)}else{b(window).focus(Candy.View.Pane.Window.onFocus).blur(Candy.View.Pane.Window.onBlur)}b(window).resize(Candy.View.Pane.Chat.fitTabs)},f=function(){b("#emoticons-icon").click(function(j){i.Pane.Chat.Context.showEmoticonsMenu(j.currentTarget);j.stopPropagation()});b("#chat-autoscroll-control").click(Candy.View.Pane.Chat.Toolbar.onAutoscrollControlClick);b("#chat-sound-control").click(Candy.View.Pane.Chat.Toolbar.onSoundControlClick);if(Candy.Util.cookieExists("candy-nosound")){b("#chat-sound-control").click()}b("#chat-statusmessage-control").click(Candy.View.Pane.Chat.Toolbar.onStatusMessageControlClick);if(Candy.Util.cookieExists("candy-nostatusmessages")){b("#chat-statusmessage-control").click()}},c=function(){b("body").delegate("li[data-tooltip]","mouseenter",Candy.View.Pane.Chat.Tooltip.show)};i.init=function(j,k){b.extend(true,h,k);a(h.language);Candy.Util.Parser.setEmoticonPath(this.getOptions().resources+"img/emoticons/");d.container=j;d.container.html(Mustache.to_html(Candy.View.Template.Chat.pane,{tooltipEmoticons:b.i18n._("tooltipEmoticons"),tooltipSound:b.i18n._("tooltipSound"),tooltipAutoscroll:b.i18n._("tooltipAutoscroll"),tooltipStatusmessage:b.i18n._("tooltipStatusmessage"),tooltipAdministration:b.i18n._("tooltipAdministration"),tooltipUsercount:b.i18n._("tooltipUsercount"),resourcesPath:this.getOptions().resources},{tabs:Candy.View.Template.Chat.tabs,rooms:Candy.View.Template.Chat.rooms,modal:Candy.View.Template.Chat.modal,toolbar:Candy.View.Template.Chat.toolbar,soundcontrol:Candy.View.Template.Chat.soundcontrol}));e();f();g();c()};i.getCurrent=function(){return d};i.getOptions=function(){return h};return i}(Candy.View||{},jQuery));Candy.Util=(function(a,b){a.jidToId=function(c){return MD5.hexdigest(c)};a.escapeJid=function(c){var d=Strophe.escapeNode(Strophe.getNodeFromJid(c)),f=Strophe.getDomainFromJid(c),e=Strophe.getResourceFromJid(c);c=d+"@"+f;if(e){c+="/"+Strophe.escapeNode(e)}return c};a.unescapeJid=function(c){var d=Strophe.unescapeNode(Strophe.getNodeFromJid(c)),f=Strophe.getDomainFromJid(c),e=Strophe.getResourceFromJid(c);c=d+"@"+f;if(e){c+="/"+Strophe.unescapeNode(e)}return c};a.crop=function(d,c){if(d.length>c){d=d.substr(0,c-3)+"..."}return d};a.setCookie=function(c,e,d){var f=new Date();f.setDate(new Date().getDate()+d);document.cookie=c+"="+e+";expires="+f.toUTCString()+";path=/"};a.cookieExists=function(c){return document.cookie.indexOf(c)>-1};a.getCookie=function(c){if(document.cookie){var d=new RegExp(escape(c)+"=([^;]*)","gm"),e=d.exec(document.cookie);if(e){return e[1]}}};a.deleteCookie=function(c){document.cookie=c+"=;expires=Thu, 01-Jan-70 00:00:01 GMT;path=/"};a.getPosLeftAccordingToWindowBounds=function(e,h){var d=b(document).width(),c=e.outerWidth(),f=c-e.outerWidth(true),g="left";if(h+c>=d){h-=c-f;g="right"}return{px:h,backgroundPositionAlignment:g}};a.getPosTopAccordingToWindowBounds=function(d,h){var g=b(document).height(),c=d.outerHeight(),e=c-d.outerHeight(true),f="top";if(h+c>=g){h-=c-e;f="bottom"}return{px:h,backgroundPositionAlignment:f}};a.localizedTime=function(d){if(d===undefined){return undefined}var c=a.iso8601toDate(d);if(c.toDateString()===new Date().toDateString()){return c.format(b.i18n._("timeFormat"))}else{return c.format(b.i18n._("dateFormat"))}};a.iso8601toDate=function(c){var e=Date.parse(c),d=0;if(isNaN(e)){var f=/^(\d{4}|[+\-]\d{6})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?))?/.exec(c);if(f){if(f[8]!=="Z"){d=+f[10]*60+(+f[11]);if(f[9]==="+"){d=-d}}return new Date(+f[1],+f[2]-1,+f[3],+f[4],+f[5]+d,+f[6],f[7]?+f[7].substr(0,3):0)}else{e=Date.parse(c.replace(/^(\d{4})(\d{2})(\d{2})/,"$1-$2-$3")+"Z")}}return new Date(e)};a.isEmptyObject=function(c){var d;for(d in c){if(c.hasOwnProperty(d)){return false}}return true};a.forceRedraw=function(c){c.css({display:"none"});setTimeout(function(){this.css({display:"block"})}.bind(c),1)};a.Parser={_emoticonPath:"",setEmoticonPath:function(c){this._emoticonPath=c},emoticons:[{plain:":)",regex:/((\s):-?\)|:-?\)(\s|$))/gm,image:"Smiling.png"},{plain:";)",regex:/((\s);-?\)|;-?\)(\s|$))/gm,image:"Winking.png"},{plain:":D",regex:/((\s):-?D|:-?D(\s|$))/gm,image:"Grinning.png"},{plain:";D",regex:/((\s);-?D|;-?D(\s|$))/gm,image:"Grinning_Winking.png"},{plain:":(",regex:/((\s):-?\(|:-?\((\s|$))/gm,image:"Unhappy.png"},{plain:"^^",regex:/((\s)\^\^|\^\^(\s|$))/gm,image:"Happy_3.png"},{plain:":P",regex:/((\s):-?P|:-?P(\s|$))/igm,image:"Tongue_Out.png"},{plain:";P",regex:/((\s);-?P|;-?P(\s|$))/igm,image:"Tongue_Out_Winking.png"},{plain:":S",regex:/((\s):-?S|:-?S(\s|$))/igm,image:"Confused.png"},{plain:":/",regex:/((\s):-?\/|:-?\/(\s|$))/gm,image:"Uncertain.png"},{plain:"8)",regex:/((\s)8-?\)|8-?\)(\s|$))/gm,image:"Sunglasses.png"},{plain:"$)",regex:/((\s)\$-?\)|\$-?\)(\s|$))/gm,image:"Greedy.png"},{plain:"oO",regex:/((\s)oO|oO(\s|$))/gm,image:"Huh.png"},{plain:":x",regex:/((\s):x|:x(\s|$))/gm,image:"Lips_Sealed.png"},{plain:":666:",regex:/((\s):666:|:666:(\s|$))/gm,image:"Devil.png"},{plain:"<3",regex:/((\s)<3|<3(\s|$))/gm,image:"Heart.png"}],emotify:function(d){var c;for(c=this.emoticons.length-1;c>=0;c--){d=d.replace(this.emoticons[c].regex,'$2$1$3')}return d},linkify:function(c){c=c.replace(/(^|[^\/])(www\.[^\.]+\.[\S]+(\b|$))/gi,"$1http://$2");return c.replace(/(\b(https?|ftp|file):\/\/[\-A-Z0-9+&@#\/%?=~_|!:,.;]*[\-A-Z0-9+&@#\/%=~_|])/ig,'$1')},escape:function(c){return b("
").text(c).html()},all:function(c){if(c){c=this.escape(c);c=this.linkify(c);c=this.emotify(c)}return c}};return a}(Candy.Util||{},jQuery));Candy.Util.Observable=(function(a){var b={};a.addObserver=function(c,d){if(b[c]===undefined){b[c]=[]}b[c].push(d)};a.deleteObserver=function(c,d){delete b[c][d]};a.clearObservers=function(c){if(c!==undefined){b[c]=[]}else{b={}}};a.notifyObservers=function(f,c){var d=b[f],e;for(e=d.length-1;e>=0;e--){d[e].update(a,c)}};return a}(Candy.Util.Observable||{}));Candy.Core.Action=(function(a,c,b){a.Jabber={Version:function(d){Candy.Core.getConnection().send($iq({type:"result",to:d.attr("from"),from:d.attr("to"),id:d.attr("id")}).c("query",{name:Candy.about.name,version:Candy.about.version,os:navigator.userAgent}))},Roster:function(){Candy.Core.getConnection().send($iq({type:"get",xmlns:c.NS.CLIENT}).c("query",{xmlns:c.NS.ROSTER}).tree())},Presence:function(d){Candy.Core.getConnection().send($pres(d).tree())},Services:function(){Candy.Core.getConnection().send($iq({type:"get",xmlns:c.NS.CLIENT}).c("query",{xmlns:c.NS.DISCO_ITEMS}).tree())},Autojoin:function(){if(Candy.Core.getOptions().autojoin===true){Candy.Core.getConnection().send($iq({type:"get",xmlns:c.NS.CLIENT}).c("query",{xmlns:c.NS.PRIVATE}).c("storage",{xmlns:c.NS.BOOKMARKS}).tree())}else{if(b.isArray(Candy.Core.getOptions().autojoin)){b.each(Candy.Core.getOptions().autojoin,function(){a.Jabber.Room.Join(this.valueOf())})}}},ResetIgnoreList:function(){Candy.Core.getConnection().send($iq({type:"set",from:Candy.Core.getUser().getJid(),id:"set1"}).c("query",{xmlns:c.NS.PRIVACY}).c("list",{name:"ignore"}).c("item",{action:"allow",order:"0"}).tree())},RemoveIgnoreList:function(){Candy.Core.getConnection().send($iq({type:"set",from:Candy.Core.getUser().getJid(),id:"remove1"}).c("query",{xmlns:c.NS.PRIVACY}).c("list",{name:"ignore"}).tree())},GetIgnoreList:function(){Candy.Core.getConnection().send($iq({type:"get",from:Candy.Core.getUser().getJid(),id:"get1"}).c("query",{xmlns:c.NS.PRIVACY}).c("list",{name:"ignore"}).tree())},SetIgnoreListActive:function(){Candy.Core.getConnection().send($iq({type:"set",from:Candy.Core.getUser().getJid(),id:"set2"}).c("query",{xmlns:c.NS.PRIVACY}).c("active",{name:"ignore"}).tree())},GetJidIfAnonymous:function(){if(!Candy.Core.getUser().getJid()){Candy.Core.log("[Jabber] Anonymous login");Candy.Core.getUser().data.jid=Candy.Core.getConnection().jid}},Room:{Join:function(d,e){a.Jabber.Room.Disco(d);Candy.Core.getConnection().muc.join(d,Candy.Core.getUser().getNick(),null,null,e)},Leave:function(d){Candy.Core.getConnection().muc.leave(d,Candy.Core.getRoom(d).getUser().getNick(),function(){})},Disco:function(d){Candy.Core.getConnection().send($iq({type:"get",from:Candy.Core.getUser().getJid(),to:d,id:"disco3"}).c("query",{xmlns:c.NS.DISCO_INFO}).tree())},Message:function(d,f,e){f=b.trim(f);if(f===""){return false}Candy.Core.getConnection().muc.message(Candy.Util.escapeJid(d),undefined,f,e);return true},IgnoreUnignore:function(d){Candy.Core.getUser().addToOrRemoveFromPrivacyList("ignore",d);Candy.Core.Action.Jabber.Room.UpdatePrivacyList()},UpdatePrivacyList:function(){var d=Candy.Core.getUser(),f=$iq({type:"set",from:d.getJid(),id:"edit1"}).c("query",{xmlns:"jabber:iq:privacy"}).c("list",{name:"ignore"}),e=d.getPrivacyList("ignore");if(e.length>0){b.each(e,function(g,h){f.c("item",{type:"jid",value:Candy.Util.escapeJid(h),action:"deny",order:g}).c("message").up().up()})}else{f.c("item",{action:"allow",order:"0"})}Candy.Core.getConnection().send(f.tree())},Admin:{UserAction:function(d,i,g,h){var f,e={nick:c.escapeNode(c.getResourceFromJid(i))};switch(g){case"kick":f="kick1";e.role="none";break;case"ban":f="ban1";e.affiliation="outcast";break;default:return false}Candy.Core.getConnection().send($iq({type:"set",from:Candy.Core.getUser().getJid(),to:d,id:f}).c("query",{xmlns:c.NS.MUC_ADMIN}).c("item",e).c("reason").t(h).tree());return true},SetSubject:function(d,e){Candy.Core.getConnection().muc.setTopic(d,e)}}}};return a}(Candy.Core.Action||{},Strophe,jQuery));Candy.Core.ChatRoom=function(a){this.room={jid:a,name:null};this.user=null;this.roster=new Candy.Core.ChatRoster();this.setUser=function(b){this.user=b};this.getUser=function(){return this.user};this.getJid=function(){return this.room.jid};this.setName=function(b){this.room.name=b};this.getName=function(){return this.room.name};this.setRoster=function(b){this.roster=b};this.getRoster=function(){return this.roster}};Candy.Core.ChatRoster=function(){this.items={};this.add=function(a){this.items[a.getJid()]=a};this.remove=function(a){delete this.items[a]};this.get=function(a){return this.items[a]};this.getAll=function(){return this.items}};Candy.Core.ChatUser=function(b,a,c,d){this.ROLE_MODERATOR="moderator";this.AFFILIATION_OWNER="owner";this.data={jid:b,nick:Strophe.unescapeNode(a),affiliation:c,role:d,privacyLists:{},customData:{}};this.getJid=function(){if(this.data.jid){return Candy.Util.unescapeJid(this.data.jid)}return};this.getEscapedJid=function(){return Candy.Util.escapeJid(this.data.jid)};this.getNick=function(){return Strophe.unescapeNode(this.data.nick)};this.getRole=function(){return this.data.role};this.getAffiliation=function(){return this.data.affiliation};this.isModerator=function(){return this.getRole()===this.ROLE_MODERATOR||this.getAffiliation()===this.AFFILIATION_OWNER};this.addToOrRemoveFromPrivacyList=function(g,f){if(!this.data.privacyLists[g]){this.data.privacyLists[g]=[]}var e=-1;if((e=this.data.privacyLists[g].indexOf(f))!==-1){this.data.privacyLists[g].splice(e,1)}else{this.data.privacyLists[g].push(f)}return this.data.privacyLists[g]};this.getPrivacyList=function(e){if(!this.data.privacyLists[e]){this.data.privacyLists[e]=[]}return this.data.privacyLists[e]};this.isInPrivacyList=function(f,e){if(!this.data.privacyLists[f]){return false}return this.data.privacyLists[f].indexOf(e)!==-1};this.setCustomData=function(e){this.data.customData=e};this.getCustomData=function(){return this.data.customData}};Candy.Core.Event=(function(a,e,c,d){var b;for(b in d){if(d.hasOwnProperty(b)){a[b]=d[b]}}a.KEYS={CHAT:1,PRESENCE:2,MESSAGE:3,LOGIN:4,PRESENCE_ERROR:5};a.Strophe={Connect:function(f){switch(f){case e.Status.CONNECTED:Candy.Core.log("[Connection] Connected");Candy.Core.Action.Jabber.GetJidIfAnonymous();case e.Status.ATTACHED:Candy.Core.log("[Connection] Attached");Candy.Core.Action.Jabber.Presence();Candy.Core.Action.Jabber.Autojoin();Candy.Core.Action.Jabber.GetIgnoreList();break;case e.Status.DISCONNECTED:Candy.Core.log("[Connection] Disconnected");break;case e.Status.AUTHFAIL:Candy.Core.log("[Connection] Authentication failed");break;case e.Status.CONNECTING:Candy.Core.log("[Connection] Connecting");break;case e.Status.DISCONNECTING:Candy.Core.log("[Connection] Disconnecting");break;case e.Status.AUTHENTICATING:Candy.Core.log("[Connection] Authenticating");break;case e.Status.ERROR:case e.Status.CONNFAIL:Candy.Core.log("[Connection] Failed ("+f+")");break;default:Candy.Core.log("[Connection] What?!");break}a.notifyObservers(a.KEYS.CHAT,{type:"connection",status:f})}};a.Login=function(f){a.notifyObservers(a.KEYS.LOGIN,{presetJid:f})};a.Jabber={Version:function(f){Candy.Core.log("[Jabber] Version");Candy.Core.Action.Jabber.Version(c(f));return true},Presence:function(f){Candy.Core.log("[Jabber] Presence");f=c(f);if(f.children('x[xmlns^="'+e.NS.MUC+'"]').length>0){if(f.attr("type")==="error"){a.Jabber.Room.PresenceError(f)}else{a.Jabber.Room.Presence(f)}}return true},Bookmarks:function(f){Candy.Core.log("[Jabber] Bookmarks");c("conference",f).each(function(){var g=c(this);if(g.attr("autojoin")){Candy.Core.Action.Jabber.Room.Join(g.attr("jid"))}});return true},PrivacyList:function(g){Candy.Core.log("[Jabber] PrivacyList");var f=Candy.Core.getUser();c('list[name="ignore"] item',g).each(function(){var h=c(this);if(h.attr("action")==="deny"){f.addToOrRemoveFromPrivacyList("ignore",h.attr("value"))}});Candy.Core.Action.Jabber.SetIgnoreListActive();return false},PrivacyListError:function(f){Candy.Core.log("[Jabber] PrivacyListError");if(c('error[code="404"][type="cancel"] item-not-found',f)){Candy.Core.Action.Jabber.ResetIgnoreList();Candy.Core.Action.Jabber.SetIgnoreListActive()}return false},Message:function(i){Candy.Core.log("[Jabber] Message");var i=c(i),h=i.attr("from"),g=i.attr("type"),f=i.attr("to");if(h!==e.getDomainFromJid(h)&&(g==="groupchat"||g==="chat"||g==="error")){a.Jabber.Room.Message(i)}else{if(!f&&h===e.getDomainFromJid(h)){a.notifyObservers(a.KEYS.CHAT,{type:(g||"message"),message:i.children("body").text()})}else{if(f&&h===e.getDomainFromJid(h)){a.notifyObservers(a.KEYS.CHAT,{type:(g||"message"),subject:i.children("subject").text(),message:i.children("body").text()})}}}return true},Room:{Leave:function(f){Candy.Core.log("[Jabber:Room] Leave");var f=c(f),l=f.attr("from"),n=e.getBareJidFromJid(l);if(!Candy.Core.getRoom(n)){return false}var j=Candy.Core.getRoom(n).getName(),m=f.find("item"),k="leave",i,h;delete Candy.Core.getRooms()[n];if(m.attr("role")==="none"){if(f.find("status").attr("code")==="307"){k="kick"}else{if(f.find("status").attr("code")==="301"){k="ban"}}i=m.find("reason").text();h=m.find("actor").attr("jid")}var g=new Candy.Core.ChatUser(l,e.getResourceFromJid(l),m.attr("affiliation"),m.attr("role"));a.notifyObservers(a.KEYS.PRESENCE,{roomJid:n,roomName:j,type:k,reason:i,actor:h,user:g});return true},Disco:function(i){Candy.Core.log("[Jabber:Room] Disco");var i=c(i),g=e.getBareJidFromJid(i.attr("from"));if(!Candy.Core.getRooms()[g]){Candy.Core.getRooms()[g]=new Candy.Core.ChatRoom(g)}var f=i.find("identity").attr("name"),h=Candy.Core.getRoom(g);if(h.getName()===null){h.setName(f)}return true},Presence:function(h){Candy.Core.log("[Jabber:Room] Presence");var l=Candy.Util.unescapeJid(h.attr("from")),o=e.getBareJidFromJid(l),m=h.attr("type");if(e.getResourceFromJid(l)===Candy.Core.getUser().getNick()&&m==="unavailable"){a.Jabber.Room.Leave(h);return true}var g=Candy.Core.getRoom(o);if(!g){Candy.Core.getRooms()[o]=new Candy.Core.ChatRoom(o);g=Candy.Core.getRoom(o)}var k=g.getRoster(),i,j,n=h.find("item");if(m!=="unavailable"){var f=e.getResourceFromJid(l);j=new Candy.Core.ChatUser(l,f,n.attr("affiliation"),n.attr("role"));if(g.getUser()===null&&Candy.Core.getUser().getNick()===f){g.setUser(j)}k.add(j);i="join"}else{i="leave";if(n.attr("role")==="none"){if(h.find("status").attr("code")==="307"){i="kick"}else{if(h.find("status").attr("code")==="301"){i="ban"}}}j=k.get(l);k.remove(l)}a.notifyObservers(a.KEYS.PRESENCE,{roomJid:o,roomName:g.getName(),user:j,action:i,currentUser:Candy.Core.getUser()});return true},PresenceError:function(i){Candy.Core.log("[Jabber:Room] Presence Error");var j=Candy.Util.unescapeJid(i.attr("from")),g=e.getBareJidFromJid(j),h=Candy.Core.getRooms()[g],f=h.getName();delete h;a.notifyObservers(a.KEYS.PRESENCE_ERROR,{msg:i,type:i.children("error").children()[0].tagName.toLowerCase(),roomJid:g,roomName:f})},Message:function(h){Candy.Core.log("[Jabber:Room] Message");var o,n;if(h.children("subject").length>0){o=Candy.Util.unescapeJid(e.getBareJidFromJid(h.attr("from")));n={name:e.getNodeFromJid(o),body:h.children("subject").text(),type:"subject"}}else{if(h.attr("type")==="error"){var m=h.children("error");if(m.attr("code")==="500"&&m.children("text").length>0){o=h.attr("from");n={type:"info",body:m.children("text").text()}}}else{if(h.children("body").length>0){if(h.attr("type")==="chat"){o=Candy.Util.unescapeJid(h.attr("from"));var f=e.getBareJidFromJid(o),i=!Candy.Core.getRoom(f),g=i?e.getNodeFromJid(o):e.getResourceFromJid(o);n={name:g,body:h.children("body").text(),type:h.attr("type"),isNoConferenceRoomJid:i}}else{o=Candy.Util.unescapeJid(e.getBareJidFromJid(h.attr("from")));var j=e.getResourceFromJid(h.attr("from"));if(j){j=e.unescapeNode(j);n={name:j,body:h.children("body").text(),type:h.attr("type")}}else{n={name:"",body:h.children("body").text(),type:"info"}}}}else{return true}}}var k=h.children("delay")?h.children("delay"):h.children('x[xmlns="'+e.NS.DELAY+'"]'),l=k!==undefined?k.attr("stamp"):null;a.notifyObservers(a.KEYS.MESSAGE,{roomJid:o,message:n,timestamp:l});return true}}};return a}(Candy.Core.Event||{},Strophe,jQuery,Candy.Util.Observable));Candy.View.Event=(function(a,b){a.Chat={onAdminMessage:function(c){return},onDisconnect:function(){return},onAuthfail:function(){return}};a.Room={onAdd:function(c){return},onShow:function(c){return},onHide:function(c){return},onSubjectChange:function(c){return},onClose:function(c){return},onPresenceChange:function(c){return}};a.Roster={onUpdate:function(c){return},onContextMenu:function(c){return{}},afterContextMenu:function(c){return}};a.Message={beforeShow:function(c){return c.message},onShow:function(c){return},beforeSend:function(c){return c}};return a}(Candy.View.Event||{},jQuery));Candy.View.Observer=(function(a,b){a.Chat={update:function(e,d){if(d.type==="connection"){switch(d.status){case Strophe.Status.CONNECTING:case Strophe.Status.AUTHENTICATING:Candy.View.Pane.Chat.Modal.show(b.i18n._("statusConnecting"),false,true);break;case Strophe.Status.ATTACHED:case Strophe.Status.CONNECTED:Candy.View.Pane.Chat.Modal.show(b.i18n._("statusConnected"));Candy.View.Pane.Chat.Modal.hide();break;case Strophe.Status.DISCONNECTING:Candy.View.Pane.Chat.Modal.show(b.i18n._("statusDisconnecting"),false,true);break;case Strophe.Status.DISCONNECTED:var c=Candy.Core.isAnonymousConnection()?Strophe.getDomainFromJid(Candy.Core.getUser().getJid()):null;Candy.View.Pane.Chat.Modal.showLoginForm(b.i18n._("statusDisconnected"),c);Candy.View.Event.Chat.onDisconnect();break;case Strophe.Status.AUTHFAIL:Candy.View.Pane.Chat.Modal.showLoginForm(b.i18n._("statusAuthfail"));Candy.View.Event.Chat.onAuthfail();break;default:Candy.View.Pane.Chat.Modal.show(b.i18n._("status",d.status));break}}else{if(d.type==="message"){Candy.View.Pane.Chat.adminMessage((d.subject||""),d.message)}else{if(d.type==="chat"||d.type==="groupchat"){Candy.View.Pane.Chat.onInfoMessage(Candy.View.getCurrent().roomJid,(d.subject||""),d.message)}}}}};a.Presence={update:function(h,e){if(e.type==="leave"){var c=Candy.View.Pane.Room.getUser(e.roomJid);Candy.View.Pane.Room.close(e.roomJid);a.Presence.notifyPrivateChats(c,e.type)}else{if(e.type==="kick"||e.type==="ban"){var g=e.actor?Strophe.getNodeFromJid(e.actor):null,f,d=[e.roomName];if(g){d.push(g)}switch(e.type){case"kick":f=b.i18n._((g?"youHaveBeenKickedBy":"youHaveBeenKicked"),d);break;case"ban":f=b.i18n._((g?"youHaveBeenBannedBy":"youHaveBeenBanned"),d);break}Candy.View.Pane.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.adminMessageReason,{reason:e.reason,_action:f,_reason:b.i18n._("reasonWas",[e.reason])}));setTimeout(function(){Candy.View.Pane.Chat.Modal.hide(function(){Candy.View.Pane.Room.close(e.roomJid);a.Presence.notifyPrivateChats(e.user,e.type)})},5000);Candy.View.Event.Room.onPresenceChange({type:e.type,reason:e.reason,roomJid:e.roomJid,user:e.user})}else{if(!Candy.View.Pane.Chat.rooms[e.roomJid]){Candy.View.Pane.Room.init(e.roomJid,e.roomName);Candy.View.Pane.Room.show(e.roomJid)}Candy.View.Pane.Roster.update(e.roomJid,e.user,e.action,e.currentUser);if(Candy.View.Pane.Chat.rooms[e.user.getJid()]){Candy.View.Pane.Roster.update(e.user.getJid(),e.user,e.action,e.currentUser);Candy.View.Pane.PrivateRoom.setStatus(e.user.getJid(),e.action)}}}},notifyPrivateChats:function(d,e){Candy.Core.log("[View:Observer] notify Private Chats");var c;for(c in Candy.View.Pane.Chat.rooms){if(Candy.View.Pane.Chat.rooms.hasOwnProperty(c)&&Candy.View.Pane.Room.getUser(c)&&d.getJid()===Candy.View.Pane.Room.getUser(c).getJid()){Candy.View.Pane.Roster.update(c,d,e,d);Candy.View.Pane.PrivateRoom.setStatus(c,e)}}}};a.PresenceError={update:function(e,c){switch(c.type){case"not-authorized":var d;if(c.msg.children("x").children("password").length>0){d=b.i18n._("passwordEnteredInvalid",[c.roomName])}Candy.View.Pane.Chat.Modal.showEnterPasswordForm(c.roomJid,c.roomName,d);break;case"conflict":Candy.View.Pane.Chat.Modal.showNicknameConflictForm(c.roomJid);break;case"registration-required":Candy.View.Pane.Chat.Modal.showError("errorMembersOnly",[c.roomName]);break;case"service-unavailable":Candy.View.Pane.Chat.Modal.showError("errorMaxOccupantsReached",[c.roomName]);break}}};a.Message={update:function(d,c){if(c.message.type==="subject"){if(!Candy.View.Pane.Chat.rooms[c.roomJid]){Candy.View.Pane.Room.init(c.roomJid,c.message.name);Candy.View.Pane.Room.show(c.roomJid)}Candy.View.Pane.Room.setSubject(c.roomJid,c.message.body)}else{if(c.message.type==="info"){Candy.View.Pane.Chat.infoMessage(c.roomJid,c.message.body)}else{if(c.message.type==="chat"&&!Candy.View.Pane.Chat.rooms[c.roomJid]){Candy.View.Pane.PrivateRoom.open(c.roomJid,c.message.name,false,c.message.isNoConferenceRoomJid)}Candy.View.Pane.Message.show(c.roomJid,c.message.name,c.message.body,c.timestamp)}}}};a.Login={update:function(d,c){Candy.View.Pane.Chat.Modal.showLoginForm(null,c.presetJid)}};return a}(Candy.View.Observer||{},jQuery));Candy.View.Pane=(function(a,b){a.Window={_hasFocus:true,_plainTitle:document.title,_unreadMessagesCount:0,autoscroll:true,hasFocus:function(){return a.Window._hasFocus},increaseUnreadMessages:function(){a.Window.renderUnreadMessages(++a.Window._unreadMessagesCount)},reduceUnreadMessages:function(c){a.Window._unreadMessagesCount-=c;if(a.Window._unreadMessagesCount<=0){a.Window.clearUnreadMessages()}else{a.Window.renderUnreadMessages(a.Window._unreadMessagesCount)}},clearUnreadMessages:function(){a.Window._unreadMessagesCount=0;document.title=a.Window._plainTitle},renderUnreadMessages:function(c){document.title=Candy.View.Template.Window.unreadmessages.replace("{{count}}",c).replace("{{title}}",a.Window._plainTitle)},onFocus:function(){a.Window._hasFocus=true;if(Candy.View.getCurrent().roomJid){a.Room.setFocusToForm(Candy.View.getCurrent().roomJid);a.Chat.clearUnreadMessages(Candy.View.getCurrent().roomJid)}},onBlur:function(){a.Window._hasFocus=false}};a.Chat={rooms:[],addTab:function(d,c,e){var h=Candy.Util.jidToId(d),f=Mustache.to_html(Candy.View.Template.Chat.tab,{roomJid:d,roomId:h,name:c||Strophe.getNodeFromJid(d),privateUserChat:function(){return e==="chat"},roomType:e}),g=b(f).appendTo("#chat-tabs");g.click(a.Chat.tabClick);b("a.close",g).click(a.Chat.tabClose);a.Chat.fitTabs()},getTab:function(c){return b("#chat-tabs").children('li[data-roomjid="'+c+'"]')},removeTab:function(c){a.Chat.getTab(c).remove();a.Chat.fitTabs()},setActiveTab:function(c){b("#chat-tabs").children().each(function(){var d=b(this);if(d.attr("data-roomjid")===c){d.addClass("active")}else{d.removeClass("active")}})},increaseUnreadMessages:function(d){var c=this.getTab(d).find(".unread");c.show().text(c.text()!==""?parseInt(c.text(),10)+1:1);if(a.Chat.rooms[d].type==="chat"){a.Window.increaseUnreadMessages()}},clearUnreadMessages:function(d){var c=a.Chat.getTab(d).find(".unread");a.Window.reduceUnreadMessages(c.text());c.hide().text("")},tabClick:function(d){var c=Candy.View.getCurrent().roomJid;a.Chat.rooms[c].scrollPosition=a.Room.getPane(c,".message-pane-wrapper").scrollTop();a.Room.show(b(this).attr("data-roomjid"));d.preventDefault()},tabClose:function(d){var c=b(this).parent().attr("data-roomjid");if(a.Chat.rooms[c].type==="chat"){a.Room.close(c)}else{Candy.Core.Action.Jabber.Room.Leave(c)}return false},allTabsClosed:function(){Candy.Core.disconnect();a.Chat.Toolbar.hide();return},fitTabs:function(){var g=b("#chat-tabs").innerWidth(),f=0,e=b("#chat-tabs").children();e.each(function(){f+=b(this).css({width:"auto",overflow:"visible"}).outerWidth(true)});if(f>g){var c=e.outerWidth(true)-e.width(),d=Math.floor((g)/e.length)-c;e.css({width:d,overflow:"hidden"})}},updateToolbar:function(c){b("#chat-toolbar").find(".context").click(function(d){a.Chat.Context.show(d.currentTarget,c);d.stopPropagation()});Candy.View.Pane.Chat.Toolbar.updateUsercount(Candy.View.Pane.Chat.rooms[c].usercount)},adminMessage:function(d,e){if(Candy.View.getCurrent().roomJid){var c=Mustache.to_html(Candy.View.Template.Chat.adminMessage,{subject:d,message:e,sender:b.i18n._("administratorMessageSubject"),time:Candy.Util.localizedTime(new Date().toGMTString())});b("#chat-rooms").children().each(function(){a.Room.appendToMessagePane(b(this).attr("data-roomjid"),c)});a.Room.scrollToBottom(Candy.View.getCurrent().roomJid);Candy.View.Event.Chat.onAdminMessage({subject:d,message:e})}},infoMessage:function(c,d,e){a.Chat.onInfoMessage(c,d,e)},onInfoMessage:function(c,e,f){if(Candy.View.getCurrent().roomJid){var d=Mustache.to_html(Candy.View.Template.Chat.infoMessage,{subject:e,message:b.i18n._(f),time:Candy.Util.localizedTime(new Date().toGMTString())});a.Room.appendToMessagePane(c,d);if(Candy.View.getCurrent().roomJid===c){a.Room.scrollToBottom(Candy.View.getCurrent().roomJid)}}},Toolbar:{show:function(){b("#chat-toolbar").show()},hide:function(){b("#chat-toolbar").hide()},playSound:function(){a.Chat.Toolbar.onPlaySound()},onPlaySound:function(){var c=document.getElementById("chat-sound-player");c.SetVariable("method:stop","");c.SetVariable("method:play","")},onSoundControlClick:function(){var c=b("#chat-sound-control");if(c.hasClass("checked")){a.Chat.Toolbar.playSound=function(){};Candy.Util.setCookie("candy-nosound","1",365)}else{a.Chat.Toolbar.playSound=function(){a.Chat.Toolbar.onPlaySound()};Candy.Util.deleteCookie("candy-nosound")}c.toggleClass("checked")},onAutoscrollControlClick:function(){var c=b("#chat-autoscroll-control");if(c.hasClass("checked")){a.Room.scrollToBottom=function(d){a.Room.onScrollToStoredPosition(d)};a.Window.autoscroll=false}else{a.Room.scrollToBottom=function(d){a.Room.onScrollToBottom(d)};a.Room.scrollToBottom(Candy.View.getCurrent().roomJid);a.Window.autoscroll=true}c.toggleClass("checked")},onStatusMessageControlClick:function(){var c=b("#chat-statusmessage-control");if(c.hasClass("checked")){a.Chat.infoMessage=function(){};Candy.Util.setCookie("candy-nostatusmessages","1",365)}else{a.Chat.infoMessage=function(d,e,f){a.Chat.onInfoMessage(d,e,f)};Candy.Util.deleteCookie("candy-nostatusmessages")}c.toggleClass("checked")},updateUsercount:function(c){b("#chat-usercount").text(c)}},Modal:{show:function(d,e,c){if(e){a.Chat.Modal.showCloseControl()}else{a.Chat.Modal.hideCloseControl()}if(c){a.Chat.Modal.showSpinner()}else{a.Chat.Modal.hideSpinner()}b("#chat-modal").stop(false,true);b("#chat-modal-body").html(d);b("#chat-modal").fadeIn("fast");b("#chat-modal-overlay").show()},hide:function(c){b("#chat-modal").fadeOut("fast",function(){b("#chat-modal-body").text("");b("#chat-modal-overlay").hide()});b(document).keydown(function(d){if(d.which===27){d.preventDefault()}});if(c){c()}},showSpinner:function(){b("#chat-modal-spinner").show()},hideSpinner:function(){b("#chat-modal-spinner").hide()},showCloseControl:function(){b("#admin-message-cancel").show().click(function(c){a.Chat.Modal.hide();c.preventDefault()});b(document).keydown(function(c){if(c.which===27){a.Chat.Modal.hide();c.preventDefault()}})},hideCloseControl:function(){b("#admin-message-cancel").hide().click(function(){})},showLoginForm:function(d,c){a.Chat.Modal.show((d?d:"")+Mustache.to_html(Candy.View.Template.Login.form,{_labelUsername:b.i18n._("labelUsername"),_labelPassword:b.i18n._("labelPassword"),_loginSubmit:b.i18n._("loginSubmit"),displayPassword:!Candy.Core.isAnonymousConnection(),displayUsername:Candy.Core.isAnonymousConnection()||!c,presetJid:c?c:false}));b("#login-form").children()[0].focus();b("#login-form").submit(function(g){var h=b("#username").val(),e=b("#password").val();if(!Candy.Core.isAnonymousConnection()){var f=Candy.Core.getUser()&&h.indexOf("@")<0?h+"@"+Strophe.getDomainFromJid(Candy.Core.getUser().getJid()):h;if(f.indexOf("@")<0&&!Candy.Core.getUser()){Candy.View.Pane.Chat.Modal.showLoginForm(b.i18n._("loginInvalid"))}else{Candy.Core.connect(f,e)}}else{Candy.Core.connect(c,null,h)}return false})},showEnterPasswordForm:function(d,c,e){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.enterPasswordForm,{roomName:c,_labelPassword:b.i18n._("labelPassword"),_label:(e?e:b.i18n._("enterRoomPassword",[c])),_joinSubmit:b.i18n._("enterRoomPasswordSubmit")}),true);b("#password").focus();b("#enter-password-form").submit(function(){var f=b("#password").val();a.Chat.Modal.hide(function(){Candy.Core.Action.Jabber.Room.Join(d,f)});return false})},showNicknameConflictForm:function(c){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.nicknameConflictForm,{_labelNickname:b.i18n._("labelUsername"),_label:b.i18n._("nicknameConflict"),_loginSubmit:b.i18n._("loginSubmit")}));b("#nickname").focus();b("#nickname-conflict-form").submit(function(){var d=b("#nickname").val();a.Chat.Modal.hide(function(){Candy.Core.getUser().data.nick=d;Candy.Core.Action.Jabber.Room.Join(c)});return false})},showError:function(d,c){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.displayError,{_error:b.i18n._(d,c)}),true)}},Tooltip:{show:function(g,f){var h=b("#tooltip"),i=b(g.currentTarget);if(!f){f=i.attr("data-tooltip")}if(h.length===0){var d=Mustache.to_html(Candy.View.Template.Chat.tooltip);b("#chat-pane").append(d);h=b("#tooltip")}b("#context-menu").hide();h.stop(false,true);h.children("div").html(f);var j=i.offset(),c=Candy.Util.getPosLeftAccordingToWindowBounds(h,j.left),e=Candy.Util.getPosTopAccordingToWindowBounds(h,j.top);h.css({left:c.px,top:e.px,backgroundPosition:c.backgroundPositionAlignment+" "+e.backgroundPositionAlignment}).fadeIn("fast");i.mouseleave(function(k){k.stopPropagation();b("#tooltip").stop(false,true).fadeOut("fast",function(){b(this).css({top:0,left:0})})})}},Context:{init:function(){if(b("#context-menu").length===0){var c=Mustache.to_html(Candy.View.Template.Chat.Context.menu);b("#chat-pane").append(c);b("#context-menu").mouseleave(function(){b(this).fadeOut("fast")})}},show:function(e,p,h){e=b(e);var f=a.Chat.rooms[p].id,d=b("#context-menu"),o=b("ul li",d);b("#tooltip").hide();if(!h){h=Candy.Core.getUser()}o.remove();var k=this.getMenuLinks(p,h,e),c,l=function(r,q){return function(s){s.data.callback(s,r,q);b("#context-menu").hide()}};for(c in k){if(k.hasOwnProperty(c)){var n=k[c],j=Mustache.to_html(Candy.View.Template.Chat.Context.menulinks,{roomId:f,"class":n["class"],id:c,label:n.label});b("ul",d).append(j);b("#context-menu-"+c).bind("click",n,l(p,h))}}if(c){var m=e.offset(),g=Candy.Util.getPosLeftAccordingToWindowBounds(d,m.left),i=Candy.Util.getPosTopAccordingToWindowBounds(d,m.top);d.css({left:g.px,top:i.px,backgroundPosition:g.backgroundPositionAlignment+" "+i.backgroundPositionAlignment});d.fadeIn("fast");Candy.View.Event.Roster.afterContextMenu({roomJid:p,user:h,element:d});return true}},getMenuLinks:function(d,c,e){var f=b.extend(this.initialMenuLinks(e),Candy.View.Event.Roster.onContextMenu({roomJid:d,user:c,elem:e})),g;for(g in f){if(f.hasOwnProperty(g)&&f[g].requiredPermission!==undefined&&!f[g].requiredPermission(c,a.Room.getUser(d),e)){delete f[g]}}return f},initialMenuLinks:function(){return{"private":{requiredPermission:function(c,d){return d.getNick()!==c.getNick()&&Candy.Core.getRoom(Candy.View.getCurrent().roomJid)&&!Candy.Core.getUser().isInPrivacyList("ignore",c.getJid())},"class":"private",label:b.i18n._("privateActionLabel"),callback:function(f,d,c){b("#user-"+Candy.Util.jidToId(d)+"-"+Candy.Util.jidToId(c.getJid())).click()}},ignore:{requiredPermission:function(c,d){return d.getNick()!==c.getNick()&&!Candy.Core.getUser().isInPrivacyList("ignore",c.getJid())},"class":"ignore",label:b.i18n._("ignoreActionLabel"),callback:function(f,d,c){Candy.View.Pane.Room.ignoreUser(d,c.getJid())}},unignore:{requiredPermission:function(c,d){return d.getNick()!==c.getNick()&&Candy.Core.getUser().isInPrivacyList("ignore",c.getJid())},"class":"unignore",label:b.i18n._("unignoreActionLabel"),callback:function(f,d,c){Candy.View.Pane.Room.unignoreUser(d,c.getJid())}},kick:{requiredPermission:function(c,d){return d.getNick()!==c.getNick()&&d.isModerator()&&!c.isModerator()},"class":"kick",label:b.i18n._("kickActionLabel"),callback:function(f,d,c){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm,{_label:b.i18n._("reason"),_submit:b.i18n._("kickActionLabel")}),true);b("#context-modal-field").focus();b("#context-modal-form").submit(function(e){Candy.Core.Action.Jabber.Room.Admin.UserAction(d,c.getJid(),"kick",b("#context-modal-field").val());a.Chat.Modal.hide();return false})}},ban:{requiredPermission:function(c,d){return d.getNick()!==c.getNick()&&d.isModerator()&&!c.isModerator()},"class":"ban",label:b.i18n._("banActionLabel"),callback:function(f,d,c){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm,{_label:b.i18n._("reason"),_submit:b.i18n._("banActionLabel")}),true);b("#context-modal-field").focus();b("#context-modal-form").submit(function(g){Candy.Core.Action.Jabber.Room.Admin.UserAction(d,c.getJid(),"ban",b("#context-modal-field").val());a.Chat.Modal.hide();return false})}},subject:{requiredPermission:function(c,d){return d.getNick()===c.getNick()&&d.isModerator()},"class":"subject",label:b.i18n._("setSubjectActionLabel"),callback:function(f,d,c){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm,{_label:b.i18n._("subject"),_submit:b.i18n._("setSubjectActionLabel")}),true);b("#context-modal-field").focus();b("#context-modal-form").submit(function(g){Candy.Core.Action.Jabber.Room.Admin.SetSubject(d,b("#context-modal-field").val());a.Chat.Modal.hide();g.preventDefault()})}}}},showEmoticonsMenu:function(h){h=b(h);var k=h.offset(),j=b("#context-menu"),g=b("ul",j),e="",d;b("#tooltip").hide();for(d=Candy.Util.Parser.emoticons.length-1;d>=0;d--){e=''+Candy.Util.Parser.emoticons[d].plain+''+e}g.html('
  • '+e+"
  • ");g.find("img").click(function(){var i=Candy.View.Pane.Room.getPane(Candy.View.getCurrent().roomJid,".message-form").children(".field"),m=i.val(),l=b(this).attr("alt")+" ";i.val(m?m+" "+l:l).focus()});var c=Candy.Util.getPosLeftAccordingToWindowBounds(j,k.left),f=Candy.Util.getPosTopAccordingToWindowBounds(j,k.top);j.css({left:c.px,top:f.px,backgroundPosition:c.backgroundPositionAlignment+" "+f.backgroundPositionAlignment});j.fadeIn("fast");return true}}};a.Room={init:function(d,c,e){e=e||"groupchat";if(Candy.Util.isEmptyObject(a.Chat.rooms)){a.Chat.Toolbar.show()}var f=Candy.Util.jidToId(d);a.Chat.rooms[d]={id:f,usercount:0,name:c,type:e,messageCount:0,scrollPosition:-1};b("#chat-rooms").append(Mustache.to_html(Candy.View.Template.Room.pane,{roomId:f,roomJid:d,roomType:e,form:{_messageSubmit:b.i18n._("messageSubmit")},roster:{_userOnline:b.i18n._("userOnline")}},{roster:Candy.View.Template.Roster.pane,messages:Candy.View.Template.Message.pane,form:Candy.View.Template.Room.form}));a.Chat.addTab(d,c,e);a.Room.getPane(d,".message-form").submit(a.Message.submit);Candy.View.Event.Room.onAdd({roomJid:d,type:e,element:a.Room.getPane(d)});return f},show:function(c){var d=a.Chat.rooms[c].id;b(".room-pane").each(function(){var e=b(this);if(e.attr("id")===("chat-room-"+d)){e.show();Candy.View.getCurrent().roomJid=c;a.Chat.updateToolbar(c);a.Chat.setActiveTab(c);a.Chat.clearUnreadMessages(c);a.Room.setFocusToForm(c);a.Room.scrollToBottom(c);Candy.View.Event.Room.onShow({roomJid:c,element:e})}else{e.hide();Candy.View.Event.Room.onHide({roomJid:c,element:e})}})},setSubject:function(c,e){var d=Mustache.to_html(Candy.View.Template.Room.subject,{subject:e,roomName:a.Chat.rooms[c].name,_roomSubject:b.i18n._("roomSubject"),time:Candy.Util.localizedTime(new Date().toGMTString())});a.Room.appendToMessagePane(c,d);a.Room.scrollToBottom(c);Candy.View.Event.Room.onSubjectChange({roomJid:c,element:a.Room.getPane(c),subject:e})},close:function(c){a.Chat.removeTab(c);a.Window.clearUnreadMessages();a.Room.getPane(c).remove();var d=b("#chat-rooms").children();if(Candy.View.getCurrent().roomJid===c){Candy.View.getCurrent().roomJid=null;if(d.length===0){a.Chat.allTabsClosed()}else{a.Room.show(d.last().attr("data-roomjid"))}}delete a.Chat.rooms[c];Candy.View.Event.Room.onClose({roomJid:c})},appendToMessagePane:function(c,d){a.Room.getPane(c,".message-pane").append(d);a.Chat.rooms[c].messageCount++;a.Room.sliceMessagePane(c)},sliceMessagePane:function(c){if(a.Window.autoscroll){var d=Candy.View.getOptions().messages;if(a.Chat.rooms[c].messageCount>d.limit){a.Room.getPane(c,".message-pane").children().slice(0,d.remove*2).remove();a.Chat.rooms[c].messageCount-=d.remove}}},scrollToBottom:function(c){a.Room.onScrollToBottom(c)},onScrollToBottom:function(c){var d=a.Room.getPane(c,".message-pane-wrapper");d.scrollTop(d.prop("scrollHeight"))},onScrollToStoredPosition:function(c){if(a.Chat.rooms[c].scrollPosition>-1){var d=a.Room.getPane(c,".message-pane-wrapper");d.scrollTop(a.Chat.rooms[c].scrollPosition);a.Chat.rooms[c].scrollPosition=-1}},setFocusToForm:function(c){var f=a.Room.getPane(c,".message-form");if(f){try{f.children(".field")[0].focus()}catch(d){}}},setUser:function(d,c){a.Chat.rooms[d].user=c;var f=a.Room.getPane(d),e=b("#chat-pane");f.attr("data-userjid",c.getJid());if(c.isModerator()){if(c.getRole()===c.ROLE_MODERATOR){e.addClass("role-moderator")}if(c.getAffiliation()===c.AFFILIATION_OWNER){e.addClass("affiliation-owner")}}else{e.removeClass("role-moderator affiliation-owner")}a.Chat.Context.init()},getUser:function(c){return a.Chat.rooms[c].user},ignoreUser:function(c,d){Candy.Core.Action.Jabber.Room.IgnoreUnignore(d);Candy.View.Pane.Room.addIgnoreIcon(c,d)},unignoreUser:function(c,d){Candy.Core.Action.Jabber.Room.IgnoreUnignore(d);Candy.View.Pane.Room.removeIgnoreIcon(c,d)},addIgnoreIcon:function(c,d){if(Candy.View.Pane.Chat.rooms[d]){b("#user-"+Candy.View.Pane.Chat.rooms[d].id+"-"+Candy.Util.jidToId(d)).addClass("status-ignored")}if(Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(c)]){b("#user-"+Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(c)].id+"-"+Candy.Util.jidToId(d)).addClass("status-ignored")}},removeIgnoreIcon:function(c,d){if(Candy.View.Pane.Chat.rooms[d]){b("#user-"+Candy.View.Pane.Chat.rooms[d].id+"-"+Candy.Util.jidToId(d)).removeClass("status-ignored")}if(Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(c)]){b("#user-"+Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(c)].id+"-"+Candy.Util.jidToId(d)).removeClass("status-ignored")}},getPane:function(c,d){if(a.Chat.rooms[c]){if(d){if(a.Chat.rooms[c]["pane-"+d]){return a.Chat.rooms[c]["pane-"+d]}else{a.Chat.rooms[c]["pane-"+d]=b("#chat-room-"+a.Chat.rooms[c].id).find(d);return a.Chat.rooms[c]["pane-"+d]}}else{return b("#chat-room-"+a.Chat.rooms[c].id)}}}};a.PrivateRoom={open:function(e,c,f,g){var d=g?Candy.Core.getUser():a.Room.getUser(Strophe.getBareJidFromJid(e));if(Candy.Core.getUser().isInPrivacyList("ignore",e)){return false}if(!a.Chat.rooms[e]){a.Room.init(e,c,"chat")}if(f){a.Room.show(e)}a.Roster.update(e,new Candy.Core.ChatUser(e,c),"join",d);a.Roster.update(e,d,"join",d);a.PrivateRoom.setStatus(e,"join");if(g){a.Chat.infoMessage(e,b.i18n._("presenceUnknownWarningSubject"),b.i18n._("presenceUnknownWarning"))}Candy.View.Event.Room.onAdd({roomJid:e,type:"chat",element:a.Room.getPane(e)})},setStatus:function(d,c){var e=a.Room.getPane(d,".message-form");if(c==="join"){a.Chat.getTab(d).addClass("online").removeClass("offline");e.children(".field").removeAttr("disabled");e.children(".submit").removeAttr("disabled");a.Chat.getTab(d)}else{a.Chat.getTab(d).addClass("offline").removeClass("online");e.children(".field").attr("disabled",true);e.children(".submit").attr("disabled",true)}}};a.Roster={update:function(n,i,h,e){var f=a.Chat.rooms[n].id,k=Candy.Util.jidToId(i.getJid()),c=-1;if(h==="join"){c=1;var j=Mustache.to_html(Candy.View.Template.Roster.user,{roomId:f,userId:k,userJid:i.getJid(),nick:i.getNick(),displayNick:Candy.Util.crop(i.getNick(),Candy.View.getOptions().crop.roster.nickname),role:i.getRole(),affiliation:i.getAffiliation(),me:e!==undefined&&i.getNick()===e.getNick(),tooltipRole:b.i18n._("tooltipRole"),tooltipIgnored:b.i18n._("tooltipIgnored")}),m=b("#user-"+f+"-"+k);if(m.length<1){var d=false,l=a.Room.getPane(n,".roster-pane");if(l.children().length>0){var g=i.getNick().toUpperCase();l.children().each(function(){var o=b(this);if(o.attr("data-nick").toUpperCase()>g){o.before(j);d=true;return false}return true})}if(!d){l.append(j)}a.Roster.joinAnimation("user-"+f+"-"+k);if(e!==undefined&&i.getNick()!==e.getNick()&&a.Room.getUser(n)){if(a.Chat.rooms[n].type==="chat"){a.Chat.onInfoMessage(n,b.i18n._("userJoinedRoom",[i.getNick()]))}else{a.Chat.infoMessage(n,b.i18n._("userJoinedRoom",[i.getNick()]))}}}else{c=0;m.replaceWith(j);b("#user-"+f+"-"+k).css({opacity:1}).show()}if(e!==undefined&&e.getNick()===i.getNick()){a.Room.setUser(n,i)}else{b("#user-"+f+"-"+k).click(a.Roster.userClick)}b("#user-"+f+"-"+k+" .context").click(function(o){a.Chat.Context.show(o.currentTarget,n,i);o.stopPropagation()});if(e!==undefined&&e.isInPrivacyList("ignore",i.getJid())){Candy.View.Pane.Room.addIgnoreIcon(n,i.getJid())}}else{if(h==="leave"){a.Roster.leaveAnimation("user-"+f+"-"+k);if(a.Chat.rooms[n].type==="chat"){a.Chat.onInfoMessage(n,b.i18n._("userLeftRoom",[i.getNick()]))}else{a.Chat.infoMessage(n,b.i18n._("userLeftRoom",[i.getNick()]))}}else{if(h==="kick"){a.Roster.leaveAnimation("user-"+f+"-"+k);a.Chat.onInfoMessage(n,b.i18n._("userHasBeenKickedFromRoom",[i.getNick()]))}else{if(h==="ban"){a.Roster.leaveAnimation("user-"+f+"-"+k);a.Chat.onInfoMessage(n,b.i18n._("userHasBeenBannedFromRoom",[i.getNick()]))}}}}Candy.View.Pane.Chat.rooms[n].usercount+=c;if(n===Candy.View.getCurrent().roomJid){Candy.View.Pane.Chat.Toolbar.updateUsercount(Candy.View.Pane.Chat.rooms[n].usercount)}Candy.View.Event.Roster.onUpdate({roomJid:n,user:i,action:h,element:b("#user-"+f+"-"+k)})},userClick:function(){var c=b(this);a.PrivateRoom.open(c.attr("data-jid"),c.attr("data-nick"),true)},joinAnimation:function(c){b("#"+c).stop(true).slideDown("normal",function(){b(this).animate({opacity:1})})},leaveAnimation:function(c){b("#"+c).stop(true).attr("id","#"+c+"-leaving").animate({opacity:0},{complete:function(){b(this).slideUp("normal",function(){b(this).remove()})}})}};a.Message={submit:function(e){var c=Candy.View.Pane.Chat.rooms[Candy.View.getCurrent().roomJid].type,d=b(this).children(".field").val().substring(0,Candy.View.getOptions().crop.message.body);d=Candy.View.Event.Message.beforeSend(d);Candy.Core.Action.Jabber.Room.Message(Candy.View.getCurrent().roomJid,d,c);if(c==="chat"&&d){a.Message.show(Candy.View.getCurrent().roomJid,a.Room.getUser(Candy.View.getCurrent().roomJid).getNick(),d)}b(this).children(".field").val("").focus();e.preventDefault()},show:function(c,d,g,h){g=Candy.Util.Parser.all(g.substring(0,Candy.View.getOptions().crop.message.body));g=Candy.View.Event.Message.beforeShow({roomJid:c,nick:d,message:g});if(!g){return}var e=Mustache.to_html(Candy.View.Template.Message.item,{name:d,displayName:Candy.Util.crop(d,Candy.View.getOptions().crop.message.nickname),message:g,time:Candy.Util.localizedTime(h||new Date().toGMTString())});a.Room.appendToMessagePane(c,e);var f=a.Room.getPane(c,".message-pane").children().last();f.find("a.name").click(function(i){i.preventDefault();if(d!==a.Room.getUser(Candy.View.getCurrent().roomJid).getNick()&&Candy.Core.getRoom(c).getRoster().get(c+"/"+d)){Candy.View.Pane.PrivateRoom.open(c+"/"+d,d,true)}});if(Candy.View.getCurrent().roomJid!==c||!a.Window.hasFocus()){a.Chat.increaseUnreadMessages(c);if(Candy.View.Pane.Chat.rooms[c].type==="chat"&&!a.Window.hasFocus()){a.Chat.Toolbar.playSound()}}if(Candy.View.getCurrent().roomJid===c){a.Room.scrollToBottom(c)}Candy.View.Event.Message.onShow({roomJid:c,element:f,nick:d,message:g})}};return a}(Candy.View.Pane||{},jQuery));Candy.View.Template=(function(a){a.Window={unreadmessages:"({{count}}) {{title}}"};a.Chat={pane:'
    {{> tabs}}{{> toolbar}}{{> rooms}}
    {{> modal}}',rooms:'
    ',tabs:'
      ',tab:'
    • {{#privateUserChat}}@{{/privateUserChat}}{{name}}\u00D7
    • ',modal:'
      ',adminMessage:'
      {{time}}
      {{sender}}{{subject}} {{message}}
      ',infoMessage:'
      {{time}}
      {{subject}} {{message}}
      ',toolbar:'
      • {{> soundcontrol}}
      ',soundcontrol:' % endif +% if show_chat: + + + + +% endif + % if timer_expiration_duration: @@ -148,6 +189,18 @@
      +% if show_chat: +
      +
      + Open Chat + Close Chat +
      +
      + ## The Candy.js plugin wants to render in an element with #candy +
      +
      +
      +% endif % if course.show_calculator: