fixing tab in chat

This commit is contained in:
2014-09-13 17:52:21 +02:00
parent 9196953a48
commit 0119cfa3a4
4 changed files with 189 additions and 97 deletions

141
jquery/common.js vendored
View File

@@ -1,23 +1,40 @@
/* jQuery functions */ /* jQuery functions */
(function($) { (function($) {
$.fn.getCursorPosition = function() { $.fn.getCursorPosition = function() {
var input = this.get(0); var input = this.get(0);
if (!input) return; // No (input) element found if (!input) return; // No (input) element found
if ('selectionStart' in input) { if ('selectionStart' in input) {
// Standard-compliant browsers // Standard-compliant browsers
return input.selectionStart; return input.selectionStart;
} else if (document.selection) { } else if (document.selection) {
// IE // IE
input.focus(); input.focus();
var sel = document.selection.createRange(); var sel = document.selection.createRange();
var selLen = document.selection.createRange().text.length; var selLen = document.selection.createRange().text.length;
sel.moveStart('character', -input.value.length); sel.moveStart('character', -input.value.length);
return sel.text.length - selLen; return sel.text.length - selLen;
} }
}; };
})(jQuery); })(jQuery);
$.fn.setCursorPosition = function(pos)
{
this.each(function(index, elem)
{
if(elem.setSelectionRange) elem.setSelectionRange(pos, pos);
else if(elem.createTextRange)
{
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
});
return this;
};
$.prototype.addButton = function(sType, sTitle, oClickLink, sId, sButtonClass, sTmpVar) $.prototype.addButton = function(sType, sTitle, oClickLink, sId, sButtonClass, sTmpVar)
{ {
$This = $(this); $This = $(this);
@@ -120,29 +137,48 @@ $.prototype.checkForm = function(sSelector)
/* Common functions */ /* Common functions */
String.prototype.stripVowelAccent = function() String.prototype.stripVowelAccent = function()
{ {
var sText = this; var sec = ['193','225','192','224','194','226','461','462','258','259','195','227','7842','7843','7840','7841','196','228','197','229','256','257','260','261','7844','7845','7846','7847','7850','7851','7848','7849','7852','7853','7854','7855','7856','7857','7860','7861','7858','7859','7862','7863','506','507','262','263','264','265','268','269','266','267','199','231','270','271','272','273','201','233','200','232','202','234','282','283','276','277','7868','7869','7866','7867','278','279','203','235','274','275','280','281','7870','7871','7872','7873','7876','7877','7874','7875','7864','7865','7878','7879','286','287','284','285','288','289','290','291','292','293','294','295','205','237','204','236','300','301','206','238','463','464','207','239','296','297','302','303','298','299','7880','7881','7882','7883','308','309','310','311','313','314','317','318','315','316','321','322','319','320','323','324','327','328','209','241','325','326','211','243','210','242','334','335','212','244','7888','7889','7890','7891','7894','7895','7892','7893','465','466','214','246','336','337','213','245','216','248','510','511','332','333','7886','7887','416','417','7898','7899','7900','7901','7904','7905','7902','7903','7906','7907','7884','7885','7896','7897','7764','7765','7766','7767','340','341','344','345','342','343','346','347','348','349','352','353','350','351','356','357','354','355','358','359','218','250','217','249','364','365','219','251','467','468','366','367','220','252','471','472','475','476','473','474','469','470','368','369','360','361','370','371','362','363','7910','7911','431','432','7912','7913','7914','7915','7918','7919','7916','7917','7920','7921','7908','7909','7810','7811','7808','7809','372','373','7812','7813','221','253','7922','7923','374','375','376','255','7928','7929','7926','7927','7924','7925','377','378','381','382','379','380','208'];
var rExps= var rep = ['A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','C','c','C','c','C','c','C','c','C','c','D','d','D','d','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','G','g','G','g','G','g','G','g','H','h','H','h','I','i','I','i','I','i','I','i','I','i','I','i','I','i','I','i','I','i','I','i','I','i','J','j','K','k','L','l','L','l','L','l','L','l','L','l','N','n','N','n','N','n','N','n','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','P','p','P','p','R','r','R','r','R','r','S','s','S','s','S','s','S','s','T','t','T','t','T','t','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','W','w','W','w','W','w','W','w','Y','y','Y','y','Y','y','Y','y','Y','y','Y','y','Y','y','Z','z','Z','z','Z','z','D'];
[
{re:/[\xC0-\xC6]/g, ch:'A'}, var seclen = sec.length;
{re:/[\xE0-\xE6]/g, ch:'a'}, var repwith = -1;
{re:/[\xC8-\xCB]/g, ch:'E'}, var text = this;
{re:/[\xE8-\xEB]/g, ch:'e'}, text = text.replace(/\r/g,'').split('\n');
{re:/[\xCC-\xCF]/g, ch:'I'}, var textout = new Array();
{re:/[\xEC-\xEF]/g, ch:'i'}, var linecnt = text.length;
{re:/[\xD2-\xD6]/g, ch:'O'}, var toremout = '';
{re:/[\xF2-\xF6]/g, ch:'o'}, var chcoat = '';
{re:/[\xD9-\xDC]/g, ch:'U'}, for(var x=0;x<linecnt;x++)
{re:/[\xF9-\xFC]/g, ch:'u'},
{re:/[\xD1]/g, ch:'N'},
{re:/[\xF1]/g, ch:'n'}
];
for(var i=0, len=rExps.length; i<len; i++)
{ {
sText=sText.replace(rExps[i].re, rExps[i].ch); torem = text[x].split('');
toremout = new Array();
toremlen = torem.length;
for(var y=0;y<toremlen;y++)
{
chcoat = torem[y].charCodeAt(0);
if(chcoat > 124)
{
for(var z=0;z<seclen;z++)
{
if(chcoat == sec[z])
{
repwith = rep[z];
z = seclen;
}
}
}
if(repwith != -1)
{
toremout[y] = repwith;
repwith = -1;
}
else toremout[y] = torem[y];
}
textout[x] = toremout.join('');
} }
return sText; return textout.join('\n');
}; }
String.prototype.replaceAll = function(regex, text) String.prototype.replaceAll = function(regex, text)
{ {
@@ -337,6 +373,39 @@ function setElem(aoAnchor, asPath, oValue)
} }
} }
function array_search(needle, haystack, argStrict)
{
var strict = !! argStrict,
key = '';
if(typeof needle === 'object' && needle.exec)
{
// Duck-type for RegExp
if(!strict)
{
// Let's consider case sensitive searches as strict
var flags = 'i' + (needle.global ? 'g' : '') + (needle.multiline ? 'm' : '') + (needle.sticky ? 'y' : '');
needle = new RegExp(needle.source, flags);
}
for(key in haystack)
{
if(haystack.hasOwnProperty(key))
{
if(needle.test(haystack[key])) return key;
}
}
return false;
}
for(key in haystack)
{
if(haystack.hasOwnProperty(key))
{
if((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) return key;
}
}
return false;
}
/* /*
//Queue element //Queue element
( (

View File

@@ -24,7 +24,7 @@
</div> </div>
<div id="chat_input" class="tiny_round"> <div id="chat_input" class="tiny_round">
<form id="chat_form" name="chat_form"> <form id="chat_form" name="chat_form">
<i id="message_img" class="fa fa-fw fa-20 fa-c-comment"></i><input type="text" id="message" name="message" value="" maxlength="500" /> <i id="message_img" class="fa fa-fw fa-20 fa-c-comment"></i><input type="text" id="message" name="message" value="" maxlength="500" autofocus />
<input type="hidden" id="chan" name="chan" value="" maxlength="50" /> <input type="hidden" id="chan" name="chan" value="" maxlength="50" />
</form> </form>
</div> </div>
@@ -84,6 +84,7 @@ databap.pageInit = function()
self.tmp('get_news', false); self.tmp('get_news', false);
self.tmp('last_message_id', '0'); self.tmp('last_message_id', '0');
self.tmp('scrolling', 'boolean'); self.tmp('scrolling', 'boolean');
databap.tmp('tab_info', 'object');
//Main elements //Main elements
$MsgInput = databap.getMainElem('#message'); $MsgInput = databap.getMainElem('#message');
@@ -488,6 +489,7 @@ function quitChan(sChanKeyName)
function add_message(e) function add_message(e)
{ {
if(e.keyCode != 9) databap.tmp('tab_info', {}); //See case 9, tab
switch(e.keyCode) switch(e.keyCode)
{ {
case 13 : //enter case 13 : //enter
@@ -535,67 +537,84 @@ function add_message(e)
} }
break; break;
case 9 : //tab case 9 : //tab
/* Action Plan $This = databap.getMainElem('#message');
- Detect current caret position : $this.getCursorPosition() var sChatMsg = $This.val();
- Find word wrapped around cursor : while loop until non alphanum char before and after caret position var iChatMsgLen = sChatMsg.length;
-
*/ if(!e.altKey && iChatMsgLen>0)
//Init
$this = databap.getMainElem('#message');
var chat_message = $.trim($this.val());
if(!e.altKey && chat_message.length>0)
{ {
var user_name = ""; var iCurPos, iFirstPos, iOffset, sWord, sWordLen;
var index = 0;
//Finding last word
var last_word = (chat_message.lastIndexOf(" ")==-1)?chat_message:chat_message.substr(chat_message.lastIndexOf(" ") + 1);
//debug(last_word);
if(last_word.substr(0, 1)=='@') last_word = last_word.substr(1);
var last_word_len = last_word.length;
var approx_nick = last_word.toLowerCase();
//Tabbing through positive results //Loading previous data
var existing_nick = false; bLooping = !$.isEmptyObject(databap.tmp('tab_info'));
var userIndex = $.inArray(last_word, users_list); if(bLooping)
if(userIndex==-1)
{ {
//Recording first search keyword sChatMsg = databap.tmp(['tab_info', 'chat_msg']);
//debug('buffering approx nick : "'+last_word+'"'); iCurPos = databap.tmp(['tab_info', 'cur_pos']);
prev_approx_nick = approx_nick; iFirstPos = databap.tmp(['tab_info', 'first_pos']);
prev_approx_nick_len = last_word_len; sWord = databap.tmp(['tab_info', 'word']);
userIndex = users_list.length - 1;
} }
else existing_nick = true; else
{
//debug('last word : "'+last_word+'"'); //Find word in chat message input box
//debug('existing_nick : '+existing_nick); iCurPos = $This.getCursorPosition();
iFirstPos = sChatMsg.substr(0, iCurPos).lastIndexOf(' ') + 1;
//Next nickname in the list iOffset = sChatMsg.substr(iFirstPos).indexOf(' ');
index = (userIndex+1)%users_list.length; sWord = sChatMsg.substr(iFirstPos, (iOffset==-1)?iChatMsgLen:iOffset);
count = 0;
//@ excluded
//loop on the nickname list if(sWord.substr(0, 1)=='@')
while(count<users_list.length)
{
//debug('index: '+index);
var nick = users_list[index];
var lower_nick = nick.toLowerCase();
if
(
!existing_nick && lower_nick.substr(0, last_word_len) == approx_nick ||
existing_nick && lower_nick.substr(0, prev_approx_nick_len) == prev_approx_nick
)
{ {
user_name = nick; iFirstPos++;
break; sWord = sWord.substr(1);
} }
index = (index+1)%users_list.length;
count++;
} }
//debug('chat message : '+chat_message); sWordLen = sWord.length;
if(user_name!='') $this.val(chat_message.substr(0, chat_message.length - last_word_len)+user_name+' ');
//No guess if not at least one letter
if(sWordLen>0)
{
//turn to safename for matching
var sSafeWord = getSafeNickname(sWord);
var iSafeWordLen = sSafeWord.length;
//List of current channel users
var asUserList = databap.tmp(['users', getChanKeyName(currentChan())]);
var asSafeUserList = Object.keys(asUserList);
var iUserListLen = asSafeUserList.length;
//Starting list where we left off
var iCount = 0;
var iIndex = 0;
if(bLooping) iIndex = (Number(array_search(databap.tmp(['tab_info', 'safe_nickname']), asSafeUserList)) + 1)%iUserListLen;
//Looping on user names to find the one(s) starting with the searched word
while(iCount < iUserListLen)
{
//Checking for first letters of user names
if(sSafeWord == asSafeUserList[iIndex].substr(0, sSafeWord.length)) break;
//Looping to the top of the list once finished
iIndex = (iIndex + 1)%iUserListLen;
iCount++;
}
if(iCount !== iUserListLen)
{
//Replace text in message input box
var sBeforeWord = sChatMsg.substr(0, iFirstPos);
var sAfterWord = sChatMsg.substr(iFirstPos+sWordLen);
var sSafeNickName = asSafeUserList[iIndex];
var sNickName = asUserList[sSafeNickName];
$This.val(sBeforeWord+sNickName+sAfterWord);
$This.setCursorPosition((sBeforeWord+sNickName).length);
//Save value for tab-loops
if(bLooping) databap.tmp(['tab_info', 'safe_nickname'], sSafeNickName); //not saving index in case of user list refresh
else databap.tmp(['tab_info'], {'chat_msg':sChatMsg, 'cur_pos':iCurPos, 'first_pos':iFirstPos, 'word':sWord, 'safe_nickname':sSafeNickName});
}
else databap.feedback('warning', 'Aucun nickname commençant "'+sWord+'" par n\'a été trouvé');
}
} }
break; break;
/*default:debug(e.keyCode);break;*/ /*default:debug(e.keyCode);break;*/
@@ -809,7 +828,7 @@ function refresh_users()
{ {
//empty current users list //empty current users list
databap.getMainElem('#connected_users').empty(); databap.getMainElem('#connected_users').empty();
users_list = []; databap.tmp('users', {});
$.each $.each
( (
@@ -821,8 +840,8 @@ function refresh_users()
chan_info, chan_info,
function(key, user_info) function(key, user_info)
{ {
var sNickName = user_info.nickname.replace('"', '\''); var sNickName = user_info.nickname;
users_list.push(sNickName); databap.tmp(['users', sChankeyName, getSafeNickname(sNickName)], sNickName);
var profileLink = databap.getInternalLink('profil', user_info.id_user); var profileLink = databap.getInternalLink('profil', user_info.id_user);
var mission = 'Mission actuelle : '+(user_info.status || 'Aucune'); var mission = 'Mission actuelle : '+(user_info.status || 'Aucune');
var pm = 'Cliquez pour lancer un channel privé avec '+user_info.name+' ('+user_info.company+')'; var pm = 'Cliquez pour lancer un channel privé avec '+user_info.name+' ('+user_info.company+')';
@@ -830,7 +849,7 @@ function refresh_users()
.append($('<a>', {'class':'connected_user_logo', href:profileLink, title:mission, target:'_blank'}) .append($('<a>', {'class':'connected_user_logo', href:profileLink, title:mission, target:'_blank'})
.append($('<img>', {src:databap.consts.app_image_folder+user_info.logo})) .append($('<img>', {src:databap.consts.app_image_folder+user_info.logo}))
.append((user_info.afk=='1')?$('<i>', {class:'fa fa-c-afk afk'}):'')) .append((user_info.afk=='1')?$('<i>', {class:'fa fa-c-afk afk'}):''))
.append($('<a>', {'class':'connected_user_name clickable '+sNickName, id:user_info.id_user, title:pm}).text(sNickName)); .append($('<a>', {'class':'connected_user_name clickable '+sNickName.replace('"', '\''), id:user_info.id_user, title:pm}).text(sNickName));
$user.find('.connected_user_name').click(joinPmChan); $user.find('.connected_user_name').click(joinPmChan);
databap.getMainElem('#connected_users').append($user); databap.getMainElem('#connected_users').append($user);
} }
@@ -852,6 +871,11 @@ function refresh_users()
} }
} }
function getSafeNickname(sNickName)
{
return sNickName.stripVowelAccent().toLowerCase();
}
function setPm() function setPm()
{ {
var name = $(this).text(); var name = $(this).text();

View File

@@ -24,7 +24,7 @@
<table> <table>
<tr> <tr>
<td class="desc">Nom &amp; prénom</td> <td class="desc">Nom &amp; prénom</td>
<td class="value"><input type="text" name="auth_name" id="auth_name" class="round" value="" /></td> <td class="value"><input type="text" name="auth_name" id="auth_name" class="round" value="" autofocus /></td>
</tr> </tr>
<tr> <tr>
<td class="desc">Mot de passe</td> <td class="desc">Mot de passe</td>

1
todo
View File

@@ -8,7 +8,6 @@ Internal:
- put feedback box in title - put feedback box in title
Bug fix: Bug fix:
- [1.0.0] Tab dans chat
- [1.0.1] Check le document type plutot que l'extension pour les /img - [1.0.1] Check le document type plutot que l'extension pour les /img
- [1.0.1] Resize .gif - [1.0.1] Resize .gif
- Fix les "xxx se déconnecte" intempestives - Fix les "xxx se déconnecte" intempestives