Browse Source

add alias textcompletion for peers invitation form; textcompletion refactoring

master
Simon Grim 9 years ago
parent
commit
7ef1f0129e
  1. 11
      css/profile.css
  2. 30
      following.html
  3. 30
      home.html
  4. 21
      js/interface_common.js
  5. 10
      js/tmobile.js
  6. 42
      js/twister_directmsg.js
  7. 145
      js/twister_following.js
  8. 8
      theme_calm/css/profile.css
  9. 8
      theme_nin/css/style.css
  10. 13
      theme_nin/js/theme_option.js
  11. 22
      tmobile.html

11
css/profile.css

@ -296,10 +296,19 @@ h2.profile-screen-name { @@ -296,10 +296,19 @@ h2.profile-screen-name {
padding: 4px 0;
}
.group-messages-control .invite-form input {
.group-messages-control .invite-form textarea {
border: solid 1px rgba(0, 0, 0, .3);
border-radius: 3px;
vertical-align: middle;
width: 73%;
height: 20px;
resize: none;
margin: 0 4px;
padding: 1px 4px;
}
.group-messages-control .invite-form textarea:focus {
border: solid 1px rgba(227, 79, 66, .5);
}
.group-messages-control .invite-form button {

30
following.html

@ -80,18 +80,7 @@ @@ -80,18 +80,7 @@
<li><a href="#">Outro Fulano</a></li>
<li><a href="#">Mais outro</a></li>
</ul>
<ul class="userMenu-search-profiles">
<li id="search-profile-template" style="display: none;">
<div class="mini-profile-info" data-screen-name="">
<a href="#" class="open-profile-modal">
<img class="mini-profile-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="mini-screen-name">@<b></b></span>
<span class="mini-profile-name"></span>
</a>
<button class="follow">Follow</button>
</div>
</li>
</ul>
<ul class="userMenu-search-profiles"></ul>
</div>
</li>
</ul>
@ -183,6 +172,19 @@ @@ -183,6 +172,19 @@
<!-- TEMPLATES INIT -->
<div id="templates" style="display:none;">
<div id="search-profile-template">
<li>
<div class="mini-profile-info">
<a class="open-profile-modal">
<img class="mini-profile-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo" />
<span class="mini-screen-name">@<b></b></span>
<span class="mini-profile-name"></span>
</a>
<button class="follow">Follow</button>
</div>
</li>
</div>
<!-- TEMPLATE DE WHO-TO-FOLLOW SUGGESTION -->
<li id="follow-suggestion-template" class="twister-user">
<div class="">
@ -414,7 +416,7 @@ @@ -414,7 +416,7 @@
<button class="invite">Invite peers</button>
<button class="leave">Leave group</button>
<div class="invite-form">
<input type="text"><button disabled="disabled">Invite</button>
<textarea></textarea><button disabled="disabled">Invite</button>
</div>
</div>
</div>
@ -430,7 +432,7 @@ @@ -430,7 +432,7 @@
<button class="show-secret-key" disabled="disabled">Secret Key</button>
<button class="leave" disabled="disabled">Leave group</button>
<div class="invite-form">
<input type="text"><button disabled="disabled">Invite</button>
<textarea></textarea><button disabled="disabled">Invite</button>
</div>
<div class="secret-key"></div>
</div>

30
home.html

@ -86,18 +86,7 @@ @@ -86,18 +86,7 @@
<li><a href="#">Outro Fulano</a></li>
<li><a href="#">Mais outro</a></li>
</ul>
<ul class="userMenu-search-profiles">
<li id="search-profile-template" style="display: none;">
<div class="mini-profile-info" data-screen-name="">
<a href="#" class="open-profile-modal">
<img class="mini-profile-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="mini-screen-name">@<b></b></span>
<span class="mini-profile-name"></span>
</a>
<button class="follow">Follow</button>
</div>
</li>
</ul>
<ul class="userMenu-search-profiles"></ul>
</div>
</li>
</ul>
@ -198,6 +187,19 @@ @@ -198,6 +187,19 @@
<!-- TEMPLATES INIT -->
<div id="templates" style="display:none;">
<div id="search-profile-template">
<li>
<div class="mini-profile-info">
<a class="open-profile-modal">
<img class="mini-profile-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo" />
<span class="mini-screen-name">@<b></b></span>
<span class="mini-profile-name"></span>
</a>
<button class="follow">Follow</button>
</div>
</li>
</div>
<!-- TEMPLATE DE WHO-TO-FOLLOW MODULE -->
<div id="who-to-follow-template">
<div>
@ -506,7 +508,7 @@ @@ -506,7 +508,7 @@
<button class="invite">Invite peers</button>
<button class="leave">Leave group</button>
<div class="invite-form">
<input type="text" /><button disabled="disabled">Invite</button>
<textarea></textarea><button disabled="disabled">Invite</button>
</div>
</div>
</div>
@ -522,7 +524,7 @@ @@ -522,7 +524,7 @@
<button class="show-secret-key" disabled="disabled">Secret Key</button>
<button class="leave" disabled="disabled">Leave group</button>
<div class="invite-form">
<input type="text" /><button disabled="disabled">Invite</button>
<textarea></textarea><button disabled="disabled">Invite</button>
</div>
<div class="secret-key"></div>
</div>

21
js/interface_common.js

@ -800,7 +800,7 @@ function replyTextInput(event) { @@ -800,7 +800,7 @@ function replyTextInput(event) {
$(tas[i]).caret(caretPos);
replyTextUpdateRemaining(tas[i]);
if ($.fn.textcomplete)
setTextcompleteOnElement(tas[i]);
setTextcompleteOnElement(tas[i], getMentionsForAutoComplete());
}
}
} else if (tas.length > 1 && tas[i].value.length === 0) {
@ -1571,10 +1571,10 @@ function initInterfaceCommon() { @@ -1571,10 +1571,10 @@ function initInterfaceCommon() {
$('.bitmessage-ctc').on('click', promptCopyAttrData);
if ($.fn.textcomplete) {
$('textarea').on({
'focus': setTextcompleteOnEventTarget,
'focusout': function () {$(this).textcomplete('destroy');}
});
$('.post-area-new textarea')
.on('focus', {req: getMentionsForAutoComplete}, setTextcompleteOnEventTarget)
.on('focusout', unsetTextcompleteOnEventTarget)
;
}
}
@ -1598,17 +1598,22 @@ function inputEnterActivator(event) { @@ -1598,17 +1598,22 @@ function inputEnterActivator(event) {
function setTextcompleteOnEventTarget(event) {
// cursor has not set yet and we need to wait 100ms to skip global click event
setTimeout(setTextcompleteOnElement, 100, event.target);
setTimeout(setTextcompleteOnElement, 100, event.target,
typeof event.data.req === 'function' ? event.data.req() : event.data.req);
}
function setTextcompleteOnElement(elem) {
function setTextcompleteOnElement(elem, req) {
elem = $(elem);
elem.textcomplete(getMentionsForAutoComplete(), {
elem.textcomplete(req, {
appendTo: (elem.parents('.dashboard').length) ? elem.parent() : $('body'),
listPosition: setTextcompleteDropdownListPos
});
}
function unsetTextcompleteOnEventTarget(event) {
$(event.target).textcomplete('destroy');
}
// following workaround function is for calls from $.fn.textcomplete only
// we need this because currently implementation of caret position detection is way too imperfect
function setTextcompleteDropdownListPos(position) {

10
js/tmobile.js

@ -432,9 +432,13 @@ function installCreateUserClick() { @@ -432,9 +432,13 @@ function installCreateUserClick() {
}
function installUserSearchHandler() {
var $userSearchField = $( ".userMenu-search-field" );
$userSearchField.unbind('keyup').keyup( userSearchKeypress );
$userSearchField.unbind('click').bind( "click", userSearchKeypress );
$('.userMenu-search-field')
.off('click input')
.on('keyup', userSearchEnter)
.on('click keyup',
{hashtags: true, handleRet: processDropdownUserResults,
handleRetZero: closeSearchDialog}, userSearchKeypress)
;
}
function installProfileEditHandlers() {

42
js/twister_directmsg.js

@ -263,6 +263,11 @@ function openGroupMessagesNewGroupModal() { @@ -263,6 +263,11 @@ function openGroupMessagesNewGroupModal() {
modal.content.find('.description').on('input',
{parentSelector: '.module', enterSelector: '.create'}, inputEnterActivator);
modal.content.find('.invite')
.on('input', {handleRet: groupMsgInviteFormInputHandleUserSearchRet}, userSearchKeypress)
.on('focus', {req: groupMsgInviteFormInputSetTextcompleteReq}, setTextcompleteOnEventTarget)
.on('focusout', unsetTextcompleteOnEventTarget)
;
modal.content.find('.create').on('click', function (event) {
var elemEvent = $(event.target);
var elemForm = elemEvent.parents('.module')
@ -408,6 +413,28 @@ function groupMsgGetGroupInfo(groupAlias, cbFunc, cbArgs) { @@ -408,6 +413,28 @@ function groupMsgGetGroupInfo(groupAlias, cbFunc, cbArgs) {
);
}
function groupMsgInviteFormInputHandleUserSearchRet() {
// working with global results because of search function in textcomplete strategy, see groupMsgInviteFormInputSetTextcompleteReq
var i = _lastSearchUsersResults.indexOf(defaultScreenName);
if (i !== -1)
_lastSearchUsersResults.splice(i, 1);
}
function groupMsgInviteFormInputSetTextcompleteReq() {
return [{
match: /\B@(\w*)$/,
search: function (term, callback) {
callback($.map(_lastSearchUsersResults, function (mention) {
return mention.indexOf(term) === 0 ? mention : null;
}));
},
index: 1,
replace: function (mention) {
return '@'+mention+' ';
}
}]
}
function initInterfaceDirectMsg() {
$('.direct-messages').attr('href', '#directmessages');
$('.userMenu-messages a').attr('href', '#directmessages');
@ -429,12 +456,21 @@ function initInterfaceDirectMsg() { @@ -429,12 +456,21 @@ function initInterfaceDirectMsg() {
$(event.target).siblings('.invite-form').toggle();
});
$('.group-messages-control .invite-form input').on('input',
{parentSelector: '.invite-form', enterSelector: 'button'}, inputEnterActivator);
$('.group-messages-control .invite-form textarea')
.on('input', {parentSelector: '.invite-form', enterSelector: 'button',
handleRet: groupMsgInviteFormInputHandleUserSearchRet},
function (event) {
inputEnterActivator(event);
userSearchKeypress(event);
}
)
.on('focus', {req: groupMsgInviteFormInputSetTextcompleteReq}, setTextcompleteOnEventTarget)
.on('focusout', unsetTextcompleteOnEventTarget)
;
$('.group-messages-control .invite-form button').on('click', function (event) {
var elemEvent = $(event.target);
var elemInput = elemEvent.siblings('input');
var elemInput = elemEvent.siblings('textarea');
var peersToInvite = elemInput.val().toLowerCase().match(/@\w+/g);
if (peersToInvite)
peersToInvite = peersToInvite.join('').slice(1).split('@');

145
js/twister_following.js

@ -10,9 +10,10 @@ var _followsPerPage = 200; @@ -10,9 +10,10 @@ var _followsPerPage = 200;
var _maxFollowingPages = 50;
var _followingSeqNum = 0;
var _followSuggestions = [];
var _searchingPartialUsers = "";
var _searchingPartialName = '';
var _searchKeypressTimer = undefined;
var _lastSearchUsersResults = [];
var _lastSearchUsersResultsRemovedFromDHTgetQueue = true;
var _lastLoadFromDhtTime = 0;
var twisterFollowingO = undefined;
@ -578,101 +579,96 @@ function processWhoToFollowSuggestion(suggestion, followedBy) { @@ -578,101 +579,96 @@ function processWhoToFollowSuggestion(suggestion, followedBy) {
console.warn('nothing to proceed: no twisters to follow was suggested');
}
function closeSearchDialog()
{
$(".userMenu-search-field").siblings().slideUp( "fast" );
function closeSearchDialog(event) {
var elemEvent = event ? $(event.target) : this;
elemEvent.siblings('.search-results').slideUp('fast');
if (!_lastSearchUsersResultsRemovedFromDHTgetQueue) {
removeUsersFromDhtgetQueue(_lastSearchUsersResults);
_lastSearchUsersResults = [];
_lastSearchUsersResultsRemovedFromDHTgetQueue = true;
}
}
function userSearchKeypress(event) {
var partialName = $(".userMenu-search-field").val().toLowerCase();
var searchResults = $(".search-results");
if ( partialName.substr( 0, 1 ) == '#' ) {
if(searchResults.is(":visible"))
searchResults.slideUp( "fast" );
var elemEvent = $(event.target);
var partialName = elemEvent.val().toLowerCase();
if ( event.which == 13 )
window.location.hash = '#hashtag?hashtag=' + encodeURIComponent(partialName.substr(1));
if (event.data.hashtags && partialName[0] === '#') {
var searchResults = elemEvent.siblings('.search-results');
if (searchResults.is(':visible'))
searchResults.slideUp('fast');
return;
}
if ( partialName.substr( 0, 1 ) == '@' ) {
partialName = partialName.substr( 1 );
}
//var partialName = item.val();
var words = partialName.match(/\b\w+/g);
if (words && words.length) {
partialName = words.pop();
if( !partialName.length ) {
closeSearchDialog();
} else {
if( _searchKeypressTimer !== undefined )
if (typeof _searchKeypressTimer !== 'undefined')
clearTimeout(_searchKeypressTimer);
if( _searchingPartialUsers.length ) {
_searchingPartialUsers = partialName;
if (_searchingPartialName.length) {
_searchingPartialName = partialName;
} else {
_searchKeypressTimer = setTimeout(function () {
_searchKeypressTimer = undefined;
searchPartialUsername(partialName);
event.data.partialName = partialName;
searchPartialUsername(event);
}, 600);
}
}
}
function searchPartialUsername(partialName) {
_searchingPartialUsers = partialName;
twisterRpc("listusernamespartial", [partialName,10],
function(partialName, ret) {
processDropdownUserResults(partialName, ret)
}, partialName,
function(cbArg, ret) {
console.log("ajax error:" + ret);
}, {});
} else
closeSearchDialog(event);
}
function processDropdownUserResults(partialName, results){
function searchPartialUsername(event) {
_searchingPartialName = event.data.partialName;
twisterRpc('listusernamespartial', [event.data.partialName, 10],
function(event, ret) {
if (event.data.partialName !== _searchingPartialName)
setTimeout(searchPartialUsername, 100, event);
else {
if (!_lastSearchUsersResultsRemovedFromDHTgetQueue)
removeUsersFromDhtgetQueue(_lastSearchUsersResults);
else
_lastSearchUsersResultsRemovedFromDHTgetQueue = false;
_lastSearchUsersResults = ret;
if( partialName != _searchingPartialUsers ) {
searchPartialUsername( _searchingPartialUsers );
return;
if (ret && ret.length) {
if (event.data.handleRet)
event.data.handleRet(event, ret);
} else {
if (event.data.handleRetZero)
event.data.handleRetZero(event);
}
removeUsersFromDhtgetQueue( _lastSearchUsersResults );
_lastSearchUsersResults = results;
var typeaheadAccounts = $(".userMenu-search-profiles");
var template = $("#search-profile-template").detach();
_searchingPartialName = '';
}
}, event,
function(req, ret) {console.warn('ajax error:' + ret.message);}, null
);
}
typeaheadAccounts.empty();
typeaheadAccounts.append(template);
function processDropdownUserResults(event, results) {
var container = $('.userMenu-search-profiles').empty();
var template = $('#search-profile-template').children();
if( results.length ) {
for (var i = 0; i < results.length; i++) {
if( results[i] == defaultScreenName )
if (results[i] === defaultScreenName)
continue;
var resItem = template.clone(true);
resItem.removeAttr('id');
resItem.show();
resItem.find(".mini-profile-info").attr("data-screen-name", results[i]);
resItem.find(".mini-screen-name b").text(results[i]);
resItem.find("a.open-profile-modal").attr("href",$.MAL.userUrl(results[i]));
getAvatar(results[i],resItem.find(".mini-profile-photo"));
getFullname(results[i],resItem.find(".mini-profile-name"));
resItem.appendTo(typeaheadAccounts);
if (followingUsers.indexOf(results[i]) >= 0)
var item = template.clone(true);
item.find('.mini-profile-info').attr('data-screen-name', results[i]);
item.find('.mini-screen-name b').text(results[i]);
item.find('a.open-profile-modal').attr('href', $.MAL.userUrl(results[i]));
getAvatar(results[i], item.find('.mini-profile-photo'));
getFullname(results[i], item.find('.mini-profile-name'));
item.appendTo(container);
if (followingUsers.indexOf(results[i]) !== -1)
toggleFollowButton(results[i], true);
}
$.MAL.searchUserListLoaded();
} else {
closeSearchDialog();
}
_searchingPartialUsers = "";
}
function userClickFollow(e) {
@ -700,10 +696,13 @@ function userClickFollow(e) { @@ -700,10 +696,13 @@ function userClickFollow(e) {
}
function initUserSearch() {
var $userSearchField = $( ".userMenu-search-field" );
$userSearchField.keyup( userSearchKeypress );
$userSearchField.bind( "click", userSearchKeypress );
$(".userMenu-search").clickoutside( closeSearchDialog );
var elem = $('.userMenu-search-field')
.on('click input',
{hashtags: true, handleRet: processDropdownUserResults,
handleRetZero: closeSearchDialog}, userSearchKeypress)
.on('keyup', userSearchEnter)
;
$('.userMenu-search').clickoutside(closeSearchDialog.bind(elem));
// following stuff should be moved to special function
$('button.follow').on('click', userClickFollow);
@ -716,6 +715,14 @@ function initUserSearch() { @@ -716,6 +715,14 @@ function initUserSearch() {
;
}
function userSearchEnter(event) {
if (event.which === 13) {
var str = $(event.target).val().toLowerCase().trim();
if (str[0] === '#')
window.location.hash = '#hashtag?hashtag=' + encodeURIComponent(str.slice(1));
}
}
function followingListPublicCheckbox(e) {
e.stopPropagation();

8
theme_calm/css/profile.css

@ -385,14 +385,18 @@ h2.profile-screen-name { @@ -385,14 +385,18 @@ h2.profile-screen-name {
padding: 4px 0;
}
.group-messages-control .invite-form input {
.group-messages-control .invite-form textarea {
border: solid 1px rgba(0, 0, 0, .3);
border-radius: 3px;
vertical-align: middle;
width: 73%;
height: 20px;
resize: none;
margin: 0 4px;
padding: 1px 4px;
}
.group-messages-control .invite-form input:focus {
.group-messages-control .invite-form textarea:focus {
border: solid 1px rgba(118, 145, 206, .8);
}

8
theme_nin/css/style.css

@ -3008,14 +3008,18 @@ ol.toptrends-list a:hover { @@ -3008,14 +3008,18 @@ ol.toptrends-list a:hover {
padding: 4px 0;
}
.group-messages-control .invite-form input {
.group-messages-control .invite-form textarea {
font-size: 1.1em;
border: 1px solid rgba(0, 0, 0, .1);
vertical-align: middle;
width: 73%;
height: 20px;
resize: none;
margin: 0 4px;
padding: 1px 4px;
}
.group-messages-control .invite-form input:focus {
.group-messages-control .invite-form textarea:focus {
border-bottom: solid 1px #B4C669;
}

13
theme_nin/js/theme_option.js

@ -5,7 +5,6 @@ $(function(){ @@ -5,7 +5,6 @@ $(function(){
$('.twister-user-remove').html('');
$('.profile-card-main').attr('style', '');
$('img[src$="img/tornado_avatar.png"]').attr("src","theme_nin/img/tornado_avatar.png");
$('.userMenu-search-profiles button').html('').attr('title',polyglot.t('Follow'));
$('.mini-profile-actions span').html('');
$.globalEval(postToElem.toString().replace(/postContext.append\(_templatePostRtBy/,
@ -37,13 +36,17 @@ $(function(){ @@ -37,13 +36,17 @@ $(function(){
this.slideUp(150);
}).bind($('.left .post-area-new')));
$(".userMenu-search-profiles .follow")
.on("eventToggleFollow", function() {
$('#search-profile-template .follow')
.html('')
.attr('title', polyglot.t('Follow'))
.on('eventToggleFollow', function() {
$(this).text('').attr('title', polyglot.t('Follow'));
})
.on("eventToggleUnfollow", function() {
.on('eventToggleUnfollow', function() {
$(this).text('').attr('title', polyglot.t('Unfollow'));
});
})
;
if (/\/options.html$/i.test(document.location))
$(document).ready(localizeLabels);

22
tmobile.html

@ -658,16 +658,7 @@ @@ -658,16 +658,7 @@
</div>
<div>&nbsp;</div>
<div>
<ul class="userMenu-search-profiles" data-role="listview">
<li id="search-profile-template" style="display: none;">
<a class="mini-profile-info open-profile-modal" data-screen-name="">
<img class="mini-profile-photo avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="mini-screen-name">@<b></b></span>
<span class="mini-profile-name"></span>
<!-- <button class="follow">Follow</button> -->
</a>
</li>
</ul>
<ul class="userMenu-search-profiles" data-role="listview"></ul>
</div>
</div>
@ -741,6 +732,17 @@ @@ -741,6 +732,17 @@
<div id="anywhere"></div>
<div id="templates" style="display:none;">
<div id="search-profile-template">
<li>
<a class="mini-profile-info open-profile-modal" data-screen-name="">
<img class="mini-profile-photo avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo" />
<span class="mini-screen-name">@<b></b></span>
<span class="mini-profile-name"></span>
<!-- <button class="follow">Follow</button> -->
</a>
</li>
</div>
<li id="post-template-home" class="post-li module post" data-time="">
<img class="avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<div class="post-data" data-userpost="" data-content_to_rt="" data-content_to_sigrt=""

Loading…
Cancel
Save