diff --git a/test/client-old/spec/controllers/chatCtrlSpec.js b/test/client-old/spec/controllers/chatCtrlSpec.js index 81a19f8efc..2b5d2a0f45 100644 --- a/test/client-old/spec/controllers/chatCtrlSpec.js +++ b/test/client-old/spec/controllers/chatCtrlSpec.js @@ -1,14 +1,14 @@ 'use strict'; describe("Chat Controller", function() { - var scope, ctrl, user, $rootScope, $controller; + var scope, ctrl, user, $rootScope, $controller, $httpBackend, html; beforeEach(function() { module(function($provide) { $provide.value('User', {}); }); - inject(function(_$rootScope_, _$controller_){ + inject(function(_$rootScope_, _$controller_, _$compile_, _$httpBackend_){ user = specHelper.newUser(); user._id = "unique-user-id"; $rootScope = _$rootScope_; @@ -16,13 +16,20 @@ describe("Chat Controller", function() { scope = _$rootScope_.$new(); $controller = _$controller_; + $httpBackend = _$httpBackend_; // Load RootCtrl to ensure shared behaviors are loaded $controller('RootCtrl', {$scope: scope, User: {user: user}}); - ctrl = $controller('ChatCtrl', {$scope: scope}); + html = _$compile_('
')(scope); + document.body.appendChild(html[0]); + ctrl = $controller('ChatCtrl', {$scope: scope, $element: html}); }); }); + + afterEach(function() { + html.remove(); + }); describe('copyToDo', function() { it('when copying a user message it opens modal with information from message', function() { @@ -68,5 +75,47 @@ describe("Chat Controller", function() { })); }); }); + + it('updates model on enter key press', function() { + // Set initial state of the page with some dummy data. + scope.group = { name: 'group' }; + + // The main controller is going to try to fetch the template right off. + // No big deal, just return an empty string. + $httpBackend.when('GET', 'partials/main.html').respond(''); + + // Let the page settle, and the controllers set their initial state. + $rootScope.$digest(); + + // Watch for calls to postChat & make sure it doesn't do anything. + let postChatSpy = sandbox.stub(scope, 'postChat'); + + // Pretend we typed 'aaa' into the textarea. + var textarea = html.find('textarea'); + textarea[0].value = 'aaa'; + let inputEvent = new Event('input'); + textarea[0].dispatchEvent(inputEvent); + + // Give a change for the ng-model watchers to notice that the value in the + // textarea has changed. + $rootScope.$digest(); + + // Since no time has elapsed and we debounce the model change, we should + // see no model update just yet. + expect(scope.message.content).to.equal(''); + + // Now, press the enter key in the textarea. We use jquery here to paper + // over browser differences with initializing the keyboard event. + var keyboardEvent = jQuery.Event('keydown', {keyCode: 13, key: 'Enter', metaKey: true}); + jQuery(textarea).trigger(keyboardEvent); + + // Now, allow the model to update given the changes to the page still + // without letting any time elapse... + $rootScope.$digest(); + + // ... and nevertheless seeing the desired call to postChat with the right + // data. Yay! + postChatSpy.should.have.been.calledWith(scope.group, 'aaa'); + }); }); diff --git a/website/client-old/js/controllers/chatCtrl.js b/website/client-old/js/controllers/chatCtrl.js index 9c5b8124f0..99ef552c9c 100644 --- a/website/client-old/js/controllers/chatCtrl.js +++ b/website/client-old/js/controllers/chatCtrl.js @@ -60,12 +60,6 @@ habitrpg.controller('ChatCtrl', ['$scope', 'Groups', 'Chat', 'User', '$http', 'A }); } - $scope.keyDownListener = function (e) { - if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { - $scope.postChat($scope.group, $scope.message.content); - } - }; - $scope.deleteChatMessage = function(group, message){ if(message.uuid === User.user.id || (User.user.backer && User.user.contributor.admin)){ var previousMsg = (group.chat && group.chat[0]) ? group.chat[0].id : false; diff --git a/website/client-old/js/directives/submit-form-on-enter.directive.js b/website/client-old/js/directives/submit-form-on-enter.directive.js new file mode 100644 index 0000000000..31ad88253c --- /dev/null +++ b/website/client-old/js/directives/submit-form-on-enter.directive.js @@ -0,0 +1,25 @@ +'use strict'; + +(function(){ + + angular + .module('habitrpg') + .directive('submitOnMetaEnter', submitOnMetaEnter); + + function submitOnMetaEnter() { + return { + restrict: 'A', + link: function($scope, element, attrs) { + element.on('keydown', function(event) { + if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) { + // Note that we use the normal browser way to invoke the submit + // event, because jquery's triggerHandler executes events in a + // strange order! + var event = new Event('submit'); + element[0].form.dispatchEvent(event); + } + }); + } + } + } +}()); diff --git a/website/client-old/manifest.json b/website/client-old/manifest.json index 537c83074f..5e7f31c037 100644 --- a/website/client-old/manifest.json +++ b/website/client-old/manifest.json @@ -76,13 +76,14 @@ "js/directives/close-menu.directive.js", "js/directives/expand-menu.directive.js", "js/directives/from-now.directive.js", + "js/directives/focus-element.directive.js", "js/directives/habitrpg-tasks.directive.js", "js/directives/hrpg-sort-checklist.directive.js", "js/directives/hrpg-sort-tags.directive.js", "js/directives/hrpg-sort-tasks.directive.js", "js/directives/popover-html-popup.directive.js", "js/directives/popover-html.directive.js", - "js/directives/focus-element.directive.js", + "js/directives/submit-form-on-enter.directive.js", "js/directives/when-scrolled.directive.js", "js/controllers/authCtrl.js", diff --git a/website/views/options/social/chat-box.jade b/website/views/options/social/chat-box.jade index 4b79a0ad55..98a44f9b47 100644 --- a/website/views/options/social/chat-box.jade +++ b/website/views/options/social/chat-box.jade @@ -8,7 +8,7 @@ div.chat-form.guidelines-not-accepted(ng-if='!user.flags.communityGuidelinesAcce form.chat-form(ng-if='user.flags.communityGuidelinesAccepted' ng-submit='postChat(group,message.content)') div(ng-controller='AutocompleteCtrl') - textarea.form-control(rows=4, ng-keydown='keyDownListener($event)', ng-model='message.content', updateinterval='250', flag='@', at-user, auto-complete placeholder="{{group._id == TAVERN_ID ? env.t('tavernCommunityGuidelinesPlaceholder') : ''}}", ng-disabled='_sending == true') + textarea.form-control(rows=4, submit-on-meta-enter, ng-model='message.content', ng-model-options='{debounce: 250}', updateinterval='250', flag='@', at-user, auto-complete placeholder="{{group._id == TAVERN_ID ? env.t('tavernCommunityGuidelinesPlaceholder') : ''}}", ng-disabled='_sending == true') span.user-list ul.list-at-user(ng-show="query") li(ng-repeat='msg in response | filter:filterUser | limitTo: 5', ng-click='performCompletion(msg)')