mention js working minus tracking keypresses with the hidden message field.
This commit is contained in:
parent
7d21f7bfdd
commit
3efc31c68f
4 changed files with 153 additions and 60 deletions
|
|
@ -160,7 +160,7 @@ class Person < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def as_json(opts={})
|
||||
{:id => self.guid, :name => self.name, :avatar => self.profile.image_url(:thumb_small), :url => "/people/#{self.id}"}
|
||||
{:id => self.guid, :name => self.name, :avatar => self.profile.image_url(:thumb_small), :handle => self.diaspora_handle, :url => "/people/#{self.id}"}
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class StatusMessage < Post
|
|||
identifiers = self.message.scan(regex).map do |match|
|
||||
match.last
|
||||
end
|
||||
Person.where(:diaspora_handle => identifiers)
|
||||
self.person.owner.contact_people.where(:diaspora_handle => identifiers)
|
||||
end
|
||||
|
||||
def to_activity
|
||||
|
|
|
|||
|
|
@ -36,11 +36,6 @@ var Publisher = {
|
|||
return Publisher.cachedHiddenInput;
|
||||
},
|
||||
|
||||
appendToHiddenField: function(evt){
|
||||
Publisher.hiddenInput().val(
|
||||
Publisher.input().val());
|
||||
},
|
||||
|
||||
autocompletion: {
|
||||
options : function(){return {
|
||||
minChars : 1,
|
||||
|
|
@ -58,13 +53,71 @@ var Publisher = {
|
|||
return row.name;
|
||||
}
|
||||
};},
|
||||
|
||||
onSelect : function(input, data, formatted) {
|
||||
addMentionToVisibleInput(input, formatted);
|
||||
hiddenMentionFromPerson : function(personData){
|
||||
return "@{" + personData.name + "; " + personData.handle + "}";
|
||||
},
|
||||
|
||||
addMentionToVisibleInput: function(input, formatted){
|
||||
var cursorIndex = input[0].selectionStart;
|
||||
onSelect : function(visibleInput, data, formatted) {
|
||||
var visibleCursorIndex = visibleInput[0].selectionStart;
|
||||
var visibleLoc = Publisher.autocompletion.addMentionToInput(visibleInput, visibleCursorIndex, formatted);
|
||||
|
||||
|
||||
var hiddenCursorIndex = visibleCursorIndex + Publisher.autocompletion.mentionList.offsetFrom(visibleCursorIndex);
|
||||
var hiddenLoc = Publisher.autocompletion.addMentionToInput(Publisher.hiddenInput(), hiddenCursorIndex, Publisher.autocompletion.hiddenMentionFromPerson(data));
|
||||
var mention = { visibleStart: visibleLoc[0],
|
||||
visibleEnd : visibleLoc[1],
|
||||
hiddenStart : hiddenLoc[0],
|
||||
hiddenEnd : hiddenLoc[1]
|
||||
};
|
||||
},
|
||||
|
||||
mentionList : {
|
||||
mentions : [],
|
||||
push : function(mention){
|
||||
mention.offset = mention.hiddenEnd - mention.visibleEnd;
|
||||
this.mentions.push(mention);
|
||||
},
|
||||
keypressAt : function(visibleCursorIndex){
|
||||
var mentionIndex = this.mentionAt(visibleCursorIndex);
|
||||
var mention = this.mentions[mentionIndex];
|
||||
if(!mention){return;}
|
||||
var visibleMentionString = Publisher.input().val().slice(mention.visibleStart, mention.visibleEnd);
|
||||
var hiddenContent = Publisher.hiddenInput().val();
|
||||
hiddenContent = hiddenContent.slice(0,mention.hiddenStart) +
|
||||
visibleMentionString +
|
||||
hiddenContent.slice(mention.hiddenEnd);
|
||||
Publisher.hiddenInput().val(hiddenContent);
|
||||
|
||||
this.mentions.splice(mentionIndex, 1);
|
||||
},
|
||||
mentionAt : function(visibleCursorIndex){
|
||||
for(i in this.mentions){
|
||||
var mention = this.mentions[i];
|
||||
if(visibleCursorIndex >= mention.visibleStart && visibleCursorIndex < mention.visibleEnd){
|
||||
return i;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
offsetFrom: function(visibleCursorIndex){
|
||||
var mention = {visibleStart : -1, fake: true};
|
||||
var currentMention;
|
||||
for(i in this.mentions){
|
||||
currentMention = this.mentions[i];
|
||||
if(visibleCursorIndex >= currentMention.visibleStart &&
|
||||
currentMention.visibleStart > mention.visibleStart){
|
||||
mention = currentMention;
|
||||
}
|
||||
}
|
||||
if(mention && !mention.fake){
|
||||
return mention.offset;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addMentionToInput: function(input, cursorIndex, formatted){
|
||||
var inputContent = input.val();
|
||||
|
||||
var stringLoc = Publisher.autocompletion.findStringToReplace(input.val(), cursorIndex);
|
||||
|
|
@ -73,12 +126,13 @@ var Publisher = {
|
|||
var stringEnd = inputContent.slice(stringLoc[1]);
|
||||
|
||||
input.val(stringStart + formatted + stringEnd);
|
||||
return [stringStart.length, stringStart.length + stringLoc[1]]
|
||||
},
|
||||
|
||||
findStringToReplace: function(value, cursorIndex){
|
||||
var atLocation = value.lastIndexOf('@', cursorIndex);
|
||||
if(atLocation == -1){return [0,0];}
|
||||
var nextAt = value.indexOf('@', cursorIndex+1);
|
||||
var nextAt = value.indexOf(' @', cursorIndex+1);
|
||||
|
||||
if(nextAt == -1){nextAt = value.length;}
|
||||
return [atLocation, nextAt];
|
||||
|
|
@ -115,6 +169,7 @@ var Publisher = {
|
|||
initialize: function() {
|
||||
Publisher.cachedForm = false;
|
||||
Publisher.cachedInput = false;
|
||||
Publisher.cachedHiddenInput = false;
|
||||
$("div.public_toggle input").live("click", function(evt) {
|
||||
$("#publisher_service_icons").toggleClass("dim");
|
||||
if ($(this).attr('checked') == true) {
|
||||
|
|
@ -127,9 +182,7 @@ var Publisher = {
|
|||
};
|
||||
|
||||
Publisher.autocompletion.initialize();
|
||||
Publisher.updateHiddenField();
|
||||
Publisher.form().find('#status_message_fake_message').bind('keydown',
|
||||
Publisher.updateHiddenField);
|
||||
Publisher.hiddenInput().val(Publisher.input().val());
|
||||
Publisher.form().find("textarea").bind("focus", function(evt) {
|
||||
Publisher.open();
|
||||
$(this).css('min-height', '42px');
|
||||
|
|
|
|||
|
|
@ -6,21 +6,6 @@
|
|||
describe("Publisher", function() {
|
||||
|
||||
describe("initialize", function(){
|
||||
it("calls updateHiddenField", function(){
|
||||
spec.loadFixture('aspects_index_prefill');
|
||||
spyOn(Publisher, 'updateHiddenField');
|
||||
Publisher.initialize();
|
||||
expect(Publisher.updateHiddenField).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("attaches updateHiddenField to the keydown handler on fake_message", function(){
|
||||
spec.loadFixture('aspects_index_prefill');
|
||||
spyOn(Publisher, 'updateHiddenField');
|
||||
Publisher.initialize();
|
||||
Publisher.form().find('#status_message_fake_message').keydown();
|
||||
expect(Publisher.updateHiddenField.mostRecentCall.args[0].type).toBe('keydown');
|
||||
});
|
||||
|
||||
it("calls close when it does not have text", function(){
|
||||
spec.loadFixture('aspects_index');
|
||||
spyOn(Publisher, 'close');
|
||||
|
|
@ -67,17 +52,6 @@ describe("Publisher", function() {
|
|||
expect(Publisher.form().find(".options_and_submit:visible").length).toBe(0);
|
||||
});
|
||||
});
|
||||
describe("updateHiddenField", function(){
|
||||
beforeEach(function(){
|
||||
spec.loadFixture('aspects_index_prefill');
|
||||
});
|
||||
|
||||
it("copies the value of fake_message to message",function(){
|
||||
Publisher.updateHiddenField();
|
||||
expect(Publisher.form().find('#status_message_message').val()).toBe(
|
||||
Publisher.form().find('#status_message_fake_message').val());
|
||||
});
|
||||
});
|
||||
describe("input", function(){
|
||||
beforeEach(function(){
|
||||
spec.loadFixture('aspects_index_prefill');
|
||||
|
|
@ -88,6 +62,8 @@ describe("Publisher", function() {
|
|||
});
|
||||
});
|
||||
describe("autocompletion", function(){
|
||||
describe("onKeypress", function(){
|
||||
});,
|
||||
describe("searchTermFromValue", function(){
|
||||
var func;
|
||||
beforeEach(function(){func = Publisher.autocompletion.searchTermFromValue;});
|
||||
|
|
@ -124,56 +100,120 @@ describe("Publisher", function() {
|
|||
describe("onSelect", function(){
|
||||
|
||||
});
|
||||
describe("addMentionToHiddenInput", function(){
|
||||
var func;
|
||||
var input;
|
||||
|
||||
describe("mentionList", function(){
|
||||
var visibleInput, visibleVal,
|
||||
hiddenInput, hiddenVal,
|
||||
list,
|
||||
func,
|
||||
mention;
|
||||
beforeEach(function(){
|
||||
spec.loadFixture('aspects_index');
|
||||
func = Publisher.autocompletion.addMentionToHiddenInput;
|
||||
input = Publisher.input();
|
||||
list = Publisher.autocompletion.mentionList;
|
||||
func = list.keypressAt;
|
||||
visibleInput = Publisher.input();
|
||||
hiddenInput = Publisher.hiddenInput();
|
||||
mention = { visibleStart : 0,
|
||||
visibleEnd : 5,
|
||||
hiddenStart : 0,
|
||||
hiddenEnd : 21
|
||||
};
|
||||
list.mentions = [];
|
||||
list.push(mention);
|
||||
visibleVal = "Danny loves testing javascript";
|
||||
visibleInput.val(visibleVal);
|
||||
hiddenVal = "@{Danny; dan@pod.org} loves testing javascript";
|
||||
hiddenInput.val(hiddenVal);
|
||||
});
|
||||
describe("push", function(){
|
||||
it("adds mention to mentions array", function(){
|
||||
expect(list.mentions.length).toBe(1);
|
||||
expect(list.mentions[0]).toBe(mention)
|
||||
});
|
||||
});
|
||||
describe("mentionAt", function(){
|
||||
it("returns the location of the mention at that location in the mentions array", function(){
|
||||
expect(list.mentions[list.mentionAt(3)]).toBe(mention);
|
||||
});
|
||||
it("returns null if there is no mention", function(){
|
||||
expect(list.mentionAt(8)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
describe("keypressAt", function(){
|
||||
it("does nothing if there is no visible mention at that index", function(){
|
||||
list.keypressAt(8);
|
||||
expect(visibleInput.val()).toBe(visibleVal)
|
||||
expect(hiddenInput.val()).toBe(hiddenVal)
|
||||
});
|
||||
it("deletes the mention from the hidden field if there is a mention", function(){
|
||||
list.keypressAt(3);
|
||||
expect(visibleInput.val()).toBe(visibleVal)
|
||||
expect(hiddenInput.val()).toBe(visibleVal)
|
||||
});
|
||||
it("deletes the mention from the list", function(){
|
||||
list.keypressAt(3);
|
||||
expect(list.mentionAt(3)).toBeFalsy();
|
||||
});
|
||||
it("updates the offsets of the remaining mentions in the list");
|
||||
});
|
||||
describe("offsetFrom", function(){
|
||||
var func;
|
||||
beforeEach(function(){
|
||||
func = list.offsetFrom;
|
||||
});
|
||||
it("returns the offset of the mention at that location", function(){
|
||||
expect(list.offsetFrom(3)).toBe(mention.offset);
|
||||
});
|
||||
it("returns the offset of the previous mention if there is no mention there", function(){
|
||||
expect(list.offsetFrom(10)).toBe(mention.offset);
|
||||
});
|
||||
it("returns 0 if there are no mentions", function(){
|
||||
list.mentions = [];
|
||||
expect(list.offsetFrom(8)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("addMentionToVisibleInput", function(){
|
||||
|
||||
|
||||
describe("addMentionToInput", function(){
|
||||
var func;
|
||||
var input;
|
||||
var replaceWith;
|
||||
beforeEach(function(){
|
||||
spec.loadFixture('aspects_index');
|
||||
func = Publisher.autocompletion.addMentionToVisibleInput;
|
||||
func = Publisher.autocompletion.addMentionToInput;
|
||||
input = Publisher.input();
|
||||
replaceWith = "Replace with this.";
|
||||
});
|
||||
it("replaces everything after an @ if the cursor is a word after that @", function(){
|
||||
input.val('not @dan grip');
|
||||
func(input, replaceWith);
|
||||
input[0].selectionStart = 13;
|
||||
var cursorIndex = 13;
|
||||
func(input, cursorIndex, replaceWith);
|
||||
expect(input.val()).toBe('not ' + replaceWith);
|
||||
});
|
||||
it("replaces everything after an @ if the cursor is after that @", function(){
|
||||
input.val('not @dan grip');
|
||||
input[0].selectionStart = 7;
|
||||
func(input, replaceWith);
|
||||
var cursorIndex = 7;
|
||||
func(input, cursorIndex, replaceWith);
|
||||
expect(input.val()).toBe('not ' + replaceWith);
|
||||
});
|
||||
it("replaces everything after an @ at the start of the line", function(){
|
||||
input.val('@dan grip');
|
||||
input[0].selectionStart = 9;
|
||||
func(input, replaceWith);
|
||||
var cursorIndex = 9;
|
||||
func(input, cursorIndex, replaceWith);
|
||||
expect(input.val()).toBe(replaceWith);
|
||||
});
|
||||
it("replaces everything between @s if there are 2 @s and the cursor is between them", function(){
|
||||
input.val('@asdpo aoisdj @asodk');
|
||||
input[0].selectionStart = 8;
|
||||
func(input, replaceWith);
|
||||
var cursorIndex = 8;
|
||||
func(input, cursorIndex, replaceWith);
|
||||
expect(input.val()).toBe(replaceWith + ' @asodk');
|
||||
});
|
||||
it("replaces everything after the 2nd @ if there are 2 @s and the cursor after them", function(){
|
||||
input.val('@asod asdo @asd asok');
|
||||
input[0].selectionStart = 15;
|
||||
func(input, replaceWith);
|
||||
var cursorIndex = 15;
|
||||
func(input, cursorIndex, replaceWith);
|
||||
expect(input.val()).toBe('@asod asdo ' + replaceWith);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue