From 6ad8f87bddf1f2997ed95993bca8d94b5c52e3cf Mon Sep 17 00:00:00 2001 From: Simon Grim Date: Mon, 30 Mar 2015 05:16:41 +0500 Subject: [PATCH] global fix of mentions autocomleting, upd of jquery.textcomplete --- css/style.css | 68 ++--- following.html | 1 + home.html | 7 +- js/calm.js | 5 - js/interface_common.js | 88 ++++-- js/jquery.textcomplete.js | 554 ---------------------------------- js/jquery.textcomplete.min.js | 4 + js/mobile_abstract.js | 4 +- theme_calm/css/style.css | 49 +-- theme_nin/css/style.css | 37 +-- theme_nin/sass/style.sass | 22 +- 11 files changed, 131 insertions(+), 708 deletions(-) delete mode 100644 js/jquery.textcomplete.js create mode 100644 js/jquery.textcomplete.min.js diff --git a/css/style.css b/css/style.css index 6fd0162..5fb81b2 100644 --- a/css/style.css +++ b/css/style.css @@ -360,8 +360,9 @@ button.follow:hover, button.unfollow:hover, .following-list button.private:hover top: 45px; right: 10px; width: 250px; - box-shadow: 0 2px 5px #65686f; border: solid 1px rgba( 69, 71, 77, .1 ); + border-right: solid 6px rgba( 227, 79, 66, .82 ); + box-shadow: 8px 10px 15px 0px rgba(0,0,0, .3); } .dialog-modal:after { @@ -393,7 +394,7 @@ button.follow:hover, button.unfollow:hover, .following-list button.private:hover .userMenu-search-sugestions a:hover, .userMenu-search-profiles li:hover a { - background: #fefef1; + background: #fefedf; } .userMenu-search-profiles button { @@ -903,19 +904,17 @@ ol.toptrends-list { width: 5px; /*right: -5px;*/ } -.post:hover, -.post .post -{ - background: #fefef1; -} + .post:hover { + background: #fefedf; cursor: pointer; } -.post.open:hover -{ - background: #fff; + +.post .expanded-post .original { + background: #fefedf; } + .post-photo, .mini-profile-photo { @@ -2011,44 +2010,31 @@ ol.toptrends-list { right: 8px; } -/* Autocomplite*/ -.textcomplete-wrapper textarea { - display: inline; -} +/************************************* +*********** AUTOCOMPLETING *********** +**************************************/ + ul.dropdown-menu { - position: absolute; - top: 23px; - left: 170px; - z-index: 100; - display: block; - float: left; min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; + padding: 0; + margin: 0; list-style: none; background-color: #fff; - border: 1px solid rgba(0,0,0, .2); - border-radius: 6px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0,0,0, .2); - -moz-box-shadow: 0 5px 10px rgba(0,0,0, .2); - box-shadow: 0 5px 10px rgba(0,0,0, .2); - + border-radius: 0px; + border: solid 1px rgba( 69, 71, 77, .1 ); + border-right: solid 4px rgba( 227, 79, 66, .82 ); + box-shadow: 8px 10px 10px 0px rgba(0,0,0, .2); } -ul.dropdown-menu li { - line-height: 20px; -} -ul.dropdown-menu > li > a { - display: block; +ul.dropdown-menu li { padding: 3px 20px; - clear: both; font: 13px/20px "Open Sans", sans-serif; white-space: nowrap; - -webkit-transition: all 200ms; - -moz-transition: all 200ms; - -ms-transition: all 200ms; - -o-transition: all 200ms; - transition: all 200ms; +} + +ul.dropdown-menu li:hover, +ul.dropdown-menu .active, ul.dropdown-menu .active a { + background-color: #fefedf; + text-decoration: none; + cursor: pointer; } diff --git a/following.html b/following.html index a0f8ec9..72d50c1 100644 --- a/following.html +++ b/following.html @@ -25,6 +25,7 @@ + - + + changeStyle(); + diff --git a/js/calm.js b/js/calm.js index 17e33e3..bfa261a 100644 --- a/js/calm.js +++ b/js/calm.js @@ -28,8 +28,3 @@ $(function(){ }; setTimeout(dhtIndicatorBg, 300); setTimeout(function() {setInterval(dhtIndicatorBg, 2000)}, 400); - - -function homeIntInit () { - setTimeout(mensAutocomplete, 800); -} diff --git a/js/interface_common.js b/js/interface_common.js index 028c180..897df8c 100644 --- a/js/interface_common.js +++ b/js/interface_common.js @@ -798,7 +798,7 @@ function replyTextKeypress(e) { $oldta.on("blur", replyTextKeypress); $oldta.addClass('splited-post'); - tweetForm.find(".textcomplete-wrapper").append($newta); + tweetForm.find(".textcomplete-wrapper").append($newta); // FIXME come find textcomplete-wrapper anywhere in code $newta.val(cp.substr(ci)); $newta.focus(); if ($newta[0].setSelectionRange) @@ -1393,7 +1393,6 @@ function changeStyle() { style = 'theme_nin/css/style.css'; profile = 'theme_nin/css/profile.css'; $.getScript('theme_nin/js/theme_option.js'); - } if(theme == 'calm') @@ -1416,29 +1415,30 @@ function changeStyle() { setTimeout(function(){$(menu).removeAttr('style')}, 0); } -function mensAutocomplete() { - var suggests = []; - - for(var i = 0; i < followingUsers.length; i++){ - if(followingUsers[i] == localStorage.defaultScreenName) continue; - suggests.push(followingUsers[i]); - } - suggests.reverse(); - $('textarea').textcomplete([ - { // html - mentions: suggests, - match: /\B@(\w*)$/, - search: function (term, callback) { - callback($.map(this.mentions, function (mention) { - return mention.indexOf(term) === 0 ? mention : null; - })); - }, - index: 1, - replace: function (mention) { - return '@' + mention + ' '; +function getMentionsForAutoComplete() { + if (defaultScreenName && typeof(followingUsers) !== 'undefined') { + var suggests = followingUsers.slice(); + + if (suggests.indexOf(defaultScreenName) > -1) + suggests.splice(suggests.indexOf(defaultScreenName), 1); + if (suggests.length > 0) { + suggests.sort(); + + return [{ + mentions: suggests, + match: /\B@(\w*)$/, + search: function (term, callback) { + callback($.map(this.mentions, function (mention) { + return mention.indexOf(term) === 0 ? mention : null; + })); + }, + index: 1, + replace: function (mention) { + return '@'+mention+' '; + } + }]; } } -]) } function replaceDashboards() { @@ -1485,10 +1485,6 @@ function initInterfaceCommon() { }); */ - $('.dropdown-menu').on('keydown', function(e){ - e = event || window.event; - e.stopPropagation(); - }) $('.post-text').on('click', 'a', function(e){ e.stopPropagation(); }); @@ -1529,4 +1525,42 @@ function initInterfaceCommon() { $('.bitmessage-ctc').on('click', function(){ window.prompt(polyglot.t('copy_to_clipboard'), $(this).attr('data')) }); + + if (typeof($.fn.textcomplete) === 'function') { + $('textarea') + .on('focus', function () { + var element = this; + // Cursor has not set yet. And wait 100ms to skip global click event. + setTimeout(function () { + // Cursor is ready. + $(element).textcomplete(getMentionsForAutoComplete(), { + 'appendTo': ($(element).parents('.dashboard').length > 0) ? $(element).parent() : $('body'), + 'listPosition': setTextcompleteDropdownListPos + }); + }, 100); + }) + .on('focusout', function () { + $(this).textcomplete('destroy'); + }) + ; + } +} + + +// following workaround function is for calls from $.fn.textcomplete only +// we need this because currently implementation of caret position detection is way too imperfect + +function setTextcompleteDropdownListPos(position) { + position = this._applyPlacement(position); + + if (this.option.appendTo.parents('.dashboard').length > 0) { + position['position'] = 'fixed'; + position['top'] = (parseFloat(position['top']) - window.pageYOffset).toString()+'px'; + } else { + position['position'] = 'absolute'; + } + + this.$el.css(position); + + return this; } diff --git a/js/jquery.textcomplete.js b/js/jquery.textcomplete.js deleted file mode 100644 index 66bed0f..0000000 --- a/js/jquery.textcomplete.js +++ /dev/null @@ -1,554 +0,0 @@ -/*! - * jQuery.textcomplete.js - * - * Repositiory: https://github.com/yuku-t/jquery-textcomplete - * License: MIT - * Author: Yuku Takahashi - */ - -;(function ($) { - - 'use strict'; - - /** - * Exclusive execution control utility. - */ - var lock = function (func) { - var free, locked; - free = function () { locked = false; }; - return function () { - var args; - if (locked) return; - locked = true; - args = toArray(arguments); - args.unshift(free); - func.apply(this, args); - }; - }; - - /** - * Convert arguments into a real array. - */ - var toArray = function (args) { - var result; - result = Array.prototype.slice.call(args); - return result; - }; - - /** - * Get the styles of any element from property names. - */ - var getStyles = (function () { - var color; - color = $('
').css(['color']).color; - if (typeof color !== 'undefined') { - return function ($el, properties) { - return $el.css(properties); - }; - } else { // for jQuery 1.8 or below - return function ($el, properties) { - var styles; - styles = {}; - $.each(properties, function (i, property) { - styles[property] = $el.css(property); - }); - return styles; - }; - } - })(); - - /** - * Default template function. - */ - var identity = function (obj) { return obj; }; - - /** - * Memoize a search function. - */ - var memoize = function (func) { - var memo = {}; - return function (term, callback) { - if (memo[term]) { - callback(memo[term]); - } else { - func.call(this, term, function (data) { - memo[term] = (memo[term] || []).concat(data); - callback.apply(null, arguments); - }); - } - }; - }; - - /** - * Determine if the array contains a given value. - */ - var include = function (array, value) { - var i, l; - if (array.indexOf) return array.indexOf(value) != -1; - for (i = 0, l = array.length; i < l; i++) { - if (array[i] === value) return true; - } - return false; - }; - - /** - * Textarea manager class. - */ - var Completer = (function () { - var html, css, $baseWrapper, $baseList, _id; - - html = { - wrapper: '
', - list: '' - }; - css = { - wrapper: { - position: 'relative' - }, - list: { - position: 'absolute', - top: 0, - left: 0, - zIndex: '100', - display: 'none' - } - }; - $baseWrapper = $(html.wrapper).css(css.wrapper); - $baseList = $(html.list).css(css.list); - _id = 0; - - function Completer($el) { - var focus; - this.el = $el.get(0); // textarea element - focus = this.el === document.activeElement; - // Cannot wrap $el at initialize method lazily due to Firefox's behavior. - this.$el = wrapElement($el); // Focus is lost - this.id = 'textComplete' + _id++; - this.strategies = []; - if (focus) { - this.initialize(); - this.$el.focus(); - } else { - this.$el.one('focus.textComplete', $.proxy(this.initialize, this)); - } - } - - /** - * Completer's public methods - */ - $.extend(Completer.prototype, { - - /** - * Prepare ListView and bind events. - */ - initialize: function () { - var $list, globalEvents; - $list = $baseList.clone(); - this.listView = new ListView($list, this); - this.$el - .before($list) - .on({ - 'keyup.textComplete': $.proxy(this.onKeyup, this), - 'keydown.textComplete': $.proxy(this.listView.onKeydown, - this.listView) - }); - globalEvents = {}; - globalEvents['click.' + this.id] = $.proxy(this.onClickDocument, this); - globalEvents['keyup.' + this.id] = $.proxy(this.onKeyupDocument, this); - $(document).on(globalEvents); - }, - - /** - * Register strategies to the completer. - */ - register: function (strategies) { - this.strategies = this.strategies.concat(strategies); - }, - - /** - * Show autocomplete list next to the caret. - */ - renderList: function (data) { - if (this.clearAtNext) { - this.listView.clear(); - this.clearAtNext = false; - } - if (data.length) { - if (!this.listView.shown) { - this.listView - .setPosition(this.getCaretPosition()) - .clear() - .activate(); - this.listView.strategy = this.strategy; - } - data = data.slice(0, this.strategy.maxCount); - this.listView.render(data); - } - - if (!this.listView.data.length && this.listView.shown) { - this.listView.deactivate(); - } - }, - - searchCallbackFactory: function (free) { - var self = this; - return function (data, keep) { - self.renderList(data); - if (!keep) { - // This is the last callback for this search. - free(); - self.clearAtNext = true; - } - }; - }, - - /** - * Keyup event handler. - */ - onKeyup: function (e) { - var searchQuery, term; - if (this.skipSearch(e)) { return; } - - searchQuery = this.extractSearchQuery(this.getTextFromHeadToCaret()); - if (searchQuery.length) { - term = searchQuery[1]; - if (this.term === term) return; // Ignore shift-key or something. - this.term = term; - this.search(searchQuery); - } else { - this.term = null; - this.listView.deactivate(); - } - }, - - /** - * Suppress searching if it returns true. - */ - skipSearch: function (e) { - if (this.skipNextKeyup) { - this.skipNextKeyup = false; - return true; - } - switch (e.keyCode) { - case 40: - case 38: - return true; - } - }, - - onSelect: function (value) { - var pre, post, newSubStr; - pre = this.getTextFromHeadToCaret(); - post = this.el.value.substring(this.el.selectionEnd); - - newSubStr = this.strategy.replace(value); - if ($.isArray(newSubStr)) { - post = newSubStr[1] + post; - newSubStr = newSubStr[0]; - } - pre = pre.replace(this.strategy.match, newSubStr); - this.$el.val(pre + post) - .trigger('change') - .trigger('textComplete:select', value); - this.el.focus(); - this.el.selectionStart = this.el.selectionEnd = pre.length; - this.skipNextKeyup = true; - }, - - /** - * Global click event handler. - */ - onClickDocument: function (e) { - if (e.originalEvent && !e.originalEvent.keepTextCompleteDropdown) { - this.listView.deactivate(); - } - }, - - /** - * Global keyup event handler. - */ - onKeyupDocument: function (e) { - if (this.listView.shown && e.keyCode === 27) { // ESC - this.listView.deactivate(); - this.$el.focus(); - } - }, - - /** - * Remove all event handlers and the wrapper element. - */ - destroy: function () { - var $wrapper; - this.$el.off('.textComplete'); - $(document).off('.' + this.id); - if (this.listView) { this.listView.destroy(); } - $wrapper = this.$el.parent(); - $wrapper.after(this.$el).remove(); - this.$el.data('textComplete', void 0); - this.$el = null; - }, - - // Helper methods - // ============== - - /** - * Returns caret's relative coordinates from textarea's left top corner. - */ - getCaretPosition: function () { - // Browser native API does not provide the way to know the position of - // caret in pixels, so that here we use a kind of hack to accomplish - // the aim. First of all it puts a div element and completely copies - // the textarea's style to the element, then it inserts the text and a - // span element into the textarea. - // Consequently, the span element's position is the thing what we want. - - if (this.el.selectionEnd === 0) return; - var properties, css, $div, $span, position, dir; - - dir = this.$el.attr('dir') || this.$el.css('direction'); - properties = ['border-width', 'font-family', 'font-size', 'font-style', - 'font-variant', 'font-weight', 'height', 'letter-spacing', - 'word-spacing', 'line-height', 'text-decoration', 'text-align', - 'width', 'padding-top', 'padding-right', 'padding-bottom', - 'padding-left', 'margin-top', 'margin-right', 'margin-bottom', - 'margin-left' - ]; - css = $.extend({ - position: 'absolute', - overflow: 'auto', - 'white-space': 'pre-wrap', - top: 0, - left: -9999, - direction: dir - }, getStyles(this.$el, properties)); - - $div = $('
').css(css).text(this.getTextFromHeadToCaret()); - $span = $('').text('.').appendTo($div); - this.$el.before($div); - position = $span.position(); - position.top += $span.height() - this.$el.scrollTop(); - if (dir === 'rtl') { position.left -= this.listView.$el.width(); } - $div.remove(); - return position; - }, - - getTextFromHeadToCaret: function () { - var text, selectionEnd, range; - selectionEnd = this.el.selectionEnd; - if (typeof selectionEnd === 'number') { - text = this.el.value.substring(0, selectionEnd); - } else if (document.selection) { - range = this.el.createTextRange(); - range.moveStart('character', 0); - range.moveEnd('textedit'); - text = range.text; - } - return text; - }, - - /** - * Parse the value of textarea and extract search query. - */ - extractSearchQuery: function (text) { - // If a search query found, it returns used strategy and the query - // term. If the caret is currently in a code block or search query does - // not found, it returns an empty array. - - var i, l, strategy, match; - for (i = 0, l = this.strategies.length; i < l; i++) { - strategy = this.strategies[i]; - match = text.match(strategy.match); - if (match) { return [strategy, match[strategy.index]]; } - } - return []; - }, - - search: lock(function (free, searchQuery) { - var term; - this.strategy = searchQuery[0]; - term = searchQuery[1]; - this.strategy.search(term, this.searchCallbackFactory(free)); - }) - }); - - /** - * Completer's private functions - */ - var wrapElement = function ($el) { - return $el.wrap($baseWrapper.clone().css('display', $el.css('display'))); - }; - - return Completer; - })(); - - /** - * Dropdown menu manager class. - */ - var ListView = (function () { - - function ListView($el, completer) { - this.data = []; - this.$el = $el; - this.index = 0; - this.completer = completer; - - this.$el.on('click.textComplete', 'li.textcomplete-item', - $.proxy(this.onClick, this)); - } - - $.extend(ListView.prototype, { - shown: false, - - render: function (data) { - var html, i, l, index, val; - - html = ''; - for (i = 0, l = data.length; i < l; i++) { - val = data[i]; - if (include(this.data, val)) continue; - index = this.data.length; - this.data.push(val); - html += '
  • '; - html += this.strategy.template(val); - html += '
  • '; - if (this.data.length === this.strategy.maxCount) break; - } - this.$el.append(html); - if (!this.data.length) { - this.deactivate(); - } else { - this.activateIndexedItem(); - } - }, - - clear: function () { - this.data = []; - this.$el.html(''); - this.index = 0; - return this; - }, - - activateIndexedItem: function () { - this.$el.find('.active').removeClass('active'); - this.getActiveItem().addClass('active'); - }, - - getActiveItem: function () { - return $(this.$el.children().get(this.index)); - }, - - activate: function () { - if (!this.shown) { - this.$el.show(); - this.completer.$el.trigger('textComplete:show'); - this.shown = true; - } - return this; - }, - - deactivate: function () { - if (this.shown) { - this.$el.hide(); - this.completer.$el.trigger('textComplete:hide'); - this.shown = false; - this.data = this.index = null; - } - return this; - }, - - setPosition: function (position) { - this.$el.css(position); - return this; - }, - - select: function (index) { - var self = this; - this.completer.onSelect(this.data[index]); - // Deactive at next tick to allow other event handlers to know whether - // the dropdown has been shown or not. - setTimeout(function () { self.deactivate(); }, 0); - }, - - onKeydown: function (e) { - if (!this.shown) return; - if (e.keyCode === 38) { // UP - e.preventDefault(); - if (this.index === 0) { - this.index = this.data.length-1; - } else { - this.index -= 1; - } - this.activateIndexedItem(); - } else if (e.keyCode === 40) { // DOWN - e.preventDefault(); - if (this.index === this.data.length - 1) { - this.index = 0; - } else { - this.index += 1; - } - this.activateIndexedItem(); - } else if (e.keyCode === 13 || e.keyCode === 9) { // ENTER or TAB - e.preventDefault(); - - this.select(parseInt(this.getActiveItem().data('index'), 10)); - } - }, - - onClick: function (e) { - var $e = $(e.target); - e.originalEvent.keepTextCompleteDropdown = true; - if (!$e.hasClass('textcomplete-item')) { - $e = $e.parents('li.textcomplete-item'); - } - this.select(parseInt($e.data('index'), 10)); - }, - - destroy: function () { - this.deactivate(); - this.$el.off('click.textComplete').remove(); - this.$el = null; - } - }); - - return ListView; - })(); - - $.fn.textcomplete = function (strategies) { - var i, l, strategy, dataKey; - - dataKey = 'textComplete'; - - if (strategies === 'destroy') { - return this.each(function () { - var completer = $(this).data(dataKey); - if (completer) { completer.destroy(); } - }); - } - - for (i = 0, l = strategies.length; i < l; i++) { - strategy = strategies[i]; - if (!strategy.template) { - strategy.template = identity; - } - if (strategy.index == null) { - strategy.index = 2; - } - if (strategy.cache) { - strategy.search = memoize(strategy.search); - } - strategy.maxCount || (strategy.maxCount = 10); - } - - return this.each(function () { - var $this, completer; - $this = $(this); - completer = $this.data(dataKey); - if (!completer) { - completer = new Completer($this); - $this.data(dataKey, completer); - } - completer.register(strategies); - }); - }; - -})(window.jQuery || window.Zepto); diff --git a/js/jquery.textcomplete.min.js b/js/jquery.textcomplete.min.js new file mode 100644 index 0000000..daf51b9 --- /dev/null +++ b/js/jquery.textcomplete.min.js @@ -0,0 +1,4 @@ +/*! jquery-textcomplete - v0.4.0 - 2015-03-10 */if("undefined"==typeof jQuery)throw new Error("jQuery.textcomplete requires jQuery");+function(a){"use strict";var b=function(a){console.warn&&console.warn(a)};a.fn.textcomplete=function(c,d){var e=Array.prototype.slice.call(arguments);return this.each(function(){var f=a(this),g=f.data("textComplete");if(g||(g=new a.fn.textcomplete.Completer(this,d||{}),f.data("textComplete",g)),"string"==typeof c){if(!g)return;e.shift(),g[c].apply(g,e),"destroy"===c&&f.removeData("textComplete")}else a.each(c,function(c){a.each(["header","footer","placement","maxCount"],function(a){c[a]&&(g.option[a]=c[a],b(a+"as a strategy param is deprecated. Use option."),delete c[a])})}),g.register(a.fn.textcomplete.Strategy.parse(c))})}}(jQuery),+function(a){"use strict";function b(c,d){if(this.$el=a(c),this.id="textcomplete"+f++,this.strategies=[],this.views=[],this.option=a.extend({},b._getDefaults(),d),!this.$el.is("input[type=text]")&&!this.$el.is("textarea")&&!c.isContentEditable&&"true"!=c.contentEditable)throw new Error("textcomplete must be called on a Textarea or a ContentEditable.");if(c===document.activeElement)this.initialize();else{var e=this;this.$el.one("focus."+this.id,function(){e.initialize()})}}var c=function(a){var b,c;return function(){var d=Array.prototype.slice.call(arguments);if(b)return c=d,void 0;b=!0;var e=this;d.unshift(function f(){if(c){var d=c;c=void 0,d.unshift(f),a.apply(e,d)}else b=!1}),a.apply(this,d)}},d=function(a){return"[object String]"===Object.prototype.toString.call(a)},e=function(a){return"[object Function]"===Object.prototype.toString.call(a)},f=0;b._getDefaults=function(){return b.DEFAULTS||(b.DEFAULTS={appendTo:a("body"),zIndex:"100"}),b.DEFAULTS},a.extend(b.prototype,{id:null,option:null,strategies:null,adapter:null,dropdown:null,$el:null,initialize:function(){var b=this.$el.get(0);this.dropdown=new a.fn.textcomplete.Dropdown(b,this,this.option);var c,d;this.option.adapter?c=this.option.adapter:(d=this.$el.is("textarea")||this.$el.is("input[type=text]")?"number"==typeof b.selectionEnd?"Textarea":"IETextarea":"ContentEditable",c=a.fn.textcomplete[d]),this.adapter=new c(b,this,this.option)},destroy:function(){this.$el.off("."+this.id),this.adapter&&this.adapter.destroy(),this.dropdown&&this.dropdown.destroy(),this.$el=this.adapter=this.dropdown=null},trigger:function(a,b){this.dropdown||this.initialize(),null!=a||(a=this.adapter.getTextFromHeadToCaret());var c=this._extractSearchQuery(a);if(c.length){var d=c[1];if(b&&this._term===d)return;this._term=d,this._search.apply(this,c)}else this._term=null,this.dropdown.deactivate()},fire:function(a){var b=Array.prototype.slice.call(arguments,1);return this.$el.trigger(a,b),this},register:function(a){Array.prototype.push.apply(this.strategies,a)},select:function(a,b){this.adapter.select(a,b),this.fire("change").fire("textComplete:select",a,b),this.adapter.focus()},_clearAtNext:!0,_term:null,_extractSearchQuery:function(a){for(var b=0;b').css({display:"none",left:0,position:"absolute",zIndex:b.zIndex}).appendTo(c)),d}}),a.extend(b.prototype,{$el:null,$inputEl:null,completer:null,footer:null,header:null,id:null,maxCount:10,placement:"",shown:!1,data:[],className:"",destroy:function(){this.deactivate(),this.$el.off("."+this.id),this.$inputEl.off("."+this.id),this.clear(),this.$el=this.$inputEl=this.completer=null,delete d[this.id]},render:function(b){var c=this._buildContents(b),d=a.map(this.data,function(a){return a.value});this.data.length?(this._renderHeader(d),this._renderFooter(d),c&&(this._renderContents(c),this._activateIndexedItem()),this._setScroll()):this.shown&&this.deactivate()},setPosition:function(b){this.$el.css(this._applyPlacement(b));var b="absolute";return this.$inputEl.add(this.$inputEl.parents()).each(function(){return"absolute"===a(this).css("position")?!1:"fixed"===a(this).css("position")?(b="fixed",!1):void 0}),this.$el.css({position:b}),this},clear:function(){this.$el.html(""),this.data=[],this._index=0,this._$header=this._$footer=null},activate:function(){return this.shown||(this.clear(),this.$el.show(),this.className&&this.$el.addClass(this.className),this.completer.fire("textComplete:show"),this.shown=!0),this},deactivate:function(){return this.shown&&(this.$el.hide(),this.className&&this.$el.removeClass(this.className),this.completer.fire("textComplete:hide"),this.shown=!1),this},isUp:function(a){return 38===a.keyCode||a.ctrlKey&&80===a.keyCode},isDown:function(a){return 40===a.keyCode||a.ctrlKey&&78===a.keyCode},isEnter:function(a){var b=a.ctrlKey||a.altKey||a.metaKey||a.shiftKey;return!b&&(13===a.keyCode||9===a.keyCode||this.option.completeOnSpace===!0&&32===a.keyCode)},isPageup:function(a){return 33===a.keyCode},isPagedown:function(a){return 34===a.keyCode},isEscape:function(a){return 27===a.keyCode},_data:null,_index:null,_$header:null,_$footer:null,_bindEvents:function(){this.$el.on("mousedown."+this.id,".textcomplete-item",a.proxy(this._onClick,this)),this.$el.on("mouseover."+this.id,".textcomplete-item",a.proxy(this._onMouseover,this)),this.$inputEl.on("keydown."+this.id,a.proxy(this._onKeydown,this))},_onClick:function(b){var c=a(b.target);b.preventDefault(),b.originalEvent.keepTextCompleteDropdown=this.id,c.hasClass("textcomplete-item")||(c=c.closest(".textcomplete-item"));var d=this.data[parseInt(c.data("index"),10)];this.completer.select(d.value,d.strategy);var e=this;setTimeout(function(){e.deactivate()},0)},_onMouseover:function(b){var c=a(b.target);b.preventDefault(),c.hasClass("textcomplete-item")||(c=c.closest(".textcomplete-item")),this._index=parseInt(c.data("index"),10),this._activateIndexedItem()},_onKeydown:function(a){this.shown&&(this.isUp(a)?(a.preventDefault(),this._up()):this.isDown(a)?(a.preventDefault(),this._down()):this.isEnter(a)?(a.preventDefault(),this._enter()):this.isPageup(a)?(a.preventDefault(),this._pageup()):this.isPagedown(a)?(a.preventDefault(),this._pagedown()):this.isEscape(a)&&(a.preventDefault(),this.deactivate()))},_up:function(){0===this._index?this._index=this.data.length-1:this._index-=1,this._activateIndexedItem(),this._setScroll()},_down:function(){this._index===this.data.length-1?this._index=0:this._index+=1,this._activateIndexedItem(),this._setScroll()},_enter:function(){var a=this.data[parseInt(this._getActiveElement().data("index"),10)];this.completer.select(a.value,a.strategy),this.deactivate()},_pageup:function(){var b=0,c=this._getActiveElement().position().top-this.$el.innerHeight();this.$el.children().each(function(d){return a(this).position().top+a(this).outerHeight()>c?(b=d,!1):void 0}),this._index=b,this._activateIndexedItem(),this._setScroll()},_pagedown:function(){var b=this.data.length-1,c=this._getActiveElement().position().top+this.$el.innerHeight();this.$el.children().each(function(d){return a(this).position().top>c?(b=d,!1):void 0}),this._index=b,this._activateIndexedItem(),this._setScroll()},_activateIndexedItem:function(){this.$el.find(".textcomplete-item.active").removeClass("active"),this._getActiveElement().addClass("active")},_getActiveElement:function(){return this.$el.children(".textcomplete-item:nth("+this._index+")")},_setScroll:function(){var a=this._getActiveElement(),b=a.position().top,c=a.outerHeight(),d=this.$el.innerHeight(),e=this.$el.scrollTop();0===this._index||this._index==this.data.length-1||0>b?this.$el.scrollTop(b+e):b+c>d&&this.$el.scrollTop(b+c+e-d)},_buildContents:function(a){var b,d,e,f="";for(d=0;d',f+=b.strategy.template(b.value),f+="");return f},_renderHeader:function(b){if(this.header){this._$header||(this._$header=a('
  • ').prependTo(this.$el));var c=a.isFunction(this.header)?this.header(b):this.header;this._$header.html(c)}},_renderFooter:function(b){if(this.footer){this._$footer||(this._$footer=a('').appendTo(this.$el));var c=a.isFunction(this.footer)?this.footer(b):this.footer;this._$footer.html(c)}},_renderContents:function(a){this._$footer?this._$footer.before(a):this.$el.append(a)},_applyPlacement:function(a){return-1!==this.placement.indexOf("top")?a={top:"auto",bottom:this.$el.parent().height()-a.top+a.lineHeight,left:a.left}:(a.bottom="auto",delete a.lineHeight),-1!==this.placement.indexOf("absleft")?a.left=0:-1!==this.placement.indexOf("absright")&&(a.right=0,a.left="auto"),a}}),a.fn.textcomplete.Dropdown=b}(jQuery),+function(a){"use strict";function b(b){a.extend(this,b),this.cache&&(this.search=c(this.search))}var c=function(a){var b={};return function(c,d){b[c]?d(b[c]):a.call(this,c,function(a){b[c]=(b[c]||[]).concat(a),d.apply(null,arguments)})}};b.parse=function(c){return a.map(c,function(a){return new b(a)})},a.extend(b.prototype,{match:null,replace:null,search:null,cache:!1,context:function(){return!0},index:2,template:function(a){return a},idProperty:null}),a.fn.textcomplete.Strategy=b}(jQuery),+function(a){"use strict";function b(){}var c=Date.now||function(){return(new Date).getTime()},d=function(a,b){var d,e,f,g,h,i=function(){var j=c()-g;b>j?d=setTimeout(i,b-j):(d=null,h=a.apply(f,e),f=e=null)};return function(){return f=this,e=arguments,g=c(),d||(d=setTimeout(i,b)),h}};a.extend(b.prototype,{id:null,completer:null,el:null,$el:null,option:null,initialize:function(b,c,e){this.el=b,this.$el=a(b),this.id=c.id+this.constructor.name,this.completer=c,this.option=e,this.option.debounce&&(this._onKeyup=d(this._onKeyup,this.option.debounce)),this._bindEvents()},destroy:function(){this.$el.off("."+this.id),this.$el=this.el=this.completer=null},select:function(){throw new Error("Not implemented")},getCaretPosition:function(){var a=this._getCaretRelativePosition(),b=this.$el.offset();return a.top+=b.top,a.left+=b.left,a},focus:function(){this.$el.focus()},_bindEvents:function(){this.$el.on("keyup."+this.id,a.proxy(this._onKeyup,this))},_onKeyup:function(a){this._skipSearch(a)||this.completer.trigger(this.getTextFromHeadToCaret(),!0)},_skipSearch:function(a){switch(a.keyCode){case 13:case 40:case 38:return!0}if(a.ctrlKey)switch(a.keyCode){case 78:case 80:return!0}}}),a.fn.textcomplete.Adapter=b}(jQuery),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}b.DIV_PROPERTIES={left:-9999,position:"absolute",top:0,whiteSpace:"pre-wrap"},b.COPY_PROPERTIES=["border-width","font-family","font-size","font-style","font-variant","font-weight","height","letter-spacing","word-spacing","line-height","text-decoration","text-align","width","padding-top","padding-right","padding-bottom","padding-left","margin-top","margin-right","margin-bottom","margin-left","border-style","box-sizing","tab-size"],a.extend(b.prototype,a.fn.textcomplete.Adapter.prototype,{select:function(b,c){var d=this.getTextFromHeadToCaret(),e=this.el.value.substring(this.el.selectionEnd),f=c.replace(b);a.isArray(f)&&(e=f[1]+e,f=f[0]),d=d.replace(c.match,f),this.$el.val(d+e),this.el.selectionStart=this.el.selectionEnd=d.length},_getCaretRelativePosition:function(){var b=a("
    ").css(this._copyCss()).text(this.getTextFromHeadToCaret()),c=a("").text(".").appendTo(b);this.$el.before(b);var d=c.position();return d.top+=c.height()-this.$el.scrollTop(),d.lineHeight=c.height(),b.remove(),d},_copyCss:function(){return a.extend({overflow:this.el.scrollHeight>this.el.offsetHeight?"scroll":"auto"},b.DIV_PROPERTIES,this._getStyles())},_getStyles:function(a){var c=a("
    ").css(["color"]).color;return"undefined"!=typeof c?function(){return this.$el.css(b.COPY_PROPERTIES)}:function(){var c=this.$el,d={};return a.each(b.COPY_PROPERTIES,function(a,b){d[b]=c.css(b)}),d}}(a),getTextFromHeadToCaret:function(){return this.el.value.substring(0,this.el.selectionEnd)}}),a.fn.textcomplete.Textarea=b}(jQuery),+function(a){"use strict";function b(b,d,e){this.initialize(b,d,e),a(""+c+"").css({position:"absolute",top:-9999,left:-9999}).insertBefore(b)}var c="吶";a.extend(b.prototype,a.fn.textcomplete.Textarea.prototype,{select:function(b,c){var d=this.getTextFromHeadToCaret(),e=this.el.value.substring(d.length),f=c.replace(b);a.isArray(f)&&(e=f[1]+e,f=f[0]),d=d.replace(c.match,f),this.$el.val(d+e),this.el.focus();var g=this.el.createTextRange();g.collapse(!0),g.moveEnd("character",d.length),g.moveStart("character",d.length),g.select()},getTextFromHeadToCaret:function(){this.el.focus();var a=document.selection.createRange();a.moveStart("character",-this.el.value.length);var b=a.text.split(c);return 1===b.length?b[0]:b[1]}}),a.fn.textcomplete.IETextarea=b}(jQuery),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}a.extend(b.prototype,a.fn.textcomplete.Adapter.prototype,{select:function(b,c){var d=this.getTextFromHeadToCaret(),e=window.getSelection(),f=e.getRangeAt(0),g=f.cloneRange();g.selectNodeContents(f.startContainer);var h=g.toString(),i=h.substring(f.startOffset),j=c.replace(b);a.isArray(j)&&(i=j[1]+i,j=j[0]),d=d.replace(c.match,j),f.selectNodeContents(f.startContainer),f.deleteContents();var k=document.createTextNode(d+i);f.insertNode(k),f.setStart(k,d.length),f.collapse(!0),e.removeAllRanges(),e.addRange(f)},_getCaretRelativePosition:function(){var b=window.getSelection().getRangeAt(0).cloneRange(),c=document.createElement("span");b.insertNode(c),b.selectNodeContents(c),b.deleteContents();var d=a(c),e=d.offset();e.left-=this.$el.offset().left,e.top+=d.height()-this.$el.offset().top,e.lineHeight=d.height(),d.remove();var f=this.$el.attr("dir")||this.$el.css("direction");return"rtl"===f&&(e.left-=this.listView.$el.width()),e},getTextFromHeadToCaret:function(){var a=window.getSelection().getRangeAt(0),b=a.cloneRange();return b.selectNodeContents(a.startContainer),b.toString().substring(0,a.startOffset)}}),a.fn.textcomplete.ContentEditable=b}(jQuery); +/* +//@ sourceMappingURL=dist/jquery.textcomplete.min.map +*/ \ No newline at end of file diff --git a/js/mobile_abstract.js b/js/mobile_abstract.js index f7a9681..2c1bcb6 100644 --- a/js/mobile_abstract.js +++ b/js/mobile_abstract.js @@ -505,12 +505,14 @@ function filterLang(string) { // before detection attempts we cut out any mentions and links, and replace _ with space langFilterSubj = string.replace(/@\S\w*|https?:\/\/\S*/g, '').replace(/_+/g, ' ') + // cut out common frequently used words FIXME I believe there is a list of similar international stuff somewhere outside which is waiting for us, we should just find it + .replace(/\btwister|github|google|twitter\b/g, '') // replace zero-width word boundaries, such as between letters from different alphabets [or other symbols], with spaces // FIXME not so good idea because 'Za pomocą białej listy' may turn into 'Za pomoc ą bia ł ej listy' for e.g. // FIXME but first one was recognized as 'hrv' and second as 'pol' and you know it's 'pol' actually .replace(/\b/g, ' ') // cut out some more symbols - .replace(/[#\[\]\(\)\{\}\-\+\=\^\:\;\\\/]/g, '') + .replace(/[#\[\]\(\)\{\}\-\+\=\^\:\;\\\/0-9]/g, '') // clear unwanted spaces .replace(/\s+/g, ' ').trim(); diff --git a/theme_calm/css/style.css b/theme_calm/css/style.css index 9cf3225..d96eb40 100644 --- a/theme_calm/css/style.css +++ b/theme_calm/css/style.css @@ -2450,62 +2450,45 @@ textarea.splited-post { text-align: center; } -/* Autocomplite*/ -.textcomplete-wrapper textarea { - display: inline; -} +/************************************* +*********** AUTOCOMPLETING *********** +**************************************/ + ul.dropdown-menu { - position: absolute; - top: 23px; - left: 170px; - z-index: 100; - display: block; - float: left; min-width: 160px; + list-style: none; padding: 5px 0; margin: 2px 0 0; - list-style: none; background-color: #fff; border: 1px solid rgba(0,0,0, .2); border-radius: 6px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0,0,0, .2); - -moz-box-shadow: 0 5px 10px rgba(0,0,0, .2); box-shadow: 0 5px 10px rgba(0,0,0, .2); - } -ul.dropdown-menu li { - line-height: 20px; +ul.dropdown-menu li { + padding: 3px 20px; + font: 13px/20px "Open Sans", sans-serif; + white-space: nowrap; + transition: all 100ms; } -ul.dropdown-menu > .active > a { + +ul.dropdown-menu li:hover, +ul.dropdown-menu .active, ul.dropdown-menu .active a { color: #fff; text-decoration: none; background-color: #7691ce; background-image: linear-gradient(to bottom, #6f88c1, #7e9bdb); background-repeat: repeat-x; - -} -ul.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font: 13px/20px "Open Sans", sans-serif; - white-space: nowrap; cursor: pointer; - -webkit-transition: all 200ms; - -moz-transition: all 200ms; - -ms-transition: all 200ms; - -o-transition: all 200ms; - transition: all 200ms; } + ul.dropdown-menu img { width: 25px; height: 25px; margin-right: 10px; - } + + p.post-text img { width: 20px; height: 20px; diff --git a/theme_nin/css/style.css b/theme_nin/css/style.css index 3700cc7..2969a8c 100644 --- a/theme_nin/css/style.css +++ b/theme_nin/css/style.css @@ -3189,45 +3189,32 @@ ol.toptrends-list a:hover { font-style: normal; } -/* Autocomplite */ -/* line 1084, ../sass/style.sass */ -.textcomplete-wrapper textarea { - display: inline; -} + +/********** AUTOCOMPLETING *********/ /* line 1087, ../sass/style.sass */ ul.dropdown-menu { - position: absolute; - top: 23px; - left: 155px; - z-index: 100; - display: block; - float: left; min-width: 160px; - padding: 5px 0; + padding: 5px 0 7px; margin: 2px 0 0; list-style: none; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + border-bottom: solid 2px #B4C669; box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); } -/* line 1103, ../sass/style.sass */ -ul.dropdown-menu li { - line-height: 20px; -} + /* line 1105, ../sass/style.sass */ ul.dropdown-menu > li > a { - display: block; padding: 3px 20px; - clear: both; white-space: nowrap; - -webkit-transition: all 200ms; - -moz-transition: all 200ms; - -ms-transition: all 200ms; - -o-transition: all 200ms; - transition: all 200ms; + transition: all 100ms; +} + +ul.dropdown-menu li:hover, +ul.dropdown-menu .active, ul.dropdown-menu .active a { + color: #B4C669; + cursor: pointer; } @media (max-width: 1200px) { diff --git a/theme_nin/sass/style.sass b/theme_nin/sass/style.sass index a030cd5..7d4b1f3 100755 --- a/theme_nin/sass/style.sass +++ b/theme_nin/sass/style.sass @@ -1118,39 +1118,25 @@ ol.toptrends-list span font-style: normal -/* Autocomplite*/ +/********** AUTOCOMPLETING *********/ .textcomplete-wrapper textarea display: inline ul.dropdown-menu - position: absolute - top: 23px - left: 155px - z-index: 100 - display: block - float: left min-width: 160px - padding: 5px 0 + padding: 5px 0 7px margin: 2px 0 0 list-style: none background-color: #fff border: 1px solid rgba(0, 0, 0, 0.2) - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2) - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2) + border-bottom: solid 2px #B4C669 box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2) li - line-height: 20px > li > a - display: block padding: 3px 20px - clear: both white-space: nowrap - -webkit-transition: all 200ms - -moz-transition: all 200ms - -ms-transition: all 200ms - -o-transition: all 200ms - transition: all 200ms + transition: all 100ms /* Language filter messages */