Browse Source
add At.js and dependencies
add At.js and dependencies
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>pull/6982/head
No known key found for this signature in database
GPG Key ID: 7424F1874854DF23
168 changed files with 35823 additions and 1 deletions
-
3apps/comments/.bowerrc
-
1apps/comments/appinfo/app.php
-
1apps/comments/css/vendor/At.js/jquery.atwho.min.css
-
4apps/comments/js/merged.json
-
43apps/comments/js/vendor/At.js/.bower.json
-
314apps/comments/js/vendor/At.js/CHANGELOG.md
-
37apps/comments/js/vendor/At.js/CONTRIBUTING.md
-
22apps/comments/js/vendor/At.js/LICENSE-MIT
-
67apps/comments/js/vendor/At.js/README.md
-
32apps/comments/js/vendor/At.js/bower.json
-
32apps/comments/js/vendor/At.js/component.json
-
72apps/comments/js/vendor/At.js/dist/css/jquery.atwho.css
-
1apps/comments/js/vendor/At.js/dist/css/jquery.atwho.min.css
-
1212apps/comments/js/vendor/At.js/dist/js/jquery.atwho.js
-
1apps/comments/js/vendor/At.js/dist/js/jquery.atwho.min.js
-
30apps/comments/js/vendor/At.js/examples/cross_document/dataFrame.html
-
90apps/comments/js/vendor/At.js/examples/cross_document/index.html
-
10apps/comments/js/vendor/At.js/examples/cross_document/viewFrame.html
-
61apps/comments/js/vendor/At.js/examples/hashtags.html
-
44apps/comments/js/vendor/At.js/examples/medium-editor.html
-
57apps/comments/js/vendor/At.js/examples/style.css
-
53apps/comments/js/vendor/At.js/examples/tinyMCE.html
-
45apps/comments/js/vendor/At.js/examples/ueditor.html
-
103apps/comments/js/vendor/At.js/gulpfile.js
-
205apps/comments/js/vendor/At.js/index.html
-
54apps/comments/js/vendor/At.js/package.json
-
31apps/comments/js/vendor/At.js/specRunner.html
-
59apps/comments/js/vendor/At.js/src/api.coffee
-
158apps/comments/js/vendor/At.js/src/app.coffee
-
142apps/comments/js/vendor/At.js/src/controller.coffee
-
147apps/comments/js/vendor/At.js/src/default.coffee
-
174apps/comments/js/vendor/At.js/src/editableController.coffee
-
72apps/comments/js/vendor/At.js/src/jquery.atwho.css
-
59apps/comments/js/vendor/At.js/src/model.coffee
-
51apps/comments/js/vendor/At.js/src/textareaController.coffee
-
136apps/comments/js/vendor/At.js/src/view.coffee
-
17apps/comments/js/vendor/At.js/umd.template.js
-
30apps/comments/js/vendor/Caret.js/.bower.json
-
52apps/comments/js/vendor/Caret.js/CHANGELOG.md
-
79apps/comments/js/vendor/Caret.js/Gruntfile.coffee
-
22apps/comments/js/vendor/Caret.js/LICENSE-MIT
-
54apps/comments/js/vendor/Caret.js/README.md
-
20apps/comments/js/vendor/Caret.js/bower.json
-
20apps/comments/js/vendor/Caret.js/component.json
-
405apps/comments/js/vendor/Caret.js/dist/jquery.caret.js
-
2apps/comments/js/vendor/Caret.js/dist/jquery.caret.min.js
-
29apps/comments/js/vendor/Caret.js/package.json
-
311apps/comments/js/vendor/Caret.js/src/jquery.caret.coffee
-
406apps/comments/js/vendor/Caret.js/src/jquery.caret.js
-
25apps/comments/js/vendor/jquery/.bower.json
-
301apps/comments/js/vendor/jquery/AUTHORS.txt
-
36apps/comments/js/vendor/jquery/LICENSE.txt
-
67apps/comments/js/vendor/jquery/README.md
-
14apps/comments/js/vendor/jquery/bower.json
-
476apps/comments/js/vendor/jquery/dist/core.js
-
10253apps/comments/js/vendor/jquery/dist/jquery.js
-
4apps/comments/js/vendor/jquery/dist/jquery.min.js
-
1apps/comments/js/vendor/jquery/dist/jquery.min.map
-
8160apps/comments/js/vendor/jquery/dist/jquery.slim.js
-
4apps/comments/js/vendor/jquery/dist/jquery.slim.min.js
-
1apps/comments/js/vendor/jquery/dist/jquery.slim.min.map
-
36apps/comments/js/vendor/jquery/external/sizzle/LICENSE.txt
-
2272apps/comments/js/vendor/jquery/external/sizzle/dist/sizzle.js
-
3apps/comments/js/vendor/jquery/external/sizzle/dist/sizzle.min.js
-
1apps/comments/js/vendor/jquery/external/sizzle/dist/sizzle.min.map
-
5apps/comments/js/vendor/jquery/src/.eslintrc.json
-
855apps/comments/js/vendor/jquery/src/ajax.js
-
102apps/comments/js/vendor/jquery/src/ajax/jsonp.js
-
76apps/comments/js/vendor/jquery/src/ajax/load.js
-
30apps/comments/js/vendor/jquery/src/ajax/parseXML.js
-
77apps/comments/js/vendor/jquery/src/ajax/script.js
-
5apps/comments/js/vendor/jquery/src/ajax/var/location.js
-
7apps/comments/js/vendor/jquery/src/ajax/var/nonce.js
-
5apps/comments/js/vendor/jquery/src/ajax/var/rquery.js
-
169apps/comments/js/vendor/jquery/src/ajax/xhr.js
-
13apps/comments/js/vendor/jquery/src/attributes.js
-
141apps/comments/js/vendor/jquery/src/attributes/attr.js
-
174apps/comments/js/vendor/jquery/src/attributes/classes.js
-
143apps/comments/js/vendor/jquery/src/attributes/prop.js
-
33apps/comments/js/vendor/jquery/src/attributes/support.js
-
190apps/comments/js/vendor/jquery/src/attributes/val.js
-
234apps/comments/js/vendor/jquery/src/callbacks.js
-
476apps/comments/js/vendor/jquery/src/core.js
-
16apps/comments/js/vendor/jquery/src/core/DOMEval.js
-
70apps/comments/js/vendor/jquery/src/core/access.js
-
128apps/comments/js/vendor/jquery/src/core/init.js
-
13apps/comments/js/vendor/jquery/src/core/nodeName.js
-
65apps/comments/js/vendor/jquery/src/core/parseHTML.js
-
96apps/comments/js/vendor/jquery/src/core/ready-no-deferred.js
-
86apps/comments/js/vendor/jquery/src/core/ready.js
-
13apps/comments/js/vendor/jquery/src/core/readyException.js
-
14apps/comments/js/vendor/jquery/src/core/stripAndCollapse.js
-
20apps/comments/js/vendor/jquery/src/core/support.js
-
6apps/comments/js/vendor/jquery/src/core/var/rsingleTag.js
-
438apps/comments/js/vendor/jquery/src/css.js
-
26apps/comments/js/vendor/jquery/src/css/addGetHookIf.js
-
71apps/comments/js/vendor/jquery/src/css/adjustCSS.js
-
65apps/comments/js/vendor/jquery/src/css/curCSS.js
-
15apps/comments/js/vendor/jquery/src/css/hiddenVisibleSelectors.js
-
105apps/comments/js/vendor/jquery/src/css/showHide.js
@ -0,0 +1,3 @@ |
|||
{ |
|||
"directory": "js/vendor" |
|||
} |
|||
@ -0,0 +1 @@ |
|||
.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} |
|||
@ -0,0 +1,43 @@ |
|||
{ |
|||
"name": "At.js", |
|||
"version": "1.5.4", |
|||
"main": [ |
|||
"dist/js/jquery.atwho.js", |
|||
"dist/css/jquery.atwho.css" |
|||
], |
|||
"ignore": [ |
|||
"**/.*", |
|||
"node_modules", |
|||
"components", |
|||
"libs", |
|||
"spec" |
|||
], |
|||
"dependencies": { |
|||
"jquery": ">=1.7.0", |
|||
"Caret.js": "~0.2.2" |
|||
}, |
|||
"devDependencies": { |
|||
"jasmine-jquery": "~2.0.2" |
|||
}, |
|||
"keywords": [ |
|||
"mention", |
|||
"mentions", |
|||
"autocomplete", |
|||
"autocompletion", |
|||
"autosuggest", |
|||
"autosuggestion", |
|||
"atjs", |
|||
"at.js" |
|||
], |
|||
"homepage": "https://github.com/ichord/At.js", |
|||
"_release": "1.5.4", |
|||
"_resolution": { |
|||
"type": "version", |
|||
"tag": "v1.5.4", |
|||
"commit": "801c87dc804e37f134def2055b80cbc81ac98652" |
|||
}, |
|||
"_source": "https://github.com/ichord/At.js.git", |
|||
"_target": "^1.5.4", |
|||
"_originalSource": "jquery.atwho", |
|||
"_direct": true |
|||
} |
|||
@ -0,0 +1,314 @@ |
|||
### 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. |
|||
@ -0,0 +1,37 @@ |
|||
## 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. |
|||
@ -0,0 +1,22 @@ |
|||
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. |
|||
@ -0,0 +1,67 @@ |
|||
**An autocompletion library to autocomplete mentions, smileys etc. just like on Github!** |
|||
[](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) |
|||
|
|||
@ -0,0 +1,32 @@ |
|||
{ |
|||
"name": "At.js", |
|||
"version": "1.5.4", |
|||
"main": [ |
|||
"dist/js/jquery.atwho.js", |
|||
"dist/css/jquery.atwho.css" |
|||
], |
|||
"ignore": [ |
|||
"**/.*", |
|||
"node_modules", |
|||
"components", |
|||
"libs", |
|||
"spec" |
|||
], |
|||
"dependencies": { |
|||
"jquery": ">=1.7.0", |
|||
"Caret.js": "~0.2.2" |
|||
}, |
|||
"devDependencies": { |
|||
"jasmine-jquery": "~2.0.2" |
|||
}, |
|||
"keywords": [ |
|||
"mention", |
|||
"mentions", |
|||
"autocomplete", |
|||
"autocompletion", |
|||
"autosuggest", |
|||
"autosuggestion", |
|||
"atjs", |
|||
"at.js" |
|||
] |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
{ |
|||
"name": "At.js", |
|||
"repo": "ichord/At.js", |
|||
"description": "Add Github like mentions autocomplete to your application.", |
|||
"version": "1.5.4", |
|||
"demo": "http://ichord.github.com/At.js", |
|||
"dependencies": { |
|||
"ichord/Caret.js": "~0.2.2", |
|||
"component/jquery": ">= 1.7.0" |
|||
}, |
|||
"main": [ |
|||
"dist/js/jquery.atwho.js" |
|||
], |
|||
"scripts": [ |
|||
"dist/js/jquery.atwho.js" |
|||
], |
|||
"styles": [ |
|||
"dist/css/jquery.atwho.css" |
|||
], |
|||
"license": "MIT", |
|||
"keywords": [ |
|||
"mentions", |
|||
"ui", |
|||
"mentions", |
|||
"autocomplete", |
|||
"autocompletion", |
|||
"autosuggest", |
|||
"autosuggestion", |
|||
"atjs", |
|||
"at.js" |
|||
] |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
.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; |
|||
} |
|||
@ -0,0 +1 @@ |
|||
.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} |
|||
1212
apps/comments/js/vendor/At.js/dist/js/jquery.atwho.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1
apps/comments/js/vendor/At.js/dist/js/jquery.atwho.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,30 @@ |
|||
<!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> |
|||
@ -0,0 +1,90 @@ |
|||
<!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> |
|||
@ -0,0 +1,10 @@ |
|||
<!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> |
|||
@ -0,0 +1,61 @@ |
|||
<!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> |
|||
@ -0,0 +1,44 @@ |
|||
<!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> |
|||
@ -0,0 +1,57 @@ |
|||
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; |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
<!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> |
|||
@ -0,0 +1,45 @@ |
|||
<!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> |
|||
@ -0,0 +1,103 @@ |
|||
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']); |
|||
@ -0,0 +1,205 @@ |
|||
<!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> |
|||
@ -0,0 +1,54 @@ |
|||
{ |
|||
"name": "at.js", |
|||
"main": "dist/js/jquery.atwho.js", |
|||
"author": { |
|||
"name": "chord.luo", |
|||
"email": "chord.luo@gmail.com" |
|||
}, |
|||
"homepage": "http://ichord.github.com/At.js", |
|||
"license": "MIT", |
|||
"version": "1.5.4", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "https://github.com/ichord/At.js" |
|||
}, |
|||
"engines": { |
|||
"node": ">= 0.6.0" |
|||
}, |
|||
"scripts": { |
|||
"test": "gulp test" |
|||
}, |
|||
"peerDependencies": { |
|||
"jquery": ">=1.7.0 <4.0.0" |
|||
}, |
|||
"devDependencies": { |
|||
"gulp": "^3.9.0", |
|||
"gulp-bump": "^1.0.0", |
|||
"gulp-coffee": "^2.3.1", |
|||
"gulp-concat": "^2.6.0", |
|||
"gulp-cssmin": "^0.1.7", |
|||
"gulp-debug": "^2.1.2", |
|||
"gulp-header": "^1.7.1", |
|||
"gulp-jasmine": "^2.2.1", |
|||
"gulp-jasmine-phantom": "^2.0.1", |
|||
"gulp-rename": "^1.2.2", |
|||
"gulp-uglify": "^1.5.1", |
|||
"gulp-umd": "^0.2.0", |
|||
"gulp-util": "^3.0.7", |
|||
"jasmine-ajax": "^3.2.0", |
|||
"jasmine-jquery": "^2.1.1", |
|||
"phantomjs": "^1.9.19" |
|||
}, |
|||
"spm": { |
|||
"main": "dist/js/jquery.atwho.js", |
|||
"dependencies": { |
|||
"jquery": ">=1.7.2", |
|||
"caret.js": "~0.2.2" |
|||
}, |
|||
"ignore": [ |
|||
"examples", |
|||
"spec", |
|||
"src" |
|||
] |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
<!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> |
|||
@ -0,0 +1,59 @@ |
|||
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 |
|||
@ -0,0 +1,158 @@ |
|||
# 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 |
|||
@ -0,0 +1,142 @@ |
|||
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) |
|||
@ -0,0 +1,147 @@ |
|||
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) -> |
|||
@ -0,0 +1,174 @@ |
|||
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() |
|||
@ -0,0 +1,72 @@ |
|||
.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; |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
# 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 |
|||
@ -0,0 +1,51 @@ |
|||
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() |
|||
@ -0,0 +1,136 @@ |
|||
# 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') |
|||
@ -0,0 +1,17 @@ |
|||
(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 %> |
|||
})); |
|||
@ -0,0 +1,30 @@ |
|||
{ |
|||
"name": "Caret.js", |
|||
"version": "0.2.2", |
|||
"main": "src/jquery.caret.js", |
|||
"ignore": [ |
|||
"**/.*", |
|||
"node_modules", |
|||
"bower_components", |
|||
"test", |
|||
"tests", |
|||
"spec", |
|||
"index.html" |
|||
], |
|||
"dependencies": { |
|||
"jquery": ">=1.7.0" |
|||
}, |
|||
"devDependencies": { |
|||
"jasmine-jquery": "~1.5.8" |
|||
}, |
|||
"homepage": "https://github.com/ichord/Caret.js", |
|||
"_release": "0.2.2", |
|||
"_resolution": { |
|||
"type": "version", |
|||
"tag": "v0.2.2", |
|||
"commit": "b435c7049f1bce1c4db10526d956e24e8b484a52" |
|||
}, |
|||
"_source": "https://github.com/ichord/Caret.js.git", |
|||
"_target": "~0.2.2", |
|||
"_originalSource": "Caret.js" |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
### v0.2.1 |
|||
|
|||
* f66a1eb - can get offset at the benginning of a line |
|||
* 4885ddd - fix wrong position of textarea |
|||
|
|||
### v0.2.0 |
|||
|
|||
* 12119d2 - calculating in iframe's coordinate |
|||
* 959436d - implement `position` api for contentEditable |
|||
* d051ffc - fix html escaping while mirroring caret |
|||
|
|||
### v0.1.0 |
|||
|
|||
* b1f8f53 - fix Mirror div does not reset its CSS |
|||
* e88e40e - fix Bad positioning in long words |
|||
* 37d4c5e - disable auto decovery iframe |
|||
|
|||
### v0.0.7 |
|||
|
|||
* cf94271 - Added suport for .caret(pos, 0) - Nicolas Donna |
|||
* 2de2b0f - Fixed error when checking the pos arg when setting the position - Nicolas Donna |
|||
* 34ac7fa - catch error thrown in cross-domain iframe - jiyinyiyong |
|||
|
|||
* 01f1fa1 - add minified file in dist. |
|||
|
|||
### v0.0.6 |
|||
|
|||
* 287b5d8 working in iframe |
|||
|
|||
### v0.0.5 |
|||
|
|||
* aef0aa4 fix IE input position error |
|||
* 4a4f7f7 fix contenteditable null value bug |
|||
|
|||
### v0.0.4 |
|||
|
|||
* fix scrolling problem |
|||
|
|||
### v0.0.2 |
|||
|
|||
* support `contentEditable` mode |
|||
* fix ie bugs, and support IE > 6 to all mode |
|||
|
|||
### 2013-08-07 |
|||
|
|||
* fix bug: error position at beginning of textarea |
|||
* Bower |
|||
* jasmine test |
|||
|
|||
### 2013-03-31 |
|||
|
|||
* support IE browsers. |
|||
@ -0,0 +1,79 @@ |
|||
module.exports = (grunt) -> |
|||
grunt.initConfig |
|||
pkg: grunt.file.readJSON 'package.json' |
|||
bower_path: 'bower_components' |
|||
|
|||
jasmine: |
|||
src: 'src/*.js' |
|||
options: |
|||
vendor: [ |
|||
'<%= bower_path %>/jquery/dist/jquery.min.js', |
|||
'<%= bower_path %>/jasmine-jquery/lib/jasmine-jquery.js' |
|||
] |
|||
specs: 'spec/javascripts/*.js' |
|||
# keepRunner: true |
|||
|
|||
uglify: |
|||
options: |
|||
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' |
|||
build: |
|||
files: |
|||
'dist/<%= pkg.name %>.min.js': ['src/<%= pkg.name %>.js'] |
|||
|
|||
coffee: |
|||
withMaps: |
|||
options: |
|||
bare: true |
|||
sourceMap: true |
|||
files: |
|||
'src/<%= pkg.name %>.js': 'src/<%= pkg.name %>.coffee' |
|||
withoutMaps: |
|||
options: |
|||
bare: true |
|||
sourceMap: false |
|||
files: |
|||
'dist/<%= pkg.name %>.js': 'src/<%= pkg.name %>.coffee' |
|||
|
|||
watch: |
|||
scripts: |
|||
files: ['src/*.coffee'] |
|||
tasks: ['coffee', 'umd'] |
|||
|
|||
umd: |
|||
options: |
|||
template: 'umd' |
|||
deps: |
|||
'default': ['$'] |
|||
amd: ['jquery'] |
|||
cjs: ['jquery'] |
|||
global: |
|||
items: ['jQuery'] |
|||
prefix: '' |
|||
src: |
|||
src: 'src/<%= pkg.name %>.js' |
|||
dist: |
|||
src: 'dist/<%= pkg.name %>.js' |
|||
|
|||
|
|||
'json-replace': |
|||
options: |
|||
space: " ", |
|||
replace: |
|||
version: "<%= pkg.version %>" |
|||
'update-version': |
|||
files:[{ |
|||
'bower.json': 'bower.json', |
|||
'component.json': 'component.json' |
|||
}] |
|||
|
|||
grunt.loadNpmTasks 'grunt-contrib-coffee' |
|||
grunt.loadNpmTasks 'grunt-contrib-uglify' |
|||
grunt.loadNpmTasks 'grunt-contrib-jasmine' |
|||
grunt.loadNpmTasks 'grunt-json-replace' |
|||
grunt.loadNpmTasks 'grunt-contrib-watch' |
|||
grunt.loadNpmTasks 'grunt-umd' |
|||
|
|||
grunt.registerTask 'update-version', 'json-replace' |
|||
|
|||
grunt.registerTask 'default', ['coffee', 'umd', 'jasmine','update-version', 'uglify', 'watch'] |
|||
grunt.registerTask 'test', ['coffee', 'umd', 'jasmine'] |
|||
@ -0,0 +1,22 @@ |
|||
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. |
|||
@ -0,0 +1,54 @@ |
|||
Caret.js |
|||
======== |
|||
|
|||
Get caret postion or offset from inputor |
|||
|
|||
This is the core function that working in [At.js](http://ichord.github.com/At.js). |
|||
Now, It just become an simple jquery plugin so that everybody can use it. |
|||
And, of course, **At.js** is using this plugin too. |
|||
|
|||
* support iframe context |
|||
|
|||
Live Demo |
|||
========= |
|||
|
|||
http://ichord.github.com/Caret.js/ |
|||
|
|||
|
|||
Usage |
|||
===== |
|||
|
|||
```javascript |
|||
|
|||
// Get caret position |
|||
$('#inputor').caret('position'); // => {left: 15, top: 30, height: 20} |
|||
|
|||
// Get caret offset |
|||
$('#inputor').caret('offset'); // => {left: 300, top: 400, height: 20} |
|||
|
|||
var fixPos = 20 |
|||
// Get position of the 20th char in the inputor. |
|||
// not working in `contentEditable` mode |
|||
$('#inputor').caret('position', fixPos); |
|||
|
|||
// Get offset of the 20th char. |
|||
// not working in `contentEditable` mode |
|||
$('#inputor').caret('offset', fixPos); |
|||
|
|||
// more |
|||
|
|||
// Get caret position from the first char in the inputor. |
|||
$('#inputor').caret('pos'); // => 15 |
|||
|
|||
// Set caret position in the inputor |
|||
// not working in contentEditable mode |
|||
$('#inputor').caret('pos', 15); |
|||
|
|||
// set iframe context |
|||
// NOTE: Related to the iframe's cooridinate. |
|||
// You might want to get the iframe's offset/position on your own |
|||
$('#inputor').caret('offset', {iframe: theIframe}); |
|||
$('#inputor').caret('position', {iframe: theIframe}); |
|||
$('#inputor').caret('pos', 15, {iframe: theIframe}); |
|||
|
|||
``` |
|||
@ -0,0 +1,20 @@ |
|||
{ |
|||
"name": "Caret.js", |
|||
"version": "0.2.2", |
|||
"main": "src/jquery.caret.js", |
|||
"ignore": [ |
|||
"**/.*", |
|||
"node_modules", |
|||
"bower_components", |
|||
"test", |
|||
"tests", |
|||
"spec", |
|||
"index.html" |
|||
], |
|||
"dependencies": { |
|||
"jquery": ">=1.7.0" |
|||
}, |
|||
"devDependencies": { |
|||
"jasmine-jquery": "~1.5.8" |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
{ |
|||
"name": "Caret.js", |
|||
"repo": "ichord/Caret.js", |
|||
"description": "Add Github like mentions autocomplete to your application.", |
|||
"version": "0.2.2", |
|||
"keywords": [ |
|||
"At.js", |
|||
"caret", |
|||
"ui" |
|||
], |
|||
"dependencies": { |
|||
"component/jquery": "*" |
|||
}, |
|||
"demo": "http://ichord.github.com/Caret.js", |
|||
"main": "src/jquery.caret.js", |
|||
"scripts": [ |
|||
"src/jquery.caret.js" |
|||
], |
|||
"license": "MIT" |
|||
} |
|||
@ -0,0 +1,405 @@ |
|||
(function (root, factory) { |
|||
if (typeof define === 'function' && define.amd) { |
|||
// AMD. Register as an anonymous module.
|
|||
define(["jquery"], function ($) { |
|||
return (root.returnExportsGlobal = factory($)); |
|||
}); |
|||
} else if (typeof exports === 'object') { |
|||
// Node. Does not work with strict CommonJS, but
|
|||
// only CommonJS-like enviroments that support module.exports,
|
|||
// like Node.
|
|||
module.exports = factory(require("jquery")); |
|||
} else { |
|||
factory(jQuery); |
|||
} |
|||
}(this, function ($) { |
|||
|
|||
/* |
|||
Implement Github like autocomplete mentions |
|||
http://ichord.github.com/At.js
|
|||
|
|||
Copyright (c) 2013 chord.luo@gmail.com |
|||
Licensed under the MIT license. |
|||
*/ |
|||
|
|||
/* |
|||
本插件操作 textarea 或者 input 内的插入符 |
|||
只实现了获得插入符在文本框中的位置,我设置 |
|||
插入符的位置. |
|||
*/ |
|||
|
|||
"use strict"; |
|||
var EditableCaret, InputCaret, Mirror, Utils, discoveryIframeOf, methods, oDocument, oFrame, oWindow, pluginName, setContextBy; |
|||
|
|||
pluginName = 'caret'; |
|||
|
|||
EditableCaret = (function() { |
|||
function EditableCaret($inputor) { |
|||
this.$inputor = $inputor; |
|||
this.domInputor = this.$inputor[0]; |
|||
} |
|||
|
|||
EditableCaret.prototype.setPos = function(pos) { |
|||
return this.domInputor; |
|||
}; |
|||
|
|||
EditableCaret.prototype.getIEPosition = function() { |
|||
return this.getPosition(); |
|||
}; |
|||
|
|||
EditableCaret.prototype.getPosition = function() { |
|||
var inputor_offset, offset; |
|||
offset = this.getOffset(); |
|||
inputor_offset = this.$inputor.offset(); |
|||
offset.left -= inputor_offset.left; |
|||
offset.top -= inputor_offset.top; |
|||
return offset; |
|||
}; |
|||
|
|||
EditableCaret.prototype.getOldIEPos = function() { |
|||
var preCaretTextRange, textRange; |
|||
textRange = oDocument.selection.createRange(); |
|||
preCaretTextRange = oDocument.body.createTextRange(); |
|||
preCaretTextRange.moveToElementText(this.domInputor); |
|||
preCaretTextRange.setEndPoint("EndToEnd", textRange); |
|||
return preCaretTextRange.text.length; |
|||
}; |
|||
|
|||
EditableCaret.prototype.getPos = function() { |
|||
var clonedRange, pos, range; |
|||
if (range = this.range()) { |
|||
clonedRange = range.cloneRange(); |
|||
clonedRange.selectNodeContents(this.domInputor); |
|||
clonedRange.setEnd(range.endContainer, range.endOffset); |
|||
pos = clonedRange.toString().length; |
|||
clonedRange.detach(); |
|||
return pos; |
|||
} else if (oDocument.selection) { |
|||
return this.getOldIEPos(); |
|||
} |
|||
}; |
|||
|
|||
EditableCaret.prototype.getOldIEOffset = function() { |
|||
var range, rect; |
|||
range = oDocument.selection.createRange().duplicate(); |
|||
range.moveStart("character", -1); |
|||
rect = range.getBoundingClientRect(); |
|||
return { |
|||
height: rect.bottom - rect.top, |
|||
left: rect.left, |
|||
top: rect.top |
|||
}; |
|||
}; |
|||
|
|||
EditableCaret.prototype.getOffset = function(pos) { |
|||
var clonedRange, offset, range, rect, shadowCaret; |
|||
if (oWindow.getSelection && (range = this.range())) { |
|||
if (range.endOffset - 1 > 0 && range.endContainer === !this.domInputor) { |
|||
clonedRange = range.cloneRange(); |
|||
clonedRange.setStart(range.endContainer, range.endOffset - 1); |
|||
clonedRange.setEnd(range.endContainer, range.endOffset); |
|||
rect = clonedRange.getBoundingClientRect(); |
|||
offset = { |
|||
height: rect.height, |
|||
left: rect.left + rect.width, |
|||
top: rect.top |
|||
}; |
|||
clonedRange.detach(); |
|||
} |
|||
if (!offset || (offset != null ? offset.height : void 0) === 0) { |
|||
clonedRange = range.cloneRange(); |
|||
shadowCaret = $(oDocument.createTextNode("|")); |
|||
clonedRange.insertNode(shadowCaret[0]); |
|||
clonedRange.selectNode(shadowCaret[0]); |
|||
rect = clonedRange.getBoundingClientRect(); |
|||
offset = { |
|||
height: rect.height, |
|||
left: rect.left, |
|||
top: rect.top |
|||
}; |
|||
shadowCaret.remove(); |
|||
clonedRange.detach(); |
|||
} |
|||
} else if (oDocument.selection) { |
|||
offset = this.getOldIEOffset(); |
|||
} |
|||
if (offset) { |
|||
offset.top += $(oWindow).scrollTop(); |
|||
offset.left += $(oWindow).scrollLeft(); |
|||
} |
|||
return offset; |
|||
}; |
|||
|
|||
EditableCaret.prototype.range = function() { |
|||
var sel; |
|||
if (!oWindow.getSelection) { |
|||
return; |
|||
} |
|||
sel = oWindow.getSelection(); |
|||
if (sel.rangeCount > 0) { |
|||
return sel.getRangeAt(0); |
|||
} else { |
|||
return null; |
|||
} |
|||
}; |
|||
|
|||
return EditableCaret; |
|||
|
|||
})(); |
|||
|
|||
InputCaret = (function() { |
|||
function InputCaret($inputor) { |
|||
this.$inputor = $inputor; |
|||
this.domInputor = this.$inputor[0]; |
|||
} |
|||
|
|||
InputCaret.prototype.getIEPos = function() { |
|||
var endRange, inputor, len, normalizedValue, pos, range, textInputRange; |
|||
inputor = this.domInputor; |
|||
range = oDocument.selection.createRange(); |
|||
pos = 0; |
|||
if (range && range.parentElement() === inputor) { |
|||
normalizedValue = inputor.value.replace(/\r\n/g, "\n"); |
|||
len = normalizedValue.length; |
|||
textInputRange = inputor.createTextRange(); |
|||
textInputRange.moveToBookmark(range.getBookmark()); |
|||
endRange = inputor.createTextRange(); |
|||
endRange.collapse(false); |
|||
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { |
|||
pos = len; |
|||
} else { |
|||
pos = -textInputRange.moveStart("character", -len); |
|||
} |
|||
} |
|||
return pos; |
|||
}; |
|||
|
|||
InputCaret.prototype.getPos = function() { |
|||
if (oDocument.selection) { |
|||
return this.getIEPos(); |
|||
} else { |
|||
return this.domInputor.selectionStart; |
|||
} |
|||
}; |
|||
|
|||
InputCaret.prototype.setPos = function(pos) { |
|||
var inputor, range; |
|||
inputor = this.domInputor; |
|||
if (oDocument.selection) { |
|||
range = inputor.createTextRange(); |
|||
range.move("character", pos); |
|||
range.select(); |
|||
} else if (inputor.setSelectionRange) { |
|||
inputor.setSelectionRange(pos, pos); |
|||
} |
|||
return inputor; |
|||
}; |
|||
|
|||
InputCaret.prototype.getIEOffset = function(pos) { |
|||
var h, textRange, x, y; |
|||
textRange = this.domInputor.createTextRange(); |
|||
pos || (pos = this.getPos()); |
|||
textRange.move('character', pos); |
|||
x = textRange.boundingLeft; |
|||
y = textRange.boundingTop; |
|||
h = textRange.boundingHeight; |
|||
return { |
|||
left: x, |
|||
top: y, |
|||
height: h |
|||
}; |
|||
}; |
|||
|
|||
InputCaret.prototype.getOffset = function(pos) { |
|||
var $inputor, offset, position; |
|||
$inputor = this.$inputor; |
|||
if (oDocument.selection) { |
|||
offset = this.getIEOffset(pos); |
|||
offset.top += $(oWindow).scrollTop() + $inputor.scrollTop(); |
|||
offset.left += $(oWindow).scrollLeft() + $inputor.scrollLeft(); |
|||
return offset; |
|||
} else { |
|||
offset = $inputor.offset(); |
|||
position = this.getPosition(pos); |
|||
return offset = { |
|||
left: offset.left + position.left - $inputor.scrollLeft(), |
|||
top: offset.top + position.top - $inputor.scrollTop(), |
|||
height: position.height |
|||
}; |
|||
} |
|||
}; |
|||
|
|||
InputCaret.prototype.getPosition = function(pos) { |
|||
var $inputor, at_rect, end_range, format, html, mirror, start_range; |
|||
$inputor = this.$inputor; |
|||
format = function(value) { |
|||
value = value.replace(/<|>|`|"|&/g, '?').replace(/\r\n|\r|\n/g, "<br/>"); |
|||
if (/firefox/i.test(navigator.userAgent)) { |
|||
value = value.replace(/\s/g, ' '); |
|||
} |
|||
return value; |
|||
}; |
|||
if (pos === void 0) { |
|||
pos = this.getPos(); |
|||
} |
|||
start_range = $inputor.val().slice(0, pos); |
|||
end_range = $inputor.val().slice(pos); |
|||
html = "<span style='position: relative; display: inline;'>" + format(start_range) + "</span>"; |
|||
html += "<span id='caret' style='position: relative; display: inline;'>|</span>"; |
|||
html += "<span style='position: relative; display: inline;'>" + format(end_range) + "</span>"; |
|||
mirror = new Mirror($inputor); |
|||
return at_rect = mirror.create(html).rect(); |
|||
}; |
|||
|
|||
InputCaret.prototype.getIEPosition = function(pos) { |
|||
var h, inputorOffset, offset, x, y; |
|||
offset = this.getIEOffset(pos); |
|||
inputorOffset = this.$inputor.offset(); |
|||
x = offset.left - inputorOffset.left; |
|||
y = offset.top - inputorOffset.top; |
|||
h = offset.height; |
|||
return { |
|||
left: x, |
|||
top: y, |
|||
height: h |
|||
}; |
|||
}; |
|||
|
|||
return InputCaret; |
|||
|
|||
})(); |
|||
|
|||
Mirror = (function() { |
|||
Mirror.prototype.css_attr = ["borderBottomWidth", "borderLeftWidth", "borderRightWidth", "borderTopStyle", "borderRightStyle", "borderBottomStyle", "borderLeftStyle", "borderTopWidth", "boxSizing", "fontFamily", "fontSize", "fontWeight", "height", "letterSpacing", "lineHeight", "marginBottom", "marginLeft", "marginRight", "marginTop", "outlineWidth", "overflow", "overflowX", "overflowY", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "textAlign", "textOverflow", "textTransform", "whiteSpace", "wordBreak", "wordWrap"]; |
|||
|
|||
function Mirror($inputor) { |
|||
this.$inputor = $inputor; |
|||
} |
|||
|
|||
Mirror.prototype.mirrorCss = function() { |
|||
var css, |
|||
_this = this; |
|||
css = { |
|||
position: 'absolute', |
|||
left: -9999, |
|||
top: 0, |
|||
zIndex: -20000 |
|||
}; |
|||
if (this.$inputor.prop('tagName') === 'TEXTAREA') { |
|||
this.css_attr.push('width'); |
|||
} |
|||
$.each(this.css_attr, function(i, p) { |
|||
return css[p] = _this.$inputor.css(p); |
|||
}); |
|||
return css; |
|||
}; |
|||
|
|||
Mirror.prototype.create = function(html) { |
|||
this.$mirror = $('<div></div>'); |
|||
this.$mirror.css(this.mirrorCss()); |
|||
this.$mirror.html(html); |
|||
this.$inputor.after(this.$mirror); |
|||
return this; |
|||
}; |
|||
|
|||
Mirror.prototype.rect = function() { |
|||
var $flag, pos, rect; |
|||
$flag = this.$mirror.find("#caret"); |
|||
pos = $flag.position(); |
|||
rect = { |
|||
left: pos.left, |
|||
top: pos.top, |
|||
height: $flag.height() |
|||
}; |
|||
this.$mirror.remove(); |
|||
return rect; |
|||
}; |
|||
|
|||
return Mirror; |
|||
|
|||
})(); |
|||
|
|||
Utils = { |
|||
contentEditable: function($inputor) { |
|||
return !!($inputor[0].contentEditable && $inputor[0].contentEditable === 'true'); |
|||
} |
|||
}; |
|||
|
|||
methods = { |
|||
pos: function(pos) { |
|||
if (pos || pos === 0) { |
|||
return this.setPos(pos); |
|||
} else { |
|||
return this.getPos(); |
|||
} |
|||
}, |
|||
position: function(pos) { |
|||
if (oDocument.selection) { |
|||
return this.getIEPosition(pos); |
|||
} else { |
|||
return this.getPosition(pos); |
|||
} |
|||
}, |
|||
offset: function(pos) { |
|||
var offset; |
|||
offset = this.getOffset(pos); |
|||
return offset; |
|||
} |
|||
}; |
|||
|
|||
oDocument = null; |
|||
|
|||
oWindow = null; |
|||
|
|||
oFrame = null; |
|||
|
|||
setContextBy = function(settings) { |
|||
var iframe; |
|||
if (iframe = settings != null ? settings.iframe : void 0) { |
|||
oFrame = iframe; |
|||
oWindow = iframe.contentWindow; |
|||
return oDocument = iframe.contentDocument || oWindow.document; |
|||
} else { |
|||
oFrame = void 0; |
|||
oWindow = window; |
|||
return oDocument = document; |
|||
} |
|||
}; |
|||
|
|||
discoveryIframeOf = function($dom) { |
|||
var error; |
|||
oDocument = $dom[0].ownerDocument; |
|||
oWindow = oDocument.defaultView || oDocument.parentWindow; |
|||
try { |
|||
return oFrame = oWindow.frameElement; |
|||
} catch (_error) { |
|||
error = _error; |
|||
} |
|||
}; |
|||
|
|||
$.fn.caret = function(method, value, settings) { |
|||
var caret; |
|||
if (methods[method]) { |
|||
if ($.isPlainObject(value)) { |
|||
setContextBy(value); |
|||
value = void 0; |
|||
} else { |
|||
setContextBy(settings); |
|||
} |
|||
caret = Utils.contentEditable(this) ? new EditableCaret(this) : new InputCaret(this); |
|||
return methods[method].apply(caret, [value]); |
|||
} else { |
|||
return $.error("Method " + method + " does not exist on jQuery.caret"); |
|||
} |
|||
}; |
|||
|
|||
$.fn.caret.EditableCaret = EditableCaret; |
|||
|
|||
$.fn.caret.InputCaret = InputCaret; |
|||
|
|||
$.fn.caret.Utils = Utils; |
|||
|
|||
$.fn.caret.apis = methods; |
|||
|
|||
|
|||
})); |
|||
2
apps/comments/js/vendor/Caret.js/dist/jquery.caret.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,29 @@ |
|||
{ |
|||
"name": "jquery.caret", |
|||
"version": "0.2.2", |
|||
"description": "Get caret position and offset from inputor", |
|||
"main": "index.js", |
|||
"dependencies": { |
|||
"grunt": "~0.4.1" |
|||
}, |
|||
"devDependencies": { |
|||
"grunt-contrib-coffee": "~0.6.4", |
|||
"grunt-contrib-jasmine": "~0.5.1", |
|||
"grunt-contrib-uglify": "~0.2.0", |
|||
"grunt-contrib-watch": "^0.6.1", |
|||
"grunt-json-replace": "~0.1.2", |
|||
"grunt-umd": "^2.2.1" |
|||
}, |
|||
"scripts": { |
|||
"test": "grunt test --verbose" |
|||
}, |
|||
"repository": "", |
|||
"keywords": [ |
|||
"jquery", |
|||
"caret", |
|||
"offset", |
|||
"position" |
|||
], |
|||
"author": "Harold.luo <chord.luo@gmail.com>", |
|||
"license": "MIT" |
|||
} |
|||
@ -0,0 +1,311 @@ |
|||
### |
|||
Implement Github like autocomplete mentions |
|||
http://ichord.github.com/At.js |
|||
|
|||
Copyright (c) 2013 chord.luo@gmail.com |
|||
Licensed under the MIT license. |
|||
### |
|||
|
|||
### |
|||
本插件操作 textarea 或者 input 内的插入符 |
|||
只实现了获得插入符在文本框中的位置,我设置 |
|||
插入符的位置. |
|||
### |
|||
"use strict"; |
|||
|
|||
pluginName = 'caret' |
|||
|
|||
class EditableCaret |
|||
constructor: (@$inputor) -> |
|||
@domInputor = @$inputor[0] |
|||
|
|||
# NOTE: Duck type |
|||
setPos: (pos) -> @domInputor |
|||
getIEPosition: -> this.getPosition() |
|||
getPosition: -> |
|||
offset = this.getOffset() |
|||
inputor_offset = @$inputor.offset() |
|||
offset.left -= inputor_offset.left |
|||
offset.top -= inputor_offset.top |
|||
offset |
|||
|
|||
getOldIEPos: -> |
|||
textRange = oDocument.selection.createRange() |
|||
preCaretTextRange = oDocument.body.createTextRange() |
|||
preCaretTextRange.moveToElementText(@domInputor) |
|||
preCaretTextRange.setEndPoint("EndToEnd", textRange) |
|||
preCaretTextRange.text.length |
|||
|
|||
getPos: -> |
|||
if range = this.range() # Major Browser and IE > 10 |
|||
clonedRange = range.cloneRange() |
|||
clonedRange.selectNodeContents(@domInputor) |
|||
clonedRange.setEnd(range.endContainer, range.endOffset) |
|||
pos = clonedRange.toString().length |
|||
clonedRange.detach() |
|||
pos |
|||
else if oDocument.selection #IE < 9 |
|||
this.getOldIEPos() |
|||
|
|||
getOldIEOffset: -> |
|||
range = oDocument.selection.createRange().duplicate() |
|||
range.moveStart "character", -1 |
|||
rect = range.getBoundingClientRect() |
|||
{ height: rect.bottom - rect.top, left: rect.left, top: rect.top } |
|||
|
|||
getOffset: (pos) -> |
|||
if oWindow.getSelection and range = this.range() |
|||
# endContainer would be the inputor in Firefox at the begnning of a line |
|||
if range.endOffset - 1 > 0 and range.endContainer is not @domInputor |
|||
clonedRange = range.cloneRange() |
|||
clonedRange.setStart(range.endContainer, range.endOffset - 1) |
|||
clonedRange.setEnd(range.endContainer, range.endOffset) |
|||
rect = clonedRange.getBoundingClientRect() |
|||
offset = { height: rect.height, left: rect.left + rect.width, top: rect.top } |
|||
clonedRange.detach() |
|||
# At the begnning of the inputor, the offset height is 0 in Chrome and Safari |
|||
# This work fine in all browers but except while the inputor break a line into two (wrapped line). |
|||
# so we can't use it in all cases. |
|||
if !offset or offset?.height == 0 |
|||
clonedRange = range.cloneRange() |
|||
shadowCaret = $ oDocument.createTextNode "|" |
|||
clonedRange.insertNode shadowCaret[0] |
|||
clonedRange.selectNode shadowCaret[0] |
|||
rect = clonedRange.getBoundingClientRect() |
|||
offset = {height: rect.height, left: rect.left, top: rect.top } |
|||
shadowCaret.remove() |
|||
clonedRange.detach() |
|||
else if oDocument.selection # ie < 9 |
|||
offset = this.getOldIEOffset() |
|||
|
|||
if offset |
|||
offset.top += $(oWindow).scrollTop() |
|||
offset.left += $(oWindow).scrollLeft() |
|||
|
|||
offset |
|||
|
|||
range: -> |
|||
return unless oWindow.getSelection |
|||
sel = oWindow.getSelection() |
|||
if sel.rangeCount > 0 then sel.getRangeAt(0) else null |
|||
|
|||
|
|||
class InputCaret |
|||
|
|||
constructor: (@$inputor) -> |
|||
@domInputor = @$inputor[0] |
|||
|
|||
getIEPos: -> |
|||
# https://github.com/ichord/Caret.js/wiki/Get-pos-of-caret-in-IE |
|||
inputor = @domInputor |
|||
range = oDocument.selection.createRange() |
|||
pos = 0 |
|||
# selection should in the inputor. |
|||
if range and range.parentElement() is inputor |
|||
normalizedValue = inputor.value.replace /\r\n/g, "\n" |
|||
len = normalizedValue.length |
|||
textInputRange = inputor.createTextRange() |
|||
textInputRange.moveToBookmark range.getBookmark() |
|||
endRange = inputor.createTextRange() |
|||
endRange.collapse false |
|||
if textInputRange.compareEndPoints("StartToEnd", endRange) > -1 |
|||
pos = len |
|||
else |
|||
pos = -textInputRange.moveStart "character", -len |
|||
pos |
|||
|
|||
getPos: -> |
|||
if oDocument.selection then this.getIEPos() else @domInputor.selectionStart |
|||
|
|||
setPos: (pos) -> |
|||
inputor = @domInputor |
|||
if oDocument.selection #IE |
|||
range = inputor.createTextRange() |
|||
range.move "character", pos |
|||
range.select() |
|||
else if inputor.setSelectionRange |
|||
inputor.setSelectionRange pos, pos |
|||
inputor |
|||
|
|||
getIEOffset: (pos) -> |
|||
textRange = @domInputor.createTextRange() |
|||
pos ||= this.getPos() |
|||
textRange.move('character', pos) |
|||
|
|||
x = textRange.boundingLeft |
|||
y = textRange.boundingTop |
|||
h = textRange.boundingHeight |
|||
|
|||
{left: x, top: y, height: h} |
|||
|
|||
getOffset: (pos) -> |
|||
$inputor = @$inputor |
|||
if oDocument.selection |
|||
offset = this.getIEOffset(pos) |
|||
offset.top += $(oWindow).scrollTop() + $inputor.scrollTop() |
|||
offset.left += $(oWindow).scrollLeft() + $inputor.scrollLeft() |
|||
offset |
|||
else |
|||
offset = $inputor.offset() |
|||
position = this.getPosition(pos) |
|||
offset = |
|||
left: offset.left + position.left - $inputor.scrollLeft() |
|||
top: offset.top + position.top - $inputor.scrollTop() |
|||
height: position.height |
|||
|
|||
getPosition: (pos)-> |
|||
$inputor = @$inputor |
|||
format = (value) -> |
|||
value = value.replace(/<|>|`|"|&/g, '?').replace(/\r\n|\r|\n/g,"<br/>") |
|||
if /firefox/i.test navigator.userAgent |
|||
value = value.replace(/\s/g, ' ') |
|||
value |
|||
pos = this.getPos() if pos is undefined |
|||
start_range = $inputor.val().slice(0, pos) |
|||
end_range = $inputor.val().slice(pos) |
|||
html = "<span style='position: relative; display: inline;'>"+format(start_range)+"</span>" |
|||
html += "<span id='caret' style='position: relative; display: inline;'>|</span>" |
|||
html += "<span style='position: relative; display: inline;'>"+format(end_range)+"</span>" |
|||
|
|||
mirror = new Mirror($inputor) |
|||
at_rect = mirror.create(html).rect() |
|||
|
|||
getIEPosition: (pos) -> |
|||
offset = this.getIEOffset pos |
|||
inputorOffset = @$inputor.offset() |
|||
x = offset.left - inputorOffset.left |
|||
y = offset.top - inputorOffset.top |
|||
h = offset.height |
|||
|
|||
{left: x, top: y, height: h} |
|||
|
|||
# @example |
|||
# mirror = new Mirror($("textarea#inputor")) |
|||
# html = "<p>We will get the rect of <span>@</span>icho</p>" |
|||
# mirror.create(html).rect() |
|||
class Mirror |
|||
css_attr: [ |
|||
"borderBottomWidth", |
|||
"borderLeftWidth", |
|||
"borderRightWidth", |
|||
"borderTopStyle", |
|||
"borderRightStyle", |
|||
"borderBottomStyle", |
|||
"borderLeftStyle", |
|||
"borderTopWidth", |
|||
"boxSizing", |
|||
"fontFamily", |
|||
"fontSize", |
|||
"fontWeight", |
|||
"height", |
|||
"letterSpacing", |
|||
"lineHeight", |
|||
"marginBottom", |
|||
"marginLeft", |
|||
"marginRight", |
|||
"marginTop", |
|||
"outlineWidth", |
|||
"overflow", |
|||
"overflowX", |
|||
"overflowY", |
|||
"paddingBottom", |
|||
"paddingLeft", |
|||
"paddingRight", |
|||
"paddingTop", |
|||
"textAlign", |
|||
"textOverflow", |
|||
"textTransform", |
|||
"whiteSpace", |
|||
"wordBreak", |
|||
"wordWrap", |
|||
] |
|||
|
|||
constructor: (@$inputor) -> |
|||
|
|||
mirrorCss: -> |
|||
css = |
|||
position: 'absolute' |
|||
left: -9999 |
|||
top: 0 |
|||
zIndex: -20000 |
|||
if @$inputor.prop( 'tagName' ) == 'TEXTAREA' |
|||
@css_attr.push( 'width' ) |
|||
$.each @css_attr, (i,p) => |
|||
css[p] = @$inputor.css p |
|||
css |
|||
|
|||
create: (html) -> |
|||
@$mirror = $('<div></div>') |
|||
@$mirror.css this.mirrorCss() |
|||
@$mirror.html(html) |
|||
@$inputor.after(@$mirror) |
|||
this |
|||
|
|||
# 获得标记的位置 |
|||
# |
|||
# @return [Object] 标记的坐标 |
|||
# {left: 0, top: 0, bottom: 0} |
|||
rect: -> |
|||
$flag = @$mirror.find "#caret" |
|||
pos = $flag.position() |
|||
rect = {left: pos.left, top: pos.top, height: $flag.height() } |
|||
@$mirror.remove() |
|||
rect |
|||
|
|||
Utils = |
|||
contentEditable: ($inputor)-> |
|||
!!($inputor[0].contentEditable && $inputor[0].contentEditable == 'true') |
|||
|
|||
methods = |
|||
pos: (pos) -> |
|||
if pos or pos == 0 |
|||
this.setPos pos |
|||
else |
|||
this.getPos() |
|||
|
|||
position: (pos) -> |
|||
if oDocument.selection then this.getIEPosition pos else this.getPosition pos |
|||
|
|||
offset: (pos) -> |
|||
offset = this.getOffset(pos) |
|||
offset |
|||
|
|||
oDocument = null |
|||
oWindow = null |
|||
oFrame = null |
|||
setContextBy = (settings) -> |
|||
if iframe = settings?.iframe |
|||
oFrame = iframe |
|||
oWindow = iframe.contentWindow |
|||
oDocument = iframe.contentDocument || oWindow.document |
|||
else |
|||
oFrame = undefined |
|||
oWindow = window |
|||
oDocument = document |
|||
discoveryIframeOf = ($dom) -> |
|||
oDocument = $dom[0].ownerDocument |
|||
oWindow = oDocument.defaultView || oDocument.parentWindow |
|||
try |
|||
oFrame = oWindow.frameElement |
|||
catch error |
|||
# throws error in cross-domain iframes |
|||
|
|||
$.fn.caret = (method, value, settings) -> |
|||
# http://stackoverflow.com/questions/16010204/get-reference-of-window-object-from-a-dom-element |
|||
if methods[method] |
|||
if $.isPlainObject(value) |
|||
setContextBy value |
|||
value = undefined |
|||
else |
|||
setContextBy settings |
|||
caret = if Utils.contentEditable(this) then new EditableCaret(this) else new InputCaret(this) |
|||
methods[method].apply caret, [value] |
|||
else |
|||
$.error "Method #{method} does not exist on jQuery.caret" |
|||
|
|||
|
|||
|
|||
$.fn.caret.EditableCaret = EditableCaret |
|||
$.fn.caret.InputCaret = InputCaret |
|||
$.fn.caret.Utils = Utils |
|||
$.fn.caret.apis = methods |
|||
@ -0,0 +1,406 @@ |
|||
(function (root, factory) { |
|||
if (typeof define === 'function' && define.amd) { |
|||
// AMD. Register as an anonymous module.
|
|||
define(["jquery"], function ($) { |
|||
return (root.returnExportsGlobal = factory($)); |
|||
}); |
|||
} else if (typeof exports === 'object') { |
|||
// Node. Does not work with strict CommonJS, but
|
|||
// only CommonJS-like enviroments that support module.exports,
|
|||
// like Node.
|
|||
module.exports = factory(require("jquery")); |
|||
} else { |
|||
factory(jQuery); |
|||
} |
|||
}(this, function ($) { |
|||
|
|||
//@ sourceMappingURL=jquery.caret.map
|
|||
/* |
|||
Implement Github like autocomplete mentions |
|||
http://ichord.github.com/At.js
|
|||
|
|||
Copyright (c) 2013 chord.luo@gmail.com |
|||
Licensed under the MIT license. |
|||
*/ |
|||
|
|||
/* |
|||
本插件操作 textarea 或者 input 内的插入符 |
|||
只实现了获得插入符在文本框中的位置,我设置 |
|||
插入符的位置. |
|||
*/ |
|||
|
|||
"use strict"; |
|||
var EditableCaret, InputCaret, Mirror, Utils, discoveryIframeOf, methods, oDocument, oFrame, oWindow, pluginName, setContextBy; |
|||
|
|||
pluginName = 'caret'; |
|||
|
|||
EditableCaret = (function() { |
|||
function EditableCaret($inputor) { |
|||
this.$inputor = $inputor; |
|||
this.domInputor = this.$inputor[0]; |
|||
} |
|||
|
|||
EditableCaret.prototype.setPos = function(pos) { |
|||
return this.domInputor; |
|||
}; |
|||
|
|||
EditableCaret.prototype.getIEPosition = function() { |
|||
return this.getPosition(); |
|||
}; |
|||
|
|||
EditableCaret.prototype.getPosition = function() { |
|||
var inputor_offset, offset; |
|||
offset = this.getOffset(); |
|||
inputor_offset = this.$inputor.offset(); |
|||
offset.left -= inputor_offset.left; |
|||
offset.top -= inputor_offset.top; |
|||
return offset; |
|||
}; |
|||
|
|||
EditableCaret.prototype.getOldIEPos = function() { |
|||
var preCaretTextRange, textRange; |
|||
textRange = oDocument.selection.createRange(); |
|||
preCaretTextRange = oDocument.body.createTextRange(); |
|||
preCaretTextRange.moveToElementText(this.domInputor); |
|||
preCaretTextRange.setEndPoint("EndToEnd", textRange); |
|||
return preCaretTextRange.text.length; |
|||
}; |
|||
|
|||
EditableCaret.prototype.getPos = function() { |
|||
var clonedRange, pos, range; |
|||
if (range = this.range()) { |
|||
clonedRange = range.cloneRange(); |
|||
clonedRange.selectNodeContents(this.domInputor); |
|||
clonedRange.setEnd(range.endContainer, range.endOffset); |
|||
pos = clonedRange.toString().length; |
|||
clonedRange.detach(); |
|||
return pos; |
|||
} else if (oDocument.selection) { |
|||
return this.getOldIEPos(); |
|||
} |
|||
}; |
|||
|
|||
EditableCaret.prototype.getOldIEOffset = function() { |
|||
var range, rect; |
|||
range = oDocument.selection.createRange().duplicate(); |
|||
range.moveStart("character", -1); |
|||
rect = range.getBoundingClientRect(); |
|||
return { |
|||
height: rect.bottom - rect.top, |
|||
left: rect.left, |
|||
top: rect.top |
|||
}; |
|||
}; |
|||
|
|||
EditableCaret.prototype.getOffset = function(pos) { |
|||
var clonedRange, offset, range, rect, shadowCaret; |
|||
if (oWindow.getSelection && (range = this.range())) { |
|||
if (range.endOffset - 1 > 0 && range.endContainer === !this.domInputor) { |
|||
clonedRange = range.cloneRange(); |
|||
clonedRange.setStart(range.endContainer, range.endOffset - 1); |
|||
clonedRange.setEnd(range.endContainer, range.endOffset); |
|||
rect = clonedRange.getBoundingClientRect(); |
|||
offset = { |
|||
height: rect.height, |
|||
left: rect.left + rect.width, |
|||
top: rect.top |
|||
}; |
|||
clonedRange.detach(); |
|||
} |
|||
if (!offset || (offset != null ? offset.height : void 0) === 0) { |
|||
clonedRange = range.cloneRange(); |
|||
shadowCaret = $(oDocument.createTextNode("|")); |
|||
clonedRange.insertNode(shadowCaret[0]); |
|||
clonedRange.selectNode(shadowCaret[0]); |
|||
rect = clonedRange.getBoundingClientRect(); |
|||
offset = { |
|||
height: rect.height, |
|||
left: rect.left, |
|||
top: rect.top |
|||
}; |
|||
shadowCaret.remove(); |
|||
clonedRange.detach(); |
|||
} |
|||
} else if (oDocument.selection) { |
|||
offset = this.getOldIEOffset(); |
|||
} |
|||
if (offset) { |
|||
offset.top += $(oWindow).scrollTop(); |
|||
offset.left += $(oWindow).scrollLeft(); |
|||
} |
|||
return offset; |
|||
}; |
|||
|
|||
EditableCaret.prototype.range = function() { |
|||
var sel; |
|||
if (!oWindow.getSelection) { |
|||
return; |
|||
} |
|||
sel = oWindow.getSelection(); |
|||
if (sel.rangeCount > 0) { |
|||
return sel.getRangeAt(0); |
|||
} else { |
|||
return null; |
|||
} |
|||
}; |
|||
|
|||
return EditableCaret; |
|||
|
|||
})(); |
|||
|
|||
InputCaret = (function() { |
|||
function InputCaret($inputor) { |
|||
this.$inputor = $inputor; |
|||
this.domInputor = this.$inputor[0]; |
|||
} |
|||
|
|||
InputCaret.prototype.getIEPos = function() { |
|||
var endRange, inputor, len, normalizedValue, pos, range, textInputRange; |
|||
inputor = this.domInputor; |
|||
range = oDocument.selection.createRange(); |
|||
pos = 0; |
|||
if (range && range.parentElement() === inputor) { |
|||
normalizedValue = inputor.value.replace(/\r\n/g, "\n"); |
|||
len = normalizedValue.length; |
|||
textInputRange = inputor.createTextRange(); |
|||
textInputRange.moveToBookmark(range.getBookmark()); |
|||
endRange = inputor.createTextRange(); |
|||
endRange.collapse(false); |
|||
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { |
|||
pos = len; |
|||
} else { |
|||
pos = -textInputRange.moveStart("character", -len); |
|||
} |
|||
} |
|||
return pos; |
|||
}; |
|||
|
|||
InputCaret.prototype.getPos = function() { |
|||
if (oDocument.selection) { |
|||
return this.getIEPos(); |
|||
} else { |
|||
return this.domInputor.selectionStart; |
|||
} |
|||
}; |
|||
|
|||
InputCaret.prototype.setPos = function(pos) { |
|||
var inputor, range; |
|||
inputor = this.domInputor; |
|||
if (oDocument.selection) { |
|||
range = inputor.createTextRange(); |
|||
range.move("character", pos); |
|||
range.select(); |
|||
} else if (inputor.setSelectionRange) { |
|||
inputor.setSelectionRange(pos, pos); |
|||
} |
|||
return inputor; |
|||
}; |
|||
|
|||
InputCaret.prototype.getIEOffset = function(pos) { |
|||
var h, textRange, x, y; |
|||
textRange = this.domInputor.createTextRange(); |
|||
pos || (pos = this.getPos()); |
|||
textRange.move('character', pos); |
|||
x = textRange.boundingLeft; |
|||
y = textRange.boundingTop; |
|||
h = textRange.boundingHeight; |
|||
return { |
|||
left: x, |
|||
top: y, |
|||
height: h |
|||
}; |
|||
}; |
|||
|
|||
InputCaret.prototype.getOffset = function(pos) { |
|||
var $inputor, offset, position; |
|||
$inputor = this.$inputor; |
|||
if (oDocument.selection) { |
|||
offset = this.getIEOffset(pos); |
|||
offset.top += $(oWindow).scrollTop() + $inputor.scrollTop(); |
|||
offset.left += $(oWindow).scrollLeft() + $inputor.scrollLeft(); |
|||
return offset; |
|||
} else { |
|||
offset = $inputor.offset(); |
|||
position = this.getPosition(pos); |
|||
return offset = { |
|||
left: offset.left + position.left - $inputor.scrollLeft(), |
|||
top: offset.top + position.top - $inputor.scrollTop(), |
|||
height: position.height |
|||
}; |
|||
} |
|||
}; |
|||
|
|||
InputCaret.prototype.getPosition = function(pos) { |
|||
var $inputor, at_rect, end_range, format, html, mirror, start_range; |
|||
$inputor = this.$inputor; |
|||
format = function(value) { |
|||
value = value.replace(/<|>|`|"|&/g, '?').replace(/\r\n|\r|\n/g, "<br/>"); |
|||
if (/firefox/i.test(navigator.userAgent)) { |
|||
value = value.replace(/\s/g, ' '); |
|||
} |
|||
return value; |
|||
}; |
|||
if (pos === void 0) { |
|||
pos = this.getPos(); |
|||
} |
|||
start_range = $inputor.val().slice(0, pos); |
|||
end_range = $inputor.val().slice(pos); |
|||
html = "<span style='position: relative; display: inline;'>" + format(start_range) + "</span>"; |
|||
html += "<span id='caret' style='position: relative; display: inline;'>|</span>"; |
|||
html += "<span style='position: relative; display: inline;'>" + format(end_range) + "</span>"; |
|||
mirror = new Mirror($inputor); |
|||
return at_rect = mirror.create(html).rect(); |
|||
}; |
|||
|
|||
InputCaret.prototype.getIEPosition = function(pos) { |
|||
var h, inputorOffset, offset, x, y; |
|||
offset = this.getIEOffset(pos); |
|||
inputorOffset = this.$inputor.offset(); |
|||
x = offset.left - inputorOffset.left; |
|||
y = offset.top - inputorOffset.top; |
|||
h = offset.height; |
|||
return { |
|||
left: x, |
|||
top: y, |
|||
height: h |
|||
}; |
|||
}; |
|||
|
|||
return InputCaret; |
|||
|
|||
})(); |
|||
|
|||
Mirror = (function() { |
|||
Mirror.prototype.css_attr = ["borderBottomWidth", "borderLeftWidth", "borderRightWidth", "borderTopStyle", "borderRightStyle", "borderBottomStyle", "borderLeftStyle", "borderTopWidth", "boxSizing", "fontFamily", "fontSize", "fontWeight", "height", "letterSpacing", "lineHeight", "marginBottom", "marginLeft", "marginRight", "marginTop", "outlineWidth", "overflow", "overflowX", "overflowY", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "textAlign", "textOverflow", "textTransform", "whiteSpace", "wordBreak", "wordWrap"]; |
|||
|
|||
function Mirror($inputor) { |
|||
this.$inputor = $inputor; |
|||
} |
|||
|
|||
Mirror.prototype.mirrorCss = function() { |
|||
var css, |
|||
_this = this; |
|||
css = { |
|||
position: 'absolute', |
|||
left: -9999, |
|||
top: 0, |
|||
zIndex: -20000 |
|||
}; |
|||
if (this.$inputor.prop('tagName') === 'TEXTAREA') { |
|||
this.css_attr.push('width'); |
|||
} |
|||
$.each(this.css_attr, function(i, p) { |
|||
return css[p] = _this.$inputor.css(p); |
|||
}); |
|||
return css; |
|||
}; |
|||
|
|||
Mirror.prototype.create = function(html) { |
|||
this.$mirror = $('<div></div>'); |
|||
this.$mirror.css(this.mirrorCss()); |
|||
this.$mirror.html(html); |
|||
this.$inputor.after(this.$mirror); |
|||
return this; |
|||
}; |
|||
|
|||
Mirror.prototype.rect = function() { |
|||
var $flag, pos, rect; |
|||
$flag = this.$mirror.find("#caret"); |
|||
pos = $flag.position(); |
|||
rect = { |
|||
left: pos.left, |
|||
top: pos.top, |
|||
height: $flag.height() |
|||
}; |
|||
this.$mirror.remove(); |
|||
return rect; |
|||
}; |
|||
|
|||
return Mirror; |
|||
|
|||
})(); |
|||
|
|||
Utils = { |
|||
contentEditable: function($inputor) { |
|||
return !!($inputor[0].contentEditable && $inputor[0].contentEditable === 'true'); |
|||
} |
|||
}; |
|||
|
|||
methods = { |
|||
pos: function(pos) { |
|||
if (pos || pos === 0) { |
|||
return this.setPos(pos); |
|||
} else { |
|||
return this.getPos(); |
|||
} |
|||
}, |
|||
position: function(pos) { |
|||
if (oDocument.selection) { |
|||
return this.getIEPosition(pos); |
|||
} else { |
|||
return this.getPosition(pos); |
|||
} |
|||
}, |
|||
offset: function(pos) { |
|||
var offset; |
|||
offset = this.getOffset(pos); |
|||
return offset; |
|||
} |
|||
}; |
|||
|
|||
oDocument = null; |
|||
|
|||
oWindow = null; |
|||
|
|||
oFrame = null; |
|||
|
|||
setContextBy = function(settings) { |
|||
var iframe; |
|||
if (iframe = settings != null ? settings.iframe : void 0) { |
|||
oFrame = iframe; |
|||
oWindow = iframe.contentWindow; |
|||
return oDocument = iframe.contentDocument || oWindow.document; |
|||
} else { |
|||
oFrame = void 0; |
|||
oWindow = window; |
|||
return oDocument = document; |
|||
} |
|||
}; |
|||
|
|||
discoveryIframeOf = function($dom) { |
|||
var error; |
|||
oDocument = $dom[0].ownerDocument; |
|||
oWindow = oDocument.defaultView || oDocument.parentWindow; |
|||
try { |
|||
return oFrame = oWindow.frameElement; |
|||
} catch (_error) { |
|||
error = _error; |
|||
} |
|||
}; |
|||
|
|||
$.fn.caret = function(method, value, settings) { |
|||
var caret; |
|||
if (methods[method]) { |
|||
if ($.isPlainObject(value)) { |
|||
setContextBy(value); |
|||
value = void 0; |
|||
} else { |
|||
setContextBy(settings); |
|||
} |
|||
caret = Utils.contentEditable(this) ? new EditableCaret(this) : new InputCaret(this); |
|||
return methods[method].apply(caret, [value]); |
|||
} else { |
|||
return $.error("Method " + method + " does not exist on jQuery.caret"); |
|||
} |
|||
}; |
|||
|
|||
$.fn.caret.EditableCaret = EditableCaret; |
|||
|
|||
$.fn.caret.InputCaret = InputCaret; |
|||
|
|||
$.fn.caret.Utils = Utils; |
|||
|
|||
$.fn.caret.apis = methods; |
|||
|
|||
|
|||
})); |
|||
@ -0,0 +1,25 @@ |
|||
{ |
|||
"name": "jquery", |
|||
"main": "dist/jquery.js", |
|||
"license": "MIT", |
|||
"ignore": [ |
|||
"package.json" |
|||
], |
|||
"keywords": [ |
|||
"jquery", |
|||
"javascript", |
|||
"browser", |
|||
"library" |
|||
], |
|||
"homepage": "https://github.com/jquery/jquery-dist", |
|||
"version": "3.2.1", |
|||
"_release": "3.2.1", |
|||
"_resolution": { |
|||
"type": "version", |
|||
"tag": "3.2.1", |
|||
"commit": "77d2a51d0520d2ee44173afdf4e40a9201f5964e" |
|||
}, |
|||
"_source": "https://github.com/jquery/jquery-dist.git", |
|||
"_target": ">=1.7.0", |
|||
"_originalSource": "jquery" |
|||
} |
|||
@ -0,0 +1,301 @@ |
|||
Authors ordered by first contribution. |
|||
|
|||
John Resig <jeresig@gmail.com> |
|||
Gilles van den Hoven <gilles0181@gmail.com> |
|||
Michael Geary <mike@geary.com> |
|||
Stefan Petre <stefan.petre@gmail.com> |
|||
Yehuda Katz <wycats@gmail.com> |
|||
Corey Jewett <cj@syntheticplayground.com> |
|||
Klaus Hartl <klaus.hartl@gmail.com> |
|||
Franck Marcia <franck.marcia@gmail.com> |
|||
Jörn Zaefferer <joern.zaefferer@gmail.com> |
|||
Paul Bakaus <paul.bakaus@gmail.com> |
|||
Brandon Aaron <brandon.aaron@gmail.com> |
|||
Mike Alsup <malsup@gmail.com> |
|||
Dave Methvin <dave.methvin@gmail.com> |
|||
Ed Engelhardt <edengelhardt@gmail.com> |
|||
Sean Catchpole <littlecooldude@gmail.com> |
|||
Paul Mclanahan <pmclanahan@gmail.com> |
|||
David Serduke <davidserduke@gmail.com> |
|||
Richard D. Worth <rdworth@gmail.com> |
|||
Scott González <scott.gonzalez@gmail.com> |
|||
Ariel Flesler <aflesler@gmail.com> |
|||
Jon Evans <jon@springyweb.com> |
|||
TJ Holowaychuk <tj@vision-media.ca> |
|||
Michael Bensoussan <mickey@seesmic.com> |
|||
Robert Katić <robert.katic@gmail.com> |
|||
Louis-Rémi Babé <lrbabe@gmail.com> |
|||
Earle Castledine <mrspeaker@gmail.com> |
|||
Damian Janowski <damian.janowski@gmail.com> |
|||
Rich Dougherty <rich@rd.gen.nz> |
|||
Kim Dalsgaard <kim@kimdalsgaard.com> |
|||
Andrea Giammarchi <andrea.giammarchi@gmail.com> |
|||
Mark Gibson <jollytoad@gmail.com> |
|||
Karl Swedberg <kswedberg@gmail.com> |
|||
Justin Meyer <justinbmeyer@gmail.com> |
|||
Ben Alman <cowboy@rj3.net> |
|||
James Padolsey <cla@padolsey.net> |
|||
David Petersen <public@petersendidit.com> |
|||
Batiste Bieler <batiste.bieler@gmail.com> |
|||
Alexander Farkas <info@corrupt-system.de> |
|||
Rick Waldron <waldron.rick@gmail.com> |
|||
Filipe Fortes <filipe@fortes.com> |
|||
Neeraj Singh <neerajdotname@gmail.com> |
|||
Paul Irish <paul.irish@gmail.com> |
|||
Iraê Carvalho <irae@irae.pro.br> |
|||
Matt Curry <matt@pseudocoder.com> |
|||
Michael Monteleone <michael@michaelmonteleone.net> |
|||
Noah Sloan <noah.sloan@gmail.com> |
|||
Tom Viner <github@viner.tv> |
|||
Douglas Neiner <doug@dougneiner.com> |
|||
Adam J. Sontag <ajpiano@ajpiano.com> |
|||
Dave Reed <dareed@microsoft.com> |
|||
Ralph Whitbeck <ralph.whitbeck@gmail.com> |
|||
Carl Fürstenberg <azatoth@gmail.com> |
|||
Jacob Wright <jacwright@gmail.com> |
|||
J. Ryan Stinnett <jryans@gmail.com> |
|||
unknown <Igen005@.upcorp.ad.uprr.com> |
|||
temp01 <temp01irc@gmail.com> |
|||
Heungsub Lee <h@subl.ee> |
|||
Colin Snover <github.com@zetafleet.com> |
|||
Ryan W Tenney <ryan@10e.us> |
|||
Pinhook <contact@pinhooklabs.com> |
|||
Ron Otten <r.j.g.otten@gmail.com> |
|||
Jephte Clain <Jephte.Clain@univ-reunion.fr> |
|||
Anton Matzneller <obhvsbypqghgc@gmail.com> |
|||
Alex Sexton <AlexSexton@gmail.com> |
|||
Dan Heberden <danheberden@gmail.com> |
|||
Henri Wiechers <hwiechers@gmail.com> |
|||
Russell Holbrook <russell.holbrook@patch.com> |
|||
Julian Aubourg <aubourg.julian@gmail.com> |
|||
Gianni Alessandro Chiappetta <gianni@runlevel6.org> |
|||
Scott Jehl <scottjehl@gmail.com> |
|||
James Burke <jrburke@gmail.com> |
|||
Jonas Pfenniger <jonas@pfenniger.name> |
|||
Xavi Ramirez <xavi.rmz@gmail.com> |
|||
Jared Grippe <jared@deadlyicon.com> |
|||
Sylvester Keil <sylvester@keil.or.at> |
|||
Brandon Sterne <bsterne@mozilla.com> |
|||
Mathias Bynens <mathias@qiwi.be> |
|||
Timmy Willison <4timmywil@gmail.com> |
|||
Corey Frang <gnarf37@gmail.com> |
|||
Digitalxero <digitalxero> |
|||
Anton Kovalyov <anton@kovalyov.net> |
|||
David Murdoch <david@davidmurdoch.com> |
|||
Josh Varner <josh.varner@gmail.com> |
|||
Charles McNulty <cmcnulty@kznf.com> |
|||
Jordan Boesch <jboesch26@gmail.com> |
|||
Jess Thrysoee <jess@thrysoee.dk> |
|||
Michael Murray <m@murz.net> |
|||
Lee Carpenter <elcarpie@gmail.com> |
|||
Alexis Abril <me@alexisabril.com> |
|||
Rob Morgan <robbym@gmail.com> |
|||
John Firebaugh <john_firebaugh@bigfix.com> |
|||
Sam Bisbee <sam@sbisbee.com> |
|||
Gilmore Davidson <gilmoreorless@gmail.com> |
|||
Brian Brennan <me@brianlovesthings.com> |
|||
Xavier Montillet <xavierm02.net@gmail.com> |
|||
Daniel Pihlstrom <sciolist.se@gmail.com> |
|||
Sahab Yazdani <sahab.yazdani+github@gmail.com> |
|||
avaly <github-com@agachi.name> |
|||
Scott Hughes <hi@scott-hughes.me> |
|||
Mike Sherov <mike.sherov@gmail.com> |
|||
Greg Hazel <ghazel@gmail.com> |
|||
Schalk Neethling <schalk@ossreleasefeed.com> |
|||
Denis Knauf <Denis.Knauf@gmail.com> |
|||
Timo Tijhof <krinklemail@gmail.com> |
|||
Steen Nielsen <swinedk@gmail.com> |
|||
Anton Ryzhov <anton@ryzhov.me> |
|||
Shi Chuan <shichuanr@gmail.com> |
|||
Berker Peksag <berker.peksag@gmail.com> |
|||
Toby Brain <tobyb@freshview.com> |
|||
Matt Mueller <mattmuelle@gmail.com> |
|||
Justin <drakefjustin@gmail.com> |
|||
Daniel Herman <daniel.c.herman@gmail.com> |
|||
Oleg Gaidarenko <markelog@gmail.com> |
|||
Richard Gibson <richard.gibson@gmail.com> |
|||
Rafaël Blais Masson <rafbmasson@gmail.com> |
|||
cmc3cn <59194618@qq.com> |
|||
Joe Presbrey <presbrey@gmail.com> |
|||
Sindre Sorhus <sindresorhus@gmail.com> |
|||
Arne de Bree <arne@bukkie.nl> |
|||
Vladislav Zarakovsky <vlad.zar@gmail.com> |
|||
Andrew E Monat <amonat@gmail.com> |
|||
Oskari <admin@o-programs.com> |
|||
Joao Henrique de Andrade Bruni <joaohbruni@yahoo.com.br> |
|||
tsinha <tsinha@Anthonys-MacBook-Pro.local> |
|||
Matt Farmer <matt@frmr.me> |
|||
Trey Hunner <treyhunner@gmail.com> |
|||
Jason Moon <jmoon@socialcast.com> |
|||
Jeffery To <jeffery.to@gmail.com> |
|||
Kris Borchers <kris.borchers@gmail.com> |
|||
Vladimir Zhuravlev <private.face@gmail.com> |
|||
Jacob Thornton <jacobthornton@gmail.com> |
|||
Chad Killingsworth <chadkillingsworth@missouristate.edu> |
|||
Nowres Rafid <nowres.rafed@gmail.com> |
|||
David Benjamin <davidben@mit.edu> |
|||
Uri Gilad <antishok@gmail.com> |
|||
Chris Faulkner <thefaulkner@gmail.com> |
|||
Elijah Manor <elijah.manor@gmail.com> |
|||
Daniel Chatfield <chatfielddaniel@gmail.com> |
|||
Nikita Govorov <nikita.govorov@gmail.com> |
|||
Wesley Walser <waw325@gmail.com> |
|||
Mike Pennisi <mike@mikepennisi.com> |
|||
Markus Staab <markus.staab@redaxo.de> |
|||
Dave Riddle <david@joyvuu.com> |
|||
Callum Macrae <callum@lynxphp.com> |
|||
Benjamin Truyman <bentruyman@gmail.com> |
|||
James Huston <james@jameshuston.net> |
|||
Erick Ruiz de Chávez <erickrdch@gmail.com> |
|||
David Bonner <dbonner@cogolabs.com> |
|||
Akintayo Akinwunmi <aakinwunmi@judge.com> |
|||
MORGAN <morgan@morgangraphics.com> |
|||
Ismail Khair <ismail.khair@gmail.com> |
|||
Carl Danley <carldanley@gmail.com> |
|||
Mike Petrovich <michael.c.petrovich@gmail.com> |
|||
Greg Lavallee <greglavallee@wapolabs.com> |
|||
Daniel Gálvez <dgalvez@editablething.com> |
|||
Sai Lung Wong <sai.wong@huffingtonpost.com> |
|||
Tom H Fuertes <TomFuertes@gmail.com> |
|||
Roland Eckl <eckl.roland@googlemail.com> |
|||
Jay Merrifield <fracmak@gmail.com> |
|||
Allen J Schmidt Jr <cobrasoft@gmail.com> |
|||
Jonathan Sampson <jjdsampson@gmail.com> |
|||
Marcel Greter <marcel.greter@ocbnet.ch> |
|||
Matthias Jäggli <matthias.jaeggli@gmail.com> |
|||
David Fox <dfoxinator@gmail.com> |
|||
Yiming He <yiminghe@gmail.com> |
|||
Devin Cooper <cooper.semantics@gmail.com> |
|||
Paul Ramos <paul.b.ramos@gmail.com> |
|||
Rod Vagg <rod@vagg.org> |
|||
Bennett Sorbo <bsorbo@gmail.com> |
|||
Sebastian Burkhard <sebi.burkhard@gmail.com> |
|||
Zachary Adam Kaplan <razic@viralkitty.com> |
|||
nanto_vi <nanto@moon.email.ne.jp> |
|||
nanto <nanto@moon.email.ne.jp> |
|||
Danil Somsikov <danilasomsikov@gmail.com> |
|||
Ryunosuke SATO <tricknotes.rs@gmail.com> |
|||
Jean Boussier <jean.boussier@gmail.com> |
|||
Adam Coulombe <me@adam.co> |
|||
Andrew Plummer <plummer.andrew@gmail.com> |
|||
Mark Raddatz <mraddatz@gmail.com> |
|||
Isaac Z. Schlueter <i@izs.me> |
|||
Karl Sieburg <ksieburg@yahoo.com> |
|||
Pascal Borreli <pascal@borreli.com> |
|||
Nguyen Phuc Lam <ruado1987@gmail.com> |
|||
Dmitry Gusev <dmitry.gusev@gmail.com> |
|||
Michał Gołębiowski <m.goleb@gmail.com> |
|||
Li Xudong <istonelee@gmail.com> |
|||
Steven Benner <admin@stevenbenner.com> |
|||
Tom H Fuertes <tomfuertes@gmail.com> |
|||
Renato Oliveira dos Santos <ros3@cin.ufpe.br> |
|||
ros3cin <ros3@cin.ufpe.br> |
|||
Jason Bedard <jason+jquery@jbedard.ca> |
|||
Kyle Robinson Young <kyle@dontkry.com> |
|||
Chris Talkington <chris@talkingtontech.com> |
|||
Eddie Monge <eddie@eddiemonge.com> |
|||
Terry Jones <terry@jon.es> |
|||
Jason Merino <jasonmerino@gmail.com> |
|||
Jeremy Dunck <jdunck@gmail.com> |
|||
Chris Price <price.c@gmail.com> |
|||
Guy Bedford <guybedford@gmail.com> |
|||
Amey Sakhadeo <me@ameyms.com> |
|||
Mike Sidorov <mikes.ekb@gmail.com> |
|||
Anthony Ryan <anthonyryan1@gmail.com> |
|||
Dominik D. Geyer <dominik.geyer@gmail.com> |
|||
George Kats <katsgeorgeek@gmail.com> |
|||
Lihan Li <frankieteardrop@gmail.com> |
|||
Ronny Springer <springer.ronny@gmail.com> |
|||
Chris Antaki <ChrisAntaki@gmail.com> |
|||
Marian Sollmann <marian.sollmann@cargomedia.ch> |
|||
njhamann <njhamann@gmail.com> |
|||
Ilya Kantor <iliakan@gmail.com> |
|||
David Hong <d.hong@me.com> |
|||
John Paul <john@johnkpaul.com> |
|||
Jakob Stoeck <jakob@pokermania.de> |
|||
Christopher Jones <chris@cjqed.com> |
|||
Forbes Lindesay <forbes@lindesay.co.uk> |
|||
S. Andrew Sheppard <andrew@wq.io> |
|||
Leonardo Balter <leonardo.balter@gmail.com> |
|||
Roman Reiß <me@silverwind.io> |
|||
Benjy Cui <benjytrys@gmail.com> |
|||
Rodrigo Rosenfeld Rosas <rr.rosas@gmail.com> |
|||
John Hoven <hovenj@gmail.com> |
|||
Philip Jägenstedt <philip@foolip.org> |
|||
Christian Kosmowski <ksmwsk@gmail.com> |
|||
Liang Peng <poppinlp@gmail.com> |
|||
TJ VanToll <tj.vantoll@gmail.com> |
|||
Senya Pugach <upisfree@outlook.com> |
|||
Aurelio De Rosa <aurelioderosa@gmail.com> |
|||
Nazar Mokrynskyi <nazar@mokrynskyi.com> |
|||
Amit Merchant <bullredeyes@gmail.com> |
|||
Jason Bedard <jason+github@jbedard.ca> |
|||
Arthur Verschaeve <contact@arthurverschaeve.be> |
|||
Dan Hart <danhart@notonthehighstreet.com> |
|||
Bin Xin <rhyzix@gmail.com> |
|||
David Corbacho <davidcorbacho@gmail.com> |
|||
Veaceslav Grimalschi <grimalschi@yandex.ru> |
|||
Daniel Husar <dano.husar@gmail.com> |
|||
Frederic Hemberger <mail@frederic-hemberger.de> |
|||
Ben Toews <mastahyeti@gmail.com> |
|||
Aditya Raghavan <araghavan3@gmail.com> |
|||
Victor Homyakov <vkhomyackov@gmail.com> |
|||
Shivaji Varma <contact@shivajivarma.com> |
|||
Nicolas HENRY <icewil@gmail.com> |
|||
Anne-Gaelle Colom <coloma@westminster.ac.uk> |
|||
George Mauer <gmauer@gmail.com> |
|||
Leonardo Braga <leonardo.braga@gmail.com> |
|||
Stephen Edgar <stephen@netweb.com.au> |
|||
Thomas Tortorini <thomastortorini@gmail.com> |
|||
Winston Howes <winstonhowes@gmail.com> |
|||
Jon Hester <jon.d.hester@gmail.com> |
|||
Alexander O'Mara <me@alexomara.com> |
|||
Bastian Buchholz <buchholz.bastian@googlemail.com> |
|||
Arthur Stolyar <nekr.fabula@gmail.com> |
|||
Calvin Metcalf <calvin.metcalf@gmail.com> |
|||
Mu Haibao <mhbseal@163.com> |
|||
Richard McDaniel <rm0026@uah.edu> |
|||
Chris Rebert <github@rebertia.com> |
|||
Gabriel Schulhof <gabriel.schulhof@intel.com> |
|||
Gilad Peleg <giladp007@gmail.com> |
|||
Martin Naumann <martin@geekonaut.de> |
|||
Marek Lewandowski <m.lewandowski@cksource.com> |
|||
Bruno Pérel <brunoperel@gmail.com> |
|||
Reed Loden <reed@reedloden.com> |
|||
Daniel Nill <daniellnill@gmail.com> |
|||
Yongwoo Jeon <yongwoo.jeon@navercorp.com> |
|||
Sean Henderson <seanh.za@gmail.com> |
|||
Richard Kraaijenhagen <stdin+git@riichard.com> |
|||
Connor Atherton <c.liam.atherton@gmail.com> |
|||
Gary Ye <garysye@gmail.com> |
|||
Christian Grete <webmaster@christiangrete.com> |
|||
Liza Ramo <liza.h.ramo@gmail.com> |
|||
Julian Alexander Murillo <julian.alexander.murillo@gmail.com> |
|||
Joelle Fleurantin <joasqueeniebee@gmail.com> |
|||
Jae Sung Park <alberto.park@gmail.com> |
|||
Jun Sun <klsforever@gmail.com> |
|||
Josh Soref <apache@soref.com> |
|||
Henry Wong <henryw4k@gmail.com> |
|||
Jon Dufresne <jon.dufresne@gmail.com> |
|||
Martijn W. van der Lee <martijn@vanderlee.com> |
|||
Devin Wilson <dwilson6.github@gmail.com> |
|||
Steve Mao <maochenyan@gmail.com> |
|||
Zack Hall <zackhall@outlook.com> |
|||
Bernhard M. Wiedemann <jquerybmw@lsmod.de> |
|||
Todor Prikumov <tono_pr@abv.bg> |
|||
Jha Naman <createnaman@gmail.com> |
|||
William Robinet <william.robinet@conostix.com> |
|||
Alexander Lisianoi <all3fox@gmail.com> |
|||
Vitaliy Terziev <vitaliyterziev@gmail.com> |
|||
Joe Trumbull <trumbull.j@gmail.com> |
|||
Alexander K <xpyro@ya.ru> |
|||
Damian Senn <jquery@topaxi.codes> |
|||
Ralin Chimev <ralin.chimev@gmail.com> |
|||
Felipe Sateler <fsateler@gmail.com> |
|||
Christophe Tafani-Dereeper <christophetd@hotmail.fr> |
|||
Manoj Kumar <nithmanoj@gmail.com> |
|||
David Broder-Rodgers <broder93@gmail.com> |
|||
Alex Louden <alex@louden.com> |
|||
Alex Padilla <alexonezero@outlook.com> |
|||
南漂一卒 <shiy007@qq.com> |
|||
karan-96 <karanbatra96@gmail.com> |
|||
@ -0,0 +1,36 @@ |
|||
Copyright JS Foundation and other contributors, https://js.foundation/ |
|||
|
|||
This software consists of voluntary contributions made by many |
|||
individuals. For exact contribution history, see the revision history |
|||
available at https://github.com/jquery/jquery |
|||
|
|||
The following license applies to all parts of this software except as |
|||
documented below: |
|||
|
|||
==== |
|||
|
|||
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. |
|||
|
|||
==== |
|||
|
|||
All files located in the node_modules and external directories are |
|||
externally maintained libraries used by this software which have their |
|||
own licenses; we recommend you read them, as their terms may differ from |
|||
the terms above. |
|||
@ -0,0 +1,67 @@ |
|||
# jQuery |
|||
|
|||
> jQuery is a fast, small, and feature-rich JavaScript library. |
|||
|
|||
For information on how to get started and how to use jQuery, please see [jQuery's documentation](http://api.jquery.com/). |
|||
For source files and issues, please visit the [jQuery repo](https://github.com/jquery/jquery). |
|||
|
|||
If upgrading, please see the [blog post for 3.2.1](https://blog.jquery.com/2017/03/20/jquery-3-2-1-now-available/). This includes notable differences from the previous version and a more readable changelog. |
|||
|
|||
## Including jQuery |
|||
|
|||
Below are some of the most common ways to include jQuery. |
|||
|
|||
### Browser |
|||
|
|||
#### Script tag |
|||
|
|||
```html |
|||
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> |
|||
``` |
|||
|
|||
#### Babel |
|||
|
|||
[Babel](http://babeljs.io/) is a next generation JavaScript compiler. One of the features is the ability to use ES6/ES2015 modules now, even though browsers do not yet support this feature natively. |
|||
|
|||
```js |
|||
import $ from "jquery"; |
|||
``` |
|||
|
|||
#### Browserify/Webpack |
|||
|
|||
There are several ways to use [Browserify](http://browserify.org/) and [Webpack](https://webpack.github.io/). For more information on using these tools, please refer to the corresponding project's documention. In the script, including jQuery will usually look like this... |
|||
|
|||
```js |
|||
var $ = require("jquery"); |
|||
``` |
|||
|
|||
#### AMD (Asynchronous Module Definition) |
|||
|
|||
AMD is a module format built for the browser. For more information, we recommend [require.js' documentation](http://requirejs.org/docs/whyamd.html). |
|||
|
|||
```js |
|||
define(["jquery"], function($) { |
|||
|
|||
}); |
|||
``` |
|||
|
|||
### Node |
|||
|
|||
To include jQuery in [Node](nodejs.org), first install with npm. |
|||
|
|||
```sh |
|||
npm install jquery |
|||
``` |
|||
|
|||
For jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as [jsdom](https://github.com/tmpvar/jsdom). This can be useful for testing purposes. |
|||
|
|||
```js |
|||
require("jsdom").env("", function(err, window) { |
|||
if (err) { |
|||
console.error(err); |
|||
return; |
|||
} |
|||
|
|||
var $ = require("jquery")(window); |
|||
}); |
|||
``` |
|||
@ -0,0 +1,14 @@ |
|||
{ |
|||
"name": "jquery", |
|||
"main": "dist/jquery.js", |
|||
"license": "MIT", |
|||
"ignore": [ |
|||
"package.json" |
|||
], |
|||
"keywords": [ |
|||
"jquery", |
|||
"javascript", |
|||
"browser", |
|||
"library" |
|||
] |
|||
} |
|||
@ -0,0 +1,476 @@ |
|||
/* global Symbol */ |
|||
// Defining this global in .eslintrc.json would create a danger of using the global
|
|||
// unguarded in another place, it seems safer to define global only for this module
|
|||
|
|||
define( [ |
|||
"./var/arr", |
|||
"./var/document", |
|||
"./var/getProto", |
|||
"./var/slice", |
|||
"./var/concat", |
|||
"./var/push", |
|||
"./var/indexOf", |
|||
"./var/class2type", |
|||
"./var/toString", |
|||
"./var/hasOwn", |
|||
"./var/fnToString", |
|||
"./var/ObjectFunctionString", |
|||
"./var/support", |
|||
"./core/DOMEval" |
|||
], function( arr, document, getProto, slice, concat, push, indexOf, |
|||
class2type, toString, hasOwn, fnToString, ObjectFunctionString, |
|||
support, DOMEval ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var |
|||
version = "3.2.1", |
|||
|
|||
// Define a local copy of jQuery
|
|||
jQuery = function( selector, context ) { |
|||
|
|||
// The jQuery object is actually just the init constructor 'enhanced'
|
|||
// Need init if jQuery is called (just allow error to be thrown if not included)
|
|||
return new jQuery.fn.init( selector, context ); |
|||
}, |
|||
|
|||
// Support: Android <=4.0 only
|
|||
// Make sure we trim BOM and NBSP
|
|||
rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, |
|||
|
|||
// Matches dashed string for camelizing
|
|||
rmsPrefix = /^-ms-/, |
|||
rdashAlpha = /-([a-z])/g, |
|||
|
|||
// Used by jQuery.camelCase as callback to replace()
|
|||
fcamelCase = function( all, letter ) { |
|||
return letter.toUpperCase(); |
|||
}; |
|||
|
|||
jQuery.fn = jQuery.prototype = { |
|||
|
|||
// The current version of jQuery being used
|
|||
jquery: version, |
|||
|
|||
constructor: jQuery, |
|||
|
|||
// The default length of a jQuery object is 0
|
|||
length: 0, |
|||
|
|||
toArray: function() { |
|||
return slice.call( this ); |
|||
}, |
|||
|
|||
// Get the Nth element in the matched element set OR
|
|||
// Get the whole matched element set as a clean array
|
|||
get: function( num ) { |
|||
|
|||
// Return all the elements in a clean array
|
|||
if ( num == null ) { |
|||
return slice.call( this ); |
|||
} |
|||
|
|||
// Return just the one element from the set
|
|||
return num < 0 ? this[ num + this.length ] : this[ num ]; |
|||
}, |
|||
|
|||
// Take an array of elements and push it onto the stack
|
|||
// (returning the new matched element set)
|
|||
pushStack: function( elems ) { |
|||
|
|||
// Build a new jQuery matched element set
|
|||
var ret = jQuery.merge( this.constructor(), elems ); |
|||
|
|||
// Add the old object onto the stack (as a reference)
|
|||
ret.prevObject = this; |
|||
|
|||
// Return the newly-formed element set
|
|||
return ret; |
|||
}, |
|||
|
|||
// Execute a callback for every element in the matched set.
|
|||
each: function( callback ) { |
|||
return jQuery.each( this, callback ); |
|||
}, |
|||
|
|||
map: function( callback ) { |
|||
return this.pushStack( jQuery.map( this, function( elem, i ) { |
|||
return callback.call( elem, i, elem ); |
|||
} ) ); |
|||
}, |
|||
|
|||
slice: function() { |
|||
return this.pushStack( slice.apply( this, arguments ) ); |
|||
}, |
|||
|
|||
first: function() { |
|||
return this.eq( 0 ); |
|||
}, |
|||
|
|||
last: function() { |
|||
return this.eq( -1 ); |
|||
}, |
|||
|
|||
eq: function( i ) { |
|||
var len = this.length, |
|||
j = +i + ( i < 0 ? len : 0 ); |
|||
return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); |
|||
}, |
|||
|
|||
end: function() { |
|||
return this.prevObject || this.constructor(); |
|||
}, |
|||
|
|||
// For internal use only.
|
|||
// Behaves like an Array's method, not like a jQuery method.
|
|||
push: push, |
|||
sort: arr.sort, |
|||
splice: arr.splice |
|||
}; |
|||
|
|||
jQuery.extend = jQuery.fn.extend = function() { |
|||
var options, name, src, copy, copyIsArray, clone, |
|||
target = arguments[ 0 ] || {}, |
|||
i = 1, |
|||
length = arguments.length, |
|||
deep = false; |
|||
|
|||
// Handle a deep copy situation
|
|||
if ( typeof target === "boolean" ) { |
|||
deep = target; |
|||
|
|||
// Skip the boolean and the target
|
|||
target = arguments[ i ] || {}; |
|||
i++; |
|||
} |
|||
|
|||
// Handle case when target is a string or something (possible in deep copy)
|
|||
if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { |
|||
target = {}; |
|||
} |
|||
|
|||
// Extend jQuery itself if only one argument is passed
|
|||
if ( i === length ) { |
|||
target = this; |
|||
i--; |
|||
} |
|||
|
|||
for ( ; i < length; i++ ) { |
|||
|
|||
// Only deal with non-null/undefined values
|
|||
if ( ( options = arguments[ i ] ) != null ) { |
|||
|
|||
// Extend the base object
|
|||
for ( name in options ) { |
|||
src = target[ name ]; |
|||
copy = options[ name ]; |
|||
|
|||
// Prevent never-ending loop
|
|||
if ( target === copy ) { |
|||
continue; |
|||
} |
|||
|
|||
// Recurse if we're merging plain objects or arrays
|
|||
if ( deep && copy && ( jQuery.isPlainObject( copy ) || |
|||
( copyIsArray = Array.isArray( copy ) ) ) ) { |
|||
|
|||
if ( copyIsArray ) { |
|||
copyIsArray = false; |
|||
clone = src && Array.isArray( src ) ? src : []; |
|||
|
|||
} else { |
|||
clone = src && jQuery.isPlainObject( src ) ? src : {}; |
|||
} |
|||
|
|||
// Never move original objects, clone them
|
|||
target[ name ] = jQuery.extend( deep, clone, copy ); |
|||
|
|||
// Don't bring in undefined values
|
|||
} else if ( copy !== undefined ) { |
|||
target[ name ] = copy; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Return the modified object
|
|||
return target; |
|||
}; |
|||
|
|||
jQuery.extend( { |
|||
|
|||
// Unique for each copy of jQuery on the page
|
|||
expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), |
|||
|
|||
// Assume jQuery is ready without the ready module
|
|||
isReady: true, |
|||
|
|||
error: function( msg ) { |
|||
throw new Error( msg ); |
|||
}, |
|||
|
|||
noop: function() {}, |
|||
|
|||
isFunction: function( obj ) { |
|||
return jQuery.type( obj ) === "function"; |
|||
}, |
|||
|
|||
isWindow: function( obj ) { |
|||
return obj != null && obj === obj.window; |
|||
}, |
|||
|
|||
isNumeric: function( obj ) { |
|||
|
|||
// As of jQuery 3.0, isNumeric is limited to
|
|||
// strings and numbers (primitives or objects)
|
|||
// that can be coerced to finite numbers (gh-2662)
|
|||
var type = jQuery.type( obj ); |
|||
return ( type === "number" || type === "string" ) && |
|||
|
|||
// parseFloat NaNs numeric-cast false positives ("")
|
|||
// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
|
|||
// subtraction forces infinities to NaN
|
|||
!isNaN( obj - parseFloat( obj ) ); |
|||
}, |
|||
|
|||
isPlainObject: function( obj ) { |
|||
var proto, Ctor; |
|||
|
|||
// Detect obvious negatives
|
|||
// Use toString instead of jQuery.type to catch host objects
|
|||
if ( !obj || toString.call( obj ) !== "[object Object]" ) { |
|||
return false; |
|||
} |
|||
|
|||
proto = getProto( obj ); |
|||
|
|||
// Objects with no prototype (e.g., `Object.create( null )`) are plain
|
|||
if ( !proto ) { |
|||
return true; |
|||
} |
|||
|
|||
// Objects with prototype are plain iff they were constructed by a global Object function
|
|||
Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; |
|||
return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; |
|||
}, |
|||
|
|||
isEmptyObject: function( obj ) { |
|||
|
|||
/* eslint-disable no-unused-vars */ |
|||
// See https://github.com/eslint/eslint/issues/6125
|
|||
var name; |
|||
|
|||
for ( name in obj ) { |
|||
return false; |
|||
} |
|||
return true; |
|||
}, |
|||
|
|||
type: function( obj ) { |
|||
if ( obj == null ) { |
|||
return obj + ""; |
|||
} |
|||
|
|||
// Support: Android <=2.3 only (functionish RegExp)
|
|||
return typeof obj === "object" || typeof obj === "function" ? |
|||
class2type[ toString.call( obj ) ] || "object" : |
|||
typeof obj; |
|||
}, |
|||
|
|||
// Evaluates a script in a global context
|
|||
globalEval: function( code ) { |
|||
DOMEval( code ); |
|||
}, |
|||
|
|||
// Convert dashed to camelCase; used by the css and data modules
|
|||
// Support: IE <=9 - 11, Edge 12 - 13
|
|||
// Microsoft forgot to hump their vendor prefix (#9572)
|
|||
camelCase: function( string ) { |
|||
return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); |
|||
}, |
|||
|
|||
each: function( obj, callback ) { |
|||
var length, i = 0; |
|||
|
|||
if ( isArrayLike( obj ) ) { |
|||
length = obj.length; |
|||
for ( ; i < length; i++ ) { |
|||
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { |
|||
break; |
|||
} |
|||
} |
|||
} else { |
|||
for ( i in obj ) { |
|||
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return obj; |
|||
}, |
|||
|
|||
// Support: Android <=4.0 only
|
|||
trim: function( text ) { |
|||
return text == null ? |
|||
"" : |
|||
( text + "" ).replace( rtrim, "" ); |
|||
}, |
|||
|
|||
// results is for internal usage only
|
|||
makeArray: function( arr, results ) { |
|||
var ret = results || []; |
|||
|
|||
if ( arr != null ) { |
|||
if ( isArrayLike( Object( arr ) ) ) { |
|||
jQuery.merge( ret, |
|||
typeof arr === "string" ? |
|||
[ arr ] : arr |
|||
); |
|||
} else { |
|||
push.call( ret, arr ); |
|||
} |
|||
} |
|||
|
|||
return ret; |
|||
}, |
|||
|
|||
inArray: function( elem, arr, i ) { |
|||
return arr == null ? -1 : indexOf.call( arr, elem, i ); |
|||
}, |
|||
|
|||
// Support: Android <=4.0 only, PhantomJS 1 only
|
|||
// push.apply(_, arraylike) throws on ancient WebKit
|
|||
merge: function( first, second ) { |
|||
var len = +second.length, |
|||
j = 0, |
|||
i = first.length; |
|||
|
|||
for ( ; j < len; j++ ) { |
|||
first[ i++ ] = second[ j ]; |
|||
} |
|||
|
|||
first.length = i; |
|||
|
|||
return first; |
|||
}, |
|||
|
|||
grep: function( elems, callback, invert ) { |
|||
var callbackInverse, |
|||
matches = [], |
|||
i = 0, |
|||
length = elems.length, |
|||
callbackExpect = !invert; |
|||
|
|||
// Go through the array, only saving the items
|
|||
// that pass the validator function
|
|||
for ( ; i < length; i++ ) { |
|||
callbackInverse = !callback( elems[ i ], i ); |
|||
if ( callbackInverse !== callbackExpect ) { |
|||
matches.push( elems[ i ] ); |
|||
} |
|||
} |
|||
|
|||
return matches; |
|||
}, |
|||
|
|||
// arg is for internal usage only
|
|||
map: function( elems, callback, arg ) { |
|||
var length, value, |
|||
i = 0, |
|||
ret = []; |
|||
|
|||
// Go through the array, translating each of the items to their new values
|
|||
if ( isArrayLike( elems ) ) { |
|||
length = elems.length; |
|||
for ( ; i < length; i++ ) { |
|||
value = callback( elems[ i ], i, arg ); |
|||
|
|||
if ( value != null ) { |
|||
ret.push( value ); |
|||
} |
|||
} |
|||
|
|||
// Go through every key on the object,
|
|||
} else { |
|||
for ( i in elems ) { |
|||
value = callback( elems[ i ], i, arg ); |
|||
|
|||
if ( value != null ) { |
|||
ret.push( value ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Flatten any nested arrays
|
|||
return concat.apply( [], ret ); |
|||
}, |
|||
|
|||
// A global GUID counter for objects
|
|||
guid: 1, |
|||
|
|||
// Bind a function to a context, optionally partially applying any
|
|||
// arguments.
|
|||
proxy: function( fn, context ) { |
|||
var tmp, args, proxy; |
|||
|
|||
if ( typeof context === "string" ) { |
|||
tmp = fn[ context ]; |
|||
context = fn; |
|||
fn = tmp; |
|||
} |
|||
|
|||
// Quick check to determine if target is callable, in the spec
|
|||
// this throws a TypeError, but we will just return undefined.
|
|||
if ( !jQuery.isFunction( fn ) ) { |
|||
return undefined; |
|||
} |
|||
|
|||
// Simulated bind
|
|||
args = slice.call( arguments, 2 ); |
|||
proxy = function() { |
|||
return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); |
|||
}; |
|||
|
|||
// Set the guid of unique handler to the same of original handler, so it can be removed
|
|||
proxy.guid = fn.guid = fn.guid || jQuery.guid++; |
|||
|
|||
return proxy; |
|||
}, |
|||
|
|||
now: Date.now, |
|||
|
|||
// jQuery.support is not used in Core but other projects attach their
|
|||
// properties to it so it needs to exist.
|
|||
support: support |
|||
} ); |
|||
|
|||
if ( typeof Symbol === "function" ) { |
|||
jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; |
|||
} |
|||
|
|||
// Populate the class2type map
|
|||
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), |
|||
function( i, name ) { |
|||
class2type[ "[object " + name + "]" ] = name.toLowerCase(); |
|||
} ); |
|||
|
|||
function isArrayLike( obj ) { |
|||
|
|||
// Support: real iOS 8.2 only (not reproducible in simulator)
|
|||
// `in` check used to prevent JIT error (gh-2145)
|
|||
// hasOwn isn't used here due to false negatives
|
|||
// regarding Nodelist length in IE
|
|||
var length = !!obj && "length" in obj && obj.length, |
|||
type = jQuery.type( obj ); |
|||
|
|||
if ( type === "function" || jQuery.isWindow( obj ) ) { |
|||
return false; |
|||
} |
|||
|
|||
return type === "array" || length === 0 || |
|||
typeof length === "number" && length > 0 && ( length - 1 ) in obj; |
|||
} |
|||
|
|||
return jQuery; |
|||
} ); |
|||
10253
apps/comments/js/vendor/jquery/dist/jquery.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4
apps/comments/js/vendor/jquery/dist/jquery.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1
apps/comments/js/vendor/jquery/dist/jquery.min.map
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
8160
apps/comments/js/vendor/jquery/dist/jquery.slim.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4
apps/comments/js/vendor/jquery/dist/jquery.slim.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1
apps/comments/js/vendor/jquery/dist/jquery.slim.min.map
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,36 @@ |
|||
Copyright jQuery Foundation and other contributors, https://jquery.org/ |
|||
|
|||
This software consists of voluntary contributions made by many |
|||
individuals. For exact contribution history, see the revision history |
|||
available at https://github.com/jquery/sizzle |
|||
|
|||
The following license applies to all parts of this software except as |
|||
documented below: |
|||
|
|||
==== |
|||
|
|||
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. |
|||
|
|||
==== |
|||
|
|||
All files located in the node_modules and external directories are |
|||
externally maintained libraries used by this software which have their |
|||
own licenses; we recommend you read them, as their terms may differ from |
|||
the terms above. |
|||
2272
apps/comments/js/vendor/jquery/external/sizzle/dist/sizzle.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
3
apps/comments/js/vendor/jquery/external/sizzle/dist/sizzle.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1
apps/comments/js/vendor/jquery/external/sizzle/dist/sizzle.min.map
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,5 @@ |
|||
{ |
|||
"root": true, |
|||
|
|||
"extends": "../.eslintrc-browser.json" |
|||
} |
|||
@ -0,0 +1,855 @@ |
|||
define( [ |
|||
"./core", |
|||
"./var/document", |
|||
"./var/rnothtmlwhite", |
|||
"./ajax/var/location", |
|||
"./ajax/var/nonce", |
|||
"./ajax/var/rquery", |
|||
|
|||
"./core/init", |
|||
"./ajax/parseXML", |
|||
"./event/trigger", |
|||
"./deferred", |
|||
"./serialize" // jQuery.param
|
|||
], function( jQuery, document, rnothtmlwhite, location, nonce, rquery ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var |
|||
r20 = /%20/g, |
|||
rhash = /#.*$/, |
|||
rantiCache = /([?&])_=[^&]*/, |
|||
rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, |
|||
|
|||
// #7653, #8125, #8152: local protocol detection
|
|||
rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, |
|||
rnoContent = /^(?:GET|HEAD)$/, |
|||
rprotocol = /^\/\//, |
|||
|
|||
/* Prefilters |
|||
* 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) |
|||
* 2) These are called: |
|||
* - BEFORE asking for a transport |
|||
* - AFTER param serialization (s.data is a string if s.processData is true) |
|||
* 3) key is the dataType |
|||
* 4) the catchall symbol "*" can be used |
|||
* 5) execution will start with transport dataType and THEN continue down to "*" if needed |
|||
*/ |
|||
prefilters = {}, |
|||
|
|||
/* Transports bindings |
|||
* 1) key is the dataType |
|||
* 2) the catchall symbol "*" can be used |
|||
* 3) selection will start with transport dataType and THEN go to "*" if needed |
|||
*/ |
|||
transports = {}, |
|||
|
|||
// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
|
|||
allTypes = "*/".concat( "*" ), |
|||
|
|||
// Anchor tag for parsing the document origin
|
|||
originAnchor = document.createElement( "a" ); |
|||
originAnchor.href = location.href; |
|||
|
|||
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
|
|||
function addToPrefiltersOrTransports( structure ) { |
|||
|
|||
// dataTypeExpression is optional and defaults to "*"
|
|||
return function( dataTypeExpression, func ) { |
|||
|
|||
if ( typeof dataTypeExpression !== "string" ) { |
|||
func = dataTypeExpression; |
|||
dataTypeExpression = "*"; |
|||
} |
|||
|
|||
var dataType, |
|||
i = 0, |
|||
dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; |
|||
|
|||
if ( jQuery.isFunction( func ) ) { |
|||
|
|||
// For each dataType in the dataTypeExpression
|
|||
while ( ( dataType = dataTypes[ i++ ] ) ) { |
|||
|
|||
// Prepend if requested
|
|||
if ( dataType[ 0 ] === "+" ) { |
|||
dataType = dataType.slice( 1 ) || "*"; |
|||
( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); |
|||
|
|||
// Otherwise append
|
|||
} else { |
|||
( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
|
|||
// Base inspection function for prefilters and transports
|
|||
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { |
|||
|
|||
var inspected = {}, |
|||
seekingTransport = ( structure === transports ); |
|||
|
|||
function inspect( dataType ) { |
|||
var selected; |
|||
inspected[ dataType ] = true; |
|||
jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { |
|||
var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); |
|||
if ( typeof dataTypeOrTransport === "string" && |
|||
!seekingTransport && !inspected[ dataTypeOrTransport ] ) { |
|||
|
|||
options.dataTypes.unshift( dataTypeOrTransport ); |
|||
inspect( dataTypeOrTransport ); |
|||
return false; |
|||
} else if ( seekingTransport ) { |
|||
return !( selected = dataTypeOrTransport ); |
|||
} |
|||
} ); |
|||
return selected; |
|||
} |
|||
|
|||
return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); |
|||
} |
|||
|
|||
// A special extend for ajax options
|
|||
// that takes "flat" options (not to be deep extended)
|
|||
// Fixes #9887
|
|||
function ajaxExtend( target, src ) { |
|||
var key, deep, |
|||
flatOptions = jQuery.ajaxSettings.flatOptions || {}; |
|||
|
|||
for ( key in src ) { |
|||
if ( src[ key ] !== undefined ) { |
|||
( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; |
|||
} |
|||
} |
|||
if ( deep ) { |
|||
jQuery.extend( true, target, deep ); |
|||
} |
|||
|
|||
return target; |
|||
} |
|||
|
|||
/* Handles responses to an ajax request: |
|||
* - finds the right dataType (mediates between content-type and expected dataType) |
|||
* - returns the corresponding response |
|||
*/ |
|||
function ajaxHandleResponses( s, jqXHR, responses ) { |
|||
|
|||
var ct, type, finalDataType, firstDataType, |
|||
contents = s.contents, |
|||
dataTypes = s.dataTypes; |
|||
|
|||
// Remove auto dataType and get content-type in the process
|
|||
while ( dataTypes[ 0 ] === "*" ) { |
|||
dataTypes.shift(); |
|||
if ( ct === undefined ) { |
|||
ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); |
|||
} |
|||
} |
|||
|
|||
// Check if we're dealing with a known content-type
|
|||
if ( ct ) { |
|||
for ( type in contents ) { |
|||
if ( contents[ type ] && contents[ type ].test( ct ) ) { |
|||
dataTypes.unshift( type ); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Check to see if we have a response for the expected dataType
|
|||
if ( dataTypes[ 0 ] in responses ) { |
|||
finalDataType = dataTypes[ 0 ]; |
|||
} else { |
|||
|
|||
// Try convertible dataTypes
|
|||
for ( type in responses ) { |
|||
if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { |
|||
finalDataType = type; |
|||
break; |
|||
} |
|||
if ( !firstDataType ) { |
|||
firstDataType = type; |
|||
} |
|||
} |
|||
|
|||
// Or just use first one
|
|||
finalDataType = finalDataType || firstDataType; |
|||
} |
|||
|
|||
// If we found a dataType
|
|||
// We add the dataType to the list if needed
|
|||
// and return the corresponding response
|
|||
if ( finalDataType ) { |
|||
if ( finalDataType !== dataTypes[ 0 ] ) { |
|||
dataTypes.unshift( finalDataType ); |
|||
} |
|||
return responses[ finalDataType ]; |
|||
} |
|||
} |
|||
|
|||
/* Chain conversions given the request and the original response |
|||
* Also sets the responseXXX fields on the jqXHR instance |
|||
*/ |
|||
function ajaxConvert( s, response, jqXHR, isSuccess ) { |
|||
var conv2, current, conv, tmp, prev, |
|||
converters = {}, |
|||
|
|||
// Work with a copy of dataTypes in case we need to modify it for conversion
|
|||
dataTypes = s.dataTypes.slice(); |
|||
|
|||
// Create converters map with lowercased keys
|
|||
if ( dataTypes[ 1 ] ) { |
|||
for ( conv in s.converters ) { |
|||
converters[ conv.toLowerCase() ] = s.converters[ conv ]; |
|||
} |
|||
} |
|||
|
|||
current = dataTypes.shift(); |
|||
|
|||
// Convert to each sequential dataType
|
|||
while ( current ) { |
|||
|
|||
if ( s.responseFields[ current ] ) { |
|||
jqXHR[ s.responseFields[ current ] ] = response; |
|||
} |
|||
|
|||
// Apply the dataFilter if provided
|
|||
if ( !prev && isSuccess && s.dataFilter ) { |
|||
response = s.dataFilter( response, s.dataType ); |
|||
} |
|||
|
|||
prev = current; |
|||
current = dataTypes.shift(); |
|||
|
|||
if ( current ) { |
|||
|
|||
// There's only work to do if current dataType is non-auto
|
|||
if ( current === "*" ) { |
|||
|
|||
current = prev; |
|||
|
|||
// Convert response if prev dataType is non-auto and differs from current
|
|||
} else if ( prev !== "*" && prev !== current ) { |
|||
|
|||
// Seek a direct converter
|
|||
conv = converters[ prev + " " + current ] || converters[ "* " + current ]; |
|||
|
|||
// If none found, seek a pair
|
|||
if ( !conv ) { |
|||
for ( conv2 in converters ) { |
|||
|
|||
// If conv2 outputs current
|
|||
tmp = conv2.split( " " ); |
|||
if ( tmp[ 1 ] === current ) { |
|||
|
|||
// If prev can be converted to accepted input
|
|||
conv = converters[ prev + " " + tmp[ 0 ] ] || |
|||
converters[ "* " + tmp[ 0 ] ]; |
|||
if ( conv ) { |
|||
|
|||
// Condense equivalence converters
|
|||
if ( conv === true ) { |
|||
conv = converters[ conv2 ]; |
|||
|
|||
// Otherwise, insert the intermediate dataType
|
|||
} else if ( converters[ conv2 ] !== true ) { |
|||
current = tmp[ 0 ]; |
|||
dataTypes.unshift( tmp[ 1 ] ); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Apply converter (if not an equivalence)
|
|||
if ( conv !== true ) { |
|||
|
|||
// Unless errors are allowed to bubble, catch and return them
|
|||
if ( conv && s.throws ) { |
|||
response = conv( response ); |
|||
} else { |
|||
try { |
|||
response = conv( response ); |
|||
} catch ( e ) { |
|||
return { |
|||
state: "parsererror", |
|||
error: conv ? e : "No conversion from " + prev + " to " + current |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return { state: "success", data: response }; |
|||
} |
|||
|
|||
jQuery.extend( { |
|||
|
|||
// Counter for holding the number of active queries
|
|||
active: 0, |
|||
|
|||
// Last-Modified header cache for next request
|
|||
lastModified: {}, |
|||
etag: {}, |
|||
|
|||
ajaxSettings: { |
|||
url: location.href, |
|||
type: "GET", |
|||
isLocal: rlocalProtocol.test( location.protocol ), |
|||
global: true, |
|||
processData: true, |
|||
async: true, |
|||
contentType: "application/x-www-form-urlencoded; charset=UTF-8", |
|||
|
|||
/* |
|||
timeout: 0, |
|||
data: null, |
|||
dataType: null, |
|||
username: null, |
|||
password: null, |
|||
cache: null, |
|||
throws: false, |
|||
traditional: false, |
|||
headers: {}, |
|||
*/ |
|||
|
|||
accepts: { |
|||
"*": allTypes, |
|||
text: "text/plain", |
|||
html: "text/html", |
|||
xml: "application/xml, text/xml", |
|||
json: "application/json, text/javascript" |
|||
}, |
|||
|
|||
contents: { |
|||
xml: /\bxml\b/, |
|||
html: /\bhtml/, |
|||
json: /\bjson\b/ |
|||
}, |
|||
|
|||
responseFields: { |
|||
xml: "responseXML", |
|||
text: "responseText", |
|||
json: "responseJSON" |
|||
}, |
|||
|
|||
// Data converters
|
|||
// Keys separate source (or catchall "*") and destination types with a single space
|
|||
converters: { |
|||
|
|||
// Convert anything to text
|
|||
"* text": String, |
|||
|
|||
// Text to html (true = no transformation)
|
|||
"text html": true, |
|||
|
|||
// Evaluate text as a json expression
|
|||
"text json": JSON.parse, |
|||
|
|||
// Parse text as xml
|
|||
"text xml": jQuery.parseXML |
|||
}, |
|||
|
|||
// For options that shouldn't be deep extended:
|
|||
// you can add your own custom options here if
|
|||
// and when you create one that shouldn't be
|
|||
// deep extended (see ajaxExtend)
|
|||
flatOptions: { |
|||
url: true, |
|||
context: true |
|||
} |
|||
}, |
|||
|
|||
// Creates a full fledged settings object into target
|
|||
// with both ajaxSettings and settings fields.
|
|||
// If target is omitted, writes into ajaxSettings.
|
|||
ajaxSetup: function( target, settings ) { |
|||
return settings ? |
|||
|
|||
// Building a settings object
|
|||
ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : |
|||
|
|||
// Extending ajaxSettings
|
|||
ajaxExtend( jQuery.ajaxSettings, target ); |
|||
}, |
|||
|
|||
ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), |
|||
ajaxTransport: addToPrefiltersOrTransports( transports ), |
|||
|
|||
// Main method
|
|||
ajax: function( url, options ) { |
|||
|
|||
// If url is an object, simulate pre-1.5 signature
|
|||
if ( typeof url === "object" ) { |
|||
options = url; |
|||
url = undefined; |
|||
} |
|||
|
|||
// Force options to be an object
|
|||
options = options || {}; |
|||
|
|||
var transport, |
|||
|
|||
// URL without anti-cache param
|
|||
cacheURL, |
|||
|
|||
// Response headers
|
|||
responseHeadersString, |
|||
responseHeaders, |
|||
|
|||
// timeout handle
|
|||
timeoutTimer, |
|||
|
|||
// Url cleanup var
|
|||
urlAnchor, |
|||
|
|||
// Request state (becomes false upon send and true upon completion)
|
|||
completed, |
|||
|
|||
// To know if global events are to be dispatched
|
|||
fireGlobals, |
|||
|
|||
// Loop variable
|
|||
i, |
|||
|
|||
// uncached part of the url
|
|||
uncached, |
|||
|
|||
// Create the final options object
|
|||
s = jQuery.ajaxSetup( {}, options ), |
|||
|
|||
// Callbacks context
|
|||
callbackContext = s.context || s, |
|||
|
|||
// Context for global events is callbackContext if it is a DOM node or jQuery collection
|
|||
globalEventContext = s.context && |
|||
( callbackContext.nodeType || callbackContext.jquery ) ? |
|||
jQuery( callbackContext ) : |
|||
jQuery.event, |
|||
|
|||
// Deferreds
|
|||
deferred = jQuery.Deferred(), |
|||
completeDeferred = jQuery.Callbacks( "once memory" ), |
|||
|
|||
// Status-dependent callbacks
|
|||
statusCode = s.statusCode || {}, |
|||
|
|||
// Headers (they are sent all at once)
|
|||
requestHeaders = {}, |
|||
requestHeadersNames = {}, |
|||
|
|||
// Default abort message
|
|||
strAbort = "canceled", |
|||
|
|||
// Fake xhr
|
|||
jqXHR = { |
|||
readyState: 0, |
|||
|
|||
// Builds headers hashtable if needed
|
|||
getResponseHeader: function( key ) { |
|||
var match; |
|||
if ( completed ) { |
|||
if ( !responseHeaders ) { |
|||
responseHeaders = {}; |
|||
while ( ( match = rheaders.exec( responseHeadersString ) ) ) { |
|||
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; |
|||
} |
|||
} |
|||
match = responseHeaders[ key.toLowerCase() ]; |
|||
} |
|||
return match == null ? null : match; |
|||
}, |
|||
|
|||
// Raw string
|
|||
getAllResponseHeaders: function() { |
|||
return completed ? responseHeadersString : null; |
|||
}, |
|||
|
|||
// Caches the header
|
|||
setRequestHeader: function( name, value ) { |
|||
if ( completed == null ) { |
|||
name = requestHeadersNames[ name.toLowerCase() ] = |
|||
requestHeadersNames[ name.toLowerCase() ] || name; |
|||
requestHeaders[ name ] = value; |
|||
} |
|||
return this; |
|||
}, |
|||
|
|||
// Overrides response content-type header
|
|||
overrideMimeType: function( type ) { |
|||
if ( completed == null ) { |
|||
s.mimeType = type; |
|||
} |
|||
return this; |
|||
}, |
|||
|
|||
// Status-dependent callbacks
|
|||
statusCode: function( map ) { |
|||
var code; |
|||
if ( map ) { |
|||
if ( completed ) { |
|||
|
|||
// Execute the appropriate callbacks
|
|||
jqXHR.always( map[ jqXHR.status ] ); |
|||
} else { |
|||
|
|||
// Lazy-add the new callbacks in a way that preserves old ones
|
|||
for ( code in map ) { |
|||
statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; |
|||
} |
|||
} |
|||
} |
|||
return this; |
|||
}, |
|||
|
|||
// Cancel the request
|
|||
abort: function( statusText ) { |
|||
var finalText = statusText || strAbort; |
|||
if ( transport ) { |
|||
transport.abort( finalText ); |
|||
} |
|||
done( 0, finalText ); |
|||
return this; |
|||
} |
|||
}; |
|||
|
|||
// Attach deferreds
|
|||
deferred.promise( jqXHR ); |
|||
|
|||
// Add protocol if not provided (prefilters might expect it)
|
|||
// Handle falsy url in the settings object (#10093: consistency with old signature)
|
|||
// We also use the url parameter if available
|
|||
s.url = ( ( url || s.url || location.href ) + "" ) |
|||
.replace( rprotocol, location.protocol + "//" ); |
|||
|
|||
// Alias method option to type as per ticket #12004
|
|||
s.type = options.method || options.type || s.method || s.type; |
|||
|
|||
// Extract dataTypes list
|
|||
s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; |
|||
|
|||
// A cross-domain request is in order when the origin doesn't match the current origin.
|
|||
if ( s.crossDomain == null ) { |
|||
urlAnchor = document.createElement( "a" ); |
|||
|
|||
// Support: IE <=8 - 11, Edge 12 - 13
|
|||
// IE throws exception on accessing the href property if url is malformed,
|
|||
// e.g. http://example.com:80x/
|
|||
try { |
|||
urlAnchor.href = s.url; |
|||
|
|||
// Support: IE <=8 - 11 only
|
|||
// Anchor's host property isn't correctly set when s.url is relative
|
|||
urlAnchor.href = urlAnchor.href; |
|||
s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== |
|||
urlAnchor.protocol + "//" + urlAnchor.host; |
|||
} catch ( e ) { |
|||
|
|||
// If there is an error parsing the URL, assume it is crossDomain,
|
|||
// it can be rejected by the transport if it is invalid
|
|||
s.crossDomain = true; |
|||
} |
|||
} |
|||
|
|||
// Convert data if not already a string
|
|||
if ( s.data && s.processData && typeof s.data !== "string" ) { |
|||
s.data = jQuery.param( s.data, s.traditional ); |
|||
} |
|||
|
|||
// Apply prefilters
|
|||
inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); |
|||
|
|||
// If request was aborted inside a prefilter, stop there
|
|||
if ( completed ) { |
|||
return jqXHR; |
|||
} |
|||
|
|||
// We can fire global events as of now if asked to
|
|||
// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
|
|||
fireGlobals = jQuery.event && s.global; |
|||
|
|||
// Watch for a new set of requests
|
|||
if ( fireGlobals && jQuery.active++ === 0 ) { |
|||
jQuery.event.trigger( "ajaxStart" ); |
|||
} |
|||
|
|||
// Uppercase the type
|
|||
s.type = s.type.toUpperCase(); |
|||
|
|||
// Determine if request has content
|
|||
s.hasContent = !rnoContent.test( s.type ); |
|||
|
|||
// Save the URL in case we're toying with the If-Modified-Since
|
|||
// and/or If-None-Match header later on
|
|||
// Remove hash to simplify url manipulation
|
|||
cacheURL = s.url.replace( rhash, "" ); |
|||
|
|||
// More options handling for requests with no content
|
|||
if ( !s.hasContent ) { |
|||
|
|||
// Remember the hash so we can put it back
|
|||
uncached = s.url.slice( cacheURL.length ); |
|||
|
|||
// If data is available, append data to url
|
|||
if ( s.data ) { |
|||
cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; |
|||
|
|||
// #9682: remove data so that it's not used in an eventual retry
|
|||
delete s.data; |
|||
} |
|||
|
|||
// Add or update anti-cache param if needed
|
|||
if ( s.cache === false ) { |
|||
cacheURL = cacheURL.replace( rantiCache, "$1" ); |
|||
uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; |
|||
} |
|||
|
|||
// Put hash and anti-cache on the URL that will be requested (gh-1732)
|
|||
s.url = cacheURL + uncached; |
|||
|
|||
// Change '%20' to '+' if this is encoded form body content (gh-2658)
|
|||
} else if ( s.data && s.processData && |
|||
( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { |
|||
s.data = s.data.replace( r20, "+" ); |
|||
} |
|||
|
|||
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
|
|||
if ( s.ifModified ) { |
|||
if ( jQuery.lastModified[ cacheURL ] ) { |
|||
jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); |
|||
} |
|||
if ( jQuery.etag[ cacheURL ] ) { |
|||
jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); |
|||
} |
|||
} |
|||
|
|||
// Set the correct header, if data is being sent
|
|||
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { |
|||
jqXHR.setRequestHeader( "Content-Type", s.contentType ); |
|||
} |
|||
|
|||
// Set the Accepts header for the server, depending on the dataType
|
|||
jqXHR.setRequestHeader( |
|||
"Accept", |
|||
s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? |
|||
s.accepts[ s.dataTypes[ 0 ] ] + |
|||
( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : |
|||
s.accepts[ "*" ] |
|||
); |
|||
|
|||
// Check for headers option
|
|||
for ( i in s.headers ) { |
|||
jqXHR.setRequestHeader( i, s.headers[ i ] ); |
|||
} |
|||
|
|||
// Allow custom headers/mimetypes and early abort
|
|||
if ( s.beforeSend && |
|||
( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { |
|||
|
|||
// Abort if not done already and return
|
|||
return jqXHR.abort(); |
|||
} |
|||
|
|||
// Aborting is no longer a cancellation
|
|||
strAbort = "abort"; |
|||
|
|||
// Install callbacks on deferreds
|
|||
completeDeferred.add( s.complete ); |
|||
jqXHR.done( s.success ); |
|||
jqXHR.fail( s.error ); |
|||
|
|||
// Get transport
|
|||
transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); |
|||
|
|||
// If no transport, we auto-abort
|
|||
if ( !transport ) { |
|||
done( -1, "No Transport" ); |
|||
} else { |
|||
jqXHR.readyState = 1; |
|||
|
|||
// Send global event
|
|||
if ( fireGlobals ) { |
|||
globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); |
|||
} |
|||
|
|||
// If request was aborted inside ajaxSend, stop there
|
|||
if ( completed ) { |
|||
return jqXHR; |
|||
} |
|||
|
|||
// Timeout
|
|||
if ( s.async && s.timeout > 0 ) { |
|||
timeoutTimer = window.setTimeout( function() { |
|||
jqXHR.abort( "timeout" ); |
|||
}, s.timeout ); |
|||
} |
|||
|
|||
try { |
|||
completed = false; |
|||
transport.send( requestHeaders, done ); |
|||
} catch ( e ) { |
|||
|
|||
// Rethrow post-completion exceptions
|
|||
if ( completed ) { |
|||
throw e; |
|||
} |
|||
|
|||
// Propagate others as results
|
|||
done( -1, e ); |
|||
} |
|||
} |
|||
|
|||
// Callback for when everything is done
|
|||
function done( status, nativeStatusText, responses, headers ) { |
|||
var isSuccess, success, error, response, modified, |
|||
statusText = nativeStatusText; |
|||
|
|||
// Ignore repeat invocations
|
|||
if ( completed ) { |
|||
return; |
|||
} |
|||
|
|||
completed = true; |
|||
|
|||
// Clear timeout if it exists
|
|||
if ( timeoutTimer ) { |
|||
window.clearTimeout( timeoutTimer ); |
|||
} |
|||
|
|||
// Dereference transport for early garbage collection
|
|||
// (no matter how long the jqXHR object will be used)
|
|||
transport = undefined; |
|||
|
|||
// Cache response headers
|
|||
responseHeadersString = headers || ""; |
|||
|
|||
// Set readyState
|
|||
jqXHR.readyState = status > 0 ? 4 : 0; |
|||
|
|||
// Determine if successful
|
|||
isSuccess = status >= 200 && status < 300 || status === 304; |
|||
|
|||
// Get response data
|
|||
if ( responses ) { |
|||
response = ajaxHandleResponses( s, jqXHR, responses ); |
|||
} |
|||
|
|||
// Convert no matter what (that way responseXXX fields are always set)
|
|||
response = ajaxConvert( s, response, jqXHR, isSuccess ); |
|||
|
|||
// If successful, handle type chaining
|
|||
if ( isSuccess ) { |
|||
|
|||
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
|
|||
if ( s.ifModified ) { |
|||
modified = jqXHR.getResponseHeader( "Last-Modified" ); |
|||
if ( modified ) { |
|||
jQuery.lastModified[ cacheURL ] = modified; |
|||
} |
|||
modified = jqXHR.getResponseHeader( "etag" ); |
|||
if ( modified ) { |
|||
jQuery.etag[ cacheURL ] = modified; |
|||
} |
|||
} |
|||
|
|||
// if no content
|
|||
if ( status === 204 || s.type === "HEAD" ) { |
|||
statusText = "nocontent"; |
|||
|
|||
// if not modified
|
|||
} else if ( status === 304 ) { |
|||
statusText = "notmodified"; |
|||
|
|||
// If we have data, let's convert it
|
|||
} else { |
|||
statusText = response.state; |
|||
success = response.data; |
|||
error = response.error; |
|||
isSuccess = !error; |
|||
} |
|||
} else { |
|||
|
|||
// Extract error from statusText and normalize for non-aborts
|
|||
error = statusText; |
|||
if ( status || !statusText ) { |
|||
statusText = "error"; |
|||
if ( status < 0 ) { |
|||
status = 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Set data for the fake xhr object
|
|||
jqXHR.status = status; |
|||
jqXHR.statusText = ( nativeStatusText || statusText ) + ""; |
|||
|
|||
// Success/Error
|
|||
if ( isSuccess ) { |
|||
deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); |
|||
} else { |
|||
deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); |
|||
} |
|||
|
|||
// Status-dependent callbacks
|
|||
jqXHR.statusCode( statusCode ); |
|||
statusCode = undefined; |
|||
|
|||
if ( fireGlobals ) { |
|||
globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", |
|||
[ jqXHR, s, isSuccess ? success : error ] ); |
|||
} |
|||
|
|||
// Complete
|
|||
completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); |
|||
|
|||
if ( fireGlobals ) { |
|||
globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); |
|||
|
|||
// Handle the global AJAX counter
|
|||
if ( !( --jQuery.active ) ) { |
|||
jQuery.event.trigger( "ajaxStop" ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return jqXHR; |
|||
}, |
|||
|
|||
getJSON: function( url, data, callback ) { |
|||
return jQuery.get( url, data, callback, "json" ); |
|||
}, |
|||
|
|||
getScript: function( url, callback ) { |
|||
return jQuery.get( url, undefined, callback, "script" ); |
|||
} |
|||
} ); |
|||
|
|||
jQuery.each( [ "get", "post" ], function( i, method ) { |
|||
jQuery[ method ] = function( url, data, callback, type ) { |
|||
|
|||
// Shift arguments if data argument was omitted
|
|||
if ( jQuery.isFunction( data ) ) { |
|||
type = type || callback; |
|||
callback = data; |
|||
data = undefined; |
|||
} |
|||
|
|||
// The url can be an options object (which then must have .url)
|
|||
return jQuery.ajax( jQuery.extend( { |
|||
url: url, |
|||
type: method, |
|||
dataType: type, |
|||
data: data, |
|||
success: callback |
|||
}, jQuery.isPlainObject( url ) && url ) ); |
|||
}; |
|||
} ); |
|||
|
|||
return jQuery; |
|||
} ); |
|||
@ -0,0 +1,102 @@ |
|||
define( [ |
|||
"../core", |
|||
"./var/nonce", |
|||
"./var/rquery", |
|||
"../ajax" |
|||
], function( jQuery, nonce, rquery ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var oldCallbacks = [], |
|||
rjsonp = /(=)\?(?=&|$)|\?\?/; |
|||
|
|||
// Default jsonp settings
|
|||
jQuery.ajaxSetup( { |
|||
jsonp: "callback", |
|||
jsonpCallback: function() { |
|||
var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); |
|||
this[ callback ] = true; |
|||
return callback; |
|||
} |
|||
} ); |
|||
|
|||
// Detect, normalize options and install callbacks for jsonp requests
|
|||
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { |
|||
|
|||
var callbackName, overwritten, responseContainer, |
|||
jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? |
|||
"url" : |
|||
typeof s.data === "string" && |
|||
( s.contentType || "" ) |
|||
.indexOf( "application/x-www-form-urlencoded" ) === 0 && |
|||
rjsonp.test( s.data ) && "data" |
|||
); |
|||
|
|||
// Handle iff the expected data type is "jsonp" or we have a parameter to set
|
|||
if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { |
|||
|
|||
// Get callback name, remembering preexisting value associated with it
|
|||
callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? |
|||
s.jsonpCallback() : |
|||
s.jsonpCallback; |
|||
|
|||
// Insert callback into url or form data
|
|||
if ( jsonProp ) { |
|||
s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); |
|||
} else if ( s.jsonp !== false ) { |
|||
s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; |
|||
} |
|||
|
|||
// Use data converter to retrieve json after script execution
|
|||
s.converters[ "script json" ] = function() { |
|||
if ( !responseContainer ) { |
|||
jQuery.error( callbackName + " was not called" ); |
|||
} |
|||
return responseContainer[ 0 ]; |
|||
}; |
|||
|
|||
// Force json dataType
|
|||
s.dataTypes[ 0 ] = "json"; |
|||
|
|||
// Install callback
|
|||
overwritten = window[ callbackName ]; |
|||
window[ callbackName ] = function() { |
|||
responseContainer = arguments; |
|||
}; |
|||
|
|||
// Clean-up function (fires after converters)
|
|||
jqXHR.always( function() { |
|||
|
|||
// If previous value didn't exist - remove it
|
|||
if ( overwritten === undefined ) { |
|||
jQuery( window ).removeProp( callbackName ); |
|||
|
|||
// Otherwise restore preexisting value
|
|||
} else { |
|||
window[ callbackName ] = overwritten; |
|||
} |
|||
|
|||
// Save back as free
|
|||
if ( s[ callbackName ] ) { |
|||
|
|||
// Make sure that re-using the options doesn't screw things around
|
|||
s.jsonpCallback = originalSettings.jsonpCallback; |
|||
|
|||
// Save the callback name for future use
|
|||
oldCallbacks.push( callbackName ); |
|||
} |
|||
|
|||
// Call if it was a function and we have a response
|
|||
if ( responseContainer && jQuery.isFunction( overwritten ) ) { |
|||
overwritten( responseContainer[ 0 ] ); |
|||
} |
|||
|
|||
responseContainer = overwritten = undefined; |
|||
} ); |
|||
|
|||
// Delegate to script
|
|||
return "script"; |
|||
} |
|||
} ); |
|||
|
|||
} ); |
|||
@ -0,0 +1,76 @@ |
|||
define( [ |
|||
"../core", |
|||
"../core/stripAndCollapse", |
|||
"../core/parseHTML", |
|||
"../ajax", |
|||
"../traversing", |
|||
"../manipulation", |
|||
"../selector" |
|||
], function( jQuery, stripAndCollapse ) { |
|||
|
|||
"use strict"; |
|||
|
|||
/** |
|||
* Load a url into a page |
|||
*/ |
|||
jQuery.fn.load = function( url, params, callback ) { |
|||
var selector, type, response, |
|||
self = this, |
|||
off = url.indexOf( " " ); |
|||
|
|||
if ( off > -1 ) { |
|||
selector = stripAndCollapse( url.slice( off ) ); |
|||
url = url.slice( 0, off ); |
|||
} |
|||
|
|||
// If it's a function
|
|||
if ( jQuery.isFunction( params ) ) { |
|||
|
|||
// We assume that it's the callback
|
|||
callback = params; |
|||
params = undefined; |
|||
|
|||
// Otherwise, build a param string
|
|||
} else if ( params && typeof params === "object" ) { |
|||
type = "POST"; |
|||
} |
|||
|
|||
// If we have elements to modify, make the request
|
|||
if ( self.length > 0 ) { |
|||
jQuery.ajax( { |
|||
url: url, |
|||
|
|||
// If "type" variable is undefined, then "GET" method will be used.
|
|||
// Make value of this field explicit since
|
|||
// user can override it through ajaxSetup method
|
|||
type: type || "GET", |
|||
dataType: "html", |
|||
data: params |
|||
} ).done( function( responseText ) { |
|||
|
|||
// Save response for use in complete callback
|
|||
response = arguments; |
|||
|
|||
self.html( selector ? |
|||
|
|||
// If a selector was specified, locate the right elements in a dummy div
|
|||
// Exclude scripts to avoid IE 'Permission Denied' errors
|
|||
jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) : |
|||
|
|||
// Otherwise use the full result
|
|||
responseText ); |
|||
|
|||
// If the request succeeds, this function gets "data", "status", "jqXHR"
|
|||
// but they are ignored because response was set above.
|
|||
// If it fails, this function gets "jqXHR", "status", "error"
|
|||
} ).always( callback && function( jqXHR, status ) { |
|||
self.each( function() { |
|||
callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] ); |
|||
} ); |
|||
} ); |
|||
} |
|||
|
|||
return this; |
|||
}; |
|||
|
|||
} ); |
|||
@ -0,0 +1,30 @@ |
|||
define( [ |
|||
"../core" |
|||
], function( jQuery ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// Cross-browser xml parsing
|
|||
jQuery.parseXML = function( data ) { |
|||
var xml; |
|||
if ( !data || typeof data !== "string" ) { |
|||
return null; |
|||
} |
|||
|
|||
// Support: IE 9 - 11 only
|
|||
// IE throws on parseFromString with invalid input.
|
|||
try { |
|||
xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); |
|||
} catch ( e ) { |
|||
xml = undefined; |
|||
} |
|||
|
|||
if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { |
|||
jQuery.error( "Invalid XML: " + data ); |
|||
} |
|||
return xml; |
|||
}; |
|||
|
|||
return jQuery.parseXML; |
|||
|
|||
} ); |
|||
@ -0,0 +1,77 @@ |
|||
define( [ |
|||
"../core", |
|||
"../var/document", |
|||
"../ajax" |
|||
], function( jQuery, document ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
|
|||
jQuery.ajaxPrefilter( function( s ) { |
|||
if ( s.crossDomain ) { |
|||
s.contents.script = false; |
|||
} |
|||
} ); |
|||
|
|||
// Install script dataType
|
|||
jQuery.ajaxSetup( { |
|||
accepts: { |
|||
script: "text/javascript, application/javascript, " + |
|||
"application/ecmascript, application/x-ecmascript" |
|||
}, |
|||
contents: { |
|||
script: /\b(?:java|ecma)script\b/ |
|||
}, |
|||
converters: { |
|||
"text script": function( text ) { |
|||
jQuery.globalEval( text ); |
|||
return text; |
|||
} |
|||
} |
|||
} ); |
|||
|
|||
// Handle cache's special case and crossDomain
|
|||
jQuery.ajaxPrefilter( "script", function( s ) { |
|||
if ( s.cache === undefined ) { |
|||
s.cache = false; |
|||
} |
|||
if ( s.crossDomain ) { |
|||
s.type = "GET"; |
|||
} |
|||
} ); |
|||
|
|||
// Bind script tag hack transport
|
|||
jQuery.ajaxTransport( "script", function( s ) { |
|||
|
|||
// This transport only deals with cross domain requests
|
|||
if ( s.crossDomain ) { |
|||
var script, callback; |
|||
return { |
|||
send: function( _, complete ) { |
|||
script = jQuery( "<script>" ).prop( { |
|||
charset: s.scriptCharset, |
|||
src: s.url |
|||
} ).on( |
|||
"load error", |
|||
callback = function( evt ) { |
|||
script.remove(); |
|||
callback = null; |
|||
if ( evt ) { |
|||
complete( evt.type === "error" ? 404 : 200, evt.type ); |
|||
} |
|||
} |
|||
); |
|||
|
|||
// Use native DOM manipulation to avoid our domManip AJAX trickery
|
|||
document.head.appendChild( script[ 0 ] ); |
|||
}, |
|||
abort: function() { |
|||
if ( callback ) { |
|||
callback(); |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
} ); |
|||
|
|||
} ); |
|||
@ -0,0 +1,5 @@ |
|||
define( function() { |
|||
"use strict"; |
|||
|
|||
return window.location; |
|||
} ); |
|||
@ -0,0 +1,7 @@ |
|||
define( [ |
|||
"../../core" |
|||
], function( jQuery ) { |
|||
"use strict"; |
|||
|
|||
return jQuery.now(); |
|||
} ); |
|||
@ -0,0 +1,5 @@ |
|||
define( function() { |
|||
"use strict"; |
|||
|
|||
return ( /\?/ ); |
|||
} ); |
|||
@ -0,0 +1,169 @@ |
|||
define( [ |
|||
"../core", |
|||
"../var/support", |
|||
"../ajax" |
|||
], function( jQuery, support ) { |
|||
|
|||
"use strict"; |
|||
|
|||
jQuery.ajaxSettings.xhr = function() { |
|||
try { |
|||
return new window.XMLHttpRequest(); |
|||
} catch ( e ) {} |
|||
}; |
|||
|
|||
var xhrSuccessStatus = { |
|||
|
|||
// File protocol always yields status code 0, assume 200
|
|||
0: 200, |
|||
|
|||
// Support: IE <=9 only
|
|||
// #1450: sometimes IE returns 1223 when it should be 204
|
|||
1223: 204 |
|||
}, |
|||
xhrSupported = jQuery.ajaxSettings.xhr(); |
|||
|
|||
support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); |
|||
support.ajax = xhrSupported = !!xhrSupported; |
|||
|
|||
jQuery.ajaxTransport( function( options ) { |
|||
var callback, errorCallback; |
|||
|
|||
// Cross domain only allowed if supported through XMLHttpRequest
|
|||
if ( support.cors || xhrSupported && !options.crossDomain ) { |
|||
return { |
|||
send: function( headers, complete ) { |
|||
var i, |
|||
xhr = options.xhr(); |
|||
|
|||
xhr.open( |
|||
options.type, |
|||
options.url, |
|||
options.async, |
|||
options.username, |
|||
options.password |
|||
); |
|||
|
|||
// Apply custom fields if provided
|
|||
if ( options.xhrFields ) { |
|||
for ( i in options.xhrFields ) { |
|||
xhr[ i ] = options.xhrFields[ i ]; |
|||
} |
|||
} |
|||
|
|||
// Override mime type if needed
|
|||
if ( options.mimeType && xhr.overrideMimeType ) { |
|||
xhr.overrideMimeType( options.mimeType ); |
|||
} |
|||
|
|||
// X-Requested-With header
|
|||
// For cross-domain requests, seeing as conditions for a preflight are
|
|||
// akin to a jigsaw puzzle, we simply never set it to be sure.
|
|||
// (it can always be set on a per-request basis or even using ajaxSetup)
|
|||
// For same-domain requests, won't change header if already provided.
|
|||
if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { |
|||
headers[ "X-Requested-With" ] = "XMLHttpRequest"; |
|||
} |
|||
|
|||
// Set headers
|
|||
for ( i in headers ) { |
|||
xhr.setRequestHeader( i, headers[ i ] ); |
|||
} |
|||
|
|||
// Callback
|
|||
callback = function( type ) { |
|||
return function() { |
|||
if ( callback ) { |
|||
callback = errorCallback = xhr.onload = |
|||
xhr.onerror = xhr.onabort = xhr.onreadystatechange = null; |
|||
|
|||
if ( type === "abort" ) { |
|||
xhr.abort(); |
|||
} else if ( type === "error" ) { |
|||
|
|||
// Support: IE <=9 only
|
|||
// On a manual native abort, IE9 throws
|
|||
// errors on any property access that is not readyState
|
|||
if ( typeof xhr.status !== "number" ) { |
|||
complete( 0, "error" ); |
|||
} else { |
|||
complete( |
|||
|
|||
// File: protocol always yields status 0; see #8605, #14207
|
|||
xhr.status, |
|||
xhr.statusText |
|||
); |
|||
} |
|||
} else { |
|||
complete( |
|||
xhrSuccessStatus[ xhr.status ] || xhr.status, |
|||
xhr.statusText, |
|||
|
|||
// Support: IE <=9 only
|
|||
// IE9 has no XHR2 but throws on binary (trac-11426)
|
|||
// For XHR2 non-text, let the caller handle it (gh-2498)
|
|||
( xhr.responseType || "text" ) !== "text" || |
|||
typeof xhr.responseText !== "string" ? |
|||
{ binary: xhr.response } : |
|||
{ text: xhr.responseText }, |
|||
xhr.getAllResponseHeaders() |
|||
); |
|||
} |
|||
} |
|||
}; |
|||
}; |
|||
|
|||
// Listen to events
|
|||
xhr.onload = callback(); |
|||
errorCallback = xhr.onerror = callback( "error" ); |
|||
|
|||
// Support: IE 9 only
|
|||
// Use onreadystatechange to replace onabort
|
|||
// to handle uncaught aborts
|
|||
if ( xhr.onabort !== undefined ) { |
|||
xhr.onabort = errorCallback; |
|||
} else { |
|||
xhr.onreadystatechange = function() { |
|||
|
|||
// Check readyState before timeout as it changes
|
|||
if ( xhr.readyState === 4 ) { |
|||
|
|||
// Allow onerror to be called first,
|
|||
// but that will not handle a native abort
|
|||
// Also, save errorCallback to a variable
|
|||
// as xhr.onerror cannot be accessed
|
|||
window.setTimeout( function() { |
|||
if ( callback ) { |
|||
errorCallback(); |
|||
} |
|||
} ); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
// Create the abort callback
|
|||
callback = callback( "abort" ); |
|||
|
|||
try { |
|||
|
|||
// Do send the request (this may raise an exception)
|
|||
xhr.send( options.hasContent && options.data || null ); |
|||
} catch ( e ) { |
|||
|
|||
// #14683: Only rethrow if this hasn't been notified as an error yet
|
|||
if ( callback ) { |
|||
throw e; |
|||
} |
|||
} |
|||
}, |
|||
|
|||
abort: function() { |
|||
if ( callback ) { |
|||
callback(); |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
} ); |
|||
|
|||
} ); |
|||
@ -0,0 +1,13 @@ |
|||
define( [ |
|||
"./core", |
|||
"./attributes/attr", |
|||
"./attributes/prop", |
|||
"./attributes/classes", |
|||
"./attributes/val" |
|||
], function( jQuery ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// Return jQuery for attributes-only inclusion
|
|||
return jQuery; |
|||
} ); |
|||
@ -0,0 +1,141 @@ |
|||
define( [ |
|||
"../core", |
|||
"../core/access", |
|||
"../core/nodeName", |
|||
"./support", |
|||
"../var/rnothtmlwhite", |
|||
"../selector" |
|||
], function( jQuery, access, nodeName, support, rnothtmlwhite ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var boolHook, |
|||
attrHandle = jQuery.expr.attrHandle; |
|||
|
|||
jQuery.fn.extend( { |
|||
attr: function( name, value ) { |
|||
return access( this, jQuery.attr, name, value, arguments.length > 1 ); |
|||
}, |
|||
|
|||
removeAttr: function( name ) { |
|||
return this.each( function() { |
|||
jQuery.removeAttr( this, name ); |
|||
} ); |
|||
} |
|||
} ); |
|||
|
|||
jQuery.extend( { |
|||
attr: function( elem, name, value ) { |
|||
var ret, hooks, |
|||
nType = elem.nodeType; |
|||
|
|||
// Don't get/set attributes on text, comment and attribute nodes
|
|||
if ( nType === 3 || nType === 8 || nType === 2 ) { |
|||
return; |
|||
} |
|||
|
|||
// Fallback to prop when attributes are not supported
|
|||
if ( typeof elem.getAttribute === "undefined" ) { |
|||
return jQuery.prop( elem, name, value ); |
|||
} |
|||
|
|||
// Attribute hooks are determined by the lowercase version
|
|||
// Grab necessary hook if one is defined
|
|||
if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { |
|||
hooks = jQuery.attrHooks[ name.toLowerCase() ] || |
|||
( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); |
|||
} |
|||
|
|||
if ( value !== undefined ) { |
|||
if ( value === null ) { |
|||
jQuery.removeAttr( elem, name ); |
|||
return; |
|||
} |
|||
|
|||
if ( hooks && "set" in hooks && |
|||
( ret = hooks.set( elem, value, name ) ) !== undefined ) { |
|||
return ret; |
|||
} |
|||
|
|||
elem.setAttribute( name, value + "" ); |
|||
return value; |
|||
} |
|||
|
|||
if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { |
|||
return ret; |
|||
} |
|||
|
|||
ret = jQuery.find.attr( elem, name ); |
|||
|
|||
// Non-existent attributes return null, we normalize to undefined
|
|||
return ret == null ? undefined : ret; |
|||
}, |
|||
|
|||
attrHooks: { |
|||
type: { |
|||
set: function( elem, value ) { |
|||
if ( !support.radioValue && value === "radio" && |
|||
nodeName( elem, "input" ) ) { |
|||
var val = elem.value; |
|||
elem.setAttribute( "type", value ); |
|||
if ( val ) { |
|||
elem.value = val; |
|||
} |
|||
return value; |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
|
|||
removeAttr: function( elem, value ) { |
|||
var name, |
|||
i = 0, |
|||
|
|||
// Attribute names can contain non-HTML whitespace characters
|
|||
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
|
|||
attrNames = value && value.match( rnothtmlwhite ); |
|||
|
|||
if ( attrNames && elem.nodeType === 1 ) { |
|||
while ( ( name = attrNames[ i++ ] ) ) { |
|||
elem.removeAttribute( name ); |
|||
} |
|||
} |
|||
} |
|||
} ); |
|||
|
|||
// Hooks for boolean attributes
|
|||
boolHook = { |
|||
set: function( elem, value, name ) { |
|||
if ( value === false ) { |
|||
|
|||
// Remove boolean attributes when set to false
|
|||
jQuery.removeAttr( elem, name ); |
|||
} else { |
|||
elem.setAttribute( name, name ); |
|||
} |
|||
return name; |
|||
} |
|||
}; |
|||
|
|||
jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { |
|||
var getter = attrHandle[ name ] || jQuery.find.attr; |
|||
|
|||
attrHandle[ name ] = function( elem, name, isXML ) { |
|||
var ret, handle, |
|||
lowercaseName = name.toLowerCase(); |
|||
|
|||
if ( !isXML ) { |
|||
|
|||
// Avoid an infinite loop by temporarily removing this function from the getter
|
|||
handle = attrHandle[ lowercaseName ]; |
|||
attrHandle[ lowercaseName ] = ret; |
|||
ret = getter( elem, name, isXML ) != null ? |
|||
lowercaseName : |
|||
null; |
|||
attrHandle[ lowercaseName ] = handle; |
|||
} |
|||
return ret; |
|||
}; |
|||
} ); |
|||
|
|||
} ); |
|||
@ -0,0 +1,174 @@ |
|||
define( [ |
|||
"../core", |
|||
"../core/stripAndCollapse", |
|||
"../var/rnothtmlwhite", |
|||
"../data/var/dataPriv", |
|||
"../core/init" |
|||
], function( jQuery, stripAndCollapse, rnothtmlwhite, dataPriv ) { |
|||
|
|||
"use strict"; |
|||
|
|||
function getClass( elem ) { |
|||
return elem.getAttribute && elem.getAttribute( "class" ) || ""; |
|||
} |
|||
|
|||
jQuery.fn.extend( { |
|||
addClass: function( value ) { |
|||
var classes, elem, cur, curValue, clazz, j, finalValue, |
|||
i = 0; |
|||
|
|||
if ( jQuery.isFunction( value ) ) { |
|||
return this.each( function( j ) { |
|||
jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); |
|||
} ); |
|||
} |
|||
|
|||
if ( typeof value === "string" && value ) { |
|||
classes = value.match( rnothtmlwhite ) || []; |
|||
|
|||
while ( ( elem = this[ i++ ] ) ) { |
|||
curValue = getClass( elem ); |
|||
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); |
|||
|
|||
if ( cur ) { |
|||
j = 0; |
|||
while ( ( clazz = classes[ j++ ] ) ) { |
|||
if ( cur.indexOf( " " + clazz + " " ) < 0 ) { |
|||
cur += clazz + " "; |
|||
} |
|||
} |
|||
|
|||
// Only assign if different to avoid unneeded rendering.
|
|||
finalValue = stripAndCollapse( cur ); |
|||
if ( curValue !== finalValue ) { |
|||
elem.setAttribute( "class", finalValue ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return this; |
|||
}, |
|||
|
|||
removeClass: function( value ) { |
|||
var classes, elem, cur, curValue, clazz, j, finalValue, |
|||
i = 0; |
|||
|
|||
if ( jQuery.isFunction( value ) ) { |
|||
return this.each( function( j ) { |
|||
jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); |
|||
} ); |
|||
} |
|||
|
|||
if ( !arguments.length ) { |
|||
return this.attr( "class", "" ); |
|||
} |
|||
|
|||
if ( typeof value === "string" && value ) { |
|||
classes = value.match( rnothtmlwhite ) || []; |
|||
|
|||
while ( ( elem = this[ i++ ] ) ) { |
|||
curValue = getClass( elem ); |
|||
|
|||
// This expression is here for better compressibility (see addClass)
|
|||
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); |
|||
|
|||
if ( cur ) { |
|||
j = 0; |
|||
while ( ( clazz = classes[ j++ ] ) ) { |
|||
|
|||
// Remove *all* instances
|
|||
while ( cur.indexOf( " " + clazz + " " ) > -1 ) { |
|||
cur = cur.replace( " " + clazz + " ", " " ); |
|||
} |
|||
} |
|||
|
|||
// Only assign if different to avoid unneeded rendering.
|
|||
finalValue = stripAndCollapse( cur ); |
|||
if ( curValue !== finalValue ) { |
|||
elem.setAttribute( "class", finalValue ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return this; |
|||
}, |
|||
|
|||
toggleClass: function( value, stateVal ) { |
|||
var type = typeof value; |
|||
|
|||
if ( typeof stateVal === "boolean" && type === "string" ) { |
|||
return stateVal ? this.addClass( value ) : this.removeClass( value ); |
|||
} |
|||
|
|||
if ( jQuery.isFunction( value ) ) { |
|||
return this.each( function( i ) { |
|||
jQuery( this ).toggleClass( |
|||
value.call( this, i, getClass( this ), stateVal ), |
|||
stateVal |
|||
); |
|||
} ); |
|||
} |
|||
|
|||
return this.each( function() { |
|||
var className, i, self, classNames; |
|||
|
|||
if ( type === "string" ) { |
|||
|
|||
// Toggle individual class names
|
|||
i = 0; |
|||
self = jQuery( this ); |
|||
classNames = value.match( rnothtmlwhite ) || []; |
|||
|
|||
while ( ( className = classNames[ i++ ] ) ) { |
|||
|
|||
// Check each className given, space separated list
|
|||
if ( self.hasClass( className ) ) { |
|||
self.removeClass( className ); |
|||
} else { |
|||
self.addClass( className ); |
|||
} |
|||
} |
|||
|
|||
// Toggle whole class name
|
|||
} else if ( value === undefined || type === "boolean" ) { |
|||
className = getClass( this ); |
|||
if ( className ) { |
|||
|
|||
// Store className if set
|
|||
dataPriv.set( this, "__className__", className ); |
|||
} |
|||
|
|||
// If the element has a class name or if we're passed `false`,
|
|||
// then remove the whole classname (if there was one, the above saved it).
|
|||
// Otherwise bring back whatever was previously saved (if anything),
|
|||
// falling back to the empty string if nothing was stored.
|
|||
if ( this.setAttribute ) { |
|||
this.setAttribute( "class", |
|||
className || value === false ? |
|||
"" : |
|||
dataPriv.get( this, "__className__" ) || "" |
|||
); |
|||
} |
|||
} |
|||
} ); |
|||
}, |
|||
|
|||
hasClass: function( selector ) { |
|||
var className, elem, |
|||
i = 0; |
|||
|
|||
className = " " + selector + " "; |
|||
while ( ( elem = this[ i++ ] ) ) { |
|||
if ( elem.nodeType === 1 && |
|||
( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
} ); |
|||
|
|||
} ); |
|||
@ -0,0 +1,143 @@ |
|||
define( [ |
|||
"../core", |
|||
"../core/access", |
|||
"./support", |
|||
"../selector" |
|||
], function( jQuery, access, support ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var rfocusable = /^(?:input|select|textarea|button)$/i, |
|||
rclickable = /^(?:a|area)$/i; |
|||
|
|||
jQuery.fn.extend( { |
|||
prop: function( name, value ) { |
|||
return access( this, jQuery.prop, name, value, arguments.length > 1 ); |
|||
}, |
|||
|
|||
removeProp: function( name ) { |
|||
return this.each( function() { |
|||
delete this[ jQuery.propFix[ name ] || name ]; |
|||
} ); |
|||
} |
|||
} ); |
|||
|
|||
jQuery.extend( { |
|||
prop: function( elem, name, value ) { |
|||
var ret, hooks, |
|||
nType = elem.nodeType; |
|||
|
|||
// Don't get/set properties on text, comment and attribute nodes
|
|||
if ( nType === 3 || nType === 8 || nType === 2 ) { |
|||
return; |
|||
} |
|||
|
|||
if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { |
|||
|
|||
// Fix name and attach hooks
|
|||
name = jQuery.propFix[ name ] || name; |
|||
hooks = jQuery.propHooks[ name ]; |
|||
} |
|||
|
|||
if ( value !== undefined ) { |
|||
if ( hooks && "set" in hooks && |
|||
( ret = hooks.set( elem, value, name ) ) !== undefined ) { |
|||
return ret; |
|||
} |
|||
|
|||
return ( elem[ name ] = value ); |
|||
} |
|||
|
|||
if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { |
|||
return ret; |
|||
} |
|||
|
|||
return elem[ name ]; |
|||
}, |
|||
|
|||
propHooks: { |
|||
tabIndex: { |
|||
get: function( elem ) { |
|||
|
|||
// Support: IE <=9 - 11 only
|
|||
// elem.tabIndex doesn't always return the
|
|||
// correct value when it hasn't been explicitly set
|
|||
// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
|
|||
// Use proper attribute retrieval(#12072)
|
|||
var tabindex = jQuery.find.attr( elem, "tabindex" ); |
|||
|
|||
if ( tabindex ) { |
|||
return parseInt( tabindex, 10 ); |
|||
} |
|||
|
|||
if ( |
|||
rfocusable.test( elem.nodeName ) || |
|||
rclickable.test( elem.nodeName ) && |
|||
elem.href |
|||
) { |
|||
return 0; |
|||
} |
|||
|
|||
return -1; |
|||
} |
|||
} |
|||
}, |
|||
|
|||
propFix: { |
|||
"for": "htmlFor", |
|||
"class": "className" |
|||
} |
|||
} ); |
|||
|
|||
// Support: IE <=11 only
|
|||
// Accessing the selectedIndex property
|
|||
// forces the browser to respect setting selected
|
|||
// on the option
|
|||
// The getter ensures a default option is selected
|
|||
// when in an optgroup
|
|||
// eslint rule "no-unused-expressions" is disabled for this code
|
|||
// since it considers such accessions noop
|
|||
if ( !support.optSelected ) { |
|||
jQuery.propHooks.selected = { |
|||
get: function( elem ) { |
|||
|
|||
/* eslint no-unused-expressions: "off" */ |
|||
|
|||
var parent = elem.parentNode; |
|||
if ( parent && parent.parentNode ) { |
|||
parent.parentNode.selectedIndex; |
|||
} |
|||
return null; |
|||
}, |
|||
set: function( elem ) { |
|||
|
|||
/* eslint no-unused-expressions: "off" */ |
|||
|
|||
var parent = elem.parentNode; |
|||
if ( parent ) { |
|||
parent.selectedIndex; |
|||
|
|||
if ( parent.parentNode ) { |
|||
parent.parentNode.selectedIndex; |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
|
|||
jQuery.each( [ |
|||
"tabIndex", |
|||
"readOnly", |
|||
"maxLength", |
|||
"cellSpacing", |
|||
"cellPadding", |
|||
"rowSpan", |
|||
"colSpan", |
|||
"useMap", |
|||
"frameBorder", |
|||
"contentEditable" |
|||
], function() { |
|||
jQuery.propFix[ this.toLowerCase() ] = this; |
|||
} ); |
|||
|
|||
} ); |
|||
@ -0,0 +1,33 @@ |
|||
define( [ |
|||
"../var/document", |
|||
"../var/support" |
|||
], function( document, support ) { |
|||
|
|||
"use strict"; |
|||
|
|||
( function() { |
|||
var input = document.createElement( "input" ), |
|||
select = document.createElement( "select" ), |
|||
opt = select.appendChild( document.createElement( "option" ) ); |
|||
|
|||
input.type = "checkbox"; |
|||
|
|||
// Support: Android <=4.3 only
|
|||
// Default value for a checkbox should be "on"
|
|||
support.checkOn = input.value !== ""; |
|||
|
|||
// Support: IE <=11 only
|
|||
// Must access selectedIndex to make default options select
|
|||
support.optSelected = opt.selected; |
|||
|
|||
// Support: IE <=11 only
|
|||
// An input loses its value after becoming a radio
|
|||
input = document.createElement( "input" ); |
|||
input.value = "t"; |
|||
input.type = "radio"; |
|||
support.radioValue = input.value === "t"; |
|||
} )(); |
|||
|
|||
return support; |
|||
|
|||
} ); |
|||
@ -0,0 +1,190 @@ |
|||
define( [ |
|||
"../core", |
|||
"../core/stripAndCollapse", |
|||
"./support", |
|||
"../core/nodeName", |
|||
|
|||
"../core/init" |
|||
], function( jQuery, stripAndCollapse, support, nodeName ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var rreturn = /\r/g; |
|||
|
|||
jQuery.fn.extend( { |
|||
val: function( value ) { |
|||
var hooks, ret, isFunction, |
|||
elem = this[ 0 ]; |
|||
|
|||
if ( !arguments.length ) { |
|||
if ( elem ) { |
|||
hooks = jQuery.valHooks[ elem.type ] || |
|||
jQuery.valHooks[ elem.nodeName.toLowerCase() ]; |
|||
|
|||
if ( hooks && |
|||
"get" in hooks && |
|||
( ret = hooks.get( elem, "value" ) ) !== undefined |
|||
) { |
|||
return ret; |
|||
} |
|||
|
|||
ret = elem.value; |
|||
|
|||
// Handle most common string cases
|
|||
if ( typeof ret === "string" ) { |
|||
return ret.replace( rreturn, "" ); |
|||
} |
|||
|
|||
// Handle cases where value is null/undef or number
|
|||
return ret == null ? "" : ret; |
|||
} |
|||
|
|||
return; |
|||
} |
|||
|
|||
isFunction = jQuery.isFunction( value ); |
|||
|
|||
return this.each( function( i ) { |
|||
var val; |
|||
|
|||
if ( this.nodeType !== 1 ) { |
|||
return; |
|||
} |
|||
|
|||
if ( isFunction ) { |
|||
val = value.call( this, i, jQuery( this ).val() ); |
|||
} else { |
|||
val = value; |
|||
} |
|||
|
|||
// Treat null/undefined as ""; convert numbers to string
|
|||
if ( val == null ) { |
|||
val = ""; |
|||
|
|||
} else if ( typeof val === "number" ) { |
|||
val += ""; |
|||
|
|||
} else if ( Array.isArray( val ) ) { |
|||
val = jQuery.map( val, function( value ) { |
|||
return value == null ? "" : value + ""; |
|||
} ); |
|||
} |
|||
|
|||
hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; |
|||
|
|||
// If set returns undefined, fall back to normal setting
|
|||
if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { |
|||
this.value = val; |
|||
} |
|||
} ); |
|||
} |
|||
} ); |
|||
|
|||
jQuery.extend( { |
|||
valHooks: { |
|||
option: { |
|||
get: function( elem ) { |
|||
|
|||
var val = jQuery.find.attr( elem, "value" ); |
|||
return val != null ? |
|||
val : |
|||
|
|||
// Support: IE <=10 - 11 only
|
|||
// option.text throws exceptions (#14686, #14858)
|
|||
// Strip and collapse whitespace
|
|||
// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
|
|||
stripAndCollapse( jQuery.text( elem ) ); |
|||
} |
|||
}, |
|||
select: { |
|||
get: function( elem ) { |
|||
var value, option, i, |
|||
options = elem.options, |
|||
index = elem.selectedIndex, |
|||
one = elem.type === "select-one", |
|||
values = one ? null : [], |
|||
max = one ? index + 1 : options.length; |
|||
|
|||
if ( index < 0 ) { |
|||
i = max; |
|||
|
|||
} else { |
|||
i = one ? index : 0; |
|||
} |
|||
|
|||
// Loop through all the selected options
|
|||
for ( ; i < max; i++ ) { |
|||
option = options[ i ]; |
|||
|
|||
// Support: IE <=9 only
|
|||
// IE8-9 doesn't update selected after form reset (#2551)
|
|||
if ( ( option.selected || i === index ) && |
|||
|
|||
// Don't return options that are disabled or in a disabled optgroup
|
|||
!option.disabled && |
|||
( !option.parentNode.disabled || |
|||
!nodeName( option.parentNode, "optgroup" ) ) ) { |
|||
|
|||
// Get the specific value for the option
|
|||
value = jQuery( option ).val(); |
|||
|
|||
// We don't need an array for one selects
|
|||
if ( one ) { |
|||
return value; |
|||
} |
|||
|
|||
// Multi-Selects return an array
|
|||
values.push( value ); |
|||
} |
|||
} |
|||
|
|||
return values; |
|||
}, |
|||
|
|||
set: function( elem, value ) { |
|||
var optionSet, option, |
|||
options = elem.options, |
|||
values = jQuery.makeArray( value ), |
|||
i = options.length; |
|||
|
|||
while ( i-- ) { |
|||
option = options[ i ]; |
|||
|
|||
/* eslint-disable no-cond-assign */ |
|||
|
|||
if ( option.selected = |
|||
jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 |
|||
) { |
|||
optionSet = true; |
|||
} |
|||
|
|||
/* eslint-enable no-cond-assign */ |
|||
} |
|||
|
|||
// Force browsers to behave consistently when non-matching value is set
|
|||
if ( !optionSet ) { |
|||
elem.selectedIndex = -1; |
|||
} |
|||
return values; |
|||
} |
|||
} |
|||
} |
|||
} ); |
|||
|
|||
// Radios and checkboxes getter/setter
|
|||
jQuery.each( [ "radio", "checkbox" ], function() { |
|||
jQuery.valHooks[ this ] = { |
|||
set: function( elem, value ) { |
|||
if ( Array.isArray( value ) ) { |
|||
return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); |
|||
} |
|||
} |
|||
}; |
|||
if ( !support.checkOn ) { |
|||
jQuery.valHooks[ this ].get = function( elem ) { |
|||
return elem.getAttribute( "value" ) === null ? "on" : elem.value; |
|||
}; |
|||
} |
|||
} ); |
|||
|
|||
} ); |
|||
@ -0,0 +1,234 @@ |
|||
define( [ |
|||
"./core", |
|||
"./var/rnothtmlwhite" |
|||
], function( jQuery, rnothtmlwhite ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// Convert String-formatted options into Object-formatted ones
|
|||
function createOptions( options ) { |
|||
var object = {}; |
|||
jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { |
|||
object[ flag ] = true; |
|||
} ); |
|||
return object; |
|||
} |
|||
|
|||
/* |
|||
* Create a callback list using the following parameters: |
|||
* |
|||
* options: an optional list of space-separated options that will change how |
|||
* the callback list behaves or a more traditional option object |
|||
* |
|||
* By default a callback list will act like an event callback list and can be |
|||
* "fired" multiple times. |
|||
* |
|||
* Possible options: |
|||
* |
|||
* once: will ensure the callback list can only be fired once (like a Deferred) |
|||
* |
|||
* memory: will keep track of previous values and will call any callback added |
|||
* after the list has been fired right away with the latest "memorized" |
|||
* values (like a Deferred) |
|||
* |
|||
* unique: will ensure a callback can only be added once (no duplicate in the list) |
|||
* |
|||
* stopOnFalse: interrupt callings when a callback returns false |
|||
* |
|||
*/ |
|||
jQuery.Callbacks = function( options ) { |
|||
|
|||
// Convert options from String-formatted to Object-formatted if needed
|
|||
// (we check in cache first)
|
|||
options = typeof options === "string" ? |
|||
createOptions( options ) : |
|||
jQuery.extend( {}, options ); |
|||
|
|||
var // Flag to know if list is currently firing
|
|||
firing, |
|||
|
|||
// Last fire value for non-forgettable lists
|
|||
memory, |
|||
|
|||
// Flag to know if list was already fired
|
|||
fired, |
|||
|
|||
// Flag to prevent firing
|
|||
locked, |
|||
|
|||
// Actual callback list
|
|||
list = [], |
|||
|
|||
// Queue of execution data for repeatable lists
|
|||
queue = [], |
|||
|
|||
// Index of currently firing callback (modified by add/remove as needed)
|
|||
firingIndex = -1, |
|||
|
|||
// Fire callbacks
|
|||
fire = function() { |
|||
|
|||
// Enforce single-firing
|
|||
locked = locked || options.once; |
|||
|
|||
// Execute callbacks for all pending executions,
|
|||
// respecting firingIndex overrides and runtime changes
|
|||
fired = firing = true; |
|||
for ( ; queue.length; firingIndex = -1 ) { |
|||
memory = queue.shift(); |
|||
while ( ++firingIndex < list.length ) { |
|||
|
|||
// Run callback and check for early termination
|
|||
if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && |
|||
options.stopOnFalse ) { |
|||
|
|||
// Jump to end and forget the data so .add doesn't re-fire
|
|||
firingIndex = list.length; |
|||
memory = false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Forget the data if we're done with it
|
|||
if ( !options.memory ) { |
|||
memory = false; |
|||
} |
|||
|
|||
firing = false; |
|||
|
|||
// Clean up if we're done firing for good
|
|||
if ( locked ) { |
|||
|
|||
// Keep an empty list if we have data for future add calls
|
|||
if ( memory ) { |
|||
list = []; |
|||
|
|||
// Otherwise, this object is spent
|
|||
} else { |
|||
list = ""; |
|||
} |
|||
} |
|||
}, |
|||
|
|||
// Actual Callbacks object
|
|||
self = { |
|||
|
|||
// Add a callback or a collection of callbacks to the list
|
|||
add: function() { |
|||
if ( list ) { |
|||
|
|||
// If we have memory from a past run, we should fire after adding
|
|||
if ( memory && !firing ) { |
|||
firingIndex = list.length - 1; |
|||
queue.push( memory ); |
|||
} |
|||
|
|||
( function add( args ) { |
|||
jQuery.each( args, function( _, arg ) { |
|||
if ( jQuery.isFunction( arg ) ) { |
|||
if ( !options.unique || !self.has( arg ) ) { |
|||
list.push( arg ); |
|||
} |
|||
} else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { |
|||
|
|||
// Inspect recursively
|
|||
add( arg ); |
|||
} |
|||
} ); |
|||
} )( arguments ); |
|||
|
|||
if ( memory && !firing ) { |
|||
fire(); |
|||
} |
|||
} |
|||
return this; |
|||
}, |
|||
|
|||
// Remove a callback from the list
|
|||
remove: function() { |
|||
jQuery.each( arguments, function( _, arg ) { |
|||
var index; |
|||
while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { |
|||
list.splice( index, 1 ); |
|||
|
|||
// Handle firing indexes
|
|||
if ( index <= firingIndex ) { |
|||
firingIndex--; |
|||
} |
|||
} |
|||
} ); |
|||
return this; |
|||
}, |
|||
|
|||
// Check if a given callback is in the list.
|
|||
// If no argument is given, return whether or not list has callbacks attached.
|
|||
has: function( fn ) { |
|||
return fn ? |
|||
jQuery.inArray( fn, list ) > -1 : |
|||
list.length > 0; |
|||
}, |
|||
|
|||
// Remove all callbacks from the list
|
|||
empty: function() { |
|||
if ( list ) { |
|||
list = []; |
|||
} |
|||
return this; |
|||
}, |
|||
|
|||
// Disable .fire and .add
|
|||
// Abort any current/pending executions
|
|||
// Clear all callbacks and values
|
|||
disable: function() { |
|||
locked = queue = []; |
|||
list = memory = ""; |
|||
return this; |
|||
}, |
|||
disabled: function() { |
|||
return !list; |
|||
}, |
|||
|
|||
// Disable .fire
|
|||
// Also disable .add unless we have memory (since it would have no effect)
|
|||
// Abort any pending executions
|
|||
lock: function() { |
|||
locked = queue = []; |
|||
if ( !memory && !firing ) { |
|||
list = memory = ""; |
|||
} |
|||
return this; |
|||
}, |
|||
locked: function() { |
|||
return !!locked; |
|||
}, |
|||
|
|||
// Call all callbacks with the given context and arguments
|
|||
fireWith: function( context, args ) { |
|||
if ( !locked ) { |
|||
args = args || []; |
|||
args = [ context, args.slice ? args.slice() : args ]; |
|||
queue.push( args ); |
|||
if ( !firing ) { |
|||
fire(); |
|||
} |
|||
} |
|||
return this; |
|||
}, |
|||
|
|||
// Call all the callbacks with the given arguments
|
|||
fire: function() { |
|||
self.fireWith( this, arguments ); |
|||
return this; |
|||
}, |
|||
|
|||
// To know if the callbacks have already been called at least once
|
|||
fired: function() { |
|||
return !!fired; |
|||
} |
|||
}; |
|||
|
|||
return self; |
|||
}; |
|||
|
|||
return jQuery; |
|||
} ); |
|||
@ -0,0 +1,476 @@ |
|||
/* global Symbol */ |
|||
// Defining this global in .eslintrc.json would create a danger of using the global
|
|||
// unguarded in another place, it seems safer to define global only for this module
|
|||
|
|||
define( [ |
|||
"./var/arr", |
|||
"./var/document", |
|||
"./var/getProto", |
|||
"./var/slice", |
|||
"./var/concat", |
|||
"./var/push", |
|||
"./var/indexOf", |
|||
"./var/class2type", |
|||
"./var/toString", |
|||
"./var/hasOwn", |
|||
"./var/fnToString", |
|||
"./var/ObjectFunctionString", |
|||
"./var/support", |
|||
"./core/DOMEval" |
|||
], function( arr, document, getProto, slice, concat, push, indexOf, |
|||
class2type, toString, hasOwn, fnToString, ObjectFunctionString, |
|||
support, DOMEval ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var |
|||
version = "3.2.1", |
|||
|
|||
// Define a local copy of jQuery
|
|||
jQuery = function( selector, context ) { |
|||
|
|||
// The jQuery object is actually just the init constructor 'enhanced'
|
|||
// Need init if jQuery is called (just allow error to be thrown if not included)
|
|||
return new jQuery.fn.init( selector, context ); |
|||
}, |
|||
|
|||
// Support: Android <=4.0 only
|
|||
// Make sure we trim BOM and NBSP
|
|||
rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, |
|||
|
|||
// Matches dashed string for camelizing
|
|||
rmsPrefix = /^-ms-/, |
|||
rdashAlpha = /-([a-z])/g, |
|||
|
|||
// Used by jQuery.camelCase as callback to replace()
|
|||
fcamelCase = function( all, letter ) { |
|||
return letter.toUpperCase(); |
|||
}; |
|||
|
|||
jQuery.fn = jQuery.prototype = { |
|||
|
|||
// The current version of jQuery being used
|
|||
jquery: version, |
|||
|
|||
constructor: jQuery, |
|||
|
|||
// The default length of a jQuery object is 0
|
|||
length: 0, |
|||
|
|||
toArray: function() { |
|||
return slice.call( this ); |
|||
}, |
|||
|
|||
// Get the Nth element in the matched element set OR
|
|||
// Get the whole matched element set as a clean array
|
|||
get: function( num ) { |
|||
|
|||
// Return all the elements in a clean array
|
|||
if ( num == null ) { |
|||
return slice.call( this ); |
|||
} |
|||
|
|||
// Return just the one element from the set
|
|||
return num < 0 ? this[ num + this.length ] : this[ num ]; |
|||
}, |
|||
|
|||
// Take an array of elements and push it onto the stack
|
|||
// (returning the new matched element set)
|
|||
pushStack: function( elems ) { |
|||
|
|||
// Build a new jQuery matched element set
|
|||
var ret = jQuery.merge( this.constructor(), elems ); |
|||
|
|||
// Add the old object onto the stack (as a reference)
|
|||
ret.prevObject = this; |
|||
|
|||
// Return the newly-formed element set
|
|||
return ret; |
|||
}, |
|||
|
|||
// Execute a callback for every element in the matched set.
|
|||
each: function( callback ) { |
|||
return jQuery.each( this, callback ); |
|||
}, |
|||
|
|||
map: function( callback ) { |
|||
return this.pushStack( jQuery.map( this, function( elem, i ) { |
|||
return callback.call( elem, i, elem ); |
|||
} ) ); |
|||
}, |
|||
|
|||
slice: function() { |
|||
return this.pushStack( slice.apply( this, arguments ) ); |
|||
}, |
|||
|
|||
first: function() { |
|||
return this.eq( 0 ); |
|||
}, |
|||
|
|||
last: function() { |
|||
return this.eq( -1 ); |
|||
}, |
|||
|
|||
eq: function( i ) { |
|||
var len = this.length, |
|||
j = +i + ( i < 0 ? len : 0 ); |
|||
return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); |
|||
}, |
|||
|
|||
end: function() { |
|||
return this.prevObject || this.constructor(); |
|||
}, |
|||
|
|||
// For internal use only.
|
|||
// Behaves like an Array's method, not like a jQuery method.
|
|||
push: push, |
|||
sort: arr.sort, |
|||
splice: arr.splice |
|||
}; |
|||
|
|||
jQuery.extend = jQuery.fn.extend = function() { |
|||
var options, name, src, copy, copyIsArray, clone, |
|||
target = arguments[ 0 ] || {}, |
|||
i = 1, |
|||
length = arguments.length, |
|||
deep = false; |
|||
|
|||
// Handle a deep copy situation
|
|||
if ( typeof target === "boolean" ) { |
|||
deep = target; |
|||
|
|||
// Skip the boolean and the target
|
|||
target = arguments[ i ] || {}; |
|||
i++; |
|||
} |
|||
|
|||
// Handle case when target is a string or something (possible in deep copy)
|
|||
if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { |
|||
target = {}; |
|||
} |
|||
|
|||
// Extend jQuery itself if only one argument is passed
|
|||
if ( i === length ) { |
|||
target = this; |
|||
i--; |
|||
} |
|||
|
|||
for ( ; i < length; i++ ) { |
|||
|
|||
// Only deal with non-null/undefined values
|
|||
if ( ( options = arguments[ i ] ) != null ) { |
|||
|
|||
// Extend the base object
|
|||
for ( name in options ) { |
|||
src = target[ name ]; |
|||
copy = options[ name ]; |
|||
|
|||
// Prevent never-ending loop
|
|||
if ( target === copy ) { |
|||
continue; |
|||
} |
|||
|
|||
// Recurse if we're merging plain objects or arrays
|
|||
if ( deep && copy && ( jQuery.isPlainObject( copy ) || |
|||
( copyIsArray = Array.isArray( copy ) ) ) ) { |
|||
|
|||
if ( copyIsArray ) { |
|||
copyIsArray = false; |
|||
clone = src && Array.isArray( src ) ? src : []; |
|||
|
|||
} else { |
|||
clone = src && jQuery.isPlainObject( src ) ? src : {}; |
|||
} |
|||
|
|||
// Never move original objects, clone them
|
|||
target[ name ] = jQuery.extend( deep, clone, copy ); |
|||
|
|||
// Don't bring in undefined values
|
|||
} else if ( copy !== undefined ) { |
|||
target[ name ] = copy; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Return the modified object
|
|||
return target; |
|||
}; |
|||
|
|||
jQuery.extend( { |
|||
|
|||
// Unique for each copy of jQuery on the page
|
|||
expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), |
|||
|
|||
// Assume jQuery is ready without the ready module
|
|||
isReady: true, |
|||
|
|||
error: function( msg ) { |
|||
throw new Error( msg ); |
|||
}, |
|||
|
|||
noop: function() {}, |
|||
|
|||
isFunction: function( obj ) { |
|||
return jQuery.type( obj ) === "function"; |
|||
}, |
|||
|
|||
isWindow: function( obj ) { |
|||
return obj != null && obj === obj.window; |
|||
}, |
|||
|
|||
isNumeric: function( obj ) { |
|||
|
|||
// As of jQuery 3.0, isNumeric is limited to
|
|||
// strings and numbers (primitives or objects)
|
|||
// that can be coerced to finite numbers (gh-2662)
|
|||
var type = jQuery.type( obj ); |
|||
return ( type === "number" || type === "string" ) && |
|||
|
|||
// parseFloat NaNs numeric-cast false positives ("")
|
|||
// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
|
|||
// subtraction forces infinities to NaN
|
|||
!isNaN( obj - parseFloat( obj ) ); |
|||
}, |
|||
|
|||
isPlainObject: function( obj ) { |
|||
var proto, Ctor; |
|||
|
|||
// Detect obvious negatives
|
|||
// Use toString instead of jQuery.type to catch host objects
|
|||
if ( !obj || toString.call( obj ) !== "[object Object]" ) { |
|||
return false; |
|||
} |
|||
|
|||
proto = getProto( obj ); |
|||
|
|||
// Objects with no prototype (e.g., `Object.create( null )`) are plain
|
|||
if ( !proto ) { |
|||
return true; |
|||
} |
|||
|
|||
// Objects with prototype are plain iff they were constructed by a global Object function
|
|||
Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; |
|||
return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; |
|||
}, |
|||
|
|||
isEmptyObject: function( obj ) { |
|||
|
|||
/* eslint-disable no-unused-vars */ |
|||
// See https://github.com/eslint/eslint/issues/6125
|
|||
var name; |
|||
|
|||
for ( name in obj ) { |
|||
return false; |
|||
} |
|||
return true; |
|||
}, |
|||
|
|||
type: function( obj ) { |
|||
if ( obj == null ) { |
|||
return obj + ""; |
|||
} |
|||
|
|||
// Support: Android <=2.3 only (functionish RegExp)
|
|||
return typeof obj === "object" || typeof obj === "function" ? |
|||
class2type[ toString.call( obj ) ] || "object" : |
|||
typeof obj; |
|||
}, |
|||
|
|||
// Evaluates a script in a global context
|
|||
globalEval: function( code ) { |
|||
DOMEval( code ); |
|||
}, |
|||
|
|||
// Convert dashed to camelCase; used by the css and data modules
|
|||
// Support: IE <=9 - 11, Edge 12 - 13
|
|||
// Microsoft forgot to hump their vendor prefix (#9572)
|
|||
camelCase: function( string ) { |
|||
return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); |
|||
}, |
|||
|
|||
each: function( obj, callback ) { |
|||
var length, i = 0; |
|||
|
|||
if ( isArrayLike( obj ) ) { |
|||
length = obj.length; |
|||
for ( ; i < length; i++ ) { |
|||
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { |
|||
break; |
|||
} |
|||
} |
|||
} else { |
|||
for ( i in obj ) { |
|||
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return obj; |
|||
}, |
|||
|
|||
// Support: Android <=4.0 only
|
|||
trim: function( text ) { |
|||
return text == null ? |
|||
"" : |
|||
( text + "" ).replace( rtrim, "" ); |
|||
}, |
|||
|
|||
// results is for internal usage only
|
|||
makeArray: function( arr, results ) { |
|||
var ret = results || []; |
|||
|
|||
if ( arr != null ) { |
|||
if ( isArrayLike( Object( arr ) ) ) { |
|||
jQuery.merge( ret, |
|||
typeof arr === "string" ? |
|||
[ arr ] : arr |
|||
); |
|||
} else { |
|||
push.call( ret, arr ); |
|||
} |
|||
} |
|||
|
|||
return ret; |
|||
}, |
|||
|
|||
inArray: function( elem, arr, i ) { |
|||
return arr == null ? -1 : indexOf.call( arr, elem, i ); |
|||
}, |
|||
|
|||
// Support: Android <=4.0 only, PhantomJS 1 only
|
|||
// push.apply(_, arraylike) throws on ancient WebKit
|
|||
merge: function( first, second ) { |
|||
var len = +second.length, |
|||
j = 0, |
|||
i = first.length; |
|||
|
|||
for ( ; j < len; j++ ) { |
|||
first[ i++ ] = second[ j ]; |
|||
} |
|||
|
|||
first.length = i; |
|||
|
|||
return first; |
|||
}, |
|||
|
|||
grep: function( elems, callback, invert ) { |
|||
var callbackInverse, |
|||
matches = [], |
|||
i = 0, |
|||
length = elems.length, |
|||
callbackExpect = !invert; |
|||
|
|||
// Go through the array, only saving the items
|
|||
// that pass the validator function
|
|||
for ( ; i < length; i++ ) { |
|||
callbackInverse = !callback( elems[ i ], i ); |
|||
if ( callbackInverse !== callbackExpect ) { |
|||
matches.push( elems[ i ] ); |
|||
} |
|||
} |
|||
|
|||
return matches; |
|||
}, |
|||
|
|||
// arg is for internal usage only
|
|||
map: function( elems, callback, arg ) { |
|||
var length, value, |
|||
i = 0, |
|||
ret = []; |
|||
|
|||
// Go through the array, translating each of the items to their new values
|
|||
if ( isArrayLike( elems ) ) { |
|||
length = elems.length; |
|||
for ( ; i < length; i++ ) { |
|||
value = callback( elems[ i ], i, arg ); |
|||
|
|||
if ( value != null ) { |
|||
ret.push( value ); |
|||
} |
|||
} |
|||
|
|||
// Go through every key on the object,
|
|||
} else { |
|||
for ( i in elems ) { |
|||
value = callback( elems[ i ], i, arg ); |
|||
|
|||
if ( value != null ) { |
|||
ret.push( value ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Flatten any nested arrays
|
|||
return concat.apply( [], ret ); |
|||
}, |
|||
|
|||
// A global GUID counter for objects
|
|||
guid: 1, |
|||
|
|||
// Bind a function to a context, optionally partially applying any
|
|||
// arguments.
|
|||
proxy: function( fn, context ) { |
|||
var tmp, args, proxy; |
|||
|
|||
if ( typeof context === "string" ) { |
|||
tmp = fn[ context ]; |
|||
context = fn; |
|||
fn = tmp; |
|||
} |
|||
|
|||
// Quick check to determine if target is callable, in the spec
|
|||
// this throws a TypeError, but we will just return undefined.
|
|||
if ( !jQuery.isFunction( fn ) ) { |
|||
return undefined; |
|||
} |
|||
|
|||
// Simulated bind
|
|||
args = slice.call( arguments, 2 ); |
|||
proxy = function() { |
|||
return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); |
|||
}; |
|||
|
|||
// Set the guid of unique handler to the same of original handler, so it can be removed
|
|||
proxy.guid = fn.guid = fn.guid || jQuery.guid++; |
|||
|
|||
return proxy; |
|||
}, |
|||
|
|||
now: Date.now, |
|||
|
|||
// jQuery.support is not used in Core but other projects attach their
|
|||
// properties to it so it needs to exist.
|
|||
support: support |
|||
} ); |
|||
|
|||
if ( typeof Symbol === "function" ) { |
|||
jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; |
|||
} |
|||
|
|||
// Populate the class2type map
|
|||
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), |
|||
function( i, name ) { |
|||
class2type[ "[object " + name + "]" ] = name.toLowerCase(); |
|||
} ); |
|||
|
|||
function isArrayLike( obj ) { |
|||
|
|||
// Support: real iOS 8.2 only (not reproducible in simulator)
|
|||
// `in` check used to prevent JIT error (gh-2145)
|
|||
// hasOwn isn't used here due to false negatives
|
|||
// regarding Nodelist length in IE
|
|||
var length = !!obj && "length" in obj && obj.length, |
|||
type = jQuery.type( obj ); |
|||
|
|||
if ( type === "function" || jQuery.isWindow( obj ) ) { |
|||
return false; |
|||
} |
|||
|
|||
return type === "array" || length === 0 || |
|||
typeof length === "number" && length > 0 && ( length - 1 ) in obj; |
|||
} |
|||
|
|||
return jQuery; |
|||
} ); |
|||
@ -0,0 +1,16 @@ |
|||
define( [ |
|||
"../var/document" |
|||
], function( document ) { |
|||
"use strict"; |
|||
|
|||
function DOMEval( code, doc ) { |
|||
doc = doc || document; |
|||
|
|||
var script = doc.createElement( "script" ); |
|||
|
|||
script.text = code; |
|||
doc.head.appendChild( script ).parentNode.removeChild( script ); |
|||
} |
|||
|
|||
return DOMEval; |
|||
} ); |
|||
@ -0,0 +1,70 @@ |
|||
define( [ |
|||
"../core" |
|||
], function( jQuery ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// Multifunctional method to get and set values of a collection
|
|||
// The value/s can optionally be executed if it's a function
|
|||
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { |
|||
var i = 0, |
|||
len = elems.length, |
|||
bulk = key == null; |
|||
|
|||
// Sets many values
|
|||
if ( jQuery.type( key ) === "object" ) { |
|||
chainable = true; |
|||
for ( i in key ) { |
|||
access( elems, fn, i, key[ i ], true, emptyGet, raw ); |
|||
} |
|||
|
|||
// Sets one value
|
|||
} else if ( value !== undefined ) { |
|||
chainable = true; |
|||
|
|||
if ( !jQuery.isFunction( value ) ) { |
|||
raw = true; |
|||
} |
|||
|
|||
if ( bulk ) { |
|||
|
|||
// Bulk operations run against the entire set
|
|||
if ( raw ) { |
|||
fn.call( elems, value ); |
|||
fn = null; |
|||
|
|||
// ...except when executing function values
|
|||
} else { |
|||
bulk = fn; |
|||
fn = function( elem, key, value ) { |
|||
return bulk.call( jQuery( elem ), value ); |
|||
}; |
|||
} |
|||
} |
|||
|
|||
if ( fn ) { |
|||
for ( ; i < len; i++ ) { |
|||
fn( |
|||
elems[ i ], key, raw ? |
|||
value : |
|||
value.call( elems[ i ], i, fn( elems[ i ], key ) ) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if ( chainable ) { |
|||
return elems; |
|||
} |
|||
|
|||
// Gets
|
|||
if ( bulk ) { |
|||
return fn.call( elems ); |
|||
} |
|||
|
|||
return len ? fn( elems[ 0 ], key ) : emptyGet; |
|||
}; |
|||
|
|||
return access; |
|||
|
|||
} ); |
|||
@ -0,0 +1,128 @@ |
|||
// Initialize a jQuery object
|
|||
define( [ |
|||
"../core", |
|||
"../var/document", |
|||
"./var/rsingleTag", |
|||
|
|||
"../traversing/findFilter" |
|||
], function( jQuery, document, rsingleTag ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// A central reference to the root jQuery(document)
|
|||
var rootjQuery, |
|||
|
|||
// A simple way to check for HTML strings
|
|||
// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
|
|||
// Strict HTML recognition (#11290: must start with <)
|
|||
// Shortcut simple #id case for speed
|
|||
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, |
|||
|
|||
init = jQuery.fn.init = function( selector, context, root ) { |
|||
var match, elem; |
|||
|
|||
// HANDLE: $(""), $(null), $(undefined), $(false)
|
|||
if ( !selector ) { |
|||
return this; |
|||
} |
|||
|
|||
// Method init() accepts an alternate rootjQuery
|
|||
// so migrate can support jQuery.sub (gh-2101)
|
|||
root = root || rootjQuery; |
|||
|
|||
// Handle HTML strings
|
|||
if ( typeof selector === "string" ) { |
|||
if ( selector[ 0 ] === "<" && |
|||
selector[ selector.length - 1 ] === ">" && |
|||
selector.length >= 3 ) { |
|||
|
|||
// Assume that strings that start and end with <> are HTML and skip the regex check
|
|||
match = [ null, selector, null ]; |
|||
|
|||
} else { |
|||
match = rquickExpr.exec( selector ); |
|||
} |
|||
|
|||
// Match html or make sure no context is specified for #id
|
|||
if ( match && ( match[ 1 ] || !context ) ) { |
|||
|
|||
// HANDLE: $(html) -> $(array)
|
|||
if ( match[ 1 ] ) { |
|||
context = context instanceof jQuery ? context[ 0 ] : context; |
|||
|
|||
// Option to run scripts is true for back-compat
|
|||
// Intentionally let the error be thrown if parseHTML is not present
|
|||
jQuery.merge( this, jQuery.parseHTML( |
|||
match[ 1 ], |
|||
context && context.nodeType ? context.ownerDocument || context : document, |
|||
true |
|||
) ); |
|||
|
|||
// HANDLE: $(html, props)
|
|||
if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { |
|||
for ( match in context ) { |
|||
|
|||
// Properties of context are called as methods if possible
|
|||
if ( jQuery.isFunction( this[ match ] ) ) { |
|||
this[ match ]( context[ match ] ); |
|||
|
|||
// ...and otherwise set as attributes
|
|||
} else { |
|||
this.attr( match, context[ match ] ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return this; |
|||
|
|||
// HANDLE: $(#id)
|
|||
} else { |
|||
elem = document.getElementById( match[ 2 ] ); |
|||
|
|||
if ( elem ) { |
|||
|
|||
// Inject the element directly into the jQuery object
|
|||
this[ 0 ] = elem; |
|||
this.length = 1; |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
// HANDLE: $(expr, $(...))
|
|||
} else if ( !context || context.jquery ) { |
|||
return ( context || root ).find( selector ); |
|||
|
|||
// HANDLE: $(expr, context)
|
|||
// (which is just equivalent to: $(context).find(expr)
|
|||
} else { |
|||
return this.constructor( context ).find( selector ); |
|||
} |
|||
|
|||
// HANDLE: $(DOMElement)
|
|||
} else if ( selector.nodeType ) { |
|||
this[ 0 ] = selector; |
|||
this.length = 1; |
|||
return this; |
|||
|
|||
// HANDLE: $(function)
|
|||
// Shortcut for document ready
|
|||
} else if ( jQuery.isFunction( selector ) ) { |
|||
return root.ready !== undefined ? |
|||
root.ready( selector ) : |
|||
|
|||
// Execute immediately if ready is not present
|
|||
selector( jQuery ); |
|||
} |
|||
|
|||
return jQuery.makeArray( selector, this ); |
|||
}; |
|||
|
|||
// Give the init function the jQuery prototype for later instantiation
|
|||
init.prototype = jQuery.fn; |
|||
|
|||
// Initialize central reference
|
|||
rootjQuery = jQuery( document ); |
|||
|
|||
return init; |
|||
|
|||
} ); |
|||
@ -0,0 +1,13 @@ |
|||
define( function() { |
|||
|
|||
"use strict"; |
|||
|
|||
function nodeName( elem, name ) { |
|||
|
|||
return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); |
|||
|
|||
}; |
|||
|
|||
return nodeName; |
|||
|
|||
} ); |
|||
@ -0,0 +1,65 @@ |
|||
define( [ |
|||
"../core", |
|||
"../var/document", |
|||
"./var/rsingleTag", |
|||
"../manipulation/buildFragment", |
|||
|
|||
// This is the only module that needs core/support
|
|||
"./support" |
|||
], function( jQuery, document, rsingleTag, buildFragment, support ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// Argument "data" should be string of html
|
|||
// context (optional): If specified, the fragment will be created in this context,
|
|||
// defaults to document
|
|||
// keepScripts (optional): If true, will include scripts passed in the html string
|
|||
jQuery.parseHTML = function( data, context, keepScripts ) { |
|||
if ( typeof data !== "string" ) { |
|||
return []; |
|||
} |
|||
if ( typeof context === "boolean" ) { |
|||
keepScripts = context; |
|||
context = false; |
|||
} |
|||
|
|||
var base, parsed, scripts; |
|||
|
|||
if ( !context ) { |
|||
|
|||
// Stop scripts or inline event handlers from being executed immediately
|
|||
// by using document.implementation
|
|||
if ( support.createHTMLDocument ) { |
|||
context = document.implementation.createHTMLDocument( "" ); |
|||
|
|||
// Set the base href for the created document
|
|||
// so any parsed elements with URLs
|
|||
// are based on the document's URL (gh-2965)
|
|||
base = context.createElement( "base" ); |
|||
base.href = document.location.href; |
|||
context.head.appendChild( base ); |
|||
} else { |
|||
context = document; |
|||
} |
|||
} |
|||
|
|||
parsed = rsingleTag.exec( data ); |
|||
scripts = !keepScripts && []; |
|||
|
|||
// Single tag
|
|||
if ( parsed ) { |
|||
return [ context.createElement( parsed[ 1 ] ) ]; |
|||
} |
|||
|
|||
parsed = buildFragment( [ data ], context, scripts ); |
|||
|
|||
if ( scripts && scripts.length ) { |
|||
jQuery( scripts ).remove(); |
|||
} |
|||
|
|||
return jQuery.merge( [], parsed.childNodes ); |
|||
}; |
|||
|
|||
return jQuery.parseHTML; |
|||
|
|||
} ); |
|||
@ -0,0 +1,96 @@ |
|||
define( [ |
|||
"../core", |
|||
"../var/document" |
|||
], function( jQuery, document ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var readyCallbacks = [], |
|||
whenReady = function( fn ) { |
|||
readyCallbacks.push( fn ); |
|||
}, |
|||
executeReady = function( fn ) { |
|||
|
|||
// Prevent errors from freezing future callback execution (gh-1823)
|
|||
// Not backwards-compatible as this does not execute sync
|
|||
window.setTimeout( function() { |
|||
fn.call( document, jQuery ); |
|||
} ); |
|||
}; |
|||
|
|||
jQuery.fn.ready = function( fn ) { |
|||
whenReady( fn ); |
|||
return this; |
|||
}; |
|||
|
|||
jQuery.extend( { |
|||
|
|||
// Is the DOM ready to be used? Set to true once it occurs.
|
|||
isReady: false, |
|||
|
|||
// A counter to track how many items to wait for before
|
|||
// the ready event fires. See #6781
|
|||
readyWait: 1, |
|||
|
|||
ready: function( wait ) { |
|||
|
|||
// Abort if there are pending holds or we're already ready
|
|||
if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { |
|||
return; |
|||
} |
|||
|
|||
// Remember that the DOM is ready
|
|||
jQuery.isReady = true; |
|||
|
|||
// If a normal DOM Ready event fired, decrement, and wait if need be
|
|||
if ( wait !== true && --jQuery.readyWait > 0 ) { |
|||
return; |
|||
} |
|||
|
|||
whenReady = function( fn ) { |
|||
readyCallbacks.push( fn ); |
|||
|
|||
while ( readyCallbacks.length ) { |
|||
fn = readyCallbacks.shift(); |
|||
if ( jQuery.isFunction( fn ) ) { |
|||
executeReady( fn ); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
whenReady(); |
|||
} |
|||
} ); |
|||
|
|||
// Make jQuery.ready Promise consumable (gh-1778)
|
|||
jQuery.ready.then = jQuery.fn.ready; |
|||
|
|||
/** |
|||
* The ready event handler and self cleanup method |
|||
*/ |
|||
function completed() { |
|||
document.removeEventListener( "DOMContentLoaded", completed ); |
|||
window.removeEventListener( "load", completed ); |
|||
jQuery.ready(); |
|||
} |
|||
|
|||
// Catch cases where $(document).ready() is called
|
|||
// after the browser event has already occurred.
|
|||
// Support: IE9-10 only
|
|||
// Older IE sometimes signals "interactive" too soon
|
|||
if ( document.readyState === "complete" || |
|||
( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { |
|||
|
|||
// Handle it asynchronously to allow scripts the opportunity to delay ready
|
|||
window.setTimeout( jQuery.ready ); |
|||
|
|||
} else { |
|||
|
|||
// Use the handy event callback
|
|||
document.addEventListener( "DOMContentLoaded", completed ); |
|||
|
|||
// A fallback to window.onload, that will always work
|
|||
window.addEventListener( "load", completed ); |
|||
} |
|||
|
|||
} ); |
|||
@ -0,0 +1,86 @@ |
|||
define( [ |
|||
"../core", |
|||
"../var/document", |
|||
"../core/readyException", |
|||
"../deferred" |
|||
], function( jQuery, document ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// The deferred used on DOM ready
|
|||
var readyList = jQuery.Deferred(); |
|||
|
|||
jQuery.fn.ready = function( fn ) { |
|||
|
|||
readyList |
|||
.then( fn ) |
|||
|
|||
// Wrap jQuery.readyException in a function so that the lookup
|
|||
// happens at the time of error handling instead of callback
|
|||
// registration.
|
|||
.catch( function( error ) { |
|||
jQuery.readyException( error ); |
|||
} ); |
|||
|
|||
return this; |
|||
}; |
|||
|
|||
jQuery.extend( { |
|||
|
|||
// Is the DOM ready to be used? Set to true once it occurs.
|
|||
isReady: false, |
|||
|
|||
// A counter to track how many items to wait for before
|
|||
// the ready event fires. See #6781
|
|||
readyWait: 1, |
|||
|
|||
// Handle when the DOM is ready
|
|||
ready: function( wait ) { |
|||
|
|||
// Abort if there are pending holds or we're already ready
|
|||
if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { |
|||
return; |
|||
} |
|||
|
|||
// Remember that the DOM is ready
|
|||
jQuery.isReady = true; |
|||
|
|||
// If a normal DOM Ready event fired, decrement, and wait if need be
|
|||
if ( wait !== true && --jQuery.readyWait > 0 ) { |
|||
return; |
|||
} |
|||
|
|||
// If there are functions bound, to execute
|
|||
readyList.resolveWith( document, [ jQuery ] ); |
|||
} |
|||
} ); |
|||
|
|||
jQuery.ready.then = readyList.then; |
|||
|
|||
// The ready event handler and self cleanup method
|
|||
function completed() { |
|||
document.removeEventListener( "DOMContentLoaded", completed ); |
|||
window.removeEventListener( "load", completed ); |
|||
jQuery.ready(); |
|||
} |
|||
|
|||
// Catch cases where $(document).ready() is called
|
|||
// after the browser event has already occurred.
|
|||
// Support: IE <=9 - 10 only
|
|||
// Older IE sometimes signals "interactive" too soon
|
|||
if ( document.readyState === "complete" || |
|||
( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { |
|||
|
|||
// Handle it asynchronously to allow scripts the opportunity to delay ready
|
|||
window.setTimeout( jQuery.ready ); |
|||
|
|||
} else { |
|||
|
|||
// Use the handy event callback
|
|||
document.addEventListener( "DOMContentLoaded", completed ); |
|||
|
|||
// A fallback to window.onload, that will always work
|
|||
window.addEventListener( "load", completed ); |
|||
} |
|||
|
|||
} ); |
|||
@ -0,0 +1,13 @@ |
|||
define( [ |
|||
"../core" |
|||
], function( jQuery ) { |
|||
|
|||
"use strict"; |
|||
|
|||
jQuery.readyException = function( error ) { |
|||
window.setTimeout( function() { |
|||
throw error; |
|||
} ); |
|||
}; |
|||
|
|||
} ); |
|||
@ -0,0 +1,14 @@ |
|||
define( [ |
|||
"../var/rnothtmlwhite" |
|||
], function( rnothtmlwhite ) { |
|||
"use strict"; |
|||
|
|||
// Strip and collapse whitespace according to HTML spec
|
|||
// https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace
|
|||
function stripAndCollapse( value ) { |
|||
var tokens = value.match( rnothtmlwhite ) || []; |
|||
return tokens.join( " " ); |
|||
} |
|||
|
|||
return stripAndCollapse; |
|||
} ); |
|||
@ -0,0 +1,20 @@ |
|||
define( [ |
|||
"../var/document", |
|||
"../var/support" |
|||
], function( document, support ) { |
|||
|
|||
"use strict"; |
|||
|
|||
// Support: Safari 8 only
|
|||
// In Safari 8 documents created via document.implementation.createHTMLDocument
|
|||
// collapse sibling forms: the second one becomes a child of the first one.
|
|||
// Because of that, this security measure has to be disabled in Safari 8.
|
|||
// https://bugs.webkit.org/show_bug.cgi?id=137337
|
|||
support.createHTMLDocument = ( function() { |
|||
var body = document.implementation.createHTMLDocument( "" ).body; |
|||
body.innerHTML = "<form></form><form></form>"; |
|||
return body.childNodes.length === 2; |
|||
} )(); |
|||
|
|||
return support; |
|||
} ); |
|||
@ -0,0 +1,6 @@ |
|||
define( function() { |
|||
"use strict"; |
|||
|
|||
// Match a standalone tag
|
|||
return ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); |
|||
} ); |
|||
@ -0,0 +1,438 @@ |
|||
define( [ |
|||
"./core", |
|||
"./var/pnum", |
|||
"./core/access", |
|||
"./css/var/rmargin", |
|||
"./var/document", |
|||
"./var/rcssNum", |
|||
"./css/var/rnumnonpx", |
|||
"./css/var/cssExpand", |
|||
"./css/var/getStyles", |
|||
"./css/var/swap", |
|||
"./css/curCSS", |
|||
"./css/adjustCSS", |
|||
"./css/addGetHookIf", |
|||
"./css/support", |
|||
|
|||
"./core/init", |
|||
"./core/ready", |
|||
"./selector" // contains
|
|||
], function( jQuery, pnum, access, rmargin, document, rcssNum, rnumnonpx, cssExpand, |
|||
getStyles, swap, curCSS, adjustCSS, addGetHookIf, support ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var |
|||
|
|||
// Swappable if display is none or starts with table
|
|||
// except "table", "table-cell", or "table-caption"
|
|||
// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
|
|||
rdisplayswap = /^(none|table(?!-c[ea]).+)/, |
|||
rcustomProp = /^--/, |
|||
cssShow = { position: "absolute", visibility: "hidden", display: "block" }, |
|||
cssNormalTransform = { |
|||
letterSpacing: "0", |
|||
fontWeight: "400" |
|||
}, |
|||
|
|||
cssPrefixes = [ "Webkit", "Moz", "ms" ], |
|||
emptyStyle = document.createElement( "div" ).style; |
|||
|
|||
// Return a css property mapped to a potentially vendor prefixed property
|
|||
function vendorPropName( name ) { |
|||
|
|||
// Shortcut for names that are not vendor prefixed
|
|||
if ( name in emptyStyle ) { |
|||
return name; |
|||
} |
|||
|
|||
// Check for vendor prefixed names
|
|||
var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), |
|||
i = cssPrefixes.length; |
|||
|
|||
while ( i-- ) { |
|||
name = cssPrefixes[ i ] + capName; |
|||
if ( name in emptyStyle ) { |
|||
return name; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Return a property mapped along what jQuery.cssProps suggests or to
|
|||
// a vendor prefixed property.
|
|||
function finalPropName( name ) { |
|||
var ret = jQuery.cssProps[ name ]; |
|||
if ( !ret ) { |
|||
ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
function setPositiveNumber( elem, value, subtract ) { |
|||
|
|||
// Any relative (+/-) values have already been
|
|||
// normalized at this point
|
|||
var matches = rcssNum.exec( value ); |
|||
return matches ? |
|||
|
|||
// Guard against undefined "subtract", e.g., when used as in cssHooks
|
|||
Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : |
|||
value; |
|||
} |
|||
|
|||
function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { |
|||
var i, |
|||
val = 0; |
|||
|
|||
// If we already have the right measurement, avoid augmentation
|
|||
if ( extra === ( isBorderBox ? "border" : "content" ) ) { |
|||
i = 4; |
|||
|
|||
// Otherwise initialize for horizontal or vertical properties
|
|||
} else { |
|||
i = name === "width" ? 1 : 0; |
|||
} |
|||
|
|||
for ( ; i < 4; i += 2 ) { |
|||
|
|||
// Both box models exclude margin, so add it if we want it
|
|||
if ( extra === "margin" ) { |
|||
val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); |
|||
} |
|||
|
|||
if ( isBorderBox ) { |
|||
|
|||
// border-box includes padding, so remove it if we want content
|
|||
if ( extra === "content" ) { |
|||
val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); |
|||
} |
|||
|
|||
// At this point, extra isn't border nor margin, so remove border
|
|||
if ( extra !== "margin" ) { |
|||
val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); |
|||
} |
|||
} else { |
|||
|
|||
// At this point, extra isn't content, so add padding
|
|||
val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); |
|||
|
|||
// At this point, extra isn't content nor padding, so add border
|
|||
if ( extra !== "padding" ) { |
|||
val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return val; |
|||
} |
|||
|
|||
function getWidthOrHeight( elem, name, extra ) { |
|||
|
|||
// Start with computed style
|
|||
var valueIsBorderBox, |
|||
styles = getStyles( elem ), |
|||
val = curCSS( elem, name, styles ), |
|||
isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; |
|||
|
|||
// Computed unit is not pixels. Stop here and return.
|
|||
if ( rnumnonpx.test( val ) ) { |
|||
return val; |
|||
} |
|||
|
|||
// Check for style in case a browser which returns unreliable values
|
|||
// for getComputedStyle silently falls back to the reliable elem.style
|
|||
valueIsBorderBox = isBorderBox && |
|||
( support.boxSizingReliable() || val === elem.style[ name ] ); |
|||
|
|||
// Fall back to offsetWidth/Height when value is "auto"
|
|||
// This happens for inline elements with no explicit setting (gh-3571)
|
|||
if ( val === "auto" ) { |
|||
val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ]; |
|||
} |
|||
|
|||
// Normalize "", auto, and prepare for extra
|
|||
val = parseFloat( val ) || 0; |
|||
|
|||
// Use the active box-sizing model to add/subtract irrelevant styles
|
|||
return ( val + |
|||
augmentWidthOrHeight( |
|||
elem, |
|||
name, |
|||
extra || ( isBorderBox ? "border" : "content" ), |
|||
valueIsBorderBox, |
|||
styles |
|||
) |
|||
) + "px"; |
|||
} |
|||
|
|||
jQuery.extend( { |
|||
|
|||
// Add in style property hooks for overriding the default
|
|||
// behavior of getting and setting a style property
|
|||
cssHooks: { |
|||
opacity: { |
|||
get: function( elem, computed ) { |
|||
if ( computed ) { |
|||
|
|||
// We should always get a number back from opacity
|
|||
var ret = curCSS( elem, "opacity" ); |
|||
return ret === "" ? "1" : ret; |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
|
|||
// Don't automatically add "px" to these possibly-unitless properties
|
|||
cssNumber: { |
|||
"animationIterationCount": true, |
|||
"columnCount": true, |
|||
"fillOpacity": true, |
|||
"flexGrow": true, |
|||
"flexShrink": true, |
|||
"fontWeight": true, |
|||
"lineHeight": true, |
|||
"opacity": true, |
|||
"order": true, |
|||
"orphans": true, |
|||
"widows": true, |
|||
"zIndex": true, |
|||
"zoom": true |
|||
}, |
|||
|
|||
// Add in properties whose names you wish to fix before
|
|||
// setting or getting the value
|
|||
cssProps: { |
|||
"float": "cssFloat" |
|||
}, |
|||
|
|||
// Get and set the style property on a DOM Node
|
|||
style: function( elem, name, value, extra ) { |
|||
|
|||
// Don't set styles on text and comment nodes
|
|||
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { |
|||
return; |
|||
} |
|||
|
|||
// Make sure that we're working with the right name
|
|||
var ret, type, hooks, |
|||
origName = jQuery.camelCase( name ), |
|||
isCustomProp = rcustomProp.test( name ), |
|||
style = elem.style; |
|||
|
|||
// Make sure that we're working with the right name. We don't
|
|||
// want to query the value if it is a CSS custom property
|
|||
// since they are user-defined.
|
|||
if ( !isCustomProp ) { |
|||
name = finalPropName( origName ); |
|||
} |
|||
|
|||
// Gets hook for the prefixed version, then unprefixed version
|
|||
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; |
|||
|
|||
// Check if we're setting a value
|
|||
if ( value !== undefined ) { |
|||
type = typeof value; |
|||
|
|||
// Convert "+=" or "-=" to relative numbers (#7345)
|
|||
if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { |
|||
value = adjustCSS( elem, name, ret ); |
|||
|
|||
// Fixes bug #9237
|
|||
type = "number"; |
|||
} |
|||
|
|||
// Make sure that null and NaN values aren't set (#7116)
|
|||
if ( value == null || value !== value ) { |
|||
return; |
|||
} |
|||
|
|||
// If a number was passed in, add the unit (except for certain CSS properties)
|
|||
if ( type === "number" ) { |
|||
value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); |
|||
} |
|||
|
|||
// background-* props affect original clone's values
|
|||
if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { |
|||
style[ name ] = "inherit"; |
|||
} |
|||
|
|||
// If a hook was provided, use that value, otherwise just set the specified value
|
|||
if ( !hooks || !( "set" in hooks ) || |
|||
( value = hooks.set( elem, value, extra ) ) !== undefined ) { |
|||
|
|||
if ( isCustomProp ) { |
|||
style.setProperty( name, value ); |
|||
} else { |
|||
style[ name ] = value; |
|||
} |
|||
} |
|||
|
|||
} else { |
|||
|
|||
// If a hook was provided get the non-computed value from there
|
|||
if ( hooks && "get" in hooks && |
|||
( ret = hooks.get( elem, false, extra ) ) !== undefined ) { |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
// Otherwise just get the value from the style object
|
|||
return style[ name ]; |
|||
} |
|||
}, |
|||
|
|||
css: function( elem, name, extra, styles ) { |
|||
var val, num, hooks, |
|||
origName = jQuery.camelCase( name ), |
|||
isCustomProp = rcustomProp.test( name ); |
|||
|
|||
// Make sure that we're working with the right name. We don't
|
|||
// want to modify the value if it is a CSS custom property
|
|||
// since they are user-defined.
|
|||
if ( !isCustomProp ) { |
|||
name = finalPropName( origName ); |
|||
} |
|||
|
|||
// Try prefixed name followed by the unprefixed name
|
|||
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; |
|||
|
|||
// If a hook was provided get the computed value from there
|
|||
if ( hooks && "get" in hooks ) { |
|||
val = hooks.get( elem, true, extra ); |
|||
} |
|||
|
|||
// Otherwise, if a way to get the computed value exists, use that
|
|||
if ( val === undefined ) { |
|||
val = curCSS( elem, name, styles ); |
|||
} |
|||
|
|||
// Convert "normal" to computed value
|
|||
if ( val === "normal" && name in cssNormalTransform ) { |
|||
val = cssNormalTransform[ name ]; |
|||
} |
|||
|
|||
// Make numeric if forced or a qualifier was provided and val looks numeric
|
|||
if ( extra === "" || extra ) { |
|||
num = parseFloat( val ); |
|||
return extra === true || isFinite( num ) ? num || 0 : val; |
|||
} |
|||
|
|||
return val; |
|||
} |
|||
} ); |
|||
|
|||
jQuery.each( [ "height", "width" ], function( i, name ) { |
|||
jQuery.cssHooks[ name ] = { |
|||
get: function( elem, computed, extra ) { |
|||
if ( computed ) { |
|||
|
|||
// Certain elements can have dimension info if we invisibly show them
|
|||
// but it must have a current display style that would benefit
|
|||
return rdisplayswap.test( jQuery.css( elem, "display" ) ) && |
|||
|
|||
// Support: Safari 8+
|
|||
// Table columns in Safari have non-zero offsetWidth & zero
|
|||
// getBoundingClientRect().width unless display is changed.
|
|||
// Support: IE <=11 only
|
|||
// Running getBoundingClientRect on a disconnected node
|
|||
// in IE throws an error.
|
|||
( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? |
|||
swap( elem, cssShow, function() { |
|||
return getWidthOrHeight( elem, name, extra ); |
|||
} ) : |
|||
getWidthOrHeight( elem, name, extra ); |
|||
} |
|||
}, |
|||
|
|||
set: function( elem, value, extra ) { |
|||
var matches, |
|||
styles = extra && getStyles( elem ), |
|||
subtract = extra && augmentWidthOrHeight( |
|||
elem, |
|||
name, |
|||
extra, |
|||
jQuery.css( elem, "boxSizing", false, styles ) === "border-box", |
|||
styles |
|||
); |
|||
|
|||
// Convert to pixels if value adjustment is needed
|
|||
if ( subtract && ( matches = rcssNum.exec( value ) ) && |
|||
( matches[ 3 ] || "px" ) !== "px" ) { |
|||
|
|||
elem.style[ name ] = value; |
|||
value = jQuery.css( elem, name ); |
|||
} |
|||
|
|||
return setPositiveNumber( elem, value, subtract ); |
|||
} |
|||
}; |
|||
} ); |
|||
|
|||
jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, |
|||
function( elem, computed ) { |
|||
if ( computed ) { |
|||
return ( parseFloat( curCSS( elem, "marginLeft" ) ) || |
|||
elem.getBoundingClientRect().left - |
|||
swap( elem, { marginLeft: 0 }, function() { |
|||
return elem.getBoundingClientRect().left; |
|||
} ) |
|||
) + "px"; |
|||
} |
|||
} |
|||
); |
|||
|
|||
// These hooks are used by animate to expand properties
|
|||
jQuery.each( { |
|||
margin: "", |
|||
padding: "", |
|||
border: "Width" |
|||
}, function( prefix, suffix ) { |
|||
jQuery.cssHooks[ prefix + suffix ] = { |
|||
expand: function( value ) { |
|||
var i = 0, |
|||
expanded = {}, |
|||
|
|||
// Assumes a single number if not a string
|
|||
parts = typeof value === "string" ? value.split( " " ) : [ value ]; |
|||
|
|||
for ( ; i < 4; i++ ) { |
|||
expanded[ prefix + cssExpand[ i ] + suffix ] = |
|||
parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; |
|||
} |
|||
|
|||
return expanded; |
|||
} |
|||
}; |
|||
|
|||
if ( !rmargin.test( prefix ) ) { |
|||
jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; |
|||
} |
|||
} ); |
|||
|
|||
jQuery.fn.extend( { |
|||
css: function( name, value ) { |
|||
return access( this, function( elem, name, value ) { |
|||
var styles, len, |
|||
map = {}, |
|||
i = 0; |
|||
|
|||
if ( Array.isArray( name ) ) { |
|||
styles = getStyles( elem ); |
|||
len = name.length; |
|||
|
|||
for ( ; i < len; i++ ) { |
|||
map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); |
|||
} |
|||
|
|||
return map; |
|||
} |
|||
|
|||
return value !== undefined ? |
|||
jQuery.style( elem, name, value ) : |
|||
jQuery.css( elem, name ); |
|||
}, name, value, arguments.length > 1 ); |
|||
} |
|||
} ); |
|||
|
|||
return jQuery; |
|||
} ); |
|||
@ -0,0 +1,26 @@ |
|||
define( function() { |
|||
|
|||
"use strict"; |
|||
|
|||
function addGetHookIf( conditionFn, hookFn ) { |
|||
|
|||
// Define the hook, we'll check on the first run if it's really needed.
|
|||
return { |
|||
get: function() { |
|||
if ( conditionFn() ) { |
|||
|
|||
// Hook not needed (or it's not possible to use it due
|
|||
// to missing dependency), remove it.
|
|||
delete this.get; |
|||
return; |
|||
} |
|||
|
|||
// Hook needed; redefine it so that the support test is not executed again.
|
|||
return ( this.get = hookFn ).apply( this, arguments ); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
return addGetHookIf; |
|||
|
|||
} ); |
|||
@ -0,0 +1,71 @@ |
|||
define( [ |
|||
"../core", |
|||
"../var/rcssNum" |
|||
], function( jQuery, rcssNum ) { |
|||
|
|||
"use strict"; |
|||
|
|||
function adjustCSS( elem, prop, valueParts, tween ) { |
|||
var adjusted, |
|||
scale = 1, |
|||
maxIterations = 20, |
|||
currentValue = tween ? |
|||
function() { |
|||
return tween.cur(); |
|||
} : |
|||
function() { |
|||
return jQuery.css( elem, prop, "" ); |
|||
}, |
|||
initial = currentValue(), |
|||
unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), |
|||
|
|||
// Starting value computation is required for potential unit mismatches
|
|||
initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && |
|||
rcssNum.exec( jQuery.css( elem, prop ) ); |
|||
|
|||
if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { |
|||
|
|||
// Trust units reported by jQuery.css
|
|||
unit = unit || initialInUnit[ 3 ]; |
|||
|
|||
// Make sure we update the tween properties later on
|
|||
valueParts = valueParts || []; |
|||
|
|||
// Iteratively approximate from a nonzero starting point
|
|||
initialInUnit = +initial || 1; |
|||
|
|||
do { |
|||
|
|||
// If previous iteration zeroed out, double until we get *something*.
|
|||
// Use string for doubling so we don't accidentally see scale as unchanged below
|
|||
scale = scale || ".5"; |
|||
|
|||
// Adjust and apply
|
|||
initialInUnit = initialInUnit / scale; |
|||
jQuery.style( elem, prop, initialInUnit + unit ); |
|||
|
|||
// Update scale, tolerating zero or NaN from tween.cur()
|
|||
// Break the loop if scale is unchanged or perfect, or if we've just had enough.
|
|||
} while ( |
|||
scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations |
|||
); |
|||
} |
|||
|
|||
if ( valueParts ) { |
|||
initialInUnit = +initialInUnit || +initial || 0; |
|||
|
|||
// Apply relative offset (+=/-=) if specified
|
|||
adjusted = valueParts[ 1 ] ? |
|||
initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : |
|||
+valueParts[ 2 ]; |
|||
if ( tween ) { |
|||
tween.unit = unit; |
|||
tween.start = initialInUnit; |
|||
tween.end = adjusted; |
|||
} |
|||
} |
|||
return adjusted; |
|||
} |
|||
|
|||
return adjustCSS; |
|||
} ); |
|||
@ -0,0 +1,65 @@ |
|||
define( [ |
|||
"../core", |
|||
"./var/rnumnonpx", |
|||
"./var/rmargin", |
|||
"./var/getStyles", |
|||
"./support", |
|||
"../selector" // Get jQuery.contains
|
|||
], function( jQuery, rnumnonpx, rmargin, getStyles, support ) { |
|||
|
|||
"use strict"; |
|||
|
|||
function curCSS( elem, name, computed ) { |
|||
var width, minWidth, maxWidth, ret, |
|||
|
|||
// Support: Firefox 51+
|
|||
// Retrieving style before computed somehow
|
|||
// fixes an issue with getting wrong values
|
|||
// on detached elements
|
|||
style = elem.style; |
|||
|
|||
computed = computed || getStyles( elem ); |
|||
|
|||
// getPropertyValue is needed for:
|
|||
// .css('filter') (IE 9 only, #12537)
|
|||
// .css('--customProperty) (#3144)
|
|||
if ( computed ) { |
|||
ret = computed.getPropertyValue( name ) || computed[ name ]; |
|||
|
|||
if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { |
|||
ret = jQuery.style( elem, name ); |
|||
} |
|||
|
|||
// A tribute to the "awesome hack by Dean Edwards"
|
|||
// Android Browser returns percentage for some values,
|
|||
// but width seems to be reliably pixels.
|
|||
// This is against the CSSOM draft spec:
|
|||
// https://drafts.csswg.org/cssom/#resolved-values
|
|||
if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) { |
|||
|
|||
// Remember the original values
|
|||
width = style.width; |
|||
minWidth = style.minWidth; |
|||
maxWidth = style.maxWidth; |
|||
|
|||
// Put in the new values to get a computed value out
|
|||
style.minWidth = style.maxWidth = style.width = ret; |
|||
ret = computed.width; |
|||
|
|||
// Revert the changed values
|
|||
style.width = width; |
|||
style.minWidth = minWidth; |
|||
style.maxWidth = maxWidth; |
|||
} |
|||
} |
|||
|
|||
return ret !== undefined ? |
|||
|
|||
// Support: IE <=9 - 11 only
|
|||
// IE returns zIndex value as an integer.
|
|||
ret + "" : |
|||
ret; |
|||
} |
|||
|
|||
return curCSS; |
|||
} ); |
|||
@ -0,0 +1,15 @@ |
|||
define( [ |
|||
"../core", |
|||
"../selector" |
|||
], function( jQuery ) { |
|||
|
|||
"use strict"; |
|||
|
|||
jQuery.expr.pseudos.hidden = function( elem ) { |
|||
return !jQuery.expr.pseudos.visible( elem ); |
|||
}; |
|||
jQuery.expr.pseudos.visible = function( elem ) { |
|||
return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); |
|||
}; |
|||
|
|||
} ); |
|||
@ -0,0 +1,105 @@ |
|||
define( [ |
|||
"../core", |
|||
"../data/var/dataPriv", |
|||
"../css/var/isHiddenWithinTree" |
|||
], function( jQuery, dataPriv, isHiddenWithinTree ) { |
|||
|
|||
"use strict"; |
|||
|
|||
var defaultDisplayMap = {}; |
|||
|
|||
function getDefaultDisplay( elem ) { |
|||
var temp, |
|||
doc = elem.ownerDocument, |
|||
nodeName = elem.nodeName, |
|||
display = defaultDisplayMap[ nodeName ]; |
|||
|
|||
if ( display ) { |
|||
return display; |
|||
} |
|||
|
|||
temp = doc.body.appendChild( doc.createElement( nodeName ) ); |
|||
display = jQuery.css( temp, "display" ); |
|||
|
|||
temp.parentNode.removeChild( temp ); |
|||
|
|||
if ( display === "none" ) { |
|||
display = "block"; |
|||
} |
|||
defaultDisplayMap[ nodeName ] = display; |
|||
|
|||
return display; |
|||
} |
|||
|
|||
function showHide( elements, show ) { |
|||
var display, elem, |
|||
values = [], |
|||
index = 0, |
|||
length = elements.length; |
|||
|
|||
// Determine new display value for elements that need to change
|
|||
for ( ; index < length; index++ ) { |
|||
elem = elements[ index ]; |
|||
if ( !elem.style ) { |
|||
continue; |
|||
} |
|||
|
|||
display = elem.style.display; |
|||
if ( show ) { |
|||
|
|||
// Since we force visibility upon cascade-hidden elements, an immediate (and slow)
|
|||
// check is required in this first loop unless we have a nonempty display value (either
|
|||
// inline or about-to-be-restored)
|
|||
if ( display === "none" ) { |
|||
values[ index ] = dataPriv.get( elem, "display" ) || null; |
|||
if ( !values[ index ] ) { |
|||
elem.style.display = ""; |
|||
} |
|||
} |
|||
if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { |
|||
values[ index ] = getDefaultDisplay( elem ); |
|||
} |
|||
} else { |
|||
if ( display !== "none" ) { |
|||
values[ index ] = "none"; |
|||
|
|||
// Remember what we're overwriting
|
|||
dataPriv.set( elem, "display", display ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Set the display of the elements in a second loop to avoid constant reflow
|
|||
for ( index = 0; index < length; index++ ) { |
|||
if ( values[ index ] != null ) { |
|||
elements[ index ].style.display = values[ index ]; |
|||
} |
|||
} |
|||
|
|||
return elements; |
|||
} |
|||
|
|||
jQuery.fn.extend( { |
|||
show: function() { |
|||
return showHide( this, true ); |
|||
}, |
|||
hide: function() { |
|||
return showHide( this ); |
|||
}, |
|||
toggle: function( state ) { |
|||
if ( typeof state === "boolean" ) { |
|||
return state ? this.show() : this.hide(); |
|||
} |
|||
|
|||
return this.each( function() { |
|||
if ( isHiddenWithinTree( this ) ) { |
|||
jQuery( this ).show(); |
|||
} else { |
|||
jQuery( this ).hide(); |
|||
} |
|||
} ); |
|||
} |
|||
} ); |
|||
|
|||
return showHide; |
|||
} ); |
|||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue