Skip to content
Extraits de code Groupes Projets
Valider 038599bf rédigé par Florian Staudacher's avatar Florian Staudacher
Parcourir les fichiers

update jquery.mentionsInput to latest version

+ make some tests a little nicer
parent ea8f358a
Branches
Étiquettes
Aucune requête de fusion associée trouvée
...@@ -3,12 +3,31 @@ var Mentions = { ...@@ -3,12 +3,31 @@ var Mentions = {
return mentionsInput.mentionsInput(Mentions.options); return mentionsInput.mentionsInput(Mentions.options);
}, },
// pre-fetch the list of contacts for the current user.
// called by the initializer of the publisher, for faster ('offline')
// execution of the filtering for mentions
fetchContacts : function(){ fetchContacts : function(){
Mentions.contacts || $.getJSON("/contacts", function(data) { Mentions.contacts || $.getJSON("/contacts", function(data) {
Mentions.contacts = data; Mentions.contacts = Mentions.createList(data);
}); });
}, },
// creates a list of mentions out of a list of contacts
// @see _contactToMention
createList: function(contacts) {
return _.map(contacts, Mentions._contactToMention);
},
// takes a given contact object and modifies to fit the format
// expected by the jQuery.mentionsInput plugin.
// @see http://podio.github.com/jquery-mentions-input/
_contactToMention: function(contact) {
contact.value = contact.name;
return contact;
},
// default options for jQuery.mentionsInput
// @see http://podio.github.com/jquery-mentions-input/
options: { options: {
elastic: false, elastic: false,
minChars: 1, minChars: 1,
...@@ -20,7 +39,7 @@ var Mentions = { ...@@ -20,7 +39,7 @@ var Mentions = {
}, },
templates: { templates: {
mentionItemSyntax: _.template("@{<%= mention.name %> ; <%= mention.handle %>}") mentionItemSyntax: _.template("@{<%= name %> ; <%= handle %>}")
} }
} }
}; };
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
- content_for :head do - content_for :head do
= javascript_include_tag :people = javascript_include_tag :people
:javascript :javascript
Mentions.options.prefillMention = #{@person.to_json}; Mentions.options.prefillMention = Mentions._contactToMention(#{@person.to_json});
- content_for :page_title do - content_for :page_title do
= @person.name = @person.name
......
...@@ -38,8 +38,9 @@ Then /^the publisher should be expanded$/ do ...@@ -38,8 +38,9 @@ Then /^the publisher should be expanded$/ do
end end
When /^I append "([^"]*)" to the publisher$/ do |stuff| When /^I append "([^"]*)" to the publisher$/ do |stuff|
previous_value = page.find("#status_message_fake_text").value elem = find('#status_message_fake_text')
fill_in "status_message_fake_text", :with => previous_value + " " + stuff elem.native.send_keys ' ' + stuff
wait_until do wait_until do
page.find("#status_message_text").value.match(/#{stuff}/) page.find("#status_message_text").value.match(/#{stuff}/)
end end
......
module DebuggingCukeHelpers
def start_debugging
require 'ruby-debug'
debugger
true
end
end
World(DebuggingCukeHelpers)
When 'I debug' do When 'I debug' do
require 'ruby-debug' start_debugging
debugger
true
end end
When /^I wait for (\d+) seconds?$/ do |seconds| When /^I wait for (\d+) seconds?$/ do |seconds|
sleep seconds.to_i sleep seconds.to_i
warn "DELETEME - this step is for debugging only\n" warn "\nDELETEME - this step is for debugging, only!\n"
end end
When /^I open the error console$/ do When /^I open the error console$/ do
......
/* /*
* Mentions Input * Mentions Input
* Version 1.0 * Version 1.0.2
* Written by: Kenneth Auchenberg (Podio) * Written by: Kenneth Auchenberg (Podio)
* *
* Using underscore.js * Using underscore.js
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
autocompleteListItemAvatar : _.template('<img src="<%= avatar %>" />'), autocompleteListItemAvatar : _.template('<img src="<%= avatar %>" />'),
autocompleteListItemIcon : _.template('<div class="icon <%= icon %>"></div>'), autocompleteListItemIcon : _.template('<div class="icon <%= icon %>"></div>'),
mentionsOverlay : _.template('<div class="mentions"><div></div></div>'), mentionsOverlay : _.template('<div class="mentions"><div></div></div>'),
mentionItemSyntax : _.template('@[<%= name %>](<%= type %>:<%= id %>)'), mentionItemSyntax : _.template('@[<%= value %>](<%= type %>:<%= id %>)'),
mentionItemHighlight : _.template('<strong><span><%= name %></span></strong>') mentionItemHighlight : _.template('<strong><span><%= value %></span></strong>')
} }
}; };
...@@ -56,18 +56,24 @@ ...@@ -56,18 +56,24 @@
domNode.focus(); domNode.focus();
} }
} }
},
rtrim: function(string) {
return string.replace(/\s+$/,"");
} }
}; };
var MentionsInput = function (input) { var MentionsInput = function (settings) {
var settings;
var elmInputBox, elmInputWrapper, elmAutocompleteList, elmWrapperBox, elmMentionsOverlay, elmActiveAutoCompleteItem; var domInput, elmInputBox, elmInputWrapper, elmAutocompleteList, elmWrapperBox, elmMentionsOverlay, elmActiveAutoCompleteItem;
var mentionsCollection = []; var mentionsCollection = [];
var autocompleteItemCollection = {};
var inputBuffer = []; var inputBuffer = [];
var currentDataQuery = ''; var currentDataQuery = '';
settings = $.extend(true, {}, defaultSettings, settings );
function initTextarea() { function initTextarea() {
elmInputBox = $(input); elmInputBox = $(domInput);
if (elmInputBox.attr('data-mentions-input') == 'true') { if (elmInputBox.attr('data-mentions-input') == 'true') {
return; return;
...@@ -83,16 +89,19 @@ ...@@ -83,16 +89,19 @@
elmInputBox.bind('keypress', onInputBoxKeyPress); elmInputBox.bind('keypress', onInputBoxKeyPress);
elmInputBox.bind('input', onInputBoxInput); elmInputBox.bind('input', onInputBoxInput);
elmInputBox.bind('click', onInputBoxClick); elmInputBox.bind('click', onInputBoxClick);
elmInputBox.bind('blur', onInputBoxBlur);
if (settings.elastic) { // Elastic textareas, internal setting for the Dispora guys
if( settings.elastic ) {
elmInputBox.elastic(); elmInputBox.elastic();
} }
} }
function initAutocomplete() { function initAutocomplete() {
elmAutocompleteList = $(settings.templates.autocompleteList()); elmAutocompleteList = $(settings.templates.autocompleteList());
elmAutocompleteList.appendTo(elmWrapperBox); elmAutocompleteList.appendTo(elmWrapperBox);
elmAutocompleteList.delegate('li', 'click', onAutoCompleteItemClick); elmAutocompleteList.delegate('li', 'mousedown', onAutoCompleteItemClick);
} }
function initMentionsOverlay() { function initMentionsOverlay() {
...@@ -100,20 +109,20 @@ ...@@ -100,20 +109,20 @@
elmMentionsOverlay.prependTo(elmWrapperBox); elmMentionsOverlay.prependTo(elmWrapperBox);
} }
function updateNames() { function updateValues() {
var syntaxMessage = getInputBoxValue(); var syntaxMessage = getInputBoxValue();
_.each(mentionsCollection, function (mention) { _.each(mentionsCollection, function (mention) {
var textSyntax = settings.templates.mentionItemSyntax({ name : mention.name, type : 'contact', id : mention.id, mention: mention }); var textSyntax = settings.templates.mentionItemSyntax(mention);
syntaxMessage = syntaxMessage.replace(mention.value, textSyntax);
syntaxMessage = syntaxMessage.replace(mention.name, textSyntax);
}); });
var mentionText = utils.htmlEncode(syntaxMessage); var mentionText = utils.htmlEncode(syntaxMessage);
_.each(mentionsCollection, function (mention) { _.each(mentionsCollection, function (mention) {
var textSyntax = settings.templates.mentionItemSyntax({ name : utils.htmlEncode(mention.name), type : 'contact', id : mention.id, mention : mention }); var formattedMention = _.extend({}, mention, {value: utils.htmlEncode(mention.value)});
var textHighlight = settings.templates.mentionItemHighlight({ name : utils.htmlEncode(mention.name), mention : mention }); var textSyntax = settings.templates.mentionItemSyntax(formattedMention);
var textHighlight = settings.templates.mentionItemHighlight(formattedMention);
mentionText = mentionText.replace(textSyntax, textHighlight); mentionText = mentionText.replace(textSyntax, textHighlight);
}); });
...@@ -133,12 +142,13 @@ ...@@ -133,12 +142,13 @@
var inputText = getInputBoxValue(); var inputText = getInputBoxValue();
mentionsCollection = _.reject(mentionsCollection, function (mention, index) { mentionsCollection = _.reject(mentionsCollection, function (mention, index) {
return !mention.name || inputText.indexOf(mention.name) == -1; return !mention.value || inputText.indexOf(mention.value) == -1;
}); });
mentionsCollection = _.compact(mentionsCollection); mentionsCollection = _.compact(mentionsCollection);
} }
function addMention(mention) { function addMention(mention) {
var currentMessage = getInputBoxValue(); var currentMessage = getInputBoxValue();
// Using a regex to figure out positions // Using a regex to figure out positions
...@@ -150,9 +160,7 @@ ...@@ -150,9 +160,7 @@
var start = currentMessage.substr(0, startCaretPosition); var start = currentMessage.substr(0, startCaretPosition);
var end = currentMessage.substr(currentCaretPosition, currentMessage.length); var end = currentMessage.substr(currentCaretPosition, currentMessage.length);
var startEndIndex = (start + mention.name).length; var startEndIndex = (start + mention.value).length + 1;
var updatedMessageText = start + mention.name + end;
mentionsCollection.push(mention); mentionsCollection.push(mention);
...@@ -162,8 +170,9 @@ ...@@ -162,8 +170,9 @@
hideAutoComplete(); hideAutoComplete();
// Mentions & syntax message // Mentions & syntax message
var updatedMessageText = start + mention.value + ' ' + end;
elmInputBox.val(updatedMessageText); elmInputBox.val(updatedMessageText);
updateNames(); updateValues();
// Set correct focus and selection // Set correct focus and selection
elmInputBox.focus(); elmInputBox.focus();
...@@ -175,7 +184,8 @@ ...@@ -175,7 +184,8 @@
} }
function onAutoCompleteItemClick(e) { function onAutoCompleteItemClick(e) {
var mention = $(this).data("mention"); var elmTarget = $(this);
var mention = autocompleteItemCollection[elmTarget.attr('data-uid')];
addMention(mention); addMention(mention);
...@@ -186,21 +196,26 @@ ...@@ -186,21 +196,26 @@
resetBuffer(); resetBuffer();
} }
function onInputBoxBlur(e) {
hideAutoComplete();
}
function onInputBoxInput(e) { function onInputBoxInput(e) {
updateNames(); updateValues();
updateMentionsCollection(); updateMentionsCollection();
hideAutoComplete(); hideAutoComplete();
var triggerCharIndex = _.lastIndexOf(inputBuffer, settings.triggerChar); var triggerCharIndex = _.lastIndexOf(inputBuffer, settings.triggerChar);
if (triggerCharIndex > -1) { if (triggerCharIndex > -1) {
currentDataQuery = inputBuffer.slice(triggerCharIndex + 1).join(''); currentDataQuery = inputBuffer.slice(triggerCharIndex + 1).join('');
currentDataQuery = utils.rtrim(currentDataQuery);
_.defer(_.bind(doSearch, this, currentDataQuery)); _.defer(_.bind(doSearch, this, currentDataQuery));
} }
} }
function onInputBoxKeyPress(e) { function onInputBoxKeyPress(e) {
if(e.keyCode != KEY.BACKSPACE) { if(e.keyCode !== KEY.BACKSPACE) {
var typedValue = String.fromCharCode(e.which || e.keyCode); var typedValue = String.fromCharCode(e.which || e.keyCode);
inputBuffer.push(typedValue); inputBuffer.push(typedValue);
} }
...@@ -212,6 +227,14 @@ ...@@ -212,6 +227,14 @@
if (e.keyCode == KEY.LEFT || e.keyCode == KEY.RIGHT || e.keyCode == KEY.HOME || e.keyCode == KEY.END) { if (e.keyCode == KEY.LEFT || e.keyCode == KEY.RIGHT || e.keyCode == KEY.HOME || e.keyCode == KEY.END) {
// Defer execution to ensure carat pos has changed after HOME/END keys // Defer execution to ensure carat pos has changed after HOME/END keys
_.defer(resetBuffer); _.defer(resetBuffer);
// IE9 doesn't fire the oninput event when backspace or delete is pressed. This causes the highlighting
// to stay on the screen whenever backspace is pressed after a highlighed word. This is simply a hack
// to force updateValues() to fire when backspace/delete is pressed in IE9.
if (navigator.userAgent.indexOf("MSIE 9") > -1) {
_.defer(updateValues);
}
return; return;
} }
...@@ -247,7 +270,7 @@ ...@@ -247,7 +270,7 @@
case KEY.RETURN: case KEY.RETURN:
case KEY.TAB: case KEY.TAB:
if (elmActiveAutoCompleteItem && elmActiveAutoCompleteItem.length) { if (elmActiveAutoCompleteItem && elmActiveAutoCompleteItem.length) {
elmActiveAutoCompleteItem.click(); elmActiveAutoCompleteItem.trigger('mousedown');
return false; return false;
} }
...@@ -273,9 +296,9 @@ ...@@ -273,9 +296,9 @@
elmAutocompleteList.show(); elmAutocompleteList.show();
// Filter items that has already been mentioned // Filter items that has already been mentioned
var mentionedNames = _.pluck(mentionsCollection, 'name'); var mentionValues = _.pluck(mentionsCollection, 'value');
results = _.reject(results, function (item) { results = _.reject(results, function (item) {
return _.include(mentionedNames, item.name); return _.include(mentionValues, item.name);
}); });
if (!results.length) { if (!results.length) {
...@@ -287,15 +310,19 @@ ...@@ -287,15 +310,19 @@
var elmDropDownList = $("<ul>").appendTo(elmAutocompleteList).hide(); var elmDropDownList = $("<ul>").appendTo(elmAutocompleteList).hide();
_.each(results, function (item, index) { _.each(results, function (item, index) {
var itemUid = _.uniqueId('mention_');
autocompleteItemCollection[itemUid] = _.extend({}, item, {value: item.name});
var elmListItem = $(settings.templates.autocompleteListItem({ var elmListItem = $(settings.templates.autocompleteListItem({
'id' : utils.htmlEncode(item.id), 'id' : utils.htmlEncode(item.id),
'display' : utils.htmlEncode(item.name), 'display' : utils.htmlEncode(item.name),
'type' : utils.htmlEncode(item.type), 'type' : utils.htmlEncode(item.type),
'content' : utils.highlightTerm(utils.htmlEncode((item.name)), query) 'content' : utils.highlightTerm(utils.htmlEncode((item.name)), query)
})).data('mention', item); })).attr('data-uid', itemUid);
if (index === 0) { if (index === 0) {
selectAutoCompleteItem(elmListItem); selectAutoCompleteItem(elmListItem);
} }
if (settings.showAvatars) { if (settings.showAvatars) {
...@@ -323,18 +350,27 @@ ...@@ -323,18 +350,27 @@
} }
} }
function resetInput() {
elmInputBox.val('');
mentionsCollection = [];
updateValues();
}
// Public methods // Public methods
return { return {
init : function (options) { init : function (domTarget) {
settings = options;
domInput = domTarget;
initTextarea(); initTextarea();
initAutocomplete(); initAutocomplete();
initMentionsOverlay(); initMentionsOverlay();
resetInput();
if(options.prefillMention) { if( settings.prefillMention ) {
addMention(options.prefillMention); addMention( settings.prefillMention );
} }
}, },
val : function (callback) { val : function (callback) {
...@@ -347,9 +383,7 @@ ...@@ -347,9 +383,7 @@
}, },
reset : function () { reset : function () {
elmInputBox.val(''); resetInput();
mentionsCollection = [];
updateNames();
}, },
getMentions : function (callback) { getMentions : function (callback) {
...@@ -364,20 +398,20 @@ ...@@ -364,20 +398,20 @@
$.fn.mentionsInput = function (method, settings) { $.fn.mentionsInput = function (method, settings) {
var outerArguments = arguments;
if (typeof method === 'object' || !method) { if (typeof method === 'object' || !method) {
settings = $.extend(true, {}, defaultSettings, method); settings = method;
} }
var outerArguments = arguments;
return this.each(function () { return this.each(function () {
var instance = $.data(this, 'mentionsInput') || $.data(this, 'mentionsInput', new MentionsInput(this)); var instance = $.data(this, 'mentionsInput') || $.data(this, 'mentionsInput', new MentionsInput(settings));
if (_.isFunction(instance[method])) { if (_.isFunction(instance[method])) {
return instance[method].apply(this, Array.prototype.slice.call(outerArguments, 1)); return instance[method].apply(this, Array.prototype.slice.call(outerArguments, 1));
} else if (typeof method === 'object' || !method) { } else if (typeof method === 'object' || !method) {
return instance.init.call(this, settings); return instance.init.call(this, this);
} else { } else {
$.error('Method ' + method + ' does not exist'); $.error('Method ' + method + ' does not exist');
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter