X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=view%2Fjs%2Fautocomplete.js;h=dc649084afe83b45ae7a91d8c6907cba83aa125c;hb=969becfc157cded332756f78018a8d9935c9c88a;hp=219ad794bc86a4b18a34626ad4c691bf36a3b18b;hpb=78de9d002243ed9a2e95feb76c1ee1bbd86fc348;p=friendica.git diff --git a/view/js/autocomplete.js b/view/js/autocomplete.js index 219ad794bc..dc649084af 100644 --- a/view/js/autocomplete.js +++ b/view/js/autocomplete.js @@ -1,5 +1,6 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat /** - * @brief Friendica people autocomplete + * Friendica people autocomplete * * require jQuery, jquery.textcomplete * @@ -12,7 +13,7 @@ function contact_search(term, callback, backend_url, type, mode) { - // Check if there is a conversation id to include the unkonwn contacts of the conversation + // Check if there is a conversation id to include the unknown contacts of the conversation var conv_id = document.activeElement.id.match(/\d+$/); // Check if there is a cached result that contains the same information we would get with a full server-side search @@ -23,8 +24,8 @@ function contact_search(term, callback, backend_url, type, mode) { 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({forum:false, text: term, replace: term}); + 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 circles don't have one + matching.unshift({group: false, text: term, replace: term}); setTimeout(function() { callback(matching); } , 1); // Use "pseudo-thread" to avoid some problems return; } @@ -68,15 +69,19 @@ 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); - var forum = ((item.forum) ? 'forum' : ''); + var group = ((item.group) ? 'group' : ''); if(typeof desc === 'undefined') desc = ''; if(desc) desc = ' ('+desc+')'; - return "
{2}{3}
".format(forum, item.photo, item.name, desc, item.link); + return "
{2}{3}
".format(group, item.photo, item.name, desc, item.link); } else return "
" + item.text + "
"; } +function tag_format(item) { + return ""; +} + function editor_replace(item) { if (typeof item.replace !== 'undefined') { return '$1$2' + item.replace; @@ -192,6 +197,56 @@ function string2bb(element) { * jQuery plugin 'editor_autocomplete' */ (function( $ ) { + let textcompleteObjects = []; + + // jQuery wrapper for yuku/old-textcomplete + // uses a local object directory to avoid recreating Textcomplete objects + $.fn.textcomplete = function (strategies, options) { + return this.each(function () { + let $this = $(this); + if (!($this.data('textcompleteId') in textcompleteObjects)) { + let editor = new Textcomplete.editors.Textarea($this.get(0)); + + $this.data('textcompleteId', textcompleteObjects.length); + textcompleteObjects.push(new Textcomplete(editor, options)); + } + + textcompleteObjects[$this.data('textcompleteId')].register(strategies); + }); + }; + + /** + * This function should be called immediately after $.textcomplete() to prevent the escape key press to propagate + * after the autocompletion dropdown has closed. + * This avoids the input textarea to lose focus, the modal window to close, etc... when the expected behavior is + * to just close the autocomplete dropdown. + * + * The custom event listener name allows removing this specific event listener, the "real" event this listens to + * is the part before the first dot. + * + * @returns {*} + */ + $.fn.fixTextcompleteEscape = function () { + if (this.data('textcompleteEscapeFixed')) { + return this; + } + + this.data('textcompleteEscapeFixed', true); + + return this.on({ + 'textComplete:show': function (e) { + $(this).on('keydown.friendica.escape', function (e) { + if (e.key === 'Escape') { + e.stopPropagation(); + } + }); + }, + 'textComplete:hide': function (e) { + $(this).off('keydown.friendica.escape'); + }, + }); + } + $.fn.editor_autocomplete = function(backend_url) { // Autocomplete contacts @@ -203,8 +258,8 @@ function string2bb(element) { template: contact_format, }; - // Autocomplete forums - forums = { + // Autocomplete groups + groups = { match: /(^|\s)(!\!*)([^ \n]+)$/, index: 3, search: function(term, callback) { contact_search(term, callback, backend_url, 'f'); }, @@ -212,6 +267,23 @@ function string2bb(element) { template: contact_format, }; + // Autocomplete hashtags + tags = { + match: /(^|\s)(\#)([^ \n]{2,})$/, + index: 3, + search: function(term, callback) { + $.getJSON(baseurl + '/hashtag/' + '?t=' + term) + .done(function(data) { + callback($.map(data, function(entry) { + // .toLowerCase() enables case-insensitive search + return entry.text.toLowerCase().indexOf(term.toLowerCase()) === 0 ? entry : null; + })); + }); + }, + replace: function(item) { return "$1$2" + item.text + ' '; }, + template: tag_format + }; + // Autocomplete smilies e.g. ":like" smilies = { match: /(^|\s)(:[a-z]{2,})$/, @@ -222,14 +294,12 @@ function string2bb(element) { }; this.attr('autocomplete','off'); - this.textcomplete([contacts, forums, smilies], {className:'acpopup', zIndex:10000}); + this.textcomplete([contacts, groups, smilies, tags], {dropdown: {className:'acpopup'}}); + this.fixTextcompleteEscape(); + + return this; }; -})( jQuery ); -/** - * jQuery plugin 'search_autocomplete' - */ -(function( $ ) { $.fn.search_autocomplete = function(backend_url) { // Autocomplete contacts contacts = { @@ -240,7 +310,7 @@ function string2bb(element) { template: contact_format, }; - // Autocomplete forum accounts + // Autocomplete group accounts community = { match: /(^!)([^\n]{2,})$/, index: 2, @@ -248,39 +318,24 @@ function string2bb(element) { replace: webbie_replace, template: contact_format, }; - this.attr('autocomplete', 'off'); - var a = this.textcomplete([contacts, community], {className:'acpopup', maxCount:100, zIndex: 10000, 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, + // Autocomplete hashtags + tags = { + match: /(^|\s)(\#)([^ \n]{2,})$/, + index: 3, + search: function(term, callback) { $.getJSON(baseurl + '/hashtag/' + '?t=' + term).done(function(data) { callback($.map(data, function(entry) { return entry.text.indexOf(term) === 0 ? entry : null; })); }); }, + replace: function(item) { return "$1$2" + item.text; }, + template: tag_format }; - this.attr('autocomplete','off'); - var a = this.textcomplete([contacts], {className:'acpopup', zIndex:10000}); - - if(autosubmit) - a.on('textComplete:select', function(e,value,strategy) { submit_form(this); }); + this.attr('autocomplete', 'off'); + this.textcomplete([contacts, community, tags], {dropdown: {className:'acpopup', maxCount:100}}); + this.fixTextcompleteEscape(); + this.on('textComplete:select', function(e, value, strategy) { submit_form(this); }); - if(typeof onselect !== 'undefined') - a.on('textComplete:select', function(e, value, strategy) { onselect(value); }); + return this; }; -})( jQuery ); - -(function( $ ) { $.fn.name_autocomplete = function(backend_url, typ, autosubmit, onselect) { if(typeof typ === 'undefined') typ = ''; if(typeof autosubmit === 'undefined') autosubmit = false; @@ -295,21 +350,23 @@ function string2bb(element) { }; this.attr('autocomplete','off'); - var a = this.textcomplete([names], {className:'acpopup', zIndex:10000}); + this.textcomplete([names], {dropdown: {className:'acpopup'}}); + this.fixTextcompleteEscape(); - if(autosubmit) - a.on('textComplete:select', function(e,value,strategy) { submit_form(this); }); + if(autosubmit) { + this.on('textComplete:select', function(e,value,strategy) { submit_form(this); }); + } - if(typeof onselect !== 'undefined') - a.on('textComplete:select', function(e, value, strategy) { onselect(value); }); + if(typeof onselect !== 'undefined') { + this.on('textComplete:select', function(e, value, strategy) { onselect(value); }); + } + + return this; }; -})( jQuery ); -(function( $ ) { $.fn.bbco_autocomplete = function(type) { - - if(type=='bbcode') { - var open_close_elements = ['bold', 'italic', 'underline', 'overline', 'strike', 'quote', 'code', 'spoiler', 'map', 'img', 'url', 'audio', 'video', 'embed', 'youtube', 'vimeo', 'list', 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td', 'center', 'color', 'font', 'size', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'nobb', 'noparse', 'pre', 'abstract']; + if (type === 'bbcode') { + var open_close_elements = ['bold', 'italic', 'underline', 'overline', 'strike', 'quote', 'code', 'spoiler', 'map', 'img', 'url', 'audio', 'video', 'embed', 'youtube', 'vimeo', 'list', 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td', 'center', 'color', 'font', 'size', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'nobb', 'noparse', 'pre', 'abstract', 'share']; var open_elements = ['*', 'hr']; var elements = open_close_elements.concat(open_elements); @@ -343,11 +400,12 @@ function string2bb(element) { }; this.attr('autocomplete','off'); - var a = this.textcomplete([bbco], {className:'acpopup', zIndex:10000}); + this.textcomplete([bbco], {dropdown: {className:'acpopup'}}); + this.fixTextcompleteEscape(); - a.on('textComplete:select', function(e, value, strategy) { value; }); + this.on('textComplete:select', function(e, value, strategy) { value; }); - a.keypress(function(e){ + this.keypress(function(e){ if (e.keyCode == 13) { var x = listNewLineAutocomplete(this.id); if(x) { @@ -356,135 +414,8 @@ function string2bb(element) { } } }); + + return this; }; })( jQuery ); - -/** - * Friendica people autocomplete legacy code - * - * require jQuery, jquery.textareas - */ -function ACPopup(elm, backend_url){ - this.idsel = -1; - this.element = elm; - this.searchText = ''; - this.ready = true; - this.kp_timer = false; - this.url = backend_url; - - this.conversation_id = null; - var conv_id = this.element.id.match(/\d+$/); - if (conv_id) { - this.conversation_id = conv_id[0]; - } - - var w = $(elm).width(); - var h = $(elm).height(); - - var style = $(elm).offset(); - style.top = style.top + h; - style.width = w; - style.position = 'absolute'; - style.display = 'none'; - - this.cont = $('
'); - this.cont.css(style); - - $('body').append(this.cont); -} - -ACPopup.prototype.close = function(){ - $(this.cont).remove(); - this.ready=false; -} -ACPopup.prototype.search = function(text){ - var that = this; - this.searchText=text; - if (this.kp_timer) clearTimeout(this.kp_timer); - this.kp_timer = setTimeout( function(){that._search();}, 500); -} - -ACPopup.prototype._search = function(){ - console.log("_search"); - var that = this; - var postdata = { - start:0, - count:100, - search:this.searchText, - type:'c', - conversation: this.conversation_id, - } - - $.ajax({ - type:'POST', - url: this.url, - data: postdata, - dataType: 'json', - success:function(data){ - that.cont.html(""); - if (data.tot>0){ - that.cont.show(); - $(data.items).each(function(){ - var html = "{1} ({2})".format(this.photo, this.name, this.nick); - var nick = this.nick.replace(' ',''); - if (this.id!=='') nick += '+' + this.id; - that.add(html, nick + ' - ' + this.link); - }); - } else { - that.cont.hide(); - } - } - }); - -} - -ACPopup.prototype.add = function(label, value){ - var that = this; - var elm = $('
' + label + '
'); - elm.click(function(e){ - t = $(this).attr('title').replace(new RegExp(' \- .*'), ''); - el = $(that.element); - sel = el.getSelection(); - sel.start = sel.start - that.searchText.length; - el.setSelection(sel.start, sel.end).replaceSelectedText(t + ' ').collapseSelection(false); - that.close(); - }); - $(this.cont).append(elm); -} - -ACPopup.prototype.onkey = function(event){ - if (event.keyCode == '13') { - if(this.idsel > -1) { - this.cont.children()[this.idsel].click(); - event.preventDefault(); - } else { - this.close(); - } - } - if (event.keyCode == '38') { //cursor up - var cmax = this.cont.children().size() - 1; - this.idsel--; - if (this.idsel < 0) { - this.idsel = cmax; - } - event.preventDefault(); - } - if (event.keyCode == '40' || event.keyCode == '9') { //cursor down - var cmax = this.cont.children().size() - 1; - this.idsel++; - if (this.idsel > cmax) { - this.idsel = 0; - } - event.preventDefault(); - } - - if (event.keyCode == '38' || event.keyCode == '40' || event.keyCode == '9') { - this.cont.children().removeClass('selected'); - $(this.cont.children()[this.idsel]).addClass('selected'); - } - - if (event.keyCode == '27') { //ESC - this.close(); - } -} - +// @license-end