From 1aede4c4716d885f518d9a9d064d3934a8969cf5 Mon Sep 17 00:00:00 2001 From: nipos Date: Thu, 1 Nov 2018 18:45:46 +0100 Subject: [PATCH] Added autocomplete for usernames,hashtags and emojis and fixed a bug in the emoji picker --- README.md | 2 + assets/css/dark.css | 18 + assets/css/style.css | 63 +++- assets/js/autocomplete/license-textarea.txt | 201 +++++++++++ assets/js/autocomplete/textarea.js | 366 ++++++++++++++++++++ assets/js/halcyon/halcyonSettings.js | 13 + assets/js/halcyon/halcyonUI.js | 91 ++++- header.php | 1 + login/auth.php | 1 + settings_general.php | 11 + version.txt | 2 +- 11 files changed, 754 insertions(+), 15 deletions(-) create mode 100644 assets/js/autocomplete/license-textarea.txt create mode 100644 assets/js/autocomplete/textarea.js diff --git a/README.md b/README.md index 97102eb..303ae70 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ We moved our instances list to a wiki page: https://notabug.org/halcyon-suite/ha Read our new wiki pages: https://notabug.org/halcyon-suite/halcyon/wiki ## Blog +- Release of Version 2.1.3 - Added a autocomplete feature for usernames,hashtags and emojis,fixed a bug in the emoji picker (didn't open sometimes) - Release of Version 2.1.2 - Added toot to @someone button to profiles,remove blocked and muted people from who to follow,improved German translation - Release of Version 2.1.1 - Profile settings can be changed again,fixed various Firefox-only bugs,Removed error if browser sends no language - [Release of Version 2.1.0 - Introducing lists and more](https://nikisoft.myblog.de/nikisoft/art/11640527/Halcyon-2-1-0-Introducing-lists-and-more) @@ -57,3 +58,4 @@ Read our new wiki pages: https://notabug.org/halcyon-suite/halcyon/wiki - [distsn/vinayaka](https://github.com/distsn/vinayaka) - [LascauxSRL/lsx-emojipicker](https://github.com/LascauxSRL/lsx-emojipicker) - [osapon/Pomo](https://github.com/osapon/Pomo) +- [Summer-Dong/auto-complete-for-text-input-box](https://github.com/Summer-Dong/auto-complete-for-text-input-box) diff --git a/assets/css/dark.css b/assets/css/dark.css index d6cded3..6ea3520 100644 --- a/assets/css/dark.css +++ b/assets/css/dark.css @@ -573,3 +573,21 @@ border-bottom:0 solid #189EFC; .lsx-emojipicker-container,.lsx-emojipicker-container:before { background-color:#243447 !important; } +.dropDown { +background-color:#243447; +box-shadow:0.5px 0.5px 3px rgba(0,0,0,0.26); +border:1px solid #000; +} +.dropDown li .un { +color:#66757F; +} +.dropDown h3 { +color:#FFF !important; +} +.hoverLi { +background-color:#189EFC; +color:#FFF; +} +.hoverLi h3,.hoverLi .un { +color:#FFF !important; +} diff --git a/assets/css/style.css b/assets/css/style.css index c9a2faa..484e3ac 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1341,38 +1341,38 @@ outline:0; border:1px solid #189EFC; background-color:transparent; } -.side_widget .account_box { +.account_box { display: flex; flex-wrap: nowrap; align-items: center; height: 100%; margin-bottom: 12px; } -.side_widget .account_box .icon_box { +.account_box .icon_box { width: 48px; height: 48px; overflow: hidden; margin-right: 8px; border-radius: 5px; } -.side_widget .account_box .label_box { +.account_box .label_box { width: 200px; } -.side_widget .account_box .label_box h3 { +.account_box .label_box h3 { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: #333; } -.side_widget .account_box .label_box h3 .dn { +.account_box .label_box h3 .dn { font-size: 14px; font-weight: 700; } -.side_widget .account_box .label_box h3 .un { +.account_box .label_box h3 .un { font-size: 14px; color: #66757F; } -.side_widget .account_box .label_box .follow_button { +.account_box .label_box .follow_button { display: flex; flex-wrap: nowrap; align-items: center; @@ -1381,15 +1381,15 @@ padding: 5px 16px; margin-top: 4px; border-radius: 4px; } -.side_widget .account_box .label_box .follow_button i { +.account_box .label_box .follow_button i { color: #189EFC; margin-right: 4px; } -.side_widget .account_box .label_box .follow_button span { +.account_box .label_box .follow_button span { font-weight: 600; } -.side_widget .account_box .label_box .follow_button:hover, -.side_widget .account_box .label_box .follow_button:hover i { +.account_box .label_box .follow_button:hover, +.account_box .label_box .follow_button:hover i { background-color: #189EFC; color: #fff!important; } @@ -2522,3 +2522,44 @@ width:600px; width:900px; } } +.dropDown { +display:inline; +position:absolute; +background-color:#FFF; +list-style:none; +padding:0; +z-index:1000; +box-shadow:0.5px 0.5px 3px rgba(0,0,0,0.26); +box-sizing:border-box; +cursor:pointer; +border-radius:3px; +} +.dropDown li { +margin:0; +padding-top:5px; +padding-bottom:5px; +} +.dropDown li .un { +color:#66757F; +overflow:hidden; +white-space:nowrap; +text-overflow:ellipsis; +display:block; +} +.dropDown .icon_box .emoji { +margin:0; +vertical-align:0; +} +.hoverLi { +background-color:#189EFC; +color:#FFF; +} +.hoverLi h3,.hoverLi .un { +color:#FFF !important; +} +.showDropDown{ +display:inline; +} +.hideDropDown { +display:none; +} diff --git a/assets/js/autocomplete/license-textarea.txt b/assets/js/autocomplete/license-textarea.txt new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/assets/js/autocomplete/license-textarea.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/assets/js/autocomplete/textarea.js b/assets/js/autocomplete/textarea.js new file mode 100644 index 0000000..47cc014 --- /dev/null +++ b/assets/js/autocomplete/textarea.js @@ -0,0 +1,366 @@ +(function($) { +var blurredEle, theStartKey; +var ulNode=document.createElement('ul'); +$(ulNode).addClass("dropDown").addClass("account_list") +.attr('id','autoCompleteDropDown'); +function getCaretPosition(domElement) { +var iCaretPos = 0; +if(document.selection) { +domElement.focus(); +var oSel = document.selection.createRange(); +oSel.moveStart('character', -domElement.value.length); +iCaretPos = oSel.text.length; +} +else if(domElement.selectionStart || domElement.selectionStart === '0') { +iCaretPos = domElement.selectionStart; +} +return iCaretPos; +} +function setCaretPosition(domElement, pos) { +if(domElement.setSelectionRange) { +domElement.focus(); +domElement.setSelectionRange(pos, pos); +} +else if(domElement.createTextRange) { +var range = domElement.createTextRange(); +range.collapse(true); +range.moveEnd('character', pos); +range.moveStart('character', pos); +range.select(); +} +} +function getLastestPositionOfStartKey(ele, startKey) { +return ele.value.slice(0, getCaretPosition(ele)).lastIndexOf(startKey); +} +function extractNewInputs(node, startKey) { +if(getLastestPositionOfStartKey(node, startKey) >= 0) { +return node.value.slice(getLastestPositionOfStartKey(node, startKey), getCaretPosition(node)); +} +return ''; +} +function filterData(originData,resultName,matchedInputs) { +return !!matchedInputs && originData.filter(function(data) { +return data.name.slice(0,matchedInputs.length-1).toLowerCase() === matchedInputs.substr(1).toLowerCase(); +}); +} +function fillDropDown(node,data,resultname,prepend,instance,callback) { +getDropDown().data("instance",instance); +getDropDown().find('li').remove(); +data = data.slice(0,5); +data && +data.forEach(function(ele) { +if(ele) { +var liNode = document.createElement('li'); +$(liNode).hover(function() { +$(this).parent().find('li.hoverLi').removeClass('hoverLi'); +$(this).addClass("hoverLi"); +},function() { +$(this).removeClass("hoverLi"); +}).click(function() { +blurredEle && addToken(blurredEle,prepend,callback); +blurredEle = null; +getDropDown().removeClass('showDropDown').addClass('hideDropDown'); +}); +if(resultname) { +if(resultname == "acct") { +$(liNode).data("value",prepend+ele[resultname]+" "); +$(liNode).addClass("account_box").append($("
").addClass("icon_box").append($("").attr("src",ele.avatar).css("float","left"))) +.append($("
").addClass("label_box").append($("").addClass("dn").append($("

").html(ele.display_name).addClass("emoji_poss"))).append($("").addClass("un").html(prepend+ele.acct))); +} +else { +$(liNode).data("value",prepend+ele[resultname]+": "); +if(ele.value) { +$(liNode).addClass("account_box").append($("
").addClass("icon_box").append($("").addClass("emoji_poss").html(ele.value).css("float","left").css("font-size","32px"))) +.append($("
").addClass("label_box").append($("").addClass("dn").append($("

").html(ele.name)))); +} +else { +$(liNode).addClass("account_box").append($("
").addClass("icon_box").append($("").attr("src",ele.url).css("float","left"))) +.append($("
").addClass("label_box").append($("").addClass("dn").append($("

").html(ele.name)))); +} +} +} +else { +$(liNode).data("value",prepend+ele+" "); +$(liNode).addClass("account_box").append($("
").addClass("icon_box").append($("").addClass("emoji_poss").html("#️⃣").css("float","left").css("font-size","32px"))) +.append($("
").addClass("label_box").append($("").addClass("dn").append($("

").html(prepend+ele)))); +} +node.append(liNode); +} +}); +replace_emoji(); +} +function getDropDown() { +return $("#autoCompleteDropDown"); +} +function belongsTo(instance) { +if(getDropDown().data("instance") == instance) return true; +else return false; +} +function getHoveredLi() { +return getDropDown().find('li.hoverLi'); +} +function addToken(node,startKey,callback) { +var token = getHoveredLi().data("value"); +var inputsUtilCaret = node.value +.slice(0, getLastestPositionOfStartKey(node,startKey)) +.concat(token); +node.value = inputsUtilCaret +.concat(node.value.slice(getCaretPosition(node))); +setCaretPosition(node, inputsUtilCaret.length); +getDropdownRemoved(); +if(callback && typeof callback == "function") { +callback(); +} +} +function hasDropDown() { +return getDropDown().length; +} +function hasHoveredList() { +return getHoveredLi().length; +} +function getDropdownRemoved() { +if(hasDropDown()) { +setTimeout(function() {getDropDown().remove()},0); +} +} +function figureKeycodeOption(e,instance) { +if((e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 13) && hasDropDown() && getDropDown().css('opacity') === '1') { +// 38: arrowUp; 40: arrowDown; 13: Enter; +e.preventDefault(); +} +switch(e.keyCode) { +case 38: +if(hasHoveredList() && belongsTo(instance)) { +var preLi = getHoveredLi().removeClass('hoverLi').prev(); +preLi ? preLi.addClass('hoverLi') : getDropDown().last().addClass('hoverLi'); +} +else if(hasDropDown() && !hasHoveredList() && belongsTo(instance)) { +getDropDown().children().last().addClass('hoverLi'); +} +break; +case 40: +if(hasHoveredList() && belongsTo(instance)) { +var nextLi = getHoveredLi().removeClass('hoverLi').next(); +nextLi ? nextLi.addClass('hoverLi') : getDropDown().first().addClass('hoverLi'); +} +else if(hasDropDown() && !hasHoveredList() && belongsTo(instance)) { +getDropDown().children().first().addClass('hoverLi'); +} +break; +default: +break; +} +} +function filterSourceData(e,node,config) { +var startKey = config.startkey; +var endKey = config.endkey; +if((e.keyCode === 38 || e.keyCode === 40) && hasDropDown()&& getDropDown().css('opacity') === '1' || e.keyCode === 16) { +//38: arrowUp; 40: arrowDown; 16: shift; +e.preventDefault(); +return; +} +else if(e.keyCode === 27 && hasDropDown() && getDropDown().css('opacity') === '1') { +// 27: Esc; +getDropdownRemoved(); +return; +} +switch(e.keyCode){ +case 13: +if(hasHoveredList() && belongsTo(config.instance)) { +addToken(node,startKey,config.callback); +} +return; +default: +break; +} +if(node.value.slice(getCaretPosition(node)-1, getCaretPosition(node)) === endKey){ +getDropdownRemoved(); +return; +} +if(extractNewInputs(node,startKey).length > 1 && extractNewInputs(node,startKey).indexOf(endKey) == -1) { +if(config.arrayname) { +api.get("search?q="+encodeURIComponent(extractNewInputs(node,startKey))+"&resolve=false&limit=5",function(matchedData) { +matchedData = matchedData[config.arrayname]; +if(matchedData.length) { +if(hasDropDown()){ +getDropDown().find('li').remove(); +} +else { +$(ulNode).insertAfter(node); +} +fillDropDown(getDropDown(),matchedData,config.resultname,config.startkey,config.instance,config.callback); +getDropDown().removeClass('hideDropDown').addClass('showDropDown'); +} +else { +getDropdownRemoved(); +} +if(hasDropDown()){ +var pos = $(node).getCaretPixelPosition(); +getDropDown().css({ +'left': node.offsetLeft + pos.left, +'top': node.offsetTop + pos.top +}); +} +}); +} +else { +var matchedData = filterData(config.source,config.resultname,extractNewInputs(node,startKey)); +if(matchedData.length) { +if(hasDropDown()){ +getDropDown().find('li').remove(); +} +else { +$(ulNode).insertAfter(node); +} +fillDropDown(getDropDown(),matchedData,config.resultname,config.startkey,config.instance,config.callback); +getDropDown().removeClass('hideDropDown').addClass('showDropDown'); +} +else { +getDropdownRemoved(); +} +if(hasDropDown()){ +var pos = $(node).getCaretPixelPosition(); +getDropDown().css({ +'left': node.offsetLeft + pos.left, +'top': node.offsetTop + pos.top +}); +} +} +} +} +$.fn.autoCompleteToken = function(config) { +if(config == "destroy") { +this.off("keydown"); +this.off("keyup"); +this.off("blur"); +} +else { +this.keydown(function(e) { +figureKeycodeOption(e,config.instance); +}); +this.keyup(function(e) { +filterSourceData(e,this,config); +}); +this.blur(function() { +blurredEle = this; +theStartKey = config.startkey; +}); +} +} +}(jQuery)); +$(document).click(function(e) { +if(!$(e.target).closest('#autoCompleteDropDown').length) { +$("#autoCompleteDropDown").removeClass('showDropDown').addClass('hideDropDown'); +} +}); +(function($, window, document) { +// @license under Apache license +// * @author Bevis Zhao (i@bevis.me, http://bevis.me) +$(function() { +var calculator = { +primaryStyles: ['fontFamily', 'fontSize', 'fontWeight', 'fontVariant', 'fontStyle', +'paddingLeft', 'paddingTop', 'paddingBottom', 'paddingRight', +'marginLeft', 'marginTop', 'marginBottom', 'marginRight', +'borderLeftColor', 'borderTopColor', 'borderBottomColor', 'borderRightColor', +'borderLeftStyle', 'borderTopStyle', 'borderBottomStyle', 'borderRightStyle', +'borderLeftWidth', 'borderTopWidth', 'borderBottomWidth', 'borderRightWidth', +'line-height', 'outline'], +specificStyle: { +'word-wrap': 'break-word', +'overflow-x': 'hidden', +'overflow-y': 'auto' +}, +simulator: $('
').css({ +position: 'absolute', +top: 0, +left: 0, +visibility: 'hidden' +}).appendTo(document.body), +toHtml : function(text) { +return text.replace(//g,'>').replace(/\n/g, '
') +.replace(/(\s)/g,'$1'); +}, +getCaretPixelPosition:function() { +var cal = calculator, self = this, element = self[0], elementOffset = self.offset(); +cal.simulator.empty(); +$.each(cal.primaryStyles, function(index, styleName) { +self.cloneStyle(cal.simulator, styleName); +}); +cal.simulator.css($.extend({ +'width': self.width(), +'height': self.height() +},cal.specificStyle)); +var value = self.val(), cursorPosition = self.getCursorPosition(); +var beforeText = value.substring(0, cursorPosition), +afterText = value.substring(cursorPosition); +var before = $('').html(cal.toHtml(beforeText)), +focus = $(''), +after = $('').html(cal.toHtml(afterText)); +cal.simulator.append(before).append(focus).append(after); +var focusOffset = focus.offset(), simulatorOffset = cal.simulator.offset(); +// alert(focusOffset.left+ ',' +simulatorOffset.left + ',' + element.scrollLeft); +return { +top: focusOffset.top - simulatorOffset.top - element.scrollTop ++ (navigator.userAgent.indexOf("Firefox") != -1 ? 0 : parseInt(self.getComputedStyle("fontSize"))), +left: focus[0].offsetLeft -cal.simulator[0].offsetLeft - element.scrollLeft +}; +} +}; +$.fn.extend({ +getComputedStyle:function(styleName) { +if(this.length == 0) return; +var thiz = this[0]; +var result = this.css(styleName); +result = result || ($.browser.msie ? +thiz.currentStyle[styleName]: +document.defaultView.getComputedStyle(thiz, null)[styleName]); +return result; +}, +cloneStyle:function(target, styleName) { +var styleVal = this.getComputedStyle(styleName); +if (!!styleVal) { +$(target).css(styleName, styleVal); +} +}, +cloneAllStyle:function(target, style) { +var thiz = this[0]; +for (var styleName in thiz.style) { +var val = thiz.style[styleName]; +typeof val == 'string' || typeof val == 'number' +? this.cloneStyle(target, styleName) +: NaN; +} +}, +getCursorPosition:function() { +var thiz = this[0], result = 0; +if('selectionStart' in thiz) { +result = thiz.selectionStart; +} +else if('selection' in document) { +var range = document.selection.createRange(); +if(parseInt($.browser.version) > 6) { +thiz.focus(); +var length = document.selection.createRange().text.length; +range.moveStart('character', - thiz.value.length); +result = range.text.length - length; +} +else { +var bodyRange = document.body.createTextRange(); +bodyRange.moveToElementText(thiz); +for(; bodyRange.compareEndPoints("StartToStart", range) < 0; result++) +bodyRange.moveStart('character', 1); +for(var i = 0; i <= result; i ++){ +if (thiz.value.charAt(i) == '\n') +result++; +} +var enterCount = thiz.value.split('\n').length - 1; +result -= enterCount; +return result; +} +} +return result; +}, +getCaretPixelPosition: calculator.getCaretPixelPosition +}); +}); +})(jQuery, window, document); diff --git a/assets/js/halcyon/halcyonSettings.js b/assets/js/halcyon/halcyonSettings.js index b2fe2a6..9292342 100644 --- a/assets/js/halcyon/halcyonSettings.js +++ b/assets/js/halcyon/halcyonSettings.js @@ -7,6 +7,9 @@ $(".search_filter_wrap input[name='search_filter'][value='"+localStorage.getItem if(localStorage.setting_post_sensitive == "true") { $("#setting_post_sensitive")[0].checked = true; } +if(localStorage.setting_compose_autocomplete == "true") { +$("#setting_compose_autocomplete")[0].checked = true; +} if(localStorage.setting_who_to_follow == "true") { $("#setting_who_to_follow")[0].checked = true; } @@ -28,6 +31,16 @@ localStorage.setItem("setting_post_sensitive","false"); putMessage(__("Mark as NSFW by default disabled")); } }); +$("#setting_compose_autocomplete").change(function() { +if(this.checked) { +localStorage.setItem("setting_compose_autocomplete","true"); +putMessage(__("Autocomplete enabled")); +} +else { +localStorage.setItem("setting_compose_autocomplete","false"); +putMessage(__("Autocomplete disabled")); +} +}); $(document).on('change',".local_instance_wrap input[name='local_instance']", function(e) { if($(this).val()) { localStorage.setItem("setting_local_instance","https://"+$(this).val()); diff --git a/assets/js/halcyon/halcyonUI.js b/assets/js/halcyon/halcyonUI.js index 3d696ca..7fa1a3f 100644 --- a/assets/js/halcyon/halcyonUI.js +++ b/assets/js/halcyon/halcyonUI.js @@ -908,6 +908,62 @@ $('#js-overlay_content_wrap').addClass('view'); $('#js-overlay_content_wrap').addClass('black_05'); media_template(null, url).appendTo("#js-overlay_content .temporary_object"); } +var actEmojiData = new Array(); +for(var i=0;i i').attr('class', "fa fa-" + picon); if($(this).attr("display_name")) $('.overlay_status .overlay_status_header span').addClass("emoji_poss").html(__("Toot to")+" "+$(this).attr("display_name")); @@ -944,7 +1008,6 @@ else $('.overlay_status .overlay_status_header span').html(__("Compose new Toot" if($(this).attr("acct")) $('#overlay_status_form textarea').val($(this).attr("acct")+" "); else $('#overlay_status_form textarea').val(""); $('#overlay_status_form .character_count').html(current_instance_charlimit); -$('label[for=overlay_status_emoji]').click(function(e) {$('#overlay_status_emoji').trigger('click',e)}); $('#overlay_status_emoji').lsxEmojiPicker({ closeOnSelect:true, twemoji:!checkEmojiSupport(), @@ -1091,6 +1154,7 @@ $('#header_status_form .status_textarea textarea').removeClass('focus'); $('#header_status_form .status_bottom').addClass('invisible'); autosize.destroy($('#header_status_form .status_textarea textarea')); $('#header_status_emoji').lsxEmojiPicker("destroy"); +$('#header_status_form .status_textarea textarea').autoCompleteToken("destroy"); } }); $(document).on('change keyup','#header_status_form textarea, #header_status_form .status_spoiler', function(e) { @@ -1123,6 +1187,7 @@ e.stopPropagation(); $('#header_status_form .expand_privacy_menu_button > i').attr('class', $(this).attr('privacyicon')); $('#header_status_form .expand_privacy_menu').addClass('invisible'); }); +$('label[for=header_status_emoji]').click(function(e) {$('#header_status_emoji').trigger('click',e)}); $(document).on('click','#header_status_form', function(e) { switch(localStorage.getItem("setting_post_privacy")) { case "public":picon="globe";break; @@ -1135,10 +1200,16 @@ $('#header_status_form input[name="privacy_option"]').val([localStorage.getItem( $('#header_status_form .expand_privacy_menu_button > i').attr('class', "fa fa-" + picon); $('#header_status_form .status_textarea textarea').addClass('focus'); autosize($('#header_status_form .status_textarea textarea')); +if(localStorage.setting_compose_autocomplete == "true") { +$('#header_status_form .status_textarea textarea').autoCompleteToken({instance:1,startkey:"@",endkey:" ",arrayname:"accounts",resultname:"acct"}); +$('#header_status_form .status_textarea textarea').autoCompleteToken({instance:2,startkey:"#",endkey:" ",arrayname:"hashtags"}); +$('#header_status_form .status_textarea textarea').autoCompleteToken({instance:3,startkey:":",endkey:";",source:actEmojiData,resultname:"name",callback:function() { +$('#header_status_form .status_textarea textarea').trigger({"type":"keyup","key":":"}); +}}); +} $('#header_status_form .status_bottom').removeClass('invisible'); $('#header_status_form .submit_status_label').addClass('active_submit_button'); $('#header_status_form .character_count').html(current_instance_charlimit); -$('label[for=header_status_emoji]').click(function(e) {$('#header_status_emoji').trigger('click',e)}); $('#header_status_emoji').lsxEmojiPicker({ closeOnSelect:true, twemoji:!checkEmojiSupport(), @@ -1260,6 +1331,13 @@ replyto += "@"+mentions[i].acct+" "; } $('#reply_status_form .status_textarea textarea').addClass('focus'); autosize($('#reply_status_form .status_textarea textarea')); +if(localStorage.setting_compose_autocomplete == "true") { +$('#reply_status_form .status_textarea textarea').autoCompleteToken({instance:1,startkey:"@",endkey:" ",arrayname:"accounts",resultname:"acct"}); +$('#reply_status_form .status_textarea textarea').autoCompleteToken({instance:2,startkey:"#",endkey:" ",arrayname:"hashtags"}); +$('#reply_status_form .status_textarea textarea').autoCompleteToken({instance:3,startkey:":",endkey:";",source:actEmojiData,resultname:"name",callback:function() { +$('#reply_status_form .status_textarea textarea').trigger({"type":"keyup","key":":"}); +}}); +} $('#reply_status_form .status_bottom').removeClass('invisible'); $('#reply_status_form .submit_status_label').addClass('active_submit_button'); $('#reply_status_form textarea').val(replyto); @@ -1410,6 +1488,7 @@ $('#single_reply_status_emoji').lsxEmojiPicker("destroy"); $(document).on('click','single_reply_status_header, #single_reply_status_form', function(e) { e.stopPropagation(); }); +$('label[for=single_reply_status_emoji]').click(function(e) {$('#single_reply_status_emoji').trigger('click',e)}); $(document).on('click', '.reply_button', function(e) { e.stopPropagation(); const sid= $(this).attr('tid'), @@ -1438,13 +1517,19 @@ $('.single_reply_status .submit_status_label').addClass('active_submit_button'); $('#single_reply_status_form .status_textarea textarea').addClass('focus'); $('#single_reply_status_form .status_textarea textarea').focus(); autosize($('#single_reply_status_form .status_textarea textarea')); +if(localStorage.setting_compose_autocomplete == "true") { +$('#single_reply_status_form .status_textarea textarea').autoCompleteToken({instance:1,startkey:"@",endkey:" ",arrayname:"accounts",resultname:"acct"}); +$('#single_reply_status_form .status_textarea textarea').autoCompleteToken({instance:2,startkey:"#",endkey:" ",arrayname:"hashtags"}); +$('#single_reply_status_form .status_textarea textarea').autoCompleteToken({instance:3,startkey:":",endkey:";",source:actEmojiData,resultname:"name",callback:function() { +$('#single_reply_status_form .status_textarea textarea').trigger({"type":"keyup","key":":"}); +}}); +} $('#single_reply_status_form input[name="privacy_option"]').val([privacy_mode]); $('#single_reply_status_form .expand_privacy_menu_button > i').attr('class', "fa fa-" + picon); $('#single_reply_status_form').attr('tid',sid); $('.single_reply_status .single_reply_status_header span').addClass("emoji_poss").html(__("Reply to")+" "+display_name); $('#single_reply_status_form textarea').val(replyto); $('#single_reply_status_form .character_count').html(current_instance_charlimit); -$('label[for=single_reply_status_emoji]').click(function(e) {$('#single_reply_status_emoji').trigger('click',e)}); $('#single_reply_status_emoji').lsxEmojiPicker({ closeOnSelect:true, twemoji:!checkEmojiSupport(), diff --git a/header.php b/header.php index 29ea63b..9be17a6 100644 --- a/header.php +++ b/header.php @@ -23,6 +23,7 @@ echo ''; + diff --git a/login/auth.php b/login/auth.php index 1544389..dbb9935 100644 --- a/login/auth.php +++ b/login/auth.php @@ -42,6 +42,7 @@ localStorage.setItem('setting_who_to_follow', 'false'); localStorage.setItem('setting_show_replies', 'true'); localStorage.setItem('setting_show_content_warning', 'false'); localStorage.setItem('setting_show_nsfw', 'false'); +localStorage.setItem('setting_compose_autocomplete', 'true'); localStorage.setItem('setting_post_privacy','".$profile["source"]["privacy"]."'); localStorage.setItem('setting_post_sensitive','".$profile["source"]["sensitive"]."'); $.cookie('darktheme','false',{path:'/',expires:3650}); diff --git a/settings_general.php b/settings_general.php index 4b4c559..d6ab36f 100644 --- a/settings_general.php +++ b/settings_general.php @@ -65,6 +65,17 @@ echo "

+

+
+
+
+ +
+ +
+
+
+

diff --git a/version.txt b/version.txt index eca07e4..ac2cdeb 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.1.2 +2.1.3