Skip to content

Commit b47d9b4

Browse files
committed
Added 'history' capability to the chatbox input.
1 parent 022a643 commit b47d9b4

File tree

3 files changed

+162
-3
lines changed

3 files changed

+162
-3
lines changed

app/assets/javascripts/application.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@
2121
//= require_tree .
2222
//= stub admin/admin
2323
//= require lib/jquery.atwho
24-
//= require lib/jquery.caret
24+
//= require lib/jquery.caret
25+
//= require lib/jquery.inputHistory

app/assets/javascripts/backbone/views/chatbox.js.coffee

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Kandan.Views.Chatbox extends Backbone.View
1111

1212

1313
postMessageOnEnter: (event)->
14-
if event.keyCode == 13
14+
if event.keyCode == 13 && !(event.metaKey || event.shiftKey || event.altKey || event.ctrlKey)
1515
@postMessage(event)
1616
event.preventDefault()
1717

@@ -39,10 +39,13 @@ class Kandan.Views.Chatbox extends Backbone.View
3939
$("#activity-c#{model.cid}").attr("id", "activity-#{model.get('id')}")
4040
theId = Kandan.Helpers.Channels.getActiveChannelId()
4141
Kandan.Helpers.Channels.scrollToLatestMessage(theId)
42-
42+
4343
})
4444

4545
render: ()->
4646
@channel = @options.channel
4747
$(@el).html(@template())
48+
$(@el).find('.chat-input').inputHistory {
49+
size: 20
50+
}
4851
@
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* This file is part of Kandan.
3+
* https://github.com/kandanapp/kandan
4+
*
5+
* Kandan's code and assets are dual-licensed. Kandan is available
6+
* generally under the AGPL, and also under a custom license via
7+
* special agreement. See LICENSE for the AGPL terms, and contact us
8+
* at <[email protected]> if you're interested in development of
9+
* Kandan under a custom license.
10+
*/
11+
12+
/*
13+
This code is adapted from https://github.com/jch/jquery.inputHistory
14+
15+
Copyright (c) 2012, Jerry Cheung All rights reserved.
16+
17+
Redistribution and use in source and binary forms, with or without
18+
modification, are permitted provided that the following conditions are
19+
met:
20+
21+
Redistributions of source code must retain the above copyright notice,
22+
this list of conditions and the following disclaimer. Redistributions
23+
in binary form must reproduce the above copyright notice, this list of
24+
conditions and the following disclaimer in the documentation and/or
25+
other materials provided with the distribution.
26+
27+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38+
*/
39+
(function() {
40+
41+
(function($) {
42+
var InputHistory, normalizeKeyHandler;
43+
InputHistory = (function() {
44+
45+
InputHistory.name = 'InputHistory';
46+
47+
function InputHistory(options) {
48+
this.size = options.size || 50;
49+
this.record = [];
50+
this.values = [];
51+
this.index = 0;
52+
}
53+
54+
InputHistory.prototype.push = function(message) {
55+
/* only add to the history if the first item in the
56+
history isn't the same */
57+
if ( message != this.record[0] ) {
58+
this.record.unshift(message);
59+
}
60+
return this.record.splice(this.size);
61+
};
62+
63+
InputHistory.prototype.prev = function(val) {
64+
this.index += 1;
65+
return this.values[this.index];
66+
};
67+
68+
InputHistory.prototype.next = function() {
69+
this.index -= 1;
70+
return this.values[this.index];
71+
};
72+
73+
InputHistory.prototype.reset = function() {
74+
this.index = 0;
75+
this.values = this.record.slice(0);
76+
this.values.unshift("");
77+
}
78+
79+
InputHistory.prototype.hasNext = function() {
80+
return this.index != 0;
81+
}
82+
83+
InputHistory.prototype.hasPrev = function() {
84+
return this.index < this.values.length - 1;
85+
}
86+
87+
InputHistory.prototype.currentize = function(val) {
88+
this.values[this.index] = val;
89+
}
90+
91+
return InputHistory;
92+
93+
})();
94+
normalizeKeyHandler = function(raw, elseHandler) {
95+
elseHandler || (elseHandler = function(e) {});
96+
switch (typeof raw) {
97+
case 'number':
98+
return function(e) {
99+
return e.keyCode === raw;
100+
};
101+
case 'string':
102+
return function(e) {
103+
return "" + e.keyCode === raw;
104+
};
105+
case 'function':
106+
return raw;
107+
default:
108+
return elseHandler;
109+
}
110+
};
111+
return $.fn.inputHistory = function(options) {
112+
var history,
113+
_this = this;
114+
options || (options = {});
115+
options.data || (options.data = 'inputHistory');
116+
options.store = normalizeKeyHandler(options.store, function(e) {
117+
return e.keyCode === 13 && !e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey;
118+
});
119+
options.prev = normalizeKeyHandler(options.prev, function(e) {
120+
return (e.keyCode === 38 && e.altKey) || (e.ctrlKey && e.keyCode === 80);
121+
});
122+
options.next = normalizeKeyHandler(options.next, function(e) {
123+
return (e.keyCode === 40 && e.altKey) || (e.ctrlKey && e.keyCode === 78);
124+
});
125+
options.reset = normalizeKeyHandler(options.reset, function(e) {
126+
return e.keyCode === 27;
127+
});
128+
history = this.data(options.data) || new InputHistory(options);
129+
this.data(options.data, history);
130+
this.bind('keydown', function(e) {
131+
history.currentize(_this.val());
132+
if (options.store(e) && _this.val() != '') {
133+
history.push(_this.val());
134+
history.reset();
135+
} else if (options.prev(e)) {
136+
if (history.hasPrev()) {
137+
_this.val(history.prev());
138+
}
139+
e.preventDefault();
140+
} else if (options.next(e)) {
141+
if (history.hasNext()) {
142+
_this.val(history.next())
143+
}
144+
e.preventDefault();
145+
} else if (options.reset(e)) {
146+
_this.val("");
147+
history.reset();
148+
e.preventDefault();
149+
}
150+
});
151+
return this;
152+
};
153+
})(jQuery);
154+
155+
}).call(this);

0 commit comments

Comments
 (0)