# HG changeset patch # User domruf # Date 1544478844 -3600 # Node ID 2e7ffb755d4f3429656c048e6f5b46908c2ee734 # Parent bf514091b27fd24a25bbacd6f093ce0b2b25ce5d front-end: use At.js for MentionsAutoComplete We want to get rid of YUI, and select2 is not well suited for this purpose. So use At.js, which is made just for this use case. Original implementation was modified by Mads Kiilerich. diff -r bf514091b27f -r 2e7ffb755d4f .hgignore --- a/.hgignore Mon Dec 10 23:32:39 2018 +0100 +++ b/.hgignore Mon Dec 10 22:54:04 2018 +0100 @@ -32,6 +32,8 @@ ^kallithea/public/css/style\.css\.map$ ^kallithea/public/js/bootstrap\.js$ ^kallithea/public/js/dataTables\.bootstrap\.js$ +^kallithea/public/js/jquery\.atwho\.min\.js$ +^kallithea/public/js/jquery\.caret\.min\.js$ ^kallithea/public/js/jquery\.dataTables\.js$ ^kallithea/public/js/jquery\.flot\.js$ ^kallithea/public/js/jquery\.flot\.selection\.js$ diff -r bf514091b27f -r 2e7ffb755d4f LICENSE.md --- a/LICENSE.md Mon Dec 10 23:32:39 2018 +0100 +++ b/LICENSE.md Mon Dec 10 22:54:04 2018 +0100 @@ -84,6 +84,38 @@ +At.js +----- + +Kallithea uses the Javascript system called +[At.js](http://ichord.github.com/At.js), +which can be found together with its Corresponding Source in +https://github.com/ichord/At.js at tag v1.5.4. + +It is Copyright 2013 chord.luo@gmail.com and is under an +[MIT-permissive license](MIT-Permissive-License.txt). + +It is not distributed with Kallithea, but will be downloaded +using the ''kallithea-cli front-end-build'' command. + + + +Caret.js +-------- + +Kallithea uses the Javascript system called +[Caret.js](http://ichord.github.com/Caret.js/), +which can be found together with its Corresponding Source in +https://github.com/ichord/Caret.js at tag v0.3.1. + +It is Copyright 2013 chord.luo@gmail.com and is under an +[MIT-permissive license](MIT-Permissive-License.txt). + +It is not distributed with Kallithea, but will be downloaded +using the ''kallithea-cli front-end-build'' command. + + + DataTables ---------- diff -r bf514091b27f -r 2e7ffb755d4f kallithea/bin/kallithea_cli_front_end.py --- a/kallithea/bin/kallithea_cli_front_end.py Mon Dec 10 23:32:39 2018 +0100 +++ b/kallithea/bin/kallithea_cli_front_end.py Mon Dec 10 22:54:04 2018 +0100 @@ -66,11 +66,13 @@ click.echo("Preparing Bootstrap JS") shutil.copy(os.path.join(front_end_dir, 'node_modules', 'bootstrap', 'dist', 'js', 'bootstrap.js'), os.path.join(public_dir, 'js', 'bootstrap.js')) - click.echo("Preparing jQuery JS with Flot") + click.echo("Preparing jQuery JS with Flot, Caret and Atwho") shutil.copy(os.path.join(front_end_dir, 'node_modules', 'jquery', 'dist', 'jquery.min.js'), os.path.join(public_dir, 'js', 'jquery.min.js')) shutil.copy(os.path.join(front_end_dir, 'node_modules', 'jquery.flot', 'jquery.flot.js'), os.path.join(public_dir, 'js', 'jquery.flot.js')) shutil.copy(os.path.join(front_end_dir, 'node_modules', 'jquery.flot', 'jquery.flot.selection.js'), os.path.join(public_dir, 'js', 'jquery.flot.selection.js')) shutil.copy(os.path.join(front_end_dir, 'node_modules', 'jquery.flot', 'jquery.flot.time.js'), os.path.join(public_dir, 'js', 'jquery.flot.time.js')) + shutil.copy(os.path.join(front_end_dir, 'node_modules', 'jquery.caret', 'dist', 'jquery.caret.min.js'), os.path.join(public_dir, 'js', 'jquery.caret.min.js')) + shutil.copy(os.path.join(front_end_dir, 'node_modules', 'at.js', 'dist', 'js', 'jquery.atwho.min.js'), os.path.join(public_dir, 'js', 'jquery.atwho.min.js')) click.echo("Preparing DataTables JS") shutil.copy(os.path.join(front_end_dir, 'node_modules', 'datatables.net', 'js', 'jquery.dataTables.js'), os.path.join(public_dir, 'js', 'jquery.dataTables.js')) diff -r bf514091b27f -r 2e7ffb755d4f kallithea/front-end/package.json --- a/kallithea/front-end/package.json Mon Dec 10 23:32:39 2018 +0100 +++ b/kallithea/front-end/package.json Mon Dec 10 22:54:04 2018 +0100 @@ -2,11 +2,13 @@ "name": "kallithea", "private": true, "dependencies": { + "at.js": "1.5.4", "bootstrap": "3.3.7", "codemirror": "4.7", "datatables.net": "1.10.13", "datatables.net-bs": "1.10.13", "jquery": "1.12.3", + "jquery.caret": "0.3.1", "jquery.flot": "0.8.3", "select2": "3.5.1", "select2-bootstrap-css": "1.2.4" diff -r bf514091b27f -r 2e7ffb755d4f kallithea/public/js/base.js --- a/kallithea/public/js/base.js Mon Dec 10 23:32:39 2018 +0100 +++ b/kallithea/public/js/base.js Mon Dec 10 22:54:04 2018 +0100 @@ -751,7 +751,7 @@ tooltip_activate(); if ($textarea.length > 0) { - MentionsAutoComplete($textarea, _USERS_AC_DATA); + MentionsAutoComplete($textarea); } if (f_path) { $textarea.focus(); @@ -1155,65 +1155,30 @@ }); } -var MentionsAutoComplete = function ($inputElement, users_list) { - var $container = $('
').insertAfter($inputElement); - - var matchUsers = function (sQuery) { - // use the search string from $inputElement instead of sQuery - if(!$container.data('search')){ - // return empty list so the input list isn't shown - return [] - } - return autocompleteMatchUsers($container.data('search'), users_list); - } - - var datasource = new YAHOO.util.FunctionDataSource(matchUsers); - var mentionsAC = new YAHOO.widget.AutoComplete($inputElement[0], $container[0], datasource); - mentionsAC.useShadow = false; - mentionsAC.resultTypeList = false; - mentionsAC.animVert = false; - mentionsAC.animHoriz = false; - mentionsAC.animSpeed = 0.1; - mentionsAC.suppressInputUpdate = true; - mentionsAC.formatResult = function (oResultData, sQuery, sResultMatch) { - // use the search string from $inputElement instead of sQuery - return autocompleteFormatter(oResultData, $container.data('search'), sResultMatch); - } - - // Handler for selection of an entry - if(mentionsAC.itemSelectEvent){ - mentionsAC.itemSelectEvent.subscribe(function (sType, aArgs) { - var myAC = aArgs[0]; // reference back to the AC instance - var elLI = aArgs[1]; // reference to the selected LI element - var oData = aArgs[2]; // object literal of selected item's result data - myAC.getInputEl().value = $container.data('before') + oData.nname + ' ' + $container.data('after'); - _setCaretPosition($(myAC.getInputEl()), myAC.dataSource.before.length + oData.nname.length + 1); - }); - } - - // Must match utils2.py MENTIONS_REGEX. - // Operates on a string from char before @ up to cursor. - // Check that the char before @ doesn't look like an email address, and match to end of string. - var mentionRe = new RegExp('(?:^|[^a-zA-Z0-9])@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])$'); - - $inputElement.keyup(function(e){ - var currentMessage = $inputElement.val(); - var currentCaretPosition = $inputElement[0].selectionStart; - - $container.data('search', ''); - var messageBeforeCaret = currentMessage.substr(0, currentCaretPosition); - var lastAtPos = messageBeforeCaret.lastIndexOf('@'); - if(lastAtPos >= 0){ - // Search from one char before last @ ... if possible - var m = mentionRe.exec(messageBeforeCaret.substr(Math.max(0, lastAtPos - 1))); - if(m){ - $container.data('before', currentMessage.substr(0, lastAtPos + 1)); - $container.data('search', currentMessage.substr(lastAtPos + 1, currentCaretPosition - lastAtPos - 1)); - $container.data('after', currentMessage.substr(currentCaretPosition)); - } - } - }); -} +var MentionsAutoComplete = function ($inputElement) { + $inputElement.atwho({ + at: "@", + callbacks: { + remoteFilter: function(query, callback) { + $.getJSON( + pyroutes.url('users_and_groups_data'), + { + query: query, + types: 'users' + }, + function(data) { + callback(data.results) + } + ); + }, + sorter: function(query, items, searchKey) { + return items; + } + }, + displayTpl: "
  • " + autocompleteGravatar('${fname} ${lname} (${nname})', '${gravatar_lnk}', 16) + "
  • ", + insertTpl: "${atwho-at}${nname}" + }); +}; // Set caret at the given position in the input element diff -r bf514091b27f -r 2e7ffb755d4f kallithea/public/less/main.less --- a/kallithea/public/less/main.less Mon Dec 10 23:32:39 2018 +0100 +++ b/kallithea/public/less/main.less Mon Dec 10 22:54:04 2018 +0100 @@ -11,6 +11,7 @@ /* 3rd party styles */ @import "node_modules/bootstrap/less/bootstrap.less"; @import (inline) "node_modules/datatables.net-bs/css/dataTables.bootstrap.css"; +@import (inline) "node_modules/at.js/dist/css/jquery.atwho.css"; @import (less) "node_modules/select2/select2.css"; @import (less) "node_modules/select2-bootstrap-css/select2-bootstrap.css"; @import (less) "tmp/pygments.css"; diff -r bf514091b27f -r 2e7ffb755d4f kallithea/public/less/style.less --- a/kallithea/public/less/style.less Mon Dec 10 23:32:39 2018 +0100 +++ b/kallithea/public/less/style.less Mon Dec 10 22:54:04 2018 +0100 @@ -929,3 +929,9 @@ #context-pages > ul > li > a { height: @navbar-height; } + +/* at.js */ +.atwho-view strong { + /* the blue color doesn't look good, use normal color */ + color: inherit; +} diff -r bf514091b27f -r 2e7ffb755d4f kallithea/templates/base/root.html --- a/kallithea/templates/base/root.html Mon Dec 10 23:32:39 2018 +0100 +++ b/kallithea/templates/base/root.html Mon Dec 10 22:54:04 2018 +0100 @@ -74,6 +74,8 @@ + + ## EXTRA FOR JS <%block name="js_extra"/>