diff options
Diffstat (limited to 'apps/comments/js/vendor/At.js')
28 files changed, 0 insertions, 3469 deletions
diff --git a/apps/comments/js/vendor/At.js/CHANGELOG.md b/apps/comments/js/vendor/At.js/CHANGELOG.md deleted file mode 100644 index bfc24588475..00000000000 --- a/apps/comments/js/vendor/At.js/CHANGELOG.md +++ /dev/null @@ -1,314 +0,0 @@ -### v1.5.0 - -add `headerTpl` settings - -* 7a41d93 - #375 from vcekov/fix_scroll_position - Valentin Cekov -* ecbf34f - #373 from vcekov/val/fix_key_navigation_interefence_with_mouse - Valentin Cekov -* b68cf84 - #364 from WorktileTech/master - Harold.Luo -* f836f04 - #372 from vcekov/fix_caret_for_space_after_@ - Harold.Luo -* 06cf6bb - Properly set caret position after failed match - Valentin Cekov -* c9ed2e2 - support header template. - htz - -### v1.4.0 - -#### Contenteditable - -Pressing `Backspace` will turn the inserted element back to the origin query 'moment'. - -* 84edc9f - skip inserted element when moving left or right - ichord -* 25a61d3 - the jQuery npm package is now called jquery. Fixes #338 - Mick Staugaard -* 03ed71f - Merge pull request #351 from mociepka/master - Harold.Luo -* ae00dc3 - Point main script in package json - Michał Ociepka -* c5f31f5 - Merge branch 'dev' into HEAD - ichord -* c399397 - fix contenteditable cursor bug when typing "a" into query - ichord -* 7f4295a - fix previous replacements get clobbered when re-intering the inserted element - ichord -* f00fabd - Merge pull request #354 from lvegerano/master - Harold.Luo -* a42065e - Adds guard to event and dist file - Luis Vegerano -* e4aaa30 - Add option to disable loopUp on click - Luis Vegerano -* c9b7609 - Fix bug where callbacks would run before reaching minLen. Fixes #329. - Mike Leone -* f8692dc - Add support for minLen. Connects to issue #316. - Mike Leone -* fd7d298 - FIX: the value of `isSelecting` - ichord -* c374c93 - FIX: IME typing error - ichord - -### v1.3.0 - -* 7f2189d - fix #294 inserts "" suffix in contenteditable -* bae95d9 - add `tabSelectsMatch` setting to make tab selection optional -* e966aba - Merge pull request #298 from kkirsche/patch-1 - Harold.Luo -* 9f78239 - Remove moot `version` property from bower.json - Kevin Kirsche - -### v1.2.0 - -db09ac7 -> 886613f - -* 886613f - add `$.fn.atwho.debug = false` to trigger debug mode -* 6567af9 - Enable default events when nothing is highlighted - Teemu -* 752ad4a - Add scrollDuration option. - Takuru -* bf17d43 - add parameter to allow for a spacebar in the middle of a search so that you can match a first + last name, for example - Feather Knee -* a1d5fe7 - add `reposition` API - ichord -* 9bcb06e - add "onInsert", "onDispaly" arguments to `tplEval` - ichord -* db09ac7 - add `hide` api - ichord - -### v1.1.0 - -* lisafeather/displyTplCallBack - #259 -* ADD: `editableAtwhoQueryAttrs` options -* Added setting for 'spaceSelectsMatch' (default false/off) - -### v1.0.0 - -**The naming convention are using camel case**. -It means that every callback and setting's name are switched from underscope_naming to CamelNaming. -Sorry about this. - -Future version's naming will follow the rules of http://semver.org constantly. - -#### Options: - -* Replaced `tpl` with `displayTpl`: display template of dropdown menu items. - In previous versions, At.js will fetch the value of `data-value` to insert; It stops doing it. - Please use the `insertTpl` option to manage the content to insert instead. - The default value is `"<li>${name}</li>"` -* The `insertTpl` option will be used in *textarea* as well. - The default value is `"${atwho-at}${name}"` - -#### Callbacks: - -* Added `afterMatchFailed` callback to *contentEditable* - It will be invoked after fail to match any query and stopping matching. - Open *examples/hashtas.html* to examine how it work. -* Removed `inserting_wrapper` callback to *contentEditable* - -#### Internal changes: - -* refactor the `Controller` - Introduced `EditableController` class to control actions of `contenteditable` element. - Introduced `TextareaController` class to control actions of `textarea` element. - Both of them are inherit from the `Controller` class. - -* Refactored contentEditable mode - Inserted content are wrapped in a span: `<span class=".atwho-inserted"/>` - Querying content are wrapped in a span: `<span class=".atwho-query"/>` - -* Bring back auto-discovery to iframe. -* Fix wrong offset in iframe -* Replaced `iframeStandalone` with `iframeAdRoot` -* All processed events are preventing default and stopping propagation. - -### v0.5.2 - -* e1f6566 - fix error that doesn't display mention list on new line -* 8fe3a54 - can insert multiple node from `inserting_wrapper` -* 4080151 - scroll to top after showing -* 01555f8 - scroll long dropdown list -* 1b8999d - Add spm support -* f2b8e9c - change name in package.json -* b61bfdc - search on click -* b1efd09 - Fixes error with selecting always first item on the list on iOS WebView when using https://github.com/ftlabs/fastclick -* 7ed2890 - Allow accented characters in matcher - -### v0.5.1 - -* 219de3d - fix Goes off screen / gets cropped if there isn't enough room -* 1100c5b - No longer inherits text colour from document -* ce60958 - on more boolean argument for `setIframe` api to work cross-document issues #199 - -### v0.5.0 - -* 593893c - refactor inserting of contenteditable - Adding `inserting_wrapper` for customize wrapping inserting content. - Not to insert item as a block in Firefox. check out issue #109. - Removing `getInsertedItems`, `getInsertedIDs` API. You have to collect them on your own. -* 4d3fb8f - have to set IFRAME manually -* 1f13a16 - change space_after to suffix -* b099ebb - fix caret position error after inserting -* 2c47d7a - fix #178 hide view while clicking somewhere else - -### v0.4.12 - -* eeafab1 - fix error: will always call hidden atwho event -* b0f6ceb - Highlighter finds the first occurrence -* da256db - Adds possibility of having empty prefix (at keyword) in controllers -* b884225 - add `space_after` option -* 65d6273 - Passes esc/tab/return keyup events through to emitted hide event - -### v0.4.11 - -* bf938db - add `delay` setting, support delay searching -* a0b5a6f - fix bug: terminate if query out of max_len -* 01d6d5b - add css min file - -### v0.4.10 - -* update jquery dependence version - -### v0.4.9 - -* f317bd7 not lowercase query, add `highlight_first` option - -### v0.4.8 - -* 79bbef4 destroy atwho view container dom -* 0372d65 update bower and component keywords -* 52a41f5 add optional `before_repostion` callback -* cc1c239 Fixes #143 - ichord - -### v0.4.7 - -* resolved #133, #135, #137. -* add `beforeDestroy` event -* wouldn't concat `caret.js` into `dist/js/jquery.atwho.js` any more. -* seperate `jquery.atwho.coffee` into pieces. -* seperate testing. - -### v0.4.6 - -* 2d9ab23 fix `wrong document` error in IE iframe - -### v0.4.5 - -* 664a765 support iframe - -### v0.4.4 - -* 9ac7e75 - improve contentEditable for IE 8 - - It's still some bugs in IE 8, just DON'T use it - I don't want to spend more time on IE 8. - So it would be the ending fixup. And i will still leave related code for - a while maybe in case anyone want to help to improve it. - Just encourge your users to upgrate the browers or just switch to a - batter one please !! - -* a8371b3 - move project page to master from gh-pages. -* 24b6225 - fix bugs #122 -* 645e030 - update Caret.js to v0.0.5 - -### v0.4.3 - -* e8e7561 update `Caret.js` to `v0.0.4` - -### v0.4.2 - -* 4169b74 - binding data storage to the inputor. issues #121 -* 11d053f - reduse querying twice. issues#112 - -### v0.4.1 - -* b7721be - fix bug at view id was not been assign. close issues #99 -* 407f069 - fix bug: Can not autofocus after click the at-list in FireFox. #95 -* 917f033 - fix bug: click do not work in div-contenteditable. close issues #93 - -### v0.4.0 - -* update `Caret.js` to `v0.0.2` -* `contenteditable` support !! -* change content of default item template `tpl` -* new rule to insert the `at` : will always remove the `at` from inputor but will add it back from `tpl` in default. - so, if you are using your own `tpl` and want to show the `at` char, you have to do it yourself. -* add `insert_tpl` setting for `contenteditable`. - it will insert `data-value` of li element that eval from `tpl` in default. -* new APIs for `contenteditable`: `getInsertedItemsWithIDs`, `getInsertedItems`, `getInsertedIDs` - -### 2013-08-07 - v0.3.2 - -* bower -* remove `Caret.js` codes and add it as bower dependencies -* remove `display_flag` settings. -* add `start_with_space` settings, default `true` -* change `super_call` function to `call_default` - -### 2013-04-28 - -* release new api `load`, `run` -* add `alias` setting for `load` data or as the view's id -* matching key with a space before it -* register key in settings `{at: "@", data: []}` instead of being a argument -* `max_len` setting for max length to search -* change the default matcher regrex rule: occur at start of line or after whitespace -* will not sort the datay without valid query string - -### 2013-04-23 - -* group all data handlers as `Model` class. -* All callbacks's context would be current `Controller` - -### 2013-04-05 - -* `data` setting will be used to load data either local or remote. If it's String as URL it will preload data from remote by launch a ajax request (every times At.js call `reg` to update settings) - -* remove default `remote_filter` from callbacks list. -* add `get_data` and `save_data` function to contoller. They are used to get and save whole data for At.js -* `save_data` will invoke `data_refactor` everytime - -* will filter local data which is set in `settings` first and if it get nothing then call `remote_filter` if it's exists in callbacks list that is set by user. - -### 2013-04 - -* remove ability of changing common setting after inputor binded -* can fix list view after matched query in IE now. -* separated core function (get offset of inputor) as a jquery plugins. - -### v0.2.0 - 2012-12 - -**No more testing in IEs browsers.** - -#### Note -The name `atWho` was changed to `atwho`. - -#### New features - -* Customer data handlers(matcher, filter, sorter) and template renders(highlight, template eval) by a group of configurable callbacks. -* Support **AMD** - -#### Removed features - -* Filter by local data and remote (by ajax) data at the same time. -* Caching -* Mouse event - -#### Changed settings - -`-` mean removed option -`+` mean new added option -The one that start without `-` or `+` mean not change. - -* `-` data: [], -* `+` data: null, - -* `-` choose: "data-value", -* `+` search_key: "name", - -* `-` callback: null, -* `+` callbacks: DEFAULT_CALLBACKS, - -* `+` display_timeout: 300, - -* `-` tpl: _DEFAULT_TPL -* `+` tpl: DEFAULT_TPL - -* `-` cache: false - -Not change settings - -* cache: true, -* limit: 5, -* display_flag: true, - -### v0.1.7 - -同步 `jquery-atwho-rails` gem 的版本号 -这会是 `v0.1` 的固定版本. 不再有新功能更新. - -###v0.1.2 2012-3-23 -* box showing above instead of bottom when it get close to the bottom of window -* coffeescript here is. -* every registered character able to have thire own options such as template(`tpl`) -* every inputor (textarea, input) able to have their own registered character and different behavior - even the same character to other inputor - -###v0.1.0 -* 可以監聽多個字符 - multiple char listening. -* 顯示缺省列表. - show default list. diff --git a/apps/comments/js/vendor/At.js/CONTRIBUTING.md b/apps/comments/js/vendor/At.js/CONTRIBUTING.md deleted file mode 100644 index 629943f377e..00000000000 --- a/apps/comments/js/vendor/At.js/CONTRIBUTING.md +++ /dev/null @@ -1,37 +0,0 @@ -## Contributing - -### Code style - -**Two** space indent - -### Modifying the code -First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. - -Test that gulp is installed globally by running `grunt -v` at the command-line. If gulp isn't installed globally, run `npm install -g gulp` to install the latest version. - -* Fork and clone the repo. -* Run `npm install` and `bower install` to install all dev dependencies (including grunt). -* Modify the `*.coffee` file. -* Run `gulp` to build this project. - -Assuming that you don't see any red, you're ready to go. Just be sure to run `gulp` after making any changes, to ensure that nothing is broken. - -### Submitting pull requests - -1. Create a new branch, please don't work in your `master` branch directly. -1. Add failing tests for the change you want to make. Run `gulp` to see the tests fail. -1. Fix stuff. -1. Run `gulp` to see if the tests pass. Repeat steps 2-4 until done. -1. Open `_SpecRunner.html` unit test file(s) in actual browser to ensure tests pass everywhere. -1. Update the documentation to reflect any changes. -1. Push to your fork and submit a pull request. - -### notes - -Please don't edit files in the `dist` subdirectory and *.js files in `src` as they are generated via gulp. -You'll find source code in the `src` subdirectory! -use `bower install` or `component install` to install dependencies first. - - -### PhantomJS -While gulp can run the included unit tests via [PhantomJS](http://phantomjs.org/), this shouldn't be considered a substitute for the real thing. Please be sure to test the `_SpecRunner.html` unit test file(s) in _actual_ browsers. diff --git a/apps/comments/js/vendor/At.js/LICENSE-MIT b/apps/comments/js/vendor/At.js/LICENSE-MIT deleted file mode 100644 index 36cd1c12272..00000000000 --- a/apps/comments/js/vendor/At.js/LICENSE-MIT +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2013 chord.luo@gmail.com - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/apps/comments/js/vendor/At.js/README.md b/apps/comments/js/vendor/At.js/README.md deleted file mode 100644 index 551820afbb8..00000000000 --- a/apps/comments/js/vendor/At.js/README.md +++ /dev/null @@ -1,67 +0,0 @@ -**An autocompletion library to autocomplete mentions, smileys etc. just like on Github!** -[![Build Status](https://travis-ci.org/ichord/At.js.png)](https://travis-ci.org/ichord/At.js) - -#### Notice - -At.js now **depends on** [Caret.js](https://github.com/ichord/Caret.js). -Please read [**CHANGELOG.md**](CHANGELOG.md) for more details if you are going to update to new version. - -### Demo -http://ichord.github.com/At.js - -### Documentation -https://github.com/ichord/At.js/wiki - -### Compatibility - -* `textarea` - Chrome, Safari, Firefox, IE7+ (maybe IE6) -* `contentEditable` - Chrome, Safari, Firefox, IE9+ - -### Features Preview - -* Support IE 7+ for **textarea**. -* Supports HTML5 [**contentEditable**](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_Editable) elements (NOT including IE 8) -* Can listen to any character and not just '@'. Can set up multiple listeners for different characters with different behavior and data -* Listener events can be bound to multiple inputors. -* Format returned data using templates -* Keyboard controls in addition to mouse - - `Tab` or `Enter` keys select the value - - `Up` and `Down` navigate between values (and `Ctrl-P` and `Ctrl-N` also) - - `Right` and `left` will re-search the keyword. -* Custom data handlers and template renderers using a group of configurable callbacks -* Supports AMD - -### Requirements - -* jQuery >= 1.7.0. -* [Caret.js](https://github.com/ichord/Caret.js) - (You can use `Component` or `Bower` to install it.) - -### Integrating with your Application - -Simply include the following files in your HTML and you are good to go. - -```html -<link href="css/jquery.atwho.css" rel="stylesheet"> -<script src="http://code.jquery.com/jquery.js"></script> -<script src="js/jquery.caret.js"></script> -<script src="js/jquery.atwho.js"></script> -``` - -```javascript -$('#inputor').atwho({ - at: "@", - data:['Peter', 'Tom', 'Anne'] -}) -``` - -#### Bower & Component -For installing using Bower you can use `jquery.atwho` and for Component please use `ichord/At.js`. - -#### Rails -You can include At.js in your `Rails` application using the gem [jquery-atwho-rails](https://github.com/ichord/jquery-atwho-rails). - -### Core Team Members - -* [@ichord](https://twitter.com/_ichord) (twitter) - diff --git a/apps/comments/js/vendor/At.js/dist/css/jquery.atwho.css b/apps/comments/js/vendor/At.js/dist/css/jquery.atwho.css deleted file mode 100644 index dad94ed9641..00000000000 --- a/apps/comments/js/vendor/At.js/dist/css/jquery.atwho.css +++ /dev/null @@ -1,72 +0,0 @@ -.atwho-view { - position:absolute; - top: 0; - left: 0; - display: none; - margin-top: 18px; - background: white; - color: black; - border: 1px solid #DDD; - border-radius: 3px; - box-shadow: 0 0 5px rgba(0,0,0,0.1); - min-width: 120px; - z-index: 11110 !important; -} - -.atwho-view .atwho-header { - padding: 5px; - margin: 5px; - cursor: pointer; - border-bottom: solid 1px #eaeff1; - color: #6f8092; - font-size: 11px; - font-weight: bold; -} - -.atwho-view .atwho-header .small { - color: #6f8092; - float: right; - padding-top: 2px; - margin-right: -5px; - font-size: 12px; - font-weight: normal; -} - -.atwho-view .atwho-header:hover { - cursor: default; -} - -.atwho-view .cur { - background: #3366FF; - color: white; -} -.atwho-view .cur small { - color: white; -} -.atwho-view strong { - color: #3366FF; -} -.atwho-view .cur strong { - color: white; - font:bold; -} -.atwho-view ul { - /* width: 100px; */ - list-style:none; - padding:0; - margin:auto; - max-height: 200px; - overflow-y: auto; -} -.atwho-view ul li { - display: block; - padding: 5px 10px; - border-bottom: 1px solid #DDD; - cursor: pointer; - /* border-top: 1px solid #C8C8C8; */ -} -.atwho-view small { - font-size: smaller; - color: #777; - font-weight: normal; -} diff --git a/apps/comments/js/vendor/At.js/dist/css/jquery.atwho.min.css b/apps/comments/js/vendor/At.js/dist/css/jquery.atwho.min.css deleted file mode 100644 index f770dc73b3f..00000000000 --- a/apps/comments/js/vendor/At.js/dist/css/jquery.atwho.min.css +++ /dev/null @@ -1 +0,0 @@ -.atwho-view{position:absolute;top:0;left:0;display:none;margin-top:18px;background:#fff;color:#000;border:1px solid #DDD;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.1);min-width:120px;z-index:11110!important}.atwho-view .atwho-header{padding:5px;margin:5px;cursor:pointer;border-bottom:solid 1px #eaeff1;color:#6f8092;font-size:11px;font-weight:700}.atwho-view .atwho-header .small{color:#6f8092;float:right;padding-top:2px;margin-right:-5px;font-size:12px;font-weight:400}.atwho-view .atwho-header:hover{cursor:default}.atwho-view .cur{background:#36F;color:#fff}.atwho-view .cur small{color:#fff}.atwho-view strong{color:#36F}.atwho-view .cur strong{color:#fff;font:700}.atwho-view ul{list-style:none;padding:0;margin:auto;max-height:200px;overflow-y:auto}.atwho-view ul li{display:block;padding:5px 10px;border-bottom:1px solid #DDD;cursor:pointer}.atwho-view small{font-size:smaller;color:#777;font-weight:400}
\ No newline at end of file diff --git a/apps/comments/js/vendor/At.js/dist/js/jquery.atwho.js b/apps/comments/js/vendor/At.js/dist/js/jquery.atwho.js deleted file mode 100644 index 795b6c67dcd..00000000000 --- a/apps/comments/js/vendor/At.js/dist/js/jquery.atwho.js +++ /dev/null @@ -1,1212 +0,0 @@ -/** - * at.js - 1.5.4 - * Copyright (c) 2017 chord.luo <chord.luo@gmail.com>; - * Homepage: http://ichord.github.com/At.js - * License: MIT - */ -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module unless amdModuleId is set - define(["jquery"], function (a0) { - return (factory(a0)); - }); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(require("jquery")); - } else { - factory(jQuery); - } -}(this, function ($) { -var DEFAULT_CALLBACKS, KEY_CODE; - -KEY_CODE = { - ESC: 27, - TAB: 9, - ENTER: 13, - CTRL: 17, - A: 65, - P: 80, - N: 78, - LEFT: 37, - UP: 38, - RIGHT: 39, - DOWN: 40, - BACKSPACE: 8, - SPACE: 32 -}; - -DEFAULT_CALLBACKS = { - beforeSave: function(data) { - return Controller.arrayToDefaultHash(data); - }, - matcher: function(flag, subtext, should_startWithSpace, acceptSpaceBar) { - var _a, _y, match, regexp, space; - flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); - if (should_startWithSpace) { - flag = '(?:^|\\s)' + flag; - } - _a = decodeURI("%C3%80"); - _y = decodeURI("%C3%BF"); - space = acceptSpaceBar ? "\ " : ""; - regexp = new RegExp(flag + "([A-Za-z" + _a + "-" + _y + "0-9_" + space + "\'\.\+\-]*)$|" + flag + "([^\\x00-\\xff]*)$", 'gi'); - match = regexp.exec(subtext); - if (match) { - return match[2] || match[1]; - } else { - return null; - } - }, - filter: function(query, data, searchKey) { - var _results, i, item, len; - _results = []; - for (i = 0, len = data.length; i < len; i++) { - item = data[i]; - if (~new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase())) { - _results.push(item); - } - } - return _results; - }, - remoteFilter: null, - sorter: function(query, items, searchKey) { - var _results, i, item, len; - if (!query) { - return items; - } - _results = []; - for (i = 0, len = items.length; i < len; i++) { - item = items[i]; - item.atwho_order = new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase()); - if (item.atwho_order > -1) { - _results.push(item); - } - } - return _results.sort(function(a, b) { - return a.atwho_order - b.atwho_order; - }); - }, - tplEval: function(tpl, map) { - var error, error1, template; - template = tpl; - try { - if (typeof tpl !== 'string') { - template = tpl(map); - } - return template.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) { - return map[key]; - }); - } catch (error1) { - error = error1; - return ""; - } - }, - highlighter: function(li, query) { - var regexp; - if (!query) { - return li; - } - regexp = new RegExp(">\\s*([^\<]*?)(" + query.replace("+", "\\+") + ")([^\<]*)\\s*<", 'ig'); - return li.replace(regexp, function(str, $1, $2, $3) { - return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <'; - }); - }, - beforeInsert: function(value, $li, e) { - return value; - }, - beforeReposition: function(offset) { - return offset; - }, - afterMatchFailed: function(at, el) {} -}; - -var App; - -App = (function() { - function App(inputor) { - this.currentFlag = null; - this.controllers = {}; - this.aliasMaps = {}; - this.$inputor = $(inputor); - this.setupRootElement(); - this.listen(); - } - - App.prototype.createContainer = function(doc) { - var ref; - if ((ref = this.$el) != null) { - ref.remove(); - } - return $(doc.body).append(this.$el = $("<div class='atwho-container'></div>")); - }; - - App.prototype.setupRootElement = function(iframe, asRoot) { - var error, error1; - if (asRoot == null) { - asRoot = false; - } - if (iframe) { - this.window = iframe.contentWindow; - this.document = iframe.contentDocument || this.window.document; - this.iframe = iframe; - } else { - this.document = this.$inputor[0].ownerDocument; - this.window = this.document.defaultView || this.document.parentWindow; - try { - this.iframe = this.window.frameElement; - } catch (error1) { - error = error1; - this.iframe = null; - if ($.fn.atwho.debug) { - throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n" + error); - } - } - } - return this.createContainer((this.iframeAsRoot = asRoot) ? this.document : document); - }; - - App.prototype.controller = function(at) { - var c, current, currentFlag, ref; - if (this.aliasMaps[at]) { - current = this.controllers[this.aliasMaps[at]]; - } else { - ref = this.controllers; - for (currentFlag in ref) { - c = ref[currentFlag]; - if (currentFlag === at) { - current = c; - break; - } - } - } - if (current) { - return current; - } else { - return this.controllers[this.currentFlag]; - } - }; - - App.prototype.setContextFor = function(at) { - this.currentFlag = at; - return this; - }; - - App.prototype.reg = function(flag, setting) { - var base, controller; - controller = (base = this.controllers)[flag] || (base[flag] = this.$inputor.is('[contentEditable]') ? new EditableController(this, flag) : new TextareaController(this, flag)); - if (setting.alias) { - this.aliasMaps[setting.alias] = flag; - } - controller.init(setting); - return this; - }; - - App.prototype.listen = function() { - return this.$inputor.on('compositionstart', (function(_this) { - return function(e) { - var ref; - if ((ref = _this.controller()) != null) { - ref.view.hide(); - } - _this.isComposing = true; - return null; - }; - })(this)).on('compositionend', (function(_this) { - return function(e) { - _this.isComposing = false; - setTimeout(function(e) { - return _this.dispatch(e); - }); - return null; - }; - })(this)).on('keyup.atwhoInner', (function(_this) { - return function(e) { - return _this.onKeyup(e); - }; - })(this)).on('keydown.atwhoInner', (function(_this) { - return function(e) { - return _this.onKeydown(e); - }; - })(this)).on('blur.atwhoInner', (function(_this) { - return function(e) { - var c; - if (c = _this.controller()) { - c.expectedQueryCBId = null; - return c.view.hide(e, c.getOpt("displayTimeout")); - } - }; - })(this)).on('click.atwhoInner', (function(_this) { - return function(e) { - return _this.dispatch(e); - }; - })(this)).on('scroll.atwhoInner', (function(_this) { - return function() { - var lastScrollTop; - lastScrollTop = _this.$inputor.scrollTop(); - return function(e) { - var currentScrollTop, ref; - currentScrollTop = e.target.scrollTop; - if (lastScrollTop !== currentScrollTop) { - if ((ref = _this.controller()) != null) { - ref.view.hide(e); - } - } - lastScrollTop = currentScrollTop; - return true; - }; - }; - })(this)()); - }; - - App.prototype.shutdown = function() { - var _, c, ref; - ref = this.controllers; - for (_ in ref) { - c = ref[_]; - c.destroy(); - delete this.controllers[_]; - } - this.$inputor.off('.atwhoInner'); - return this.$el.remove(); - }; - - App.prototype.dispatch = function(e) { - var _, c, ref, results; - ref = this.controllers; - results = []; - for (_ in ref) { - c = ref[_]; - results.push(c.lookUp(e)); - } - return results; - }; - - App.prototype.onKeyup = function(e) { - var ref; - switch (e.keyCode) { - case KEY_CODE.ESC: - e.preventDefault(); - if ((ref = this.controller()) != null) { - ref.view.hide(); - } - break; - case KEY_CODE.DOWN: - case KEY_CODE.UP: - case KEY_CODE.CTRL: - case KEY_CODE.ENTER: - $.noop(); - break; - case KEY_CODE.P: - case KEY_CODE.N: - if (!e.ctrlKey) { - this.dispatch(e); - } - break; - default: - this.dispatch(e); - } - }; - - App.prototype.onKeydown = function(e) { - var ref, view; - view = (ref = this.controller()) != null ? ref.view : void 0; - if (!(view && view.visible())) { - return; - } - switch (e.keyCode) { - case KEY_CODE.ESC: - e.preventDefault(); - view.hide(e); - break; - case KEY_CODE.UP: - e.preventDefault(); - view.prev(); - break; - case KEY_CODE.DOWN: - e.preventDefault(); - view.next(); - break; - case KEY_CODE.P: - if (!e.ctrlKey) { - return; - } - e.preventDefault(); - view.prev(); - break; - case KEY_CODE.N: - if (!e.ctrlKey) { - return; - } - e.preventDefault(); - view.next(); - break; - case KEY_CODE.TAB: - case KEY_CODE.ENTER: - case KEY_CODE.SPACE: - if (!view.visible()) { - return; - } - if (!this.controller().getOpt('spaceSelectsMatch') && e.keyCode === KEY_CODE.SPACE) { - return; - } - if (!this.controller().getOpt('tabSelectsMatch') && e.keyCode === KEY_CODE.TAB) { - return; - } - if (view.highlighted()) { - e.preventDefault(); - view.choose(e); - } else { - view.hide(e); - } - break; - default: - $.noop(); - } - }; - - return App; - -})(); - -var Controller, - slice = [].slice; - -Controller = (function() { - Controller.prototype.uid = function() { - return (Math.random().toString(16) + "000000000").substr(2, 8) + (new Date().getTime()); - }; - - function Controller(app, at1) { - this.app = app; - this.at = at1; - this.$inputor = this.app.$inputor; - this.id = this.$inputor[0].id || this.uid(); - this.expectedQueryCBId = null; - this.setting = null; - this.query = null; - this.pos = 0; - this.range = null; - if ((this.$el = $("#atwho-ground-" + this.id, this.app.$el)).length === 0) { - this.app.$el.append(this.$el = $("<div id='atwho-ground-" + this.id + "'></div>")); - } - this.model = new Model(this); - this.view = new View(this); - } - - Controller.prototype.init = function(setting) { - this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting); - this.view.init(); - return this.model.reload(this.setting.data); - }; - - Controller.prototype.destroy = function() { - this.trigger('beforeDestroy'); - this.model.destroy(); - this.view.destroy(); - return this.$el.remove(); - }; - - Controller.prototype.callDefault = function() { - var args, error, error1, funcName; - funcName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; - try { - return DEFAULT_CALLBACKS[funcName].apply(this, args); - } catch (error1) { - error = error1; - return $.error(error + " Or maybe At.js doesn't have function " + funcName); - } - }; - - Controller.prototype.trigger = function(name, data) { - var alias, eventName; - if (data == null) { - data = []; - } - data.push(this); - alias = this.getOpt('alias'); - eventName = alias ? name + "-" + alias + ".atwho" : name + ".atwho"; - return this.$inputor.trigger(eventName, data); - }; - - Controller.prototype.callbacks = function(funcName) { - return this.getOpt("callbacks")[funcName] || DEFAULT_CALLBACKS[funcName]; - }; - - Controller.prototype.getOpt = function(at, default_value) { - var e, error1; - try { - return this.setting[at]; - } catch (error1) { - e = error1; - return null; - } - }; - - Controller.prototype.insertContentFor = function($li) { - var data, tpl; - tpl = this.getOpt('insertTpl'); - data = $.extend({}, $li.data('item-data'), { - 'atwho-at': this.at - }); - return this.callbacks("tplEval").call(this, tpl, data, "onInsert"); - }; - - Controller.prototype.renderView = function(data) { - var searchKey; - searchKey = this.getOpt("searchKey"); - data = this.callbacks("sorter").call(this, this.query.text, data.slice(0, 1001), searchKey); - return this.view.render(data.slice(0, this.getOpt('limit'))); - }; - - Controller.arrayToDefaultHash = function(data) { - var i, item, len, results; - if (!$.isArray(data)) { - return data; - } - results = []; - for (i = 0, len = data.length; i < len; i++) { - item = data[i]; - if ($.isPlainObject(item)) { - results.push(item); - } else { - results.push({ - name: item - }); - } - } - return results; - }; - - Controller.prototype.lookUp = function(e) { - var query, wait; - if (e && e.type === 'click' && !this.getOpt('lookUpOnClick')) { - return; - } - if (this.getOpt('suspendOnComposing') && this.app.isComposing) { - return; - } - query = this.catchQuery(e); - if (!query) { - this.expectedQueryCBId = null; - return query; - } - this.app.setContextFor(this.at); - if (wait = this.getOpt('delay')) { - this._delayLookUp(query, wait); - } else { - this._lookUp(query); - } - return query; - }; - - Controller.prototype._delayLookUp = function(query, wait) { - var now, remaining; - now = Date.now ? Date.now() : new Date().getTime(); - this.previousCallTime || (this.previousCallTime = now); - remaining = wait - (now - this.previousCallTime); - if ((0 < remaining && remaining < wait)) { - this.previousCallTime = now; - this._stopDelayedCall(); - return this.delayedCallTimeout = setTimeout((function(_this) { - return function() { - _this.previousCallTime = 0; - _this.delayedCallTimeout = null; - return _this._lookUp(query); - }; - })(this), wait); - } else { - this._stopDelayedCall(); - if (this.previousCallTime !== now) { - this.previousCallTime = 0; - } - return this._lookUp(query); - } - }; - - Controller.prototype._stopDelayedCall = function() { - if (this.delayedCallTimeout) { - clearTimeout(this.delayedCallTimeout); - return this.delayedCallTimeout = null; - } - }; - - Controller.prototype._generateQueryCBId = function() { - return {}; - }; - - Controller.prototype._lookUp = function(query) { - var _callback; - _callback = function(queryCBId, data) { - if (queryCBId !== this.expectedQueryCBId) { - return; - } - if (data && data.length > 0) { - return this.renderView(this.constructor.arrayToDefaultHash(data)); - } else { - return this.view.hide(); - } - }; - this.expectedQueryCBId = this._generateQueryCBId(); - return this.model.query(query.text, $.proxy(_callback, this, this.expectedQueryCBId)); - }; - - return Controller; - -})(); - -var TextareaController, - extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, - hasProp = {}.hasOwnProperty; - -TextareaController = (function(superClass) { - extend(TextareaController, superClass); - - function TextareaController() { - return TextareaController.__super__.constructor.apply(this, arguments); - } - - TextareaController.prototype.catchQuery = function() { - var caretPos, content, end, isString, query, start, subtext; - content = this.$inputor.val(); - caretPos = this.$inputor.caret('pos', { - iframe: this.app.iframe - }); - subtext = content.slice(0, caretPos); - query = this.callbacks("matcher").call(this, this.at, subtext, this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar")); - isString = typeof query === 'string'; - if (isString && query.length < this.getOpt('minLen', 0)) { - return; - } - if (isString && query.length <= this.getOpt('maxLen', 20)) { - start = caretPos - query.length; - end = start + query.length; - this.pos = start; - query = { - 'text': query, - 'headPos': start, - 'endPos': end - }; - this.trigger("matched", [this.at, query.text]); - } else { - query = null; - this.view.hide(); - } - return this.query = query; - }; - - TextareaController.prototype.rect = function() { - var c, iframeOffset, scaleBottom; - if (!(c = this.$inputor.caret('offset', this.pos - 1, { - iframe: this.app.iframe - }))) { - return; - } - if (this.app.iframe && !this.app.iframeAsRoot) { - iframeOffset = $(this.app.iframe).offset(); - c.left += iframeOffset.left; - c.top += iframeOffset.top; - } - scaleBottom = this.app.document.selection ? 0 : 2; - return { - left: c.left, - top: c.top, - bottom: c.top + c.height + scaleBottom - }; - }; - - TextareaController.prototype.insert = function(content, $li) { - var $inputor, source, startStr, suffix, text; - $inputor = this.$inputor; - source = $inputor.val(); - startStr = source.slice(0, Math.max(this.query.headPos - this.at.length, 0)); - suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || " "; - content += suffix; - text = "" + startStr + content + (source.slice(this.query['endPos'] || 0)); - $inputor.val(text); - $inputor.caret('pos', startStr.length + content.length, { - iframe: this.app.iframe - }); - if (!$inputor.is(':focus')) { - $inputor.focus(); - } - return $inputor.change(); - }; - - return TextareaController; - -})(Controller); - -var EditableController, - extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, - hasProp = {}.hasOwnProperty; - -EditableController = (function(superClass) { - extend(EditableController, superClass); - - function EditableController() { - return EditableController.__super__.constructor.apply(this, arguments); - } - - EditableController.prototype._getRange = function() { - var sel; - sel = this.app.window.getSelection(); - if (sel.rangeCount > 0) { - return sel.getRangeAt(0); - } - }; - - EditableController.prototype._setRange = function(position, node, range) { - if (range == null) { - range = this._getRange(); - } - if (!(range && node)) { - return; - } - node = $(node)[0]; - if (position === 'after') { - range.setEndAfter(node); - range.setStartAfter(node); - } else { - range.setEndBefore(node); - range.setStartBefore(node); - } - range.collapse(false); - return this._clearRange(range); - }; - - EditableController.prototype._clearRange = function(range) { - var sel; - if (range == null) { - range = this._getRange(); - } - sel = this.app.window.getSelection(); - if (this.ctrl_a_pressed == null) { - sel.removeAllRanges(); - return sel.addRange(range); - } - }; - - EditableController.prototype._movingEvent = function(e) { - var ref; - return e.type === 'click' || ((ref = e.which) === KEY_CODE.RIGHT || ref === KEY_CODE.LEFT || ref === KEY_CODE.UP || ref === KEY_CODE.DOWN); - }; - - EditableController.prototype._unwrap = function(node) { - var next; - node = $(node).unwrap().get(0); - if ((next = node.nextSibling) && next.nodeValue) { - node.nodeValue += next.nodeValue; - $(next).remove(); - } - return node; - }; - - EditableController.prototype.catchQuery = function(e) { - var $inserted, $query, _range, index, inserted, isString, lastNode, matched, offset, query, query_content, range; - if (!(range = this._getRange())) { - return; - } - if (!range.collapsed) { - return; - } - if (e.which === KEY_CODE.ENTER) { - ($query = $(range.startContainer).closest('.atwho-query')).contents().unwrap(); - if ($query.is(':empty')) { - $query.remove(); - } - ($query = $(".atwho-query", this.app.document)).text($query.text()).contents().last().unwrap(); - this._clearRange(); - return; - } - if (/firefox/i.test(navigator.userAgent)) { - if ($(range.startContainer).is(this.$inputor)) { - this._clearRange(); - return; - } - if (e.which === KEY_CODE.BACKSPACE && range.startContainer.nodeType === document.ELEMENT_NODE && (offset = range.startOffset - 1) >= 0) { - _range = range.cloneRange(); - _range.setStart(range.startContainer, offset); - if ($(_range.cloneContents()).contents().last().is('.atwho-inserted')) { - inserted = $(range.startContainer).contents().get(offset); - this._setRange('after', $(inserted).contents().last()); - } - } else if (e.which === KEY_CODE.LEFT && range.startContainer.nodeType === document.TEXT_NODE) { - $inserted = $(range.startContainer.previousSibling); - if ($inserted.is('.atwho-inserted') && range.startOffset === 0) { - this._setRange('after', $inserted.contents().last()); - } - } - } - $(range.startContainer).closest('.atwho-inserted').addClass('atwho-query').siblings().removeClass('atwho-query'); - if (($query = $(".atwho-query", this.app.document)).length > 0 && $query.is(':empty') && $query.text().length === 0) { - $query.remove(); - } - if (!this._movingEvent(e)) { - $query.removeClass('atwho-inserted'); - } - if ($query.length > 0) { - switch (e.which) { - case KEY_CODE.LEFT: - this._setRange('before', $query.get(0), range); - $query.removeClass('atwho-query'); - return; - case KEY_CODE.RIGHT: - this._setRange('after', $query.get(0).nextSibling, range); - $query.removeClass('atwho-query'); - return; - } - } - if ($query.length > 0 && (query_content = $query.attr('data-atwho-at-query'))) { - $query.empty().html(query_content).attr('data-atwho-at-query', null); - this._setRange('after', $query.get(0), range); - } - _range = range.cloneRange(); - _range.setStart(range.startContainer, 0); - matched = this.callbacks("matcher").call(this, this.at, _range.toString(), this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar")); - isString = typeof matched === 'string'; - if ($query.length === 0 && isString && (index = range.startOffset - this.at.length - matched.length) >= 0) { - range.setStart(range.startContainer, index); - $query = $('<span/>', this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass('atwho-query'); - range.surroundContents($query.get(0)); - lastNode = $query.contents().last().get(0); - if (lastNode) { - if (/firefox/i.test(navigator.userAgent)) { - range.setStart(lastNode, lastNode.length); - range.setEnd(lastNode, lastNode.length); - this._clearRange(range); - } else { - this._setRange('after', lastNode, range); - } - } - } - if (isString && matched.length < this.getOpt('minLen', 0)) { - return; - } - if (isString && matched.length <= this.getOpt('maxLen', 20)) { - query = { - text: matched, - el: $query - }; - this.trigger("matched", [this.at, query.text]); - return this.query = query; - } else { - this.view.hide(); - this.query = { - el: $query - }; - if ($query.text().indexOf(this.at) >= 0) { - if (this._movingEvent(e) && $query.hasClass('atwho-inserted')) { - $query.removeClass('atwho-query'); - } else if (false !== this.callbacks('afterMatchFailed').call(this, this.at, $query)) { - this._setRange("after", this._unwrap($query.text($query.text()).contents().first())); - } - } - return null; - } - }; - - EditableController.prototype.rect = function() { - var $iframe, iframeOffset, rect; - rect = this.query.el.offset(); - if (!(rect && this.query.el[0].getClientRects().length)) { - return; - } - if (this.app.iframe && !this.app.iframeAsRoot) { - iframeOffset = ($iframe = $(this.app.iframe)).offset(); - rect.left += iframeOffset.left - this.$inputor.scrollLeft(); - rect.top += iframeOffset.top - this.$inputor.scrollTop(); - } - rect.bottom = rect.top + this.query.el.height(); - return rect; - }; - - EditableController.prototype.insert = function(content, $li) { - var data, overrides, range, suffix, suffixNode; - if (!this.$inputor.is(':focus')) { - this.$inputor.focus(); - } - overrides = this.getOpt('functionOverrides'); - if (overrides.insert) { - return overrides.insert.call(this, content, $li); - } - suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || "\u00A0"; - data = $li.data('item-data'); - this.query.el.removeClass('atwho-query').addClass('atwho-inserted').html(content).attr('data-atwho-at-query', "" + data['atwho-at'] + this.query.text).attr('contenteditable', "false"); - if (range = this._getRange()) { - if (this.query.el.length) { - range.setEndAfter(this.query.el[0]); - } - range.collapse(false); - range.insertNode(suffixNode = this.app.document.createTextNode("" + suffix)); - this._setRange('after', suffixNode, range); - } - if (!this.$inputor.is(':focus')) { - this.$inputor.focus(); - } - return this.$inputor.change(); - }; - - return EditableController; - -})(Controller); - -var Model; - -Model = (function() { - function Model(context) { - this.context = context; - this.at = this.context.at; - this.storage = this.context.$inputor; - } - - Model.prototype.destroy = function() { - return this.storage.data(this.at, null); - }; - - Model.prototype.saved = function() { - return this.fetch() > 0; - }; - - Model.prototype.query = function(query, callback) { - var _remoteFilter, data, searchKey; - data = this.fetch(); - searchKey = this.context.getOpt("searchKey"); - data = this.context.callbacks('filter').call(this.context, query, data, searchKey) || []; - _remoteFilter = this.context.callbacks('remoteFilter'); - if (data.length > 0 || (!_remoteFilter && data.length === 0)) { - return callback(data); - } else { - return _remoteFilter.call(this.context, query, callback); - } - }; - - Model.prototype.fetch = function() { - return this.storage.data(this.at) || []; - }; - - Model.prototype.save = function(data) { - return this.storage.data(this.at, this.context.callbacks("beforeSave").call(this.context, data || [])); - }; - - Model.prototype.load = function(data) { - if (!(this.saved() || !data)) { - return this._load(data); - } - }; - - Model.prototype.reload = function(data) { - return this._load(data); - }; - - Model.prototype._load = function(data) { - if (typeof data === "string") { - return $.ajax(data, { - dataType: "json" - }).done((function(_this) { - return function(data) { - return _this.save(data); - }; - })(this)); - } else { - return this.save(data); - } - }; - - return Model; - -})(); - -var View; - -View = (function() { - function View(context) { - this.context = context; - this.$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>"); - this.$elUl = this.$el.children(); - this.timeoutID = null; - this.context.$el.append(this.$el); - this.bindEvent(); - } - - View.prototype.init = function() { - var header_tpl, id; - id = this.context.getOpt("alias") || this.context.at.charCodeAt(0); - header_tpl = this.context.getOpt("headerTpl"); - if (header_tpl && this.$el.children().length === 1) { - this.$el.prepend(header_tpl); - } - return this.$el.attr({ - 'id': "at-view-" + id - }); - }; - - View.prototype.destroy = function() { - return this.$el.remove(); - }; - - View.prototype.bindEvent = function() { - var $menu, lastCoordX, lastCoordY; - $menu = this.$el.find('ul'); - lastCoordX = 0; - lastCoordY = 0; - return $menu.on('mousemove.atwho-view', 'li', (function(_this) { - return function(e) { - var $cur; - if (lastCoordX === e.clientX && lastCoordY === e.clientY) { - return; - } - lastCoordX = e.clientX; - lastCoordY = e.clientY; - $cur = $(e.currentTarget); - if ($cur.hasClass('cur')) { - return; - } - $menu.find('.cur').removeClass('cur'); - return $cur.addClass('cur'); - }; - })(this)).on('click.atwho-view', 'li', (function(_this) { - return function(e) { - $menu.find('.cur').removeClass('cur'); - $(e.currentTarget).addClass('cur'); - _this.choose(e); - return e.preventDefault(); - }; - })(this)); - }; - - View.prototype.visible = function() { - return $.expr.filters.visible(this.$el[0]); - }; - - View.prototype.highlighted = function() { - return this.$el.find(".cur").length > 0; - }; - - View.prototype.choose = function(e) { - var $li, content; - if (($li = this.$el.find(".cur")).length) { - content = this.context.insertContentFor($li); - this.context._stopDelayedCall(); - this.context.insert(this.context.callbacks("beforeInsert").call(this.context, content, $li, e), $li); - this.context.trigger("inserted", [$li, e]); - this.hide(e); - } - if (this.context.getOpt("hideWithoutSuffix")) { - return this.stopShowing = true; - } - }; - - View.prototype.reposition = function(rect) { - var _window, offset, overflowOffset, ref; - _window = this.context.app.iframeAsRoot ? this.context.app.window : window; - if (rect.bottom + this.$el.height() - $(_window).scrollTop() > $(_window).height()) { - rect.bottom = rect.top - this.$el.height(); - } - if (rect.left > (overflowOffset = $(_window).width() - this.$el.width() - 5)) { - rect.left = overflowOffset; - } - offset = { - left: rect.left, - top: rect.bottom - }; - if ((ref = this.context.callbacks("beforeReposition")) != null) { - ref.call(this.context, offset); - } - this.$el.offset(offset); - return this.context.trigger("reposition", [offset]); - }; - - View.prototype.next = function() { - var cur, next, nextEl, offset; - cur = this.$el.find('.cur').removeClass('cur'); - next = cur.next(); - if (!next.length) { - next = this.$el.find('li:first'); - } - next.addClass('cur'); - nextEl = next[0]; - offset = nextEl.offsetTop + nextEl.offsetHeight + (nextEl.nextSibling ? nextEl.nextSibling.offsetHeight : 0); - return this.scrollTop(Math.max(0, offset - this.$el.height())); - }; - - View.prototype.prev = function() { - var cur, offset, prev, prevEl; - cur = this.$el.find('.cur').removeClass('cur'); - prev = cur.prev(); - if (!prev.length) { - prev = this.$el.find('li:last'); - } - prev.addClass('cur'); - prevEl = prev[0]; - offset = prevEl.offsetTop + prevEl.offsetHeight + (prevEl.nextSibling ? prevEl.nextSibling.offsetHeight : 0); - return this.scrollTop(Math.max(0, offset - this.$el.height())); - }; - - View.prototype.scrollTop = function(scrollTop) { - var scrollDuration; - scrollDuration = this.context.getOpt('scrollDuration'); - if (scrollDuration) { - return this.$elUl.animate({ - scrollTop: scrollTop - }, scrollDuration); - } else { - return this.$elUl.scrollTop(scrollTop); - } - }; - - View.prototype.show = function() { - var rect; - if (this.stopShowing) { - this.stopShowing = false; - return; - } - if (!this.visible()) { - this.$el.show(); - this.$el.scrollTop(0); - this.context.trigger('shown'); - } - if (rect = this.context.rect()) { - return this.reposition(rect); - } - }; - - View.prototype.hide = function(e, time) { - var callback; - if (!this.visible()) { - return; - } - if (isNaN(time)) { - this.$el.hide(); - return this.context.trigger('hidden', [e]); - } else { - callback = (function(_this) { - return function() { - return _this.hide(); - }; - })(this); - clearTimeout(this.timeoutID); - return this.timeoutID = setTimeout(callback, time); - } - }; - - View.prototype.render = function(list) { - var $li, $ul, i, item, len, li, tpl; - if (!($.isArray(list) && list.length > 0)) { - this.hide(); - return; - } - this.$el.find('ul').empty(); - $ul = this.$el.find('ul'); - tpl = this.context.getOpt('displayTpl'); - for (i = 0, len = list.length; i < len; i++) { - item = list[i]; - item = $.extend({}, item, { - 'atwho-at': this.context.at - }); - li = this.context.callbacks("tplEval").call(this.context, tpl, item, "onDisplay"); - $li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text)); - $li.data("item-data", item); - $ul.append($li); - } - this.show(); - if (this.context.getOpt('highlightFirst')) { - return $ul.find("li:first").addClass("cur"); - } - }; - - return View; - -})(); - -var Api; - -Api = { - load: function(at, data) { - var c; - if (c = this.controller(at)) { - return c.model.load(data); - } - }, - isSelecting: function() { - var ref; - return !!((ref = this.controller()) != null ? ref.view.visible() : void 0); - }, - hide: function() { - var ref; - return (ref = this.controller()) != null ? ref.view.hide() : void 0; - }, - reposition: function() { - var c; - if (c = this.controller()) { - return c.view.reposition(c.rect()); - } - }, - setIframe: function(iframe, asRoot) { - this.setupRootElement(iframe, asRoot); - return null; - }, - run: function() { - return this.dispatch(); - }, - destroy: function() { - this.shutdown(); - return this.$inputor.data('atwho', null); - } -}; - -$.fn.atwho = function(method) { - var _args, result; - _args = arguments; - result = null; - this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function() { - var $this, app; - if (!(app = ($this = $(this)).data("atwho"))) { - $this.data('atwho', (app = new App(this))); - } - if (typeof method === 'object' || !method) { - return app.reg(method.at, method); - } else if (Api[method] && app) { - return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1)); - } else { - return $.error("Method " + method + " does not exist on jQuery.atwho"); - } - }); - if (result != null) { - return result; - } else { - return this; - } -}; - -$.fn.atwho["default"] = { - at: void 0, - alias: void 0, - data: null, - displayTpl: "<li>${name}</li>", - insertTpl: "${atwho-at}${name}", - headerTpl: null, - callbacks: DEFAULT_CALLBACKS, - functionOverrides: {}, - searchKey: "name", - suffix: void 0, - hideWithoutSuffix: false, - startWithSpace: true, - acceptSpaceBar: false, - highlightFirst: true, - limit: 5, - maxLen: 20, - minLen: 0, - displayTimeout: 300, - delay: null, - spaceSelectsMatch: false, - tabSelectsMatch: true, - editableAtwhoQueryAttrs: {}, - scrollDuration: 150, - suspendOnComposing: true, - lookUpOnClick: true -}; - -$.fn.atwho.debug = false; - -})); diff --git a/apps/comments/js/vendor/At.js/examples/cross_document/dataFrame.html b/apps/comments/js/vendor/At.js/examples/cross_document/dataFrame.html deleted file mode 100644 index 4a1adabeccd..00000000000 --- a/apps/comments/js/vendor/At.js/examples/cross_document/dataFrame.html +++ /dev/null @@ -1,30 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title>Data Iframe</title> - <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> - <script type="text/javascript" src="http://ichord.github.io/Caret.js/src/jquery.caret.js"></script> - <script type="text/javascript" src="../../dist/js/jquery.atwho.js"></script> - <script type="text/javascript"> - $(function(){ - var names = ["Jacob","Isabella","Ethan","Emma","Michael","Olivia","Alexander","Sophia","William","Ava","Joshua","Emily","Daniel","Madison","Jayden","Abigail","Noah","Chloe","你好","你你你"]; - - var names = $.map(names,function(value,i) { - return {'id':i,'name':value,'email':value+"@email.com"}; - }); - - viewFrame = parent.frames.viewFrame - var at_config = { - at: "@", - data: names, - displayTpl: "<li>${name} <small>${email}</small></li>" - } - $(viewFrame.document.body) - .atwho('setIframe', viewFrame.frameElement, true) - .atwho(at_config); - }); - </script> -</head> -<body> -</body> -</html> diff --git a/apps/comments/js/vendor/At.js/examples/cross_document/index.html b/apps/comments/js/vendor/At.js/examples/cross_document/index.html deleted file mode 100644 index 05428b3ee08..00000000000 --- a/apps/comments/js/vendor/At.js/examples/cross_document/index.html +++ /dev/null @@ -1,90 +0,0 @@ -<!DOCTYPE HTML> -<html lang="en"> -<head> - <meta http-equiv="x-ua-compatible" content="IE=Edge"/> - <title>At.js</title> - <style type="text/css"> - html, body { - background:#F9F9F9; - padding: 0; - margin: 0; - font: 14px/1.6 "Lucida Grande", "Helvetica", sans-serif; - color: #333; - } - h1,h2,h3,h4 { - font-family: 'PT Sans', sans-serif; - line-height: 40px; - color: inherit; - font-weight: bold; - margin: 10px 0; - text-rendering: optimizelegibility; - } - h2,h3 { - color: gray; - } - strong { - color: #424242; - } - - a { - color: #4183C4; - text-decoration: none; - } - a:hover { - text-decoration: underline; - } - .wrapper { - width: 750px; - padding: 20px; - margin: 0 auto; - } - header { - margin-top:70px; - margin-bottom: 50px; - } - header h1 { - text-align: center; - font-size: 75px; - } - h1 i { - color: rgb(182, 180, 180); - font-style: normal; - font-weight: normal; - } - - .inputor { - height: 260px; - width: 90%; - border: 1px solid #dadada; - border-radius: 4px; - padding: 5px 8px; - outline: 0 none; - margin: 10px 0; - background: white; - font-size: inherit; - overflow-y: scroll; - } - .inputor:focus { - border: 1px solid rgb(6, 150, 247); - } - - footer { - margin: 30px 0; - } - - </style> - -</head> -<body> - <div class="container wrapper"> - <header> - <h1>At<i>.js</i></h1> - </header> - <div id="main"> - <h2>Cross-Document</h2> - <iframe name="dataFrame" src="dataFrame.html" style="display:none;"></iframe> - <iframe name="viewFrame" class="inputor" src="viewFrame.html"></iframe> - </div> - </div> -</body> -</html> diff --git a/apps/comments/js/vendor/At.js/examples/cross_document/viewFrame.html b/apps/comments/js/vendor/At.js/examples/cross_document/viewFrame.html deleted file mode 100644 index 84ee67d8a20..00000000000 --- a/apps/comments/js/vendor/At.js/examples/cross_document/viewFrame.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title>View Iframe</title> - <link rel="stylesheet" href="../../dist/css/jquery.atwho.css" /> -</head> -<body contenteditable=true style="height: 100%;"> - <p>hello!</p> -</body> -</html> diff --git a/apps/comments/js/vendor/At.js/examples/hashtags.html b/apps/comments/js/vendor/At.js/examples/hashtags.html deleted file mode 100644 index 3894ceea993..00000000000 --- a/apps/comments/js/vendor/At.js/examples/hashtags.html +++ /dev/null @@ -1,61 +0,0 @@ -<!DOCTYPE HTML> -<html lang="en"> -<head> - <meta http-equiv="x-ua-compatible" content="IE=Edge"/> - <title>At.js</title> - <link rel="stylesheet" href="../dist/css/jquery.atwho.css" /> - <link rel="stylesheet" href="./style.css" /> - <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> - <script type="text/javascript" src="http://ichord.github.io/Caret.js/src/jquery.caret.js"></script> - <!-- // <script type="text/javascript" src="../bower_components/jquery/dist/jquery.js"></script> --> - <!-- // <script type="text/javascript" src="../bower_components/Caret.js/dist/jquery.caret.js"></script> --> - <script type="text/javascript" src="../dist/js/jquery.atwho.js"></script> - <script type="text/javascript"> - $(function(){ - var jeremy = decodeURI("J%C3%A9r%C3%A9my") // Jérémy - var tags = ["Jacob","Isabella","Ethan","Emma","Michael","Olivia","Alexander","Sophia","William","Ava","Joshua","Emily","Daniel","Madison","Jayden","Abigail","Noah","Chloe","你好","你你你", jeremy]; - $('#editable').atwho({ - at: "#", - data: tags, - limit: 200, - callbacks: { - afterMatchFailed: function(at, el) { - // 32 is spacebar - if (at == '#') { - tags.push(el.text().trim().slice(1)); - this.model.save(tags); - this.insert(el.text().trim()); - return false; - } - } - } - }); - }); - </script> - <style type="text/css"> - /*override atwho's style*/ - .atwho-inserted { - color: #4183C4; - } - .atwho-query { - color: #4183C4; - } - </style> -</head> -<body> - <div class="container wrapper"> - <header> - <h3>Type `#` to autocomplete tags</h3> - </header> - <div id="main"> - <div id="editable" class="inputor" contentEditable="true"></div> - <footer> - <h2> - -> <a class="github" href="https://github.com/ichord/At.js">Fork me on GitHub!</a> - </h2> - </footer> - - </div> - </div> -</body> -</html> diff --git a/apps/comments/js/vendor/At.js/examples/medium-editor.html b/apps/comments/js/vendor/At.js/examples/medium-editor.html deleted file mode 100644 index f1cedf9b06d..00000000000 --- a/apps/comments/js/vendor/At.js/examples/medium-editor.html +++ /dev/null @@ -1,44 +0,0 @@ -<!DOCTYPE HTML> -<html lang="en"> -<head> - <meta http-equiv="x-ua-compatible" content="IE=Edge"/> - <title>At.js</title> - <link rel="stylesheet" href="../dist/css/jquery.atwho.css" /> - <link rel="stylesheet" type="text/css" href="http://dfimg.com/medium-editor/dist/css/medium-editor.css"> - <link rel="stylesheet" type="text/css" href="http://dfimg.com/medium-editor/dist/css/themes/default.css"> - <link rel="stylesheet" href="./style.css" /> - <!-- // <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> --> - <!-- // <script type="text/javascript" src="http://ichord.github.io/Caret.js/src/jquery.caret.js"></script> --> - <script type="text/javascript" src="../bower_components/jquery/dist/jquery.js"></script> - <script type="text/javascript" src="../bower_components/Caret.js/dist/jquery.caret.js"></script> - <script type="text/javascript" src="../dist/js/jquery.atwho.js"></script> - <script src="http://dfimg.com/medium-editor/dist/js/medium-editor.js"></script> - - <script type="text/javascript"> - $(function(){ - var jeremy = decodeURI("J%C3%A9r%C3%A9my") // Jérémy - var names = ["Jacob","Isabella","Ethan","Emma","Michael","Olivia","Alexander","Sophia","William","Ava","Joshua","Emily","Daniel","Madison","Jayden","Abigail","Noah","Chloe","你好","你你你", jeremy]; - var editor = new MediumEditor('#editor'); - $('#editor').atwho({at: "@", data: names}); - }); - </script> -</head> - -<body> - <div class="container wrapper"> - <header> - <h3>Example for medium-editor</h3> - </header> - <div id="main"> - <div id="editor" contentEditable>Easy! You should check out MoxieManager!</div> - <footer> - <h2> - -> <a class="github" href="https://github.com/ichord/At.js">Fork me on GitHub!</a> - </h2> - </footer> - - </div> - </div> -</body> - -</html> diff --git a/apps/comments/js/vendor/At.js/examples/style.css b/apps/comments/js/vendor/At.js/examples/style.css deleted file mode 100644 index 9e78ffbf748..00000000000 --- a/apps/comments/js/vendor/At.js/examples/style.css +++ /dev/null @@ -1,57 +0,0 @@ -html, body { - background:#F9F9F9; - padding: 0; - margin: 0; - font: 14px/1.6 "Lucida Grande", "Helvetica", sans-serif; - color: #333; -} -h1,h2,h3,h4 { - font-family: 'PT Sans', sans-serif; - line-height: 40px; - color: inherit; - font-weight: bold; - margin: 10px 0; - text-rendering: optimizelegibility; -} -h2,h3 { - color: gray; -} -strong { - color: #424242; -} - -a { - color: #4183C4; - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -.wrapper { - width: 750px; - padding: 20px; - margin: 0 auto; -} -header { - margin-top:30px; -} - -.inputor { - height: 160px; - width: 90%; - border: 1px solid #dadada; - border-radius: 4px; - padding: 5px 8px; - outline: 0 none; - margin: 10px 0; - background: white; - font-size: inherit; - overflow-y: scroll; -} -.inputor:focus { - border: 1px solid rgb(6, 150, 247); -} - -footer { - margin: 30px 0; -} diff --git a/apps/comments/js/vendor/At.js/examples/tinyMCE.html b/apps/comments/js/vendor/At.js/examples/tinyMCE.html deleted file mode 100644 index fca68152981..00000000000 --- a/apps/comments/js/vendor/At.js/examples/tinyMCE.html +++ /dev/null @@ -1,53 +0,0 @@ -<!DOCTYPE HTML> -<html lang="en"> -<head> - <meta http-equiv="x-ua-compatible" content="IE=Edge"/> - <title>At.js</title> - <link rel="stylesheet" href="../dist/css/jquery.atwho.css" /> - <link rel="stylesheet" href="./style.css" /> - <!-- // <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> --> - <!-- // <script type="text/javascript" src="http://ichord.github.io/Caret.js/src/jquery.caret.js"></script> --> - <script type="text/javascript" src="../bower_components/jquery/dist/jquery.js"></script> - <script type="text/javascript" src="../bower_components/Caret.js/dist/jquery.caret.js"></script> - <script type="text/javascript" src="../dist/js/jquery.atwho.js"></script> - <script src="http://tinymce.cachefly.net/4.1/tinymce.min.js"></script> - - <script type="text/javascript"> - $(function(){ - var jeremy = decodeURI("J%C3%A9r%C3%A9my") // Jérémy - var names = ["Jacob","Isabella","Ethan","Emma","Michael","Olivia","Alexander","Sophia","William","Ava","Joshua","Emily","Daniel","Madison","Jayden","Abigail","Noah","Chloe","你好","你你你", jeremy]; - tinymce.init({ - selector: "#editor", - init_instance_callback: function(editor) { - $(editor.contentDocument.activeElement).atwho({at: "@", data: names}); - }, - setup: function(editor) { - editor.on('keydown', function(e) { - if(e.keyCode == 13 && $(editor.contentDocument.activeElement).atwho('isSelecting')) - return false - }) - } - }); - - }); - </script> -</head> - -<body> - <div class="container wrapper"> - <header> - <h3>Example for tinyMCE editor</h3> - </header> - <div id="main"> - <textarea id="editor">Easy! You should check out MoxieManager!</textarea> - <footer> - <h2> - -> <a class="github" href="https://github.com/ichord/At.js">Fork me on GitHub!</a> - </h2> - </footer> - - </div> - </div> -</body> - -</html> diff --git a/apps/comments/js/vendor/At.js/examples/ueditor.html b/apps/comments/js/vendor/At.js/examples/ueditor.html deleted file mode 100644 index 34de7c92922..00000000000 --- a/apps/comments/js/vendor/At.js/examples/ueditor.html +++ /dev/null @@ -1,45 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> - <link rel="stylesheet" href="http://ueditor.baidu.com/ueditor/themes/default/css/ueditor.css" /> - <link rel="stylesheet" href="../dist/css/jquery.atwho.css" /> - - <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script> - <script type="text/javascript" src="http://ichord.github.io/Caret.js/src/jquery.caret.js"></script> - <script type="text/javascript" src="../dist/js/jquery.atwho.js"></script> - - <title>ueditor</title> -</head> -<body> - <script id="container" name="content" type="text/plain"> - test - </script> - <script src="http://ueditor.baidu.com/ueditor/ueditor.config.js"></script> - <script src="http://ueditor.baidu.com/ueditor/ueditor.all.js"></script> - - <script type="text/javascript"> - var ue = UE.getEditor('container'); - $(function(){ - var at_config = { - at: "@", - data:['Peter', 'Tom', 'Anne', 'zhangsan', 'lisi', 'wangwu', 'laoliu', 'libai', 'dupu', 'xiaozhou'], - limit: 20 - } - - var ue = UE.getEditor('container',{ - contextMenu:[], - //focus时自动清空初始化时的内容 - autoClearinitialContent:true, - //关闭字数统计 - wordCount:false, - //关闭elementPath - elementPathEnabled:false, - }); - ue.addListener('ready', function(editor){ - $(this.document.body).atwho(at_config); - }); - }); - </script> -</body> -</html> diff --git a/apps/comments/js/vendor/At.js/gulpfile.js b/apps/comments/js/vendor/At.js/gulpfile.js deleted file mode 100644 index e9699eab8d7..00000000000 --- a/apps/comments/js/vendor/At.js/gulpfile.js +++ /dev/null @@ -1,103 +0,0 @@ -var gulp = require('gulp'), - coffee = require('gulp-coffee'), - concat = require('gulp-concat'), - umd = require('gulp-umd'), - uglify = require('gulp-uglify'), - rename = require("gulp-rename"), - cssmin = require('gulp-cssmin'), - jasmine = require('gulp-jasmine-phantom'), - bump = require('gulp-bump'), - header = require('gulp-header'), - debug = require('gulp-debug'), - util = require('gulp-util'); - -var name = 'jquery.atwho'; - -gulp.task('coffee', function() { - gulp.src('src/*.coffee') - .pipe(coffee({bare: true}).on('error', util.log)) - .pipe(gulp.dest('./build/js')); -}); - -gulp.task('concat', function() { - fileList = [ - 'build/js/default.js', - 'build/js/app.js', - 'build/js/controller.js', - 'build/js/textareaController.js', - 'build/js/editableController.js', - 'build/js/model.js', - 'build/js/view.js', - 'build/js/api.js' - ] - gulp.src(fileList) - .pipe(concat(name + ".js")) - .pipe(gulp.dest('build')); -}); - -gulp.task('umd', function() { - gulp.src('build/' + name + ".js") - .pipe(umd({template: "umd.template.js"})) - .pipe(gulp.dest('build/js')); -}); - -gulp.task('bump', function() { - gulp.src(['bower.json', 'component.json', 'package.json']) - .pipe(bump({version: "1.5.4"})) - .pipe(gulp.dest('./')); -}); - -gulp.task("mark", function() { - var pkg = require('./package.json'); - var banner = ['/**', - ' * <%= pkg.name %> - <%= pkg.version %>', - ' * Copyright (c) <%= year %> <%= pkg.author.name %> <<%= pkg.author.email %>>;', - ' * Homepage: <%= pkg.homepage %>', - ' * License: <%= pkg.license %>', - ' */', - ''].join('\n'); - - gulp.src('build/js/' + name + '.js') - .pipe(header(banner, { pkg : pkg, year: (new Date).getFullYear()})) - .pipe(gulp.dest('dist/js/')) -}); - -gulp.task('compress', function() { - gulp.src('dist/js/' + name + '.js') - .pipe(uglify()) - .pipe(rename({suffix: '.min'})) - .pipe(gulp.dest('dist/js')); - - gulp.src('src/jquery.atwho.css').pipe(gulp.dest('dist/css')) - gulp.src('dist/css/' + name + '.css') - .pipe(cssmin()) - .pipe(rename({suffix: '.min'})) - .pipe(gulp.dest('dist/css')); -}); - -gulp.task('test', function () { - gulp.src('spec/**/*.coffee') - .pipe(coffee({bare: true}).on('error', util.log)) - .pipe(debug({title: "compiled specs"})) - .pipe(gulp.dest('spec/build')) - - gulp.src('spec/build/javascripts/*.spec.js') - .pipe(jasmine({ - integration: true, - specHtml: "specRunner.html" - /* TODO: have to add css to spec - vendor: [ - 'bower_components/jquery/dist/jquery.js', - 'bower_components/Caret.js/dist/jquery.caret.js', - 'dist/js/jquery.atwho.js', - 'node_modules/jasmine-jquery/lib/*.js', - 'node_modules/jasmine-ajax/lib/*.js', - 'spec/helpers/*.js', - 'spec/build/spec_helper.js' - ], - */ - })); -}); - -gulp.task('compile', ['coffee', 'umd', 'concat']); -gulp.task('default', ['compile', 'bump', 'mark', 'compress']); diff --git a/apps/comments/js/vendor/At.js/index.html b/apps/comments/js/vendor/At.js/index.html deleted file mode 100644 index a2654e0b8e5..00000000000 --- a/apps/comments/js/vendor/At.js/index.html +++ /dev/null @@ -1,205 +0,0 @@ -<!DOCTYPE HTML> -<html lang="en"> -<head> - <meta http-equiv="x-ua-compatible" content="IE=Edge"/> - <title>At.js</title> - <link rel="stylesheet" href="dist/css/jquery.atwho.css" /> - <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script> - <script type="text/javascript" src="https://ichord.github.io/Caret.js/src/jquery.caret.js"></script> - <!-- <script type="text/javascript" src="bower_components/jquery/dist/jquery.js"></script> --> - <!-- <script type="text/javascript" src="bower_components/Caret.js/dist/jquery.caret.js"></script> --> - <script type="text/javascript" src="dist/js/jquery.atwho.js"></script> - <script type="text/javascript"> - $(function(){ - $.fn.atwho.debug = true - var emojis = [ - "smile", "iphone", "girl", "smiley", "heart", "kiss", "copyright", "coffee", - "a", "ab", "airplane", "alien", "ambulance", "angel", "anger", "angry", - "arrow_forward", "arrow_left", "arrow_lower_left", "arrow_lower_right", - "arrow_right", "arrow_up", "arrow_upper_left", "arrow_upper_right", - "art", "astonished", "atm", "b", "baby", "baby_chick", "baby_symbol", - "balloon", "bamboo", "bank", "barber", "baseball", "basketball", "bath", - "bear", "beer", "beers", "beginner", "bell", "bento", "bike", "bikini", - "bird", "birthday", "black_square", "blue_car", "blue_heart", "blush", - "boar", "boat", "bomb", "book", "boot", "bouquet", "bow", "bowtie", - "boy", "bread", "briefcase", "broken_heart", "bug", "bulb", - "person_with_blond_hair", "phone", "pig", "pill", "pisces", "plus1", - "point_down", "point_left", "point_right", "point_up", "point_up_2", - "police_car", "poop", "post_office", "postbox", "pray", "princess", - "punch", "purple_heart", "question", "rabbit", "racehorse", "radio", - "up", "us", "v", "vhs", "vibration_mode", "virgo", "vs", "walking", - "warning", "watermelon", "wave", "wc", "wedding", "whale", "wheelchair", - "white_square", "wind_chime", "wink", "wink2", "wolf", "woman", - "womans_hat", "womens", "x", "yellow_heart", "zap", "zzz", "+1", - "-1" - ] - var jeremy = decodeURI("J%C3%A9r%C3%A9my") // Jérémy - var names = ["Jacob","Isabella","Ethan","Emma","Michael","Olivia","Alexander","Sophia","William","Ava","Joshua","Emily","Daniel","Madison","Jayden","Abigail","Noah","Chloe","你好","你你你", jeremy, "가"]; - - var names = $.map(names,function(value,i) { - return {'id':i,'name':value,'email':value+"@email.com"}; - }); - var emojis = $.map(emojis, function(value, i) {return {key: value, name:value}}); - - var at_config = { - at: "@", - data: names, - headerTpl: '<div class="atwho-header">Member List<small>↑ ↓ </small></div>', - insertTpl: '${name}', - displayTpl: "<li>${name} <small>${email}</small></li>", - limit: 200 - } - var emoji_config = { - at: ":", - data: emojis, - displayTpl: "<li>${name} <img src='https://assets-cdn.github.com/images/icons/emoji/${key}.png' height='20' width='20' /></li>", - insertTpl: ':${key}:', - delay: 400 - } - $inputor = $('#inputor').atwho(at_config).atwho(emoji_config); - $inputor.caret('pos', 47); - $inputor.focus().atwho('run'); - - emoji_config.insertTpl = "<img src='https://assets-cdn.github.com/images/icons/emoji/${name}.png' height='20' width='20' />" - $('#editable').atwho(at_config).atwho(emoji_config); - - ifr = $('#iframe1')[0] - doc = ifr.contentDocument || iframe.contentWindow.document - if ((ifrBody = doc.body) == null) { - // For IE - doc.write("<body></body>") - ifrBody = doc.body - } - ifrBody.contentEditable = true - ifrBody.id = 'ifrBody' - ifrBody.innerHTML = 'For <strong>WYSIWYG</strong> which using <strong>iframe</strong> such as <strong>ckeditor</strong>' - $(ifrBody).atwho('setIframe', ifr).atwho(at_config) - }); - - </script> - <!--link href='http://fonts.googleapis.com/css?family=Dosis:400,700|Bubblegum+Sans|Overlock:400,900|PT+Sans:400,700|PT+Sans+Narrow:400,700|Magra|Asap:400,700|Share:400,700&subset=latin,latin-ext' rel='stylesheet' type='text/css' --> - <link href='http://fonts.googleapis.com/css?family=PT+Sans:400,700' rel='stylesheet' type='text/css'> - - <style type="text/css"> - html, body { - background:#F9F9F9; - padding: 0; - margin: 0; - font: 14px/1.6 "Lucida Grande", "Helvetica", sans-serif; - color: #333; - } - h1,h2,h3,h4 { - font-family: 'PT Sans', sans-serif; - line-height: 40px; - color: inherit; - font-weight: bold; - margin: 10px 0; - text-rendering: optimizelegibility; - } - h2,h3 { - color: gray; - } - strong { - color: #424242; - } - - a { - color: #4183C4; - text-decoration: none; - } - a:hover { - text-decoration: underline; - } - .wrapper { - width: 750px; - padding: 20px; - margin: 0 auto; - } - header { - margin-top:70px; - margin-bottom: 50px; - } - header h1 { - text-align: center; - font-size: 75px; - } - h1 i { - color: rgb(182, 180, 180); - font-style: normal; - font-weight: normal; - } - - .inputor { - height: 160px; - width: 90%; - border: 1px solid #dadada; - border-radius: 4px; - padding: 5px 8px; - outline: 0 none; - margin: 10px 0; - background: white; - font-size: inherit; - overflow-y: scroll; - } - .inputor:focus { - border: 1px solid rgb(6, 150, 247); - } - - ul.doc { - list-style:none; - } - ul.doc li { - display:inline-block; - margin: 0 10px; - } - - footer { - margin: 30px 0; - } - - .github { - text-align: center; - } - - </style> - -</head> -<body> - <div class="container wrapper"> - <!-- <a id="github" href="https://github.com/ichord/At.js" target="_blank"><img style="position: absolute; top: 0; right: 0; border: 0; z-index:999" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a> --> - - <header> - <h1>At<i>.js</i></h1> - </header> - <div id="main"> - <div> - <textarea id="inputor" class="inputor">At.js, a github-like autocomplete library :s</textarea> - </div> - - <div id="editable" class="inputor" contentEditable="true"> - <p> - <b>And!!</b> it support <b style="font-size: 20px">ContentEditable</b> mode too!! - <img src="https://assets-cdn.github.com/images/icons/emoji/smile.png" height="20" width="20"> - <img src="https://assets-cdn.github.com/images/icons/emoji/smiley.png" height="20" width="20"> - <img src="https://assets-cdn.github.com/images/icons/emoji/coffee.png" height="20" width="20"> - </p> - <p> - <b>Try here now!</b><img src="https://assets-cdn.github.com/images/icons/emoji/point_right.png" height="20" width="20"> - <b>:h</b> - </p> - </div> - - <div class="inputor" style="overflow: hidden"> - <iframe src="" id="iframe1" style="width: 100%; height: 100%; border: 0px;"></iframe> - </div> - - <footer> - <h2> - -> <a class="github" href="https://github.com/ichord/At.js">Fork me on GitHub!</a> - </h2> - </footer> - - </div> - </div> -</body> -</html> diff --git a/apps/comments/js/vendor/At.js/specRunner.html b/apps/comments/js/vendor/At.js/specRunner.html deleted file mode 100644 index d0a5e63e8b8..00000000000 --- a/apps/comments/js/vendor/At.js/specRunner.html +++ /dev/null @@ -1,31 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <link rel="stylesheet" type="text/css" href="node_modules/gulp-jasmine-phantom/vendor/jasmine-2.0/jasmine.css" /> - <link rel="stylesheet" type="text/css" href="dist/css/jquery.atwho.css" /> - <script type="text/javascript" src="node_modules/gulp-jasmine-phantom/vendor/jasmine-2.0/jasmine.js"></script> - <script type="text/javascript" src="node_modules/gulp-jasmine-phantom/vendor/jasmine-2.0/jasmine-html.js"></script> - <script type="text/javascript" src="node_modules/gulp-jasmine-phantom/vendor/jasmine-2.0/console.js"></script> - <script type="text/javascript" src="node_modules/gulp-jasmine-phantom/vendor/jasmine-2.0/boot.js"></script> - <script type="text/javascript" src="bower_components/jquery/dist/jquery.js"></script> - <script type="text/javascript" src="bower_components/Caret.js/dist/jquery.caret.js"></script> - <script type="text/javascript" src="dist/js/jquery.atwho.js"></script> - <script type="text/javascript" src="node_modules/jasmine-jquery/lib/jasmine-jquery.js"></script> - <script type="text/javascript" src="node_modules/jasmine-ajax/lib/mock-ajax.js"></script> - <script type="text/javascript" src="spec/helpers/noConflict.js"></script> - <script type="text/javascript" src="spec/build/spec_helper.js"></script> - <script type="text/javascript" src="spec/build/javascripts/apis.spec.js"></script> - <script type="text/javascript" src="spec/build/javascripts/content_editable.spec.js"></script> - <script type="text/javascript" src="spec/build/javascripts/custom_callbacks.spec.js"></script> - <script type="text/javascript" src="spec/build/javascripts/default_callbacks.spec.js"></script> - <script type="text/javascript" src="spec/build/javascripts/events.spec.js"></script> - <script type="text/javascript" src="spec/build/javascripts/iframe.spec.js"></script> - <script type="text/javascript" src="spec/build/javascripts/settings.spec.js"></script> - <script type="text/javascript" src="spec/build/javascripts/view.spec.js"></script> - -<script type"text/javascript" src="node_modules/gulp-jasmine-phantom/lib/specRunner.js"></script> -</head> -<body> - -</body> -</html> diff --git a/apps/comments/js/vendor/At.js/src/api.coffee b/apps/comments/js/vendor/At.js/src/api.coffee deleted file mode 100644 index 2e208d3e659..00000000000 --- a/apps/comments/js/vendor/At.js/src/api.coffee +++ /dev/null @@ -1,59 +0,0 @@ -Api = - # load a flag's data - # - # @params at[String] the flag - # @params data [Array] data to storage. - load: (at, data) -> c.model.load data if c = this.controller(at) - isSelecting: () -> !!this.controller()?.view.visible() - hide: () -> this.controller()?.view.hide() - reposition: () -> - if c = this.controller() - c.view.reposition(c.rect()) - setIframe: (iframe, asRoot) -> this.setupRootElement(iframe, asRoot); null; - run: -> this.dispatch() - destroy: -> - this.shutdown() - @$inputor.data('atwho', null) - -$.fn.atwho = (method) -> - _args = arguments - result = null - this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each -> - if not app = ($this = $ this).data "atwho" - $this.data 'atwho', (app = new App this) - if typeof method is 'object' || !method - app.reg method.at, method - else if Api[method] and app - result = Api[method].apply app, Array::slice.call(_args, 1) - else - $.error "Method #{method} does not exist on jQuery.atwho" - if result? then result else this - -$.fn.atwho.default = - at: undefined - alias: undefined - data: null - displayTpl: "<li>${name}</li>" - insertTpl: "${atwho-at}${name}" - headerTpl: null - callbacks: DEFAULT_CALLBACKS - functionOverrides: {} - searchKey: "name" - suffix: undefined - hideWithoutSuffix: no - startWithSpace: yes - acceptSpaceBar: false - highlightFirst: yes - limit: 5 - maxLen: 20 - minLen: 0 - displayTimeout: 300 - delay: null - spaceSelectsMatch: no - tabSelectsMatch: yes - editableAtwhoQueryAttrs: {} - scrollDuration: 150 - suspendOnComposing: true - lookUpOnClick: true - -$.fn.atwho.debug = false diff --git a/apps/comments/js/vendor/At.js/src/app.coffee b/apps/comments/js/vendor/At.js/src/app.coffee deleted file mode 100644 index fd601b51613..00000000000 --- a/apps/comments/js/vendor/At.js/src/app.coffee +++ /dev/null @@ -1,158 +0,0 @@ -# At.js central contoller(searching, matching, evaluating and rendering.) -class App - - # @param inputor [HTML DOM Object] `input` or `textarea` - constructor: (inputor) -> - @currentFlag = null - @controllers = {} - @aliasMaps = {} - @$inputor = $(inputor) - this.setupRootElement() - this.listen() - - createContainer: (doc) -> - @$el?.remove() - $ doc.body - .append @$el = $ "<div class='atwho-container'></div>" - - setupRootElement: (iframe, asRoot=false) -> - if iframe - @window = iframe.contentWindow - @document = iframe.contentDocument || @window.document - @iframe = iframe - else - @document = @$inputor[0].ownerDocument - @window = @document.defaultView || @document.parentWindow - try - @iframe = @window.frameElement - catch error - @iframe = null - if $.fn.atwho.debug - throw new Error """ - iframe auto-discovery is failed. - Please use `setIframe` to set the target iframe manually. - #{error} - """ - this.createContainer if @iframeAsRoot = asRoot then @document else document - - controller: (at) -> - if @aliasMaps[at] - current = @controllers[@aliasMaps[at]] - else - for currentFlag, c of @controllers - if currentFlag is at - current = c - break - - if current then current else @controllers[@currentFlag] - - setContextFor: (at) -> - @currentFlag = at - this - - # At.js can register multiple at char (flag) to every inputor such as "@" and ":" - # Along with their own `settings` so that it works differently. - # After register, we still can update their `settings` such as updating `data` - # - # @param flag [String] at char (flag) - # @param settings [Hash] the settings - reg: (flag, setting) -> - controller = @controllers[flag] ||= - if @$inputor.is '[contentEditable]' - new EditableController this, flag - else - new TextareaController this, flag - # TODO: it will produce rubbish alias map, reduse this. - @aliasMaps[setting.alias] = flag if setting.alias - controller.init setting - this - - # binding jQuery events of `inputor`'s - listen: -> - @$inputor - .on 'compositionstart', (e) => - this.controller()?.view.hide() - @isComposing = true - null - .on 'compositionend', (e) => - @isComposing = false - setTimeout((e) => @dispatch(e)) - null - .on 'keyup.atwhoInner', (e) => - this.onKeyup(e) - .on 'keydown.atwhoInner', (e) => - this.onKeydown(e) - .on 'blur.atwhoInner', (e) => - if c = this.controller() - c.expectedQueryCBId = null - c.view.hide(e,c.getOpt("displayTimeout")) - .on 'click.atwhoInner', (e) => - this.dispatch e - .on 'scroll.atwhoInner', do => - # make returned handler handle the very first call properly - lastScrollTop = @$inputor.scrollTop() - (e) => - currentScrollTop = e.target.scrollTop - if lastScrollTop != currentScrollTop - @controller()?.view.hide(e) - lastScrollTop = currentScrollTop - true # ensure we don't stop bubbling - - shutdown: -> - for _, c of @controllers - c.destroy() - delete @controllers[_] - @$inputor.off '.atwhoInner' - @$el.remove() - - dispatch: (e) -> - c.lookUp(e) for _, c of @controllers - - onKeyup: (e) -> - switch e.keyCode - when KEY_CODE.ESC - e.preventDefault() - this.controller()?.view.hide() - when KEY_CODE.DOWN, KEY_CODE.UP, KEY_CODE.CTRL, KEY_CODE.ENTER - $.noop() - when KEY_CODE.P, KEY_CODE.N - this.dispatch e if not e.ctrlKey - else - this.dispatch e - # coffeescript will return everywhere!! - return - - onKeydown: (e) -> - # return if not (view = this.controller().view).visible() - view = this.controller()?.view - return if not (view and view.visible()) - switch e.keyCode - when KEY_CODE.ESC - e.preventDefault() - view.hide(e) - when KEY_CODE.UP - e.preventDefault() - view.prev() - when KEY_CODE.DOWN - e.preventDefault() - view.next() - when KEY_CODE.P - return if not e.ctrlKey - e.preventDefault() - view.prev() - when KEY_CODE.N - return if not e.ctrlKey - e.preventDefault() - view.next() - when KEY_CODE.TAB, KEY_CODE.ENTER, KEY_CODE.SPACE - return if not view.visible() - return if not this.controller().getOpt('spaceSelectsMatch') and e.keyCode == KEY_CODE.SPACE - return if not this.controller().getOpt('tabSelectsMatch') and e.keyCode == KEY_CODE.TAB - if view.highlighted() - e.preventDefault() - view.choose(e) - else - view.hide(e) - else - $.noop() - return diff --git a/apps/comments/js/vendor/At.js/src/controller.coffee b/apps/comments/js/vendor/At.js/src/controller.coffee deleted file mode 100644 index 22e263b002d..00000000000 --- a/apps/comments/js/vendor/At.js/src/controller.coffee +++ /dev/null @@ -1,142 +0,0 @@ -class Controller - uid: -> - (Math.random().toString(16)+"000000000").substr(2,8) + (new Date().getTime()) - - constructor: (@app, @at) -> - @$inputor = @app.$inputor - @id = @$inputor[0].id || this.uid() - @expectedQueryCBId = null - - @setting = null - @query = null - @pos = 0 - @range = null - if (@$el = $("#atwho-ground-#{@id}", @app.$el)).length == 0 - @app.$el.append @$el = $("<div id='atwho-ground-#{@id}'></div>") - - @model = new Model(this) - @view = new View(this) - - init: (setting) -> - @setting = $.extend {}, @setting || $.fn.atwho.default, setting - @view.init() - @model.reload @setting.data - - destroy: -> - this.trigger 'beforeDestroy' - @model.destroy() - @view.destroy() - @$el.remove() - - callDefault: (funcName, args...) -> - try - DEFAULT_CALLBACKS[funcName].apply this, args - catch error - $.error "#{error} Or maybe At.js doesn't have function #{funcName}" - - # Delegate custom `jQueryEvent` to the inputor - # This function will add `atwho` as namespace to every jQuery event - # and pass current context as the last param to it. - # - # @example - # this.trigger "roll_n_rock", [1,2,3,4] - # - # $inputor.on "rool_n_rock", (e, one, two, three, four) -> - # console.log one, two, three, four - # - # @param name [String] Event name - # @param data [Array] data to callback - trigger: (name, data=[]) -> - data.push this - alias = this.getOpt('alias') - eventName = if alias then "#{name}-#{alias}.atwho" else "#{name}.atwho" - @$inputor.trigger eventName, data - - # Get callback either in settings which was set by plugin user or in default callbacks list. - # - # @param funcName [String] callback's name - # @return [Function] The callback. - callbacks: (funcName)-> - this.getOpt("callbacks")[funcName] || DEFAULT_CALLBACKS[funcName] - - # Because different registered at chars have different settings. - # so we should give their own for them. - # - # @param at [String] setting's at name - # @param default_value [?] return this if nothing is returned from current settings. - # @return [?] setting's value - getOpt: (at, default_value) -> - try - @setting[at] - catch e - null - - insertContentFor: ($li) -> - tpl = this.getOpt('insertTpl') - data = $.extend {}, $li.data('item-data'), {'atwho-at': @at} - this.callbacks("tplEval").call(this, tpl, data, "onInsert") - - # Render list view - # - # @param data [Array] The data - renderView: (data) -> - searchKey = this.getOpt("searchKey") - data = this.callbacks("sorter").call(this, @query.text, data[0..1000] , searchKey) - @view.render data[0...this.getOpt('limit')] - - @arrayToDefaultHash: (data) -> - return data if not $.isArray data - for item in data - if $.isPlainObject item then item else name:item - - # Searching! - lookUp: (e) -> - return if e && e.type == 'click' && !@getOpt('lookUpOnClick') - return if @getOpt('suspendOnComposing') and @app.isComposing - query = @catchQuery e - if not query - @expectedQueryCBId = null - return query - @app.setContextFor @at - if wait = this.getOpt('delay') - @_delayLookUp query, wait - else - @_lookUp query - query - - _delayLookUp: (query, wait) -> - now = if Date.now then Date.now() else new Date().getTime() - @previousCallTime ||= now - remaining = wait - (now - @previousCallTime) - if 0 < remaining < wait - @previousCallTime = now - @_stopDelayedCall() - @delayedCallTimeout = setTimeout(=> - @previousCallTime = 0 - @delayedCallTimeout = null - @_lookUp query - , wait) - else - @_stopDelayedCall() - @previousCallTime = 0 if @previousCallTime isnt now - @_lookUp query - - _stopDelayedCall: -> - if @delayedCallTimeout - clearTimeout @delayedCallTimeout - @delayedCallTimeout = null - - _generateQueryCBId: -> - return {}; - - _lookUp: (query) -> - _callback = (queryCBId, data) -> - # ensure only the latest instance of this function perform actions - if queryCBId isnt @expectedQueryCBId - return - if data and data.length > 0 - this.renderView @constructor.arrayToDefaultHash data - else - @view.hide() - @expectedQueryCBId = @_generateQueryCBId() - @model.query query.text, $.proxy(_callback, this, @expectedQueryCBId) diff --git a/apps/comments/js/vendor/At.js/src/default.coffee b/apps/comments/js/vendor/At.js/src/default.coffee deleted file mode 100644 index f8c64a9fe18..00000000000 --- a/apps/comments/js/vendor/At.js/src/default.coffee +++ /dev/null @@ -1,147 +0,0 @@ -KEY_CODE = - ESC: 27 - TAB: 9 - ENTER: 13 - CTRL: 17 - A: 65 - P: 80 - N: 78 - LEFT: 37 - UP:38 - RIGHT: 39 - DOWN: 40 - BACKSPACE: 8 - SPACE: 32 - -# Functions set for handling and rendering the data. -# Others developers can override these methods to tweak At.js such as matcher. -# We can override them in `callbacks` settings. -# -# @mixin -# -# The context of these functions is `$.atwho.Controller` object and they are called in this sequences: -# -# [beforeSave, matcher, filter, remoteFilter, sorter, tplEvl, highlighter, beforeInsert, afterMatchFailed] -# -DEFAULT_CALLBACKS = - - # It would be called to restructure the data before At.js invokes `Model#save` to save data - # By default, At.js will convert it to a Hash Array. - # - # @param data [Array] data to refacotor. - # @return [Array] Data after refactor. - beforeSave: (data) -> - Controller.arrayToDefaultHash data - - # It would be called to match the `flag`. - # It will match at start of line or after whitespace - # - # @param flag [String] current `flag` ("@", etc) - # @param subtext [String] Text from start to current caret position. - # @param should_startWithSpace [boolean] accept white space as beginning of match. - # @param acceptSpaceBar [boolean] accept a space bar in the center of match, - # so you can match a first and last name, for ex. - # - # @return [String | null] Matched result. - matcher: (flag, subtext, should_startWithSpace, acceptSpaceBar) -> - # escape RegExp - flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") - flag = '(?:^|\\s)' + flag if should_startWithSpace - - # À - _a = decodeURI("%C3%80") - # ÿ - _y = decodeURI("%C3%BF") - space = if acceptSpaceBar then "\ " else "" - regexp = new RegExp "#{flag}([A-Za-z#{_a}-#{_y}0-9_#{space}\'\.\+\-]*)$|#{flag}([^\\x00-\\xff]*)$",'gi' - match = regexp.exec subtext - if match then match[2] || match[1] else null - - # --------------------- - - # Filter data by matched string. - # - # @param query [String] Matched string. - # @param data [Array] data list - # @param searchKey [String] at char for searching. - # - # @return [Array] result data. - filter: (query, data, searchKey) -> - # !!null #=> false; !!undefined #=> false; !!'' #=> false; - _results = [] - for item in data - _results.push item if ~new String(item[searchKey]).toLowerCase().indexOf query.toLowerCase() - _results - - # If a function is given, At.js will invoke it if local filter can not find any data - # - # @param params [String] matched query - # @param callback [Function] callback to render page. - remoteFilter: null - # remoteFilter: (query, callback) -> - # $.ajax url, - # data: params - # success: (data) -> - # callback(data) - - # Sorter data of course. - # - # @param query [String] matched string - # @param items [Array] data that was refactored - # @param searchKey [String] at char to search - # - # @return [Array] sorted data - sorter: (query, items, searchKey) -> - return items unless query - - _results = [] - for item in items - item.atwho_order = new String(item[searchKey]).toLowerCase().indexOf query.toLowerCase() - _results.push item if item.atwho_order > -1 - - _results.sort (a,b) -> a.atwho_order - b.atwho_order - - # Evaluate the template either as a string or as a function - # this allows someone to pass in a set of data that needs a - # different template for different data results - # - # @param tpl [function] the template function or string - # @param map [Hash] Data map to eval. - tplEval: (tpl, map) -> - template = tpl - try - template = tpl(map) unless typeof tpl == 'string' - template.replace /\$\{([^\}]*)\}/g, (tag, key, pos) -> map[key] - catch error - "" - - - # Highlight the `matched query` string. - # - # @param li [String] HTML String after eval. - # @param query [String] matched query. - # - # @return [String] highlighted string. - highlighter: (li, query) -> - return li if not query - regexp = new RegExp(">\\s*([^\<]*?)(" + query.replace("+","\\+") + ")([^\<]*)\\s*<", 'ig') - li.replace regexp, (str, $1, $2, $3) -> '> '+$1+'<strong>' + $2 + '</strong>'+$3+' <' - - # What to do before inserting item's value into inputor. - # - # @param value [String] content to insert - # @param $li [jQuery Object] the chosen item - # @param e [event Object] from the user selection (keyDown or click) - beforeInsert: (value, $li, e) -> - value - - # You can adjust the menu's offset here. - # - # @param offset [Hash] offset will be applied to menu - # beforeReposition: (offset) -> - # offset.left += 10 - # offset.top += 10 - # offset - beforeReposition: (offset) -> offset - - afterMatchFailed: (at, el) -> diff --git a/apps/comments/js/vendor/At.js/src/editableController.coffee b/apps/comments/js/vendor/At.js/src/editableController.coffee deleted file mode 100644 index d6fcaeb7995..00000000000 --- a/apps/comments/js/vendor/At.js/src/editableController.coffee +++ /dev/null @@ -1,174 +0,0 @@ -class EditableController extends Controller - - _getRange: -> - sel = @app.window.getSelection() - sel.getRangeAt(0) if sel.rangeCount > 0 - - _setRange: (position, node, range=@_getRange()) -> - return unless range and node - node = $(node)[0] - if position == 'after' - range.setEndAfter node - range.setStartAfter node - else - range.setEndBefore node - range.setStartBefore node - range.collapse false - @_clearRange range - - _clearRange: (range=@_getRange()) -> - sel = @app.window.getSelection() - #ctrl+a remove defaults using the flag - if !@ctrl_a_pressed? - sel.removeAllRanges() - sel.addRange range - - _movingEvent: (e) -> - e.type == 'click' or e.which in [KEY_CODE.RIGHT, KEY_CODE.LEFT, KEY_CODE.UP, KEY_CODE.DOWN] - - _unwrap: (node) -> - node = $(node).unwrap().get 0 - if (next = node.nextSibling) and next.nodeValue - node.nodeValue += next.nodeValue - $(next).remove() - node - - catchQuery: (e) -> - return unless range = @_getRange() - return unless range.collapsed - - if e.which == KEY_CODE.ENTER - ($query = $(range.startContainer).closest '.atwho-query') - .contents().unwrap() - $query.remove() if $query.is ':empty' - ($query = $ ".atwho-query", @app.document) - .text $query.text() - .contents().last().unwrap() - @_clearRange() - return - - # absorb range - # The range at the end of an element is not inside in firefox but not others browsers including IE. - # To normolize them, we have to move the range inside the element while deleting content or moving caret right after .atwho-inserted - if /firefox/i.test(navigator.userAgent) - if $(range.startContainer).is @$inputor - @_clearRange() - return - if e.which == KEY_CODE.BACKSPACE and range.startContainer.nodeType == document.ELEMENT_NODE \ - and (offset = range.startOffset - 1) >= 0 - _range = range.cloneRange() - _range.setStart range.startContainer, offset - if $(_range.cloneContents()).contents().last().is '.atwho-inserted' - inserted = $(range.startContainer).contents().get(offset) - @_setRange 'after', $(inserted).contents().last() - else if e.which == KEY_CODE.LEFT and range.startContainer.nodeType == document.TEXT_NODE - $inserted = $ range.startContainer.previousSibling - if $inserted.is('.atwho-inserted') and range.startOffset == 0 - @_setRange 'after', $inserted.contents().last() - - # modifying inserted element - $(range.startContainer) - .closest '.atwho-inserted' - .addClass 'atwho-query' - .siblings().removeClass 'atwho-query' - - if ($query = $ ".atwho-query", @app.document).length > 0 \ - and $query.is(':empty') and $query.text().length == 0 - $query.remove() - - if not @_movingEvent e - $query.removeClass 'atwho-inserted' - - if $query.length > 0 - switch e.which - when KEY_CODE.LEFT - @_setRange 'before', $query.get(0), range - $query.removeClass 'atwho-query' - return - when KEY_CODE.RIGHT - @_setRange 'after', $query.get(0).nextSibling, range - $query.removeClass 'atwho-query' - return - - # matching - if $query.length > 0 and query_content = $query.attr('data-atwho-at-query') - $query.empty().html(query_content).attr('data-atwho-at-query', null) - @_setRange 'after', $query.get(0), range - _range = range.cloneRange() - _range.setStart range.startContainer, 0 - matched = @callbacks("matcher").call(this, @at, _range.toString(), @getOpt('startWithSpace'), @getOpt("acceptSpaceBar")) - isString = typeof matched is 'string' - - # wrapping query with .atwho-query - if $query.length == 0 and isString \ - and (index = range.startOffset - @at.length - matched.length) >= 0 - range.setStart range.startContainer, index - $query = $ '<span/>', @app.document - .attr @getOpt "editableAtwhoQueryAttrs" - .addClass 'atwho-query' - range.surroundContents $query.get 0 - lastNode = $query.contents().last().get(0) - if lastNode - if /firefox/i.test navigator.userAgent - range.setStart lastNode, lastNode.length - range.setEnd lastNode, lastNode.length - @_clearRange range - else - @_setRange 'after', lastNode, range - - return if isString and matched.length < @getOpt('minLen', 0) - - # handle the matched result - if isString and matched.length <= @getOpt('maxLen', 20) - query = text: matched, el: $query - @trigger "matched", [@at, query.text] - @query = query - else - @view.hide() - @query = el: $query - if $query.text().indexOf(this.at) >= 0 - if @_movingEvent(e) and $query.hasClass 'atwho-inserted' - $query.removeClass('atwho-query') - else if false != @callbacks('afterMatchFailed').call this, @at, $query - @_setRange "after", @_unwrap $query.text($query.text()).contents().first() - null - - # Get offset of current at char(`flag`) - # - # @return [Hash] the offset which look likes this: {top: y, left: x, bottom: bottom} - rect: -> - rect = @query.el.offset() - # do not use {top: 0, left: 0} from jQuery when element is hidden - # happens every other time the menu is displayed on click in contenteditable - return unless rect and @query.el[0].getClientRects().length - if @app.iframe and not @app.iframeAsRoot - iframeOffset = ($iframe = $ @app.iframe).offset() - rect.left += iframeOffset.left - @$inputor.scrollLeft() - rect.top += iframeOffset.top - @$inputor.scrollTop() - rect.bottom = rect.top + @query.el.height() - rect - - # Insert value of `data-value` attribute of chosen item into inputor - # - # @param content [String] string to insert - insert: (content, $li) -> - @$inputor.focus() unless @$inputor.is ':focus' - overrides = @getOpt 'functionOverrides' - if overrides.insert - return overrides.insert.call this, content, $li - suffix = if (suffix = @getOpt 'suffix') == "" then suffix else suffix or "\u00A0" - data = $li.data('item-data') - @query.el - .removeClass 'atwho-query' - .addClass 'atwho-inserted' - .html content - .attr 'data-atwho-at-query', "" + data['atwho-at'] + @query.text - .attr 'contenteditable', "false" - if range = @_getRange() - if @query.el.length - range.setEndAfter @query.el[0] - range.collapse false - range.insertNode suffixNode = @app.document.createTextNode "" + suffix - @_setRange 'after', suffixNode, range - @$inputor.focus() unless @$inputor.is ':focus' - @$inputor.change() diff --git a/apps/comments/js/vendor/At.js/src/jquery.atwho.css b/apps/comments/js/vendor/At.js/src/jquery.atwho.css deleted file mode 100644 index dad94ed9641..00000000000 --- a/apps/comments/js/vendor/At.js/src/jquery.atwho.css +++ /dev/null @@ -1,72 +0,0 @@ -.atwho-view { - position:absolute; - top: 0; - left: 0; - display: none; - margin-top: 18px; - background: white; - color: black; - border: 1px solid #DDD; - border-radius: 3px; - box-shadow: 0 0 5px rgba(0,0,0,0.1); - min-width: 120px; - z-index: 11110 !important; -} - -.atwho-view .atwho-header { - padding: 5px; - margin: 5px; - cursor: pointer; - border-bottom: solid 1px #eaeff1; - color: #6f8092; - font-size: 11px; - font-weight: bold; -} - -.atwho-view .atwho-header .small { - color: #6f8092; - float: right; - padding-top: 2px; - margin-right: -5px; - font-size: 12px; - font-weight: normal; -} - -.atwho-view .atwho-header:hover { - cursor: default; -} - -.atwho-view .cur { - background: #3366FF; - color: white; -} -.atwho-view .cur small { - color: white; -} -.atwho-view strong { - color: #3366FF; -} -.atwho-view .cur strong { - color: white; - font:bold; -} -.atwho-view ul { - /* width: 100px; */ - list-style:none; - padding:0; - margin:auto; - max-height: 200px; - overflow-y: auto; -} -.atwho-view ul li { - display: block; - padding: 5px 10px; - border-bottom: 1px solid #DDD; - cursor: pointer; - /* border-top: 1px solid #C8C8C8; */ -} -.atwho-view small { - font-size: smaller; - color: #777; - font-weight: normal; -} diff --git a/apps/comments/js/vendor/At.js/src/model.coffee b/apps/comments/js/vendor/At.js/src/model.coffee deleted file mode 100644 index 7d09fa7943f..00000000000 --- a/apps/comments/js/vendor/At.js/src/model.coffee +++ /dev/null @@ -1,59 +0,0 @@ -# Class to process data -class Model - - constructor: (@context) -> - @at = @context.at - # NOTE: bind data storage to inputor maybe App class can handle it. - @storage = @context.$inputor - - destroy: -> - @storage.data(@at, null) - - saved: -> - this.fetch() > 0 - - # fetch data from storage by query. - # will invoke `callback` to return data - # - # @param query [String] catched string for searching - # @param callback [Function] for receiving data - query: (query, callback) -> - data = this.fetch() - searchKey = @context.getOpt("searchKey") - data = @context.callbacks('filter').call(@context, query, data, searchKey) || [] - _remoteFilter = @context.callbacks('remoteFilter') - if data.length > 0 or (!_remoteFilter and data.length == 0) - callback data - else - _remoteFilter.call(@context, query, callback) - - # get or set current data which would be shown on the list view. - # - # @param data [Array] set data - # @return [Array|undefined] current data that are showing on the list view. - fetch: -> - @storage.data(@at) || [] - - # save special flag's data to storage - # - # @param data [Array] data to save - save: (data) -> - @storage.data @at, @context.callbacks("beforeSave").call(@context, data || []) - - # load data. It wouldn't load for a second time if it has been loaded. - # - # @param data [Array] data to load - load: (data) -> - this._load(data) unless this.saved() or not data - - reload: (data) -> - this._load(data) - - # load data from local or remote with callback - # - # @param data [Array|String] data to load. - _load: (data) -> - if typeof data is "string" - $.ajax(data, dataType: "json").done (data) => this.save(data) - else - this.save data diff --git a/apps/comments/js/vendor/At.js/src/textareaController.coffee b/apps/comments/js/vendor/At.js/src/textareaController.coffee deleted file mode 100644 index 95f94bf8dcc..00000000000 --- a/apps/comments/js/vendor/At.js/src/textareaController.coffee +++ /dev/null @@ -1,51 +0,0 @@ -class TextareaController extends Controller - # Catch query string behind the at char - # - # @return [Hash] Info of the query. Look likes this: {'text': "hello", 'headPos': 0, 'endPos': 0} - catchQuery: -> - content = @$inputor.val() - caretPos = @$inputor.caret('pos', {iframe: @app.iframe}) - subtext = content.slice(0, caretPos) - query = this.callbacks("matcher").call(this, @at, subtext, this.getOpt('startWithSpace'), @getOpt("acceptSpaceBar")) - isString = typeof query is 'string' - - return if isString and query.length < this.getOpt('minLen', 0) - - if isString and query.length <= this.getOpt('maxLen', 20) - start = caretPos - query.length - end = start + query.length - @pos = start - query = {'text': query, 'headPos': start, 'endPos': end} - this.trigger "matched", [@at, query.text] - else - query = null - @view.hide() - - @query = query - - # Get offset of current at char(`flag`) - # - # @return [Hash] the offset which look likes this: {top: y, left: x, bottom: bottom} - rect: -> - return if not c = @$inputor.caret('offset', @pos - 1, {iframe: @app.iframe}) - if @app.iframe and not @app.iframeAsRoot - iframeOffset = $(@app.iframe).offset() - c.left += iframeOffset.left - c.top += iframeOffset.top - scaleBottom = if @app.document.selection then 0 else 2 - {left: c.left, top: c.top, bottom: c.top + c.height + scaleBottom} - - # Insert value of `data-value` attribute of chosen item into inputor - # - # @param content [String] string to insert - insert: (content, $li) -> - $inputor = @$inputor - source = $inputor.val() - startStr = source.slice 0, Math.max(@query.headPos - @at.length, 0) - suffix = if (suffix = @getOpt 'suffix') == "" then suffix else suffix or " " - content += suffix - text = "#{startStr}#{content}#{source.slice @query['endPos'] || 0}" - $inputor.val text - $inputor.caret('pos', startStr.length + content.length, {iframe: @app.iframe}) - $inputor.focus() unless $inputor.is ':focus' - $inputor.change() diff --git a/apps/comments/js/vendor/At.js/src/view.coffee b/apps/comments/js/vendor/At.js/src/view.coffee deleted file mode 100644 index 08785d73736..00000000000 --- a/apps/comments/js/vendor/At.js/src/view.coffee +++ /dev/null @@ -1,136 +0,0 @@ -# View class to control how At.js's view showing. -# All classes share the same DOM view. -class View - - # @param controller [Object] The Controller. - constructor: (@context) -> - @$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>") - @$elUl = @$el.children(); - @timeoutID = null - # create HTML DOM of list view if it does not exist - @context.$el.append(@$el) - this.bindEvent() - - init: -> - id = @context.getOpt("alias") || @context.at.charCodeAt(0) - header_tpl = this.context.getOpt("headerTpl") - if (header_tpl && this.$el.children().length == 1) - this.$el.prepend(header_tpl) - @$el.attr('id': "at-view-#{id}") - - destroy: -> - @$el.remove() - - bindEvent: -> - $menu = @$el.find('ul') - lastCoordX = 0 - lastCoordY = 0 - $menu.on 'mousemove.atwho-view','li', (e) => - # If the mouse hasn't actually moved then exit. - return if lastCoordX == e.clientX and lastCoordY == e.clientY - lastCoordX = e.clientX - lastCoordY = e.clientY - $cur = $(e.currentTarget) - return if $cur.hasClass('cur') - $menu.find('.cur').removeClass 'cur' - $cur.addClass 'cur' - .on 'click.atwho-view', 'li', (e) => - $menu.find('.cur').removeClass 'cur' - $(e.currentTarget).addClass 'cur' - this.choose(e) - e.preventDefault() - - # Check if view is visible - # - # @return [Boolean] - visible: -> - $.expr.filters.visible(@$el[0]) - - highlighted: -> - @$el.find(".cur").length > 0 - - choose: (e) -> - if ($li = @$el.find ".cur").length - content = @context.insertContentFor $li - - @context._stopDelayedCall() - @context.insert @context.callbacks("beforeInsert").call(@context, content, $li, e), $li - @context.trigger "inserted", [$li, e] - this.hide(e) - @stopShowing = yes if @context.getOpt("hideWithoutSuffix") - - reposition: (rect) -> - _window = if @context.app.iframeAsRoot then @context.app.window else window - if rect.bottom + @$el.height() - $(_window).scrollTop() > $(_window).height() - rect.bottom = rect.top - @$el.height() - if rect.left > overflowOffset = $(_window).width() - @$el.width() - 5 - rect.left = overflowOffset - offset = {left:rect.left, top:rect.bottom} - @context.callbacks("beforeReposition")?.call(@context, offset) - @$el.offset offset - @context.trigger "reposition", [offset] - - next: -> - cur = @$el.find('.cur').removeClass('cur') - next = cur.next() - next = @$el.find('li:first') if not next.length - next.addClass 'cur' - nextEl = next[0] - offset = nextEl.offsetTop + nextEl.offsetHeight + (if nextEl.nextSibling then nextEl.nextSibling.offsetHeight else 0) - @scrollTop Math.max(0, offset - this.$el.height()) - - prev: -> - cur = @$el.find('.cur').removeClass('cur') - prev = cur.prev() - prev = @$el.find('li:last') if not prev.length - prev.addClass 'cur' - prevEl = prev[0] - offset = prevEl.offsetTop + prevEl.offsetHeight + (if prevEl.nextSibling then prevEl.nextSibling.offsetHeight else 0) - @scrollTop Math.max(0, offset - this.$el.height()) - - scrollTop: (scrollTop) -> - scrollDuration = @context.getOpt('scrollDuration') - if scrollDuration - @$elUl.animate {scrollTop: scrollTop}, scrollDuration - else - @$elUl.scrollTop(scrollTop) - - show: -> - if @stopShowing - @stopShowing = false - return - if not this.visible() - @$el.show() - @$el.scrollTop 0 - @context.trigger 'shown' - this.reposition(rect) if rect = @context.rect() - - hide: (e, time) -> - return if not this.visible() - if isNaN(time) - @$el.hide() - @context.trigger 'hidden', [e] - else - callback = => this.hide() - clearTimeout @timeoutID - @timeoutID = setTimeout callback, time - - # render list view - render: (list) -> - if not ($.isArray(list) and list.length > 0) - this.hide() - return - - @$el.find('ul').empty() - $ul = @$el.find('ul') - tpl = @context.getOpt('displayTpl') - - for item in list - item = $.extend {}, item, {'atwho-at': @context.at} - li = @context.callbacks("tplEval").call(@context, tpl, item, "onDisplay") - $li = $ @context.callbacks("highlighter").call(@context, li, @context.query.text) - $li.data("item-data", item) - $ul.append $li - - this.show() - $ul.find("li:first").addClass "cur" if @context.getOpt('highlightFirst') diff --git a/apps/comments/js/vendor/At.js/umd.template.js b/apps/comments/js/vendor/At.js/umd.template.js deleted file mode 100644 index 9df3d0b5d65..00000000000 --- a/apps/comments/js/vendor/At.js/umd.template.js +++ /dev/null @@ -1,17 +0,0 @@ -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module unless amdModuleId is set - define(["jquery"], function (a0) { - return (factory(a0)); - }); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(require("jquery")); - } else { - factory(jQuery); - } -}(this, function ($) { -<%= contents %> -})); |