Browse Source

rework autocomplete: initial commit

pull/2449/head
rabuzarus 6 years ago
parent
commit
16e4e94b29
  1. 192
      js/autocomplete.js
  2. 2
      js/fk.autocomplete.js
  3. 2
      js/main.js
  4. 21
      library/jquery-textcomplete/LICENSE
  5. 1104
      library/jquery-textcomplete/jquery.textcomplete.js
  6. 4
      view/templates/display-head.tpl
  7. 4
      view/templates/head.tpl
  8. 2
      view/templates/jot-header.tpl

192
js/autocomplete.js

@ -0,0 +1,192 @@
/**
* Red people autocomplete
*
* require jQuery, jquery.textcomplete
*/
function contact_search(term, callback, backend_url, type) {
// Check if there is a cached result that contains the same information we would get with a full server-side search
var bt = backend_url+type;
if(!(bt in contact_search.cache)) contact_search.cache[bt] = {};
var lterm = term.toLowerCase(); // Ignore case
for(var t in contact_search.cache[bt]) {
if(lterm.indexOf(t) >= 0) { // A more broad search has been performed already, so use those results
// Filter old results locally
var matching = contact_search.cache[bt][t].filter(function (x) { return (x.name.toLowerCase().indexOf(lterm) >= 0 || (typeof x.nick !== 'undefined' && x.nick.toLowerCase().indexOf(lterm) >= 0)); }); // Need to check that nick exists because groups don't have one
matching.unshift({taggable:false, text: term, replace: term});
setTimeout(function() { callback(matching); } , 1); // Use "pseudo-thread" to avoid some problems
return;
}
}
var postdata = {
start:0,
count:100,
search:term,
type:type,
};
$.ajax({
type:'POST',
url: backend_url,
data: postdata,
dataType: 'json',
success: function(data){
// Cache results if we got them all (more information would not improve results)
// data.count represents the maximum number of items
if(data.items.length -1 < data.count) {
contact_search.cache[bt][lterm] = data.items;
}
var items = data.items.slice(0);
items.unshift({taggable:false, text: term, replace: term});
callback(items);
},
}).fail(function () {callback([]); }); // Callback must be invoked even if something went wrong.
}
contact_search.cache = {};
function contact_format(item) {
// Show contact information if not explicitly told to show something else
if(typeof item.text === 'undefined') {
var desc = ((item.label) ? item.nick + ' ' + item.label : item.nick);
if(typeof desc === 'undefined') desc = '';
if(desc) desc = ' ('+desc+')';
return "<div class='{0}' title='{4}'><img class='dropdown-menu-img-sm' src='{1}'><span class='contactname'>{2}</span><span class='dropdown-sub-text'>{3}</span><div class='clear'></div></div>".format(item.taggable, item.photo, item.name, desc, item.link);
}
else
return "<div>" + item.text + "</div>";
}
function editor_replace(item) {
if(typeof item.replace !== 'undefined') {
return '$1$2' + item.replace;
}
// $2 ensures that prefix (@,@!) is preserved
var id = item.id;
// 16 chars of hash should be enough. Full hash could be used if it can be done in a visually appealing way.
// 16 chars is also the minimum length in the backend (otherwise it's interpreted as a local id).
if(id.length > 16)
id = item.id.substring(0,16);
return '$1$2' + item.nick.replace(' ', '') + '+' + id + ' ';
}
function basic_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
return '$1'+item.name+' ';
}
function trim_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
return '$1'+item.name;
}
function submit_form(e) {
$(e).parents('form').submit();
}
/**
* jQuery plugin 'editor_autocomplete'
*/
(function( $ ) {
$.fn.editor_autocomplete = function(backend_url) {
// Autocomplete contacts
contacts = {
match: /(^|\s)(@\!*)([^ \n]+)$/,
index: 3,
search: function(term, callback) { contact_search(term, callback, backend_url, 'c'); },
replace: editor_replace,
template: contact_format,
};
smilies = {
match: /(^|\s)(:[a-z]{2,})$/,
index: 2,
search: function(term, callback) { $.getJSON('/smilies/json').done(function(data) { callback($.map(data, function(entry) { return entry.text.indexOf(term) === 0 ? entry : null; })); }); },
template: function(item) { return item.icon + item.text; },
replace: function(item) { return "$1" + item.text + ' '; },
};
this.attr('autocomplete','off');
this.textcomplete([contacts,smilies], {className:'acpopup', zIndex:1020});
};
})( jQuery );
/**
* jQuery plugin 'search_autocomplete'
*/
(function( $ ) {
$.fn.search_autocomplete = function(backend_url) {
// Autocomplete contacts
contacts = {
match: /(^@)([^\n]{2,})$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, 'x'); },
replace: basic_replace,
template: contact_format,
};
this.attr('autocomplete', 'off');
var a = this.textcomplete([contacts], {className:'acpopup', maxCount:100, zIndex: 1020, appendTo:'nav'});
a.on('textComplete:select', function(e, value, strategy) { submit_form(this); });
};
})( jQuery );
(function( $ ) {
$.fn.contact_autocomplete = function(backend_url, typ, autosubmit, onselect) {
if(typeof typ === 'undefined') typ = '';
if(typeof autosubmit === 'undefined') autosubmit = false;
// Autocomplete contacts
contacts = {
match: /(^)([^\n]+)$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, typ); },
replace: basic_replace,
template: contact_format,
};
this.attr('autocomplete','off');
var a = this.textcomplete([contacts], {className:'acpopup', zIndex:1020});
if(autosubmit)
a.on('textComplete:select', function(e,value,strategy) { submit_form(this); });
if(typeof onselect !== 'undefined')
a.on('textComplete:select', function(e, value, strategy) { onselect(value); });
};
})( jQuery );
(function( $ ) {
$.fn.name_autocomplete = function(backend_url, typ, autosubmit, onselect) {
if(typeof typ === 'undefined') typ = '';
if(typeof autosubmit === 'undefined') autosubmit = false;
// Autocomplete contacts
names = {
match: /(^)([^\n]+)$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, typ); },
replace: trim_replace,
template: contact_format,
};
this.attr('autocomplete','off');
var a = this.textcomplete([names], {className:'acpopup', zIndex:1020});
if(autosubmit)
a.on('textComplete:select', function(e,value,strategy) { submit_form(this); });
if(typeof onselect !== 'undefined')
a.on('textComplete:select', function(e, value, strategy) { onselect(value); });
};
})( jQuery );

2
js/fk.autocomplete.js

@ -86,7 +86,7 @@ ACPopup.prototype._search = function(){
if (data.tot>0){
that.cont.show();
$(data.items).each(function(){
var html = "<img src='{0}' height='16px' width='16px'>{1} ({2})".format(this.photo, this.name, this.nick);
var html = "<img class='acpopup-img' src='{0}' height='16px' width='16px'> <span class='acpopup-name'>{1}</span> <span class='acpopup-addr'>({2})</span>".format(this.photo, this.name, this.addr);
var nick = this.nick.replace(' ','');
if (this.id!=='') nick += '+' + this.id;
that.add(html, nick + ' - ' + this.link);

2
js/main.js

@ -493,7 +493,7 @@
$('body').css('cursor', 'auto');
}
/* autocomplete @nicknames */
$(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl");
// setup videos, since VideoJS won't take care of any loaded via AJAX
if(typeof videojs != 'undefined') videojs.autoSetup();

21
library/jquery-textcomplete/LICENSE

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2014 Yuku Takahashi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

1104
library/jquery-textcomplete/jquery.textcomplete.js
File diff suppressed because it is too large
View File

4
view/templates/display-head.tpl

@ -1,9 +1,9 @@
<script>
$(document).ready(function() {
$(".comment-edit-wrapper textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-edit-wrapper textarea").editor_autocomplete(baseurl+"/acl");
// make auto-complete work in more places
$(".wall-item-comment-wrapper textarea").contact_autocomplete(baseurl+"/acl");
$(".wall-item-comment-wrapper textarea").editor_autocomplete(baseurl+"/acl");
});
</script>

4
view/templates/head.tpl

@ -33,7 +33,9 @@
<!-- <script type="text/javascript" src="{{$baseurl}}/js/jquery-migrate.js" ></script>-->
<script type="text/javascript" src="{{$baseurl}}/js/jquery-migrate.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/js/jquery.textinputs.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/js/fk.autocomplete.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/library/jquery-textcomplete/jquery.textcomplete.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/js/autocomplete.js" ></script>
<!--<script type="text/javascript" src="{{$baseurl}}/js/fk.autocomplete.js" ></script>-->
<script type="text/javascript" src="{{$baseurl}}/library/colorbox/jquery.colorbox-min.js"></script>
<script type="text/javascript" src="{{$baseurl}}/library/jgrowl/jquery.jgrowl_minimized.js"></script>
<script type="text/javascript" src="{{$baseurl}}/library/datetimepicker/jquery.datetimepicker.js"></script>

2
view/templates/jot-header.tpl

@ -12,7 +12,7 @@ function initEditor(cb){
if(plaintext == 'none') {
$("#profile-jot-text-loading").hide();
$("#profile-jot-text").css({ 'height': 200, 'color': '#000' });
$("#profile-jot-text").contact_autocomplete(baseurl+"/acl");
$("#profile-jot-text").editor_autocomplete(baseurl+"/acl");
editor = true;
$("a#jot-perms-icon").colorbox({
'inline' : true,

Loading…
Cancel
Save