From 30ae2cb9dd468422fffef94af050dec6a90c91ac Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Fri, 22 Feb 2019 04:24:01 +0200 Subject: [PATCH 01/18] Add new 2019 video course made by J-Secur1ty and add the most important part of our README.md; the support that we provided over the years. Former-commit-id: 7390164a6639a7be949c04a000cef9c347d93968 --- README.md | 134 +++++++++++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index c5f97e9a..de0f30ce 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# ⚡️ Update: community-driven version 11.1.0 +# ⚡️ Stay tuned for updates: upcoming version 11.2.0 -Click [here](HISTORY.md#su-18-november-2018--v1110) to read about the versioning API that the most recent version of Iris brings to you. +Click [here](https://github.com/kataras/iris/pull/1175) to watch the progress of the upcoming release and the new features that it brings into game. # Iris Web Framework @@ -16,6 +16,38 @@ Iris offers a complete and decent solution and support for all gophers around th Learn what [others say about Iris](#support) and [star](https://github.com/kataras/iris/stargazers) this github repository to stay [up to date](https://facebook.com/iris.framework). +## Ghost? No More! Support as first class citizen + +Have you bored of waiting weeks or months for someone to respond to your github issue? Yes, **me too**. If you choose Iris for your main backend development you will never be like a ghost again. + +Iris is one of the few public github repositories that offers real support to individuals and collectivities, including companies. Unbeatable **free support**[*](#support) for three years and still counting. Navigate to the issues to see by yourself. + +In these difficult and restless days **we stand beside you**. We **do not judge bad english writing**, no matter who you are, we will be here for you. + +Check below the features and the hard work that we putted to improve how the internet is built. If you really like it and appreciate it, give a star to this github **repository for the public.** + +## Benchmarks + +### Iris vs .NET Core vs Expressjs + +[![Iris vs .NET Core(C#) vs Node.js (Express)](_benchmarks/benchmarks_graph_22_october_2018_gray.png)](_benchmarks/README.md) + +_Updated at: [Monday, 22 October 2018](_benchmarks/README.md)_ + +### Iris vs the rest Go web frameworks and routers vs any other alternative + +[![](_benchmarks/benchmarks_third_party_source_snapshot_go_23_october_2018.png)](https://github.com/the-benchmarker/web-frameworks#full-table) + +As shown in the benchmarks (from a [third-party source](https://github.com/the-benchmarker)), Iris is the fastest open-source Go web framework in the planet. The net/http 100% compatible router [muxie](https://github.com/kataras/muxie) I've created some weeks ago is also trending there with amazing results, fastest net/http router ever created as well. View the results at: + +https://github.com/the-benchmarker/web-frameworks#full-table + +## Philosophy + +The Iris philosophy is to provide robust tooling for HTTP, making it a great solution for single page applications, web sites, hybrids, or public HTTP APIs. Keep note that, so far, iris is the fastest web framework ever created in terms of performance. + +Iris does not force you to use any specific ORM or template engine. With support for the most used template engines, you can quickly craft the perfect application. + ## Installation The only requirement is the [Go Programming Language](https://golang.org/dl/) @@ -45,28 +77,6 @@ import ( -## Benchmarks - -### Iris vs .NET Core vs Expressjs - -[![Iris vs .NET Core(C#) vs Node.js (Express)](_benchmarks/benchmarks_graph_22_october_2018_gray.png)](_benchmarks/README.md) - -_Updated at: [Monday, 22 October 2018](_benchmarks/README.md)_ - -### Iris vs the rest Go web frameworks and routers vs any other alternative - -[![](_benchmarks/benchmarks_third_party_source_snapshot_go_23_october_2018.png)](https://github.com/the-benchmarker/web-frameworks#full-table) - -As shown in the benchmarks (from a [third-party source](https://github.com/the-benchmarker)), Iris is the fastest open-source Go web framework in the planet. The net/http 100% compatible router [muxie](https://github.com/kataras/muxie) I've created some weeks ago is also trending there with amazing results, fastest net/http router ever created as well. View the results at: - -https://github.com/the-benchmarker/web-frameworks#full-table - -## Philosophy - -The Iris philosophy is to provide robust tooling for HTTP, making it a great solution for single page applications, web sites, hybrids, or public HTTP APIs. Keep note that, so far, iris is the fastest web framework ever created in terms of performance. - -Iris does not force you to use any specific ORM or template engine. With support for the most used template engines, you can quickly craft the perfect application. - ## Quick start ```sh @@ -96,35 +106,6 @@ func main() { $ go run example.go ``` -## Iris starter kits - - - -1. [snowlyg/IrisApiProject: Iris + gorm + jwt + sqlite3](https://github.com/snowlyg/IrisApiProject) **NEW-Chinese** -2. [yz124/superstar: Iris + xorm to implement the star library](https://github.com/yz124/superstar) **NEW-Chinese** -3. [jebzmos4/Iris-golang: A basic CRUD API in golang with Iris](https://github.com/jebzmos4/Iris-golang) -4. [gauravtiwari/go_iris_app: A basic web app built in Iris for Go](https://github.com/gauravtiwari/go_iris_app) -5. [A mini social-network created with the awesome Iris💖💖](https://github.com/iris-contrib/Iris-Mini-Social-Network) -6. [Iris isomorphic react/hot reloadable/redux/css-modules starter kit](https://github.com/iris-contrib/iris-starter-kit) -7. [ionutvilie/react-ts: Demo project with react using typescript and Iris](https://github.com/ionutvilie/react-ts) -8. [Self-hosted Localization Management Platform built with Iris and Angular](https://github.com/iris-contrib/parrot) -9. [Iris + Docker and Kubernetes](https://github.com/iris-contrib/cloud-native-go) -10. [nanobox.io: Quickstart for Iris with Nanobox](https://guides.nanobox.io/golang/iris/from-scratch) -11. [hasura.io: A Hasura starter project with a ready to deploy Golang hello-world web app with IRIS](https://hasura.io/hub/project/hasura/hello-golang-iris) - -> Did you build something similar? Let us [know](https://github.com/kataras/iris/pulls)! - ## API Examples ### Using Get, Post, Put, Patch, Delete and Options @@ -992,6 +973,15 @@ Iris has a great collection of handlers[[1]](middleware/)[[2]](https://github.co Iris, unlike others, is 100% compatible with the standards and that's why the majority of the big companies that adapt Go to their workflow, like a very famous US Television Network, trust Iris; it's up-to-date and it will be always aligned with the std `net/http` package which is modernized by the Go Authors on each new release of the Go Programming Language. +### Video Courses + +| Description | Link | Author | Year | +| -----------|-------------|-------------|-----| +| Installing Iris | https://www.youtube.com/watch?v=BmOLFQ29J3s | WarnabiruTV | 2018 | +| Iris & Mongo DB Complete | https://www.youtube.com/watch?v=uXiNYhJqh2I&index=1&list=PLMrwI6jIZn-1tzskocnh1pptKhVmWdcbS | Musobar Media | 2018 | +| Quick Start with Iris | https://www.youtube.com/watch?v=x5OSXX9vitU&list=PLJ39kWiJXSizebElabidQeVaKeJuY6b4I | J-Secur1ty | **2019** | +| Getting Started with Iris | https://www.youtube.com/watch?v=rQxRoN6ub78&index=27&list=PLidHThAppdAH4y0DeEf-dGjB-xITVKszL | stephgdesign | 2018 | + ### Articles * [CRUD REST API in Iris (a framework for golang)](https://medium.com/@jebzmos4/crud-rest-api-in-iris-a-framework-for-golang-a5d33652401e) @@ -1008,15 +998,19 @@ Iris, unlike others, is 100% compatible with the standards and that's why the ma * [Deploying a Iris Golang app in hasura](https://medium.com/@HasuraHQ/deploy-an-iris-golang-app-with-backend-apis-in-minutes-25a559bf530b) * [A URL Shortener Service using Go, Iris and Bolt](https://medium.com/@kataras/a-url-shortener-service-using-go-iris-and-bolt-4182f0b00ae7) -### Video Courses +## Iris starter kits -* [Daily Coding - Web Framework Golang: Iris Framework]( https://www.youtube.com/watch?v=BmOLFQ29J3s) by WarnabiruTV, source: youtube, cost: **FREE** -* [Tutorial Golang MVC dengan Iris Framework & Mongo DB](https://www.youtube.com/watch?v=uXiNYhJqh2I&list=PLMrwI6jIZn-1tzskocnh1pptKhVmWdcbS) (19 parts so far) by Musobar Media, source: youtube, cost: **FREE** -* [Go/Golang 27 - Iris framework : Routage de base](https://www.youtube.com/watch?v=rQxRoN6ub78) by stephgdesign, source: youtube, cost: **FREE** -* [Go/Golang 28 - Iris framework : Templating](https://www.youtube.com/watch?v=nOKYV073S2Y) by stephgdesignn, source: youtube, cost: **FREE** -* [Go/Golang 29 - Iris framework : Paramètres](https://www.youtube.com/watch?v=K2FsprfXs1E) by stephgdesign, source: youtube, cost: **FREE** -* [Go/Golang 30 - Iris framework : Les middelwares](https://www.youtube.com/watch?v=BLPy1So6bhE) by stephgdesign, source: youtube, cost: **FREE** -* [Go/Golang 31 - Iris framework : Les sessions](https://www.youtube.com/watch?v=RnBwUrwgEZ8) by stephgdesign, source: youtube, cost: **FREE** +1. [snowlyg/IrisApiProject: Iris + gorm + jwt + sqlite3](https://github.com/snowlyg/IrisApiProject) **NEW-Chinese** +2. [yz124/superstar: Iris + xorm to implement the star library](https://github.com/yz124/superstar) **NEW-Chinese** +3. [jebzmos4/Iris-golang: A basic CRUD API in golang with Iris](https://github.com/jebzmos4/Iris-golang) +4. [gauravtiwari/go_iris_app: A basic web app built in Iris for Go](https://github.com/gauravtiwari/go_iris_app) +5. [A mini social-network created with the awesome Iris💖💖](https://github.com/iris-contrib/Iris-Mini-Social-Network) +6. [Iris isomorphic react/hot reloadable/redux/css-modules starter kit](https://github.com/iris-contrib/iris-starter-kit) +7. [ionutvilie/react-ts: Demo project with react using typescript and Iris](https://github.com/ionutvilie/react-ts) +8. [Self-hosted Localization Management Platform built with Iris and Angular](https://github.com/iris-contrib/parrot) +9. [Iris + Docker and Kubernetes](https://github.com/iris-contrib/cloud-native-go) +10. [nanobox.io: Quickstart for Iris with Nanobox](https://guides.nanobox.io/golang/iris/from-scratch) +11. [hasura.io: A Hasura starter project with a ready to deploy Golang hello-world web app with IRIS](https://hasura.io/hub/project/hasura/hello-golang-iris) ## Support @@ -1077,6 +1071,24 @@ Iris, unlike others, is 100% compatible with the standards and that's why the ma There are many companies and start-ups looking for Go web developers with Iris experience as requirement, we are searching for you every day and we post those information via our [facebook page](https://www.facebook.com/iris.framework), like the page to get notified, we have already posted some of them. +### Author + + + + + +
+ + +Gerasimos Maropoulos + +

+ + + +

+
+ ### Backers Thank you to all our backers! 🙏 [Become a backer](https://iris-go.com/donate) From 01233a3c223b1be8d543834f827300b63f458574 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Fri, 22 Mar 2019 19:34:22 +0200 Subject: [PATCH 02/18] fix https://github.com/kataras/iris/issues/1220 from last updates Former-commit-id: 1932953145c9386053cae28805020e6b6bd956a6 --- macro/macros.go | 1 + 1 file changed, 1 insertion(+) diff --git a/macro/macros.go b/macro/macros.go index 4c6f6416..99637182 100644 --- a/macro/macros.go +++ b/macro/macros.go @@ -419,6 +419,7 @@ var ( Uint64, Bool, Alphabetical, + File, Path, } ) From 486d9350e5669e51878b7ff333b8c82965d26768 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Mon, 8 Apr 2019 06:48:57 +0300 Subject: [PATCH 03/18] update snapshot Former-commit-id: 25fb22a3793282ee0c29b19a4770841145f98e7f --- ...d_party_source_snapshot_go_01_march_2019.png | Bin 0 -> 75793 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 _benchmarks/benchmarks_third_party_source_snapshot_go_01_march_2019.png diff --git a/_benchmarks/benchmarks_third_party_source_snapshot_go_01_march_2019.png b/_benchmarks/benchmarks_third_party_source_snapshot_go_01_march_2019.png new file mode 100644 index 0000000000000000000000000000000000000000..cfab740024d30b80448f73e65f7e3888314905ad GIT binary patch literal 75793 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 Date: Mon, 8 Apr 2019 07:02:15 +0300 Subject: [PATCH 04/18] A message about the new websocket capabilities Former-commit-id: 682cfd729918e570cb506ef7ea25242701f405f6 --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index de0f30ce..66930d3c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # ⚡️ Stay tuned for updates: upcoming version 11.2.0 -Click [here](https://github.com/kataras/iris/pull/1175) to watch the progress of the upcoming release and the new features that it brings into game. +Click [here](https://github.com/kataras/iris/pull/1175) to watch the progress of the upcoming release and the new features that it brings into game. + +@kataras: I was sick for almost a month, but this wasn't kept me from pushing some progress for the upcoming release. the v11.2.0 will contain a breaking change on the websockets usage, there is no other way to improve it. That one has its own repository for testing and experimentation, click [here](https://github.com/kataras/fastws/tree/master/_examples/advanced/ws) to watch the progress of the new Iris websocket capabilities and features if you can't wait more. # Iris Web Framework @@ -8,7 +10,7 @@ Click [here](https://github.com/kataras/iris/pull/1175) to watch the progress of [![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris) [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/routing%20by-example-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/tree/master/_examples/routing) [![release](https://img.shields.io/badge/release%20-v11.1-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) -Iris is a fast, simple yet fully featured and very efficient web framework for Go. +Iris is a fast, simple yet fully featured and very efficient web framework for Go. Routing is powered by the [muxie](https://github.com/kataras/muxie#philosophy) project. Iris provides a beautifully expressive and easy to use foundation for your next website or API. @@ -34,13 +36,11 @@ Check below the features and the hard work that we putted to improve how the int _Updated at: [Monday, 22 October 2018](_benchmarks/README.md)_ -### Iris vs the rest Go web frameworks and routers vs any other alternative +### Third-party -[![](_benchmarks/benchmarks_third_party_source_snapshot_go_23_october_2018.png)](https://github.com/the-benchmarker/web-frameworks#full-table) +[![](_benchmarks/benchmarks_third_party_source_snapshot_go_23_october_2018.png)](https://github.com/iris-contrib/third-party-benchmarks#full-table) -As shown in the benchmarks (from a [third-party source](https://github.com/the-benchmarker)), Iris is the fastest open-source Go web framework in the planet. The net/http 100% compatible router [muxie](https://github.com/kataras/muxie) I've created some weeks ago is also trending there with amazing results, fastest net/http router ever created as well. View the results at: - -https://github.com/the-benchmarker/web-frameworks#full-table +> Last updated at: 01 March of 2019. Click to the image to view all results. You can run this in your own hardware by following the [steps here](https://github.com/iris-contrib/third-party-benchmarks#usage). ## Philosophy From c69bd7193dc110ff5fb4f1bd2f765d7185fa8b7e Mon Sep 17 00:00:00 2001 From: Alexandre Juca Date: Tue, 9 Apr 2019 00:15:23 +0100 Subject: [PATCH 05/18] Improved english documentation Former-commit-id: 318b093489563b85c540388d77b12b63a97ce6e1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 66930d3c..679b338f 100644 --- a/README.md +++ b/README.md @@ -277,7 +277,7 @@ func main() { The package [hero](hero) contains features for binding any object or functions that `handlers` can use, these are called dependencies. -With Iris you get truly safe bindings thanks to the [hero](_examples/hero) [package](hero). It is blazing-fast, near to raw handlers performance because Iris calculates everything before even server goes online! +With Iris you get truly safe bindings thanks to the [hero](_examples/hero) [package](hero). It is blazing-fast, near to raw handlers performance because Iris calculates everything before the server even goes online! Below you will see some screenshots I prepared for you in order to be easier to understand: From f21e1e7a575b8dc37415fdc8dd2e05068b36a99c Mon Sep 17 00:00:00 2001 From: Alexandre Juca Date: Tue, 9 Apr 2019 00:20:05 +0100 Subject: [PATCH 06/18] Improved english documentation Former-commit-id: 01fe103889432389fd91f4ee497326ff32e50ee3 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 679b338f..dd2ead65 100644 --- a/README.md +++ b/README.md @@ -279,7 +279,7 @@ The package [hero](hero) contains features for binding any object or functions t With Iris you get truly safe bindings thanks to the [hero](_examples/hero) [package](hero). It is blazing-fast, near to raw handlers performance because Iris calculates everything before the server even goes online! -Below you will see some screenshots I prepared for you in order to be easier to understand: +Below you will see some screenshots I prepared to facilitate understanding: #### 1. Path Parameters - Built'n Dependencies From cc713ca1ebbc928132e15bb5f6d59175f4d3cfe1 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sun, 14 Apr 2019 21:59:24 +0300 Subject: [PATCH 07/18] Add FOSSA license scan Former-commit-id: c56690373ffd968ad08a86285752ed919f286786 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dd2ead65..2ae52c1e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Click [here](https://github.com/kataras/iris/pull/1175) to watch the progress of -[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris) [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/routing%20by-example-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/tree/master/_examples/routing) [![release](https://img.shields.io/badge/release%20-v11.1-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) +[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fkataras%2Firis.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/routing%20by-example-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/tree/master/_examples/routing) [![release](https://img.shields.io/badge/release%20-v11.1-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) Iris is a fast, simple yet fully featured and very efficient web framework for Go. Routing is powered by the [muxie](https://github.com/kataras/muxie#philosophy) project. From 6da6f80715a7a7cf29308d15f4fe4f7b093c504e Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Thu, 9 May 2019 15:17:48 +0300 Subject: [PATCH 08/18] Update README note for the upcoming websocket module Former-commit-id: f298ae460f3fe79d2d6b9770341a74e72762e6fc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ae52c1e..f5b5ef6c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Click [here](https://github.com/kataras/iris/pull/1175) to watch the progress of the upcoming release and the new features that it brings into game. -@kataras: I was sick for almost a month, but this wasn't kept me from pushing some progress for the upcoming release. the v11.2.0 will contain a breaking change on the websockets usage, there is no other way to improve it. That one has its own repository for testing and experimentation, click [here](https://github.com/kataras/fastws/tree/master/_examples/advanced/ws) to watch the progress of the new Iris websocket capabilities and features if you can't wait more. +@kataras: I was sick for almost a month, but this wasn't kept me from pushing some progress for the upcoming release. the v11.2.0 will contain a breaking change on the websockets usage, there is no other way to improve it. That one has its own repository for testing and experimentation to implement a faster and even more higher level websocket server and client written in Go which developers will be able select between [gorilla/websocket](https://github.com/gorilla/websocket) and [gobwas/ws](https://github.com/gobwas/ws) for the underline protocol communication and eventually will live into Iris, click [here](https://github.com/kataras/ws) to watch the progress of the new Iris websocket capabilities and features if you can't wait more. # Iris Web Framework From 4c0c1b3ef7a4bab0e0c716efd43772214cef645f Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sat, 25 May 2019 22:51:45 +0300 Subject: [PATCH 09/18] Create FUNDING.yml Former-commit-id: 305437f20a5cb69297971a01735018be341beba0 --- .github/FUNDING.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..85fbf7d4 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,5 @@ +# patreon: # Replace with a single Patreon username +# open_collective: # Replace with a single Open Collective username +# ko_fi: # Replace with a single Ko-fi username +# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +custom: https://iris-go.com/donate # Replace with a single custom sponsorship URL From cd3dced02a0b4397796c3ac53cee7e25572cc0f3 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Wed, 29 May 2019 19:39:41 +0300 Subject: [PATCH 10/18] Update README.md Former-commit-id: 97888d121460acc02040934d7aaada320d83b4be --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f5b5ef6c..b4494dc5 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Click [here](https://github.com/kataras/iris/pull/1175) to watch the progress of -[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fkataras%2Firis.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/routing%20by-example-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/tree/master/_examples/routing) [![release](https://img.shields.io/badge/release%20-v11.1-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) +[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fkataras%2Firis.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield) [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://chat.iris-go.com) [![view examples](https://img.shields.io/badge/routing%20by-example-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/tree/master/_examples/routing) [![release](https://img.shields.io/badge/release%20-v11.1-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) Iris is a fast, simple yet fully featured and very efficient web framework for Go. Routing is powered by the [muxie](https://github.com/kataras/muxie#philosophy) project. From af751c760231385f40e072beb6cf62c3161b08fe Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Thu, 6 Jun 2019 23:06:41 +0300 Subject: [PATCH 11/18] fix https://github.com/kataras/iris/issues/1271#issuecomment-499642546 Former-commit-id: 30043802c9eadcb4b378e773ca79f8e33bd5d573 --- context/context.go | 2 +- go.mod | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/context/context.go b/context/context.go index f437e447..46f0d6ac 100644 --- a/context/context.go +++ b/context/context.go @@ -1439,7 +1439,7 @@ func DecodeURL(uri string) string { // based on the 'escape'. func (ctx *context) RequestPath(escape bool) string { if escape { - return DecodeQuery(ctx.request.URL.EscapedPath()) + return ctx.request.URL.EscapedPath() // DecodeQuery(ctx.request.URL.EscapedPath()) } return ctx.request.URL.Path // RawPath returns empty, requesturi can be used instead also. } diff --git a/go.mod b/go.mod index a78a5582..3199ff89 100644 --- a/go.mod +++ b/go.mod @@ -22,13 +22,13 @@ require ( github.com/hashicorp/go-version v1.0.0 github.com/imkira/go-interpol v1.1.0 // indirect github.com/iris-contrib/blackfriday v2.0.0+incompatible - github.com/iris-contrib/formBinder v0.0.0-20190104093907-fbd5963f41e1 // indirect + github.com/iris-contrib/formBinder v0.0.0-20190104093907-fbd5963f41e1 github.com/iris-contrib/go.uuid v2.0.0+incompatible github.com/iris-contrib/httpexpect v0.0.0-20180314041918-ebe99fcebbce github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0 github.com/json-iterator/go v1.1.5 github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea // indirect - github.com/kataras/golog v0.0.0-20180321173939-03be10146386 // indirect + github.com/kataras/golog v0.0.0-20180321173939-03be10146386 github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d // indirect github.com/klauspost/compress v1.4.1 github.com/klauspost/cpuid v1.2.0 // indirect From 9c92952a40df3ec0b2c5c30949069da9b71fc061 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Fri, 7 Jun 2019 20:45:00 +0300 Subject: [PATCH 12/18] remove the 3rd party socket io example because its API has a breaking-change now and some features are not reproducable to that Former-commit-id: 8d89947be6a3ee6942d596c15f346c3ed6cf6728 --- _examples/README.md | 1 - _examples/README_ZH.md | 1 - .../websocket/third-party-socketio/main.go | 44 - .../third-party-socketio/public/index.html | 38 - .../public/jquery-1.11.1.js | 10309 ---------------- .../public/socket.io-1.3.7.js | 3 - 6 files changed, 10396 deletions(-) delete mode 100644 _examples/websocket/third-party-socketio/main.go delete mode 100644 _examples/websocket/third-party-socketio/public/index.html delete mode 100644 _examples/websocket/third-party-socketio/public/jquery-1.11.1.js delete mode 100644 _examples/websocket/third-party-socketio/public/socket.io-1.3.7.js diff --git a/_examples/README.md b/_examples/README.md index 38a3faa2..7288b914 100644 --- a/_examples/README.md +++ b/_examples/README.md @@ -482,7 +482,6 @@ The package is designed to work with raw websockets although its API is similar - [Connection List](websocket/connectionlist/main.go) - [TLS Enabled](websocket/secure/main.go) - [Custom Raw Go Client](websocket/custom-go-client/main.go) -- [Third-Party socket.io](websocket/third-party-socketio/main.go) > You're free to use your own favourite websockets package if you'd like so. diff --git a/_examples/README_ZH.md b/_examples/README_ZH.md index 53e2a755..19fe6ecf 100644 --- a/_examples/README_ZH.md +++ b/_examples/README_ZH.md @@ -435,7 +435,6 @@ iris websocket库依赖于它自己的[包](https://github.com/kataras/iris/tree - [连接列表](websocket/connectionlist/main.go) - [TLS支持](websocket/secure/main.go) - [自定义原始Go客户端](websocket/custom-go-client/main.go) -- [第三方socket.io](websocket/third-party-socketio/main.go) > 如果你愿意,你可以自由使用你自己喜欢的websockets包。 diff --git a/_examples/websocket/third-party-socketio/main.go b/_examples/websocket/third-party-socketio/main.go deleted file mode 100644 index c2a762e7..00000000 --- a/_examples/websocket/third-party-socketio/main.go +++ /dev/null @@ -1,44 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - - "github.com/googollee/go-socket.io" -) - -/* - go get -u github.com/googollee/go-socket.io -*/ - -func main() { - app := iris.New() - server, err := socketio.NewServer(nil) - if err != nil { - app.Logger().Fatal(err) - } - - server.On("connection", func(so socketio.Socket) { - app.Logger().Infof("on connection") - so.Join("chat") - so.On("chat message", func(msg string) { - app.Logger().Infof("emit: %v", so.Emit("chat message", msg)) - so.BroadcastTo("chat", "chat message", msg) - }) - so.On("disconnection", func() { - app.Logger().Infof("on disconnect") - }) - }) - - server.On("error", func(so socketio.Socket, err error) { - app.Logger().Errorf("error: %v", err) - }) - - // serve the socket.io endpoint. - app.Any("/socket.io/{p:path}", iris.FromStd(server)) - - // serve the index.html and the javascript libraries at - // http://localhost:8080 - app.StaticWeb("/", "./public") - - app.Run(iris.Addr("localhost:8080"), iris.WithoutPathCorrection) -} diff --git a/_examples/websocket/third-party-socketio/public/index.html b/_examples/websocket/third-party-socketio/public/index.html deleted file mode 100644 index 1b485aaf..00000000 --- a/_examples/websocket/third-party-socketio/public/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - Socket.IO chat - - - -
    -
    - -
    - - - - - \ No newline at end of file diff --git a/_examples/websocket/third-party-socketio/public/jquery-1.11.1.js b/_examples/websocket/third-party-socketio/public/jquery-1.11.1.js deleted file mode 100644 index e27f4c5f..00000000 --- a/_examples/websocket/third-party-socketio/public/jquery-1.11.1.js +++ /dev/null @@ -1,10309 +0,0 @@ -/*! - * jQuery JavaScript Library v1.11.1 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-05-01T17:42Z - */ - -(function (global, factory) { - - if (typeof module === "object" && typeof module.exports === "object") { - // For CommonJS and CommonJS-like environments where a proper window is present, - // execute the factory and get jQuery - // For environments that do not inherently posses a window with a document - // (such as Node.js), expose a jQuery-making factory as module.exports - // This accentuates the need for the creation of a real window - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info - module.exports = global.document ? - factory(global, true) : - function (w) { - if (!w.document) { - throw new Error("jQuery requires a window with a document"); - } - return factory(w); - }; - } else { - factory(global); - } - - // Pass this if window is not defined yet -}(typeof window !== "undefined" ? window : this, function (window, noGlobal) { - - // Can't do this because several apps including ASP.NET trace - // the stack via arguments.caller.callee and Firefox dies if - // you try to trace through "use strict" call chains. (#13335) - // Support: Firefox 18+ - // - - var deletedIds = []; - - var slice = deletedIds.slice; - - var concat = deletedIds.concat; - - var push = deletedIds.push; - - var indexOf = deletedIds.indexOf; - - var class2type = {}; - - var toString = class2type.toString; - - var hasOwn = class2type.hasOwnProperty; - - var support = {}; - - - - var - version = "1.11.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.1, IE<9 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // 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, - - // Start with an empty selector - selector: "", - - // 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 num != null ? - - // Return just the one element from the set - (num < 0 ? this[num + this.length] : this[num]) : - - // Return all the elements in a clean array - slice.call(this); - }, - - // 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; - ret.context = this.context; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function (callback, args) { - return jQuery.each(this, callback, args); - }, - - 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(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: deletedIds.sort, - splice: deletedIds.splice - }; - - jQuery.extend = jQuery.fn.extend = function () { - var src, copyIsArray, copy, name, options, 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 = jQuery.isArray(copy)))) { - if (copyIsArray) { - copyIsArray = false; - clone = src && jQuery.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 () { }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function (obj) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function (obj) { - return jQuery.type(obj) === "array"; - }, - - isWindow: function (obj) { - /* jshint eqeqeq: false */ - return obj != null && obj == obj.window; - }, - - isNumeric: function (obj) { - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - return !jQuery.isArray(obj) && obj - parseFloat(obj) >= 0; - }, - - isEmptyObject: function (obj) { - var name; - for (name in obj) { - return false; - } - return true; - }, - - isPlainObject: function (obj) { - var key; - - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if (!obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow(obj)) { - return false; - } - - try { - // Not own constructor property must be Object - if (obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { - return false; - } - } catch (e) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Support: IE<9 - // Handle iteration over inherited properties before own properties. - if (support.ownLast) { - for (key in obj) { - return hasOwn.call(obj, key); - } - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - for (key in obj) { } - - return key === undefined || hasOwn.call(obj, key); - }, - - type: function (obj) { - if (obj == null) { - return obj + ""; - } - return typeof obj === "object" || typeof obj === "function" ? - class2type[toString.call(obj)] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function (data) { - if (data && jQuery.trim(data)) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - (window.execScript || function (data) { - window["eval"].call(window, data); - })(data); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function (string) { - return string.replace(rmsPrefix, "ms-").replace(rdashAlpha, fcamelCase); - }, - - nodeName: function (elem, name) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function (obj, callback, args) { - var value, - i = 0, - length = obj.length, - isArray = isArraylike(obj); - - if (args) { - if (isArray) { - for (; i < length; i++) { - value = callback.apply(obj[i], args); - - if (value === false) { - break; - } - } - } else { - for (i in obj) { - value = callback.apply(obj[i], args); - - if (value === false) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if (isArray) { - for (; i < length; i++) { - value = callback.call(obj[i], i, obj[i]); - - if (value === false) { - break; - } - } - } else { - for (i in obj) { - value = callback.call(obj[i], i, obj[i]); - - if (value === false) { - break; - } - } - } - } - - return obj; - }, - - // Support: Android<4.1, IE<9 - 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) { - var len; - - if (arr) { - if (indexOf) { - return indexOf.call(arr, elem, i); - } - - len = arr.length; - i = i ? i < 0 ? Math.max(0, len + i) : i : 0; - - for (; i < len; i++) { - // Skip accessing in sparse arrays - if (i in arr && arr[i] === elem) { - return i; - } - } - } - - return -1; - }, - - merge: function (first, second) { - var len = +second.length, - j = 0, - i = first.length; - - while (j < len) { - first[i++] = second[j++]; - } - - // Support: IE<9 - // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) - if (len !== len) { - while (second[j] !== undefined) { - 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 value, - i = 0, - length = elems.length, - isArray = isArraylike(elems), - ret = []; - - // Go through the array, translating each of the items to their new values - if (isArray) { - 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 args, proxy, tmp; - - 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: function () { - return +(new Date()); - }, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support - }); - - // Populate the class2type map - jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function (i, name) { - class2type["[object " + name + "]"] = name.toLowerCase(); - }); - - function isArraylike(obj) { - var length = obj.length, - type = jQuery.type(obj); - - if (type === "function" || jQuery.isWindow(obj)) { - return false; - } - - if (obj.nodeType === 1 && length) { - return true; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && (length - 1) in obj; - } - var Sizzle = - /*! - * Sizzle CSS Selector Engine v1.10.19 - * http://sizzlejs.com/ - * - * Copyright 2013 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-04-18 - */ - (function (window) { - - var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + -(new Date()), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function (a, b) { - if (a === b) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - strundefined = typeof undefined, - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf if we can't use a native one - indexOf = arr.indexOf || function (elem) { - var i = 0, - len = this.length; - for (; i < len; i++) { - if (this[i] === elem) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace("w", "w#"), - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + characterEncoding + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"), - - rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"), - rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"), - - rattributeQuotes = new RegExp("=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g"), - - rpseudo = new RegExp(pseudos), - ridentifier = new RegExp("^" + identifier + "$"), - - matchExpr = { - "ID": new RegExp("^#(" + characterEncoding + ")"), - "CLASS": new RegExp("^\\.(" + characterEncoding + ")"), - "TAG": new RegExp("^(" + characterEncoding.replace("w", "w*") + ")"), - "ATTR": new RegExp("^" + attributes), - "PSEUDO": new RegExp("^" + pseudos), - "CHILD": new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i"), - "bool": new RegExp("^(?:" + booleans + ")$", "i"), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i") - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp("\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig"), - funescape = function (_, escaped, escapedWhitespace) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode(high + 0x10000) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00); - }; - - // Optimize for push.apply( _, NodeList ) - try { - push.apply( - (arr = slice.call(preferredDoc.childNodes)), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[preferredDoc.childNodes.length].nodeType; - } catch (e) { - push = { - apply: arr.length ? - - // Leverage slice if possible - function (target, els) { - push_native.apply(target, slice.call(els)); - } : - - // Support: IE<9 - // Otherwise append directly - function (target, els) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ((target[j++] = els[i++])) { } - target.length = j - 1; - } - }; - } - - function Sizzle(selector, context, results, seed) { - var match, elem, m, nodeType, - // QSA vars - i, groups, old, nid, newContext, newSelector; - - if ((context ? context.ownerDocument || context : preferredDoc) !== document) { - setDocument(context); - } - - context = context || document; - results = results || []; - - if (!selector || typeof selector !== "string") { - return results; - } - - if ((nodeType = context.nodeType) !== 1 && nodeType !== 9) { - return []; - } - - if (documentIsHTML && !seed) { - - // Shortcuts - if ((match = rquickExpr.exec(selector))) { - // Speed-up: Sizzle("#ID") - if ((m = match[1])) { - if (nodeType === 9) { - elem = context.getElementById(m); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document (jQuery #6963) - if (elem && elem.parentNode) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if (elem.id === m) { - results.push(elem); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) && - contains(context, elem) && elem.id === m) { - results.push(elem); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if (match[2]) { - push.apply(results, context.getElementsByTagName(selector)); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) { - push.apply(results, context.getElementsByClassName(m)); - return results; - } - } - - // QSA path - if (support.qsa && (!rbuggyQSA || !rbuggyQSA.test(selector))) { - nid = old = expando; - newContext = context; - newSelector = nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if (nodeType === 1 && context.nodeName.toLowerCase() !== "object") { - groups = tokenize(selector); - - if ((old = context.getAttribute("id"))) { - nid = old.replace(rescape, "\\$&"); - } else { - context.setAttribute("id", nid); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while (i--) { - groups[i] = nid + toSelector(groups[i]); - } - newContext = rsibling.test(selector) && testContext(context.parentNode) || context; - newSelector = groups.join(","); - } - - if (newSelector) { - try { - push.apply(results, - newContext.querySelectorAll(newSelector) - ); - return results; - } catch (qsaError) { - } finally { - if (!old) { - context.removeAttribute("id"); - } - } - } - } - } - - // All others - return select(selector.replace(rtrim, "$1"), context, results, seed); - } - - /** - * Create key-value caches of limited size - * @returns {Function(string, Object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ - function createCache() { - var keys = []; - - function cache(key, value) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if (keys.push(key + " ") > Expr.cacheLength) { - // Only keep the most recent entries - delete cache[keys.shift()]; - } - return (cache[key + " "] = value); - } - return cache; - } - - /** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ - function markFunction(fn) { - fn[expando] = true; - return fn; - } - - /** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ - function assert(fn) { - var div = document.createElement("div"); - - try { - return !!fn(div); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if (div.parentNode) { - div.parentNode.removeChild(div); - } - // release memory in IE - div = null; - } - } - - /** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ - function addHandle(attrs, handler) { - var arr = attrs.split("|"), - i = attrs.length; - - while (i--) { - Expr.attrHandle[arr[i]] = handler; - } - } - - /** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ - function siblingCheck(a, b) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - (~b.sourceIndex || MAX_NEGATIVE) - - (~a.sourceIndex || MAX_NEGATIVE); - - // Use IE sourceIndex if available on both nodes - if (diff) { - return diff; - } - - // Check if b follows a - if (cur) { - while ((cur = cur.nextSibling)) { - if (cur === b) { - return -1; - } - } - } - - return a ? 1 : -1; - } - - /** - * Returns a function to use in pseudos for input types - * @param {String} type - */ - function createInputPseudo(type) { - return function (elem) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; - } - - /** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ - function createButtonPseudo(type) { - return function (elem) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; - } - - /** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ - function createPositionalPseudo(fn) { - return markFunction(function (argument) { - argument = +argument; - return markFunction(function (seed, matches) { - var j, - matchIndexes = fn([], seed.length, argument), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while (i--) { - if (seed[(j = matchIndexes[i])]) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); - } - - /** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ - function testContext(context) { - return context && typeof context.getElementsByTagName !== strundefined && context; - } - - // Expose support vars for convenience - support = Sizzle.support = {}; - - /** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ - isXML = Sizzle.isXML = function (elem) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; - }; - - /** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ - setDocument = Sizzle.setDocument = function (node) { - var hasCompare, - doc = node ? node.ownerDocument || node : preferredDoc, - parent = doc.defaultView; - - // If no document and documentElement is available, return - if (doc === document || doc.nodeType !== 9 || !doc.documentElement) { - return document; - } - - // Set our document - document = doc; - docElem = doc.documentElement; - - // Support tests - documentIsHTML = !isXML(doc); - - // Support: IE>8 - // If iframe document is assigned to "document" variable and if iframe has been reloaded, - // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 - // IE6-8 do not support the defaultView property so parent will be undefined - if (parent && parent !== parent.top) { - // IE11 does not have attachEvent, so all must suffer - if (parent.addEventListener) { - parent.addEventListener("unload", function () { - setDocument(); - }, false); - } else if (parent.attachEvent) { - parent.attachEvent("onunload", function () { - setDocument(); - }); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) - support.attributes = assert(function (div) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function (div) { - div.appendChild(doc.createComment("")); - return !div.getElementsByTagName("*").length; - }); - - // Check if getElementsByClassName can be trusted - support.getElementsByClassName = rnative.test(doc.getElementsByClassName) && assert(function (div) { - div.innerHTML = "
    "; - - // Support: Safari<4 - // Catch class over-caching - div.firstChild.className = "i"; - // Support: Opera<10 - // Catch gEBCN failure to find non-leading classes - return div.getElementsByClassName("i").length === 2; - }); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function (div) { - docElem.appendChild(div).id = expando; - return !doc.getElementsByName || !doc.getElementsByName(expando).length; - }); - - // ID find and filter - if (support.getById) { - Expr.find["ID"] = function (id, context) { - if (typeof context.getElementById !== strundefined && documentIsHTML) { - var m = context.getElementById(id); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }; - Expr.filter["ID"] = function (id) { - var attrId = id.replace(runescape, funescape); - return function (elem) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function (id) { - var attrId = id.replace(runescape, funescape); - return function (elem) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function (tag, context) { - if (typeof context.getElementsByTagName !== strundefined) { - return context.getElementsByTagName(tag); - } - } : - function (tag, context) { - var elem, - tmp = [], - i = 0, - results = context.getElementsByTagName(tag); - - // Filter out possible comments - if (tag === "*") { - while ((elem = results[i++])) { - if (elem.nodeType === 1) { - tmp.push(elem); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function (className, context) { - if (typeof context.getElementsByClassName !== strundefined && documentIsHTML) { - return context.getElementsByClassName(className); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ((support.qsa = rnative.test(doc.querySelectorAll))) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function (div) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if (div.querySelectorAll("[msallowclip^='']").length) { - rbuggyQSA.push("[*^$]=" + whitespace + "*(?:''|\"\")"); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if (!div.querySelectorAll("[selected]").length) { - rbuggyQSA.push("\\[" + whitespace + "*(?:value|" + booleans + ")"); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if (!div.querySelectorAll(":checked").length) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function (div) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = doc.createElement("input"); - input.setAttribute("type", "hidden"); - div.appendChild(input).setAttribute("name", "D"); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if (div.querySelectorAll("[name=d]").length) { - rbuggyQSA.push("name" + whitespace + "*[*^$|!~]?="); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if (!div.querySelectorAll(":enabled").length) { - rbuggyQSA.push(":enabled", ":disabled"); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ((support.matchesSelector = rnative.test((matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector)))) { - - assert(function (div) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call(div, "div"); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call(div, "[s!='']:x"); - rbuggyMatches.push("!=", pseudos); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join("|")); - rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join("|")); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test(docElem.compareDocumentPosition); - - // Element contains another - // Purposefully does not implement inclusive descendent - // As in, an element does not contain itself - contains = hasCompare || rnative.test(docElem.contains) ? - function (a, b) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!(bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains(bup) : - a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16 - )); - } : - function (a, b) { - if (b) { - while ((b = b.parentNode)) { - if (b === a) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function (a, b) { - - // Flag for duplicate removal - if (a === b) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if (compare) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? - a.compareDocumentPosition(b) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if (compare & 1 || - (!support.sortDetached && b.compareDocumentPosition(a) === compare)) { - - // Choose the first element that is related to our preferred document - if (a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) { - return -1; - } - if (b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b)) { - return 1; - } - - // Maintain original order - return sortInput ? - (indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function (a, b) { - // Exit early if the nodes are identical - if (a === b) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [a], - bp = [b]; - - // Parentless nodes are either documents or disconnected - if (!aup || !bup) { - return a === doc ? -1 : - b === doc ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - (indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if (aup === bup) { - return siblingCheck(a, b); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ((cur = cur.parentNode)) { - ap.unshift(cur); - } - cur = b; - while ((cur = cur.parentNode)) { - bp.unshift(cur); - } - - // Walk down the tree looking for a discrepancy - while (ap[i] === bp[i]) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck(ap[i], bp[i]) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return doc; - }; - - Sizzle.matches = function (expr, elements) { - return Sizzle(expr, null, null, elements); - }; - - Sizzle.matchesSelector = function (elem, expr) { - // Set document vars if needed - if ((elem.ownerDocument || elem) !== document) { - setDocument(elem); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace(rattributeQuotes, "='$1']"); - - if (support.matchesSelector && documentIsHTML && - (!rbuggyMatches || !rbuggyMatches.test(expr)) && - (!rbuggyQSA || !rbuggyQSA.test(expr))) { - - try { - var ret = matches.call(elem, expr); - - // IE 9's matchesSelector returns false on disconnected nodes - if (ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11) { - return ret; - } - } catch (e) { } - } - - return Sizzle(expr, document, null, [elem]).length > 0; - }; - - Sizzle.contains = function (context, elem) { - // Set document vars if needed - if ((context.ownerDocument || context) !== document) { - setDocument(context); - } - return contains(context, elem); - }; - - Sizzle.attr = function (elem, name) { - // Set document vars if needed - if ((elem.ownerDocument || elem) !== document) { - setDocument(elem); - } - - var fn = Expr.attrHandle[name.toLowerCase()], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? - fn(elem, name, !documentIsHTML) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute(name) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; - }; - - Sizzle.error = function (msg) { - throw new Error("Syntax error, unrecognized expression: " + msg); - }; - - /** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ - Sizzle.uniqueSort = function (results) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice(0); - results.sort(sortOrder); - - if (hasDuplicate) { - while ((elem = results[i++])) { - if (elem === results[i]) { - j = duplicates.push(i); - } - } - while (j--) { - results.splice(duplicates[j], 1); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; - }; - - /** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ - getText = Sizzle.getText = function (elem) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if (!nodeType) { - // If no nodeType, this is expected to be an array - while ((node = elem[i++])) { - // Do not traverse comment nodes - ret += getText(node); - } - } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if (typeof elem.textContent === "string") { - return elem.textContent; - } else { - // Traverse its children - for (elem = elem.firstChild; elem; elem = elem.nextSibling) { - ret += getText(elem); - } - } - } else if (nodeType === 3 || nodeType === 4) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; - }; - - Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function (match) { - match[1] = match[1].replace(runescape, funescape); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = (match[3] || match[4] || match[5] || "").replace(runescape, funescape); - - if (match[2] === "~=") { - match[3] = " " + match[3] + " "; - } - - return match.slice(0, 4); - }, - - "CHILD": function (match) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if (match[1].slice(0, 3) === "nth") { - // nth-* requires argument - if (!match[3]) { - Sizzle.error(match[0]); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === "even" || match[3] === "odd")); - match[5] = +((match[7] + match[8]) || match[3] === "odd"); - - // other types prohibit arguments - } else if (match[3]) { - Sizzle.error(match[0]); - } - - return match; - }, - - "PSEUDO": function (match) { - var excess, - unquoted = !match[6] && match[2]; - - if (matchExpr["CHILD"].test(match[0])) { - return null; - } - - // Accept quoted arguments as-is - if (match[3]) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if (unquoted && rpseudo.test(unquoted) && - // Get excess from tokenize (recursively) - (excess = tokenize(unquoted, true)) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) { - - // excess is a negative index - match[0] = match[0].slice(0, excess); - match[2] = unquoted.slice(0, excess); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice(0, 3); - } - }, - - filter: { - - "TAG": function (nodeNameSelector) { - var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase(); - return nodeNameSelector === "*" ? - function () { return true; } : - function (elem) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function (className) { - var pattern = classCache[className + " "]; - - return pattern || - (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) && - classCache(className, function (elem) { - return pattern.test(typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || ""); - }); - }, - - "ATTR": function (name, operator, check) { - return function (elem) { - var result = Sizzle.attr(elem, name); - - if (result == null) { - return operator === "!="; - } - if (!operator) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf(check) === 0 : - operator === "*=" ? check && result.indexOf(check) > -1 : - operator === "$=" ? check && result.slice(-check.length) === check : - operator === "~=" ? (" " + result + " ").indexOf(check) > -1 : - operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" : - false; - }; - }, - - "CHILD": function (type, what, argument, first, last) { - var simple = type.slice(0, 3) !== "nth", - forward = type.slice(-4) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function (elem) { - return !!elem.parentNode; - } : - - function (elem, context, xml) { - var cache, outerCache, node, diff, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; - - if (parent) { - - // :(first|last|only)-(child|of-type) - if (simple) { - while (dir) { - node = elem; - while ((node = node[dir])) { - if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) { - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [forward ? parent.firstChild : parent.lastChild]; - - // non-xml :nth-child(...) stores cache data on `parent` - if (forward && useCache) { - // Seek `elem` from a previously-cached index - outerCache = parent[expando] || (parent[expando] = {}); - cache = outerCache[type] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; - node = nodeIndex && parent.childNodes[nodeIndex]; - - while ((node = ++nodeIndex && node && node[dir] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop())) { - - // When found, cache indexes on `parent` and break - if (node.nodeType === 1 && ++diff && node === elem) { - outerCache[type] = [dirruns, nodeIndex, diff]; - break; - } - } - - // Use previously-cached element index if available - } else if (useCache && (cache = (elem[expando] || (elem[expando] = {}))[type]) && cache[0] === dirruns) { - diff = cache[1]; - - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) - } else { - // Use the same loop as above to seek `elem` from the start - while ((node = ++nodeIndex && node && node[dir] || - (diff = nodeIndex = 0) || start.pop())) { - - if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) { - // Cache the index of each encountered element - if (useCache) { - (node[expando] || (node[expando] = {}))[type] = [dirruns, diff]; - } - - if (node === elem) { - break; - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || (diff % first === 0 && diff / first >= 0); - } - }; - }, - - "PSEUDO": function (pseudo, argument) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || - Sizzle.error("unsupported pseudo: " + pseudo); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if (fn[expando]) { - return fn(argument); - } - - // But maintain support for old signatures - if (fn.length > 1) { - args = [pseudo, pseudo, "", argument]; - return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? - markFunction(function (seed, matches) { - var idx, - matched = fn(seed, argument), - i = matched.length; - while (i--) { - idx = indexOf.call(seed, matched[i]); - seed[idx] = !(matches[idx] = matched[i]); - } - }) : - function (elem) { - return fn(elem, 0, args); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function (selector) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile(selector.replace(rtrim, "$1")); - - return matcher[expando] ? - markFunction(function (seed, matches, context, xml) { - var elem, - unmatched = matcher(seed, null, xml, []), - i = seed.length; - - // Match elements unmatched by `matcher` - while (i--) { - if ((elem = unmatched[i])) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function (elem, context, xml) { - input[0] = elem; - matcher(input, null, xml, results); - return !results.pop(); - }; - }), - - "has": markFunction(function (selector) { - return function (elem) { - return Sizzle(selector, elem).length > 0; - }; - }), - - "contains": markFunction(function (text) { - return function (elem) { - return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction(function (lang) { - // lang value must be a valid identifier - if (!ridentifier.test(lang || "")) { - Sizzle.error("unsupported lang: " + lang); - } - lang = lang.replace(runescape, funescape).toLowerCase(); - return function (elem) { - var elemLang; - do { - if ((elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang"))) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf(lang + "-") === 0; - } - } while ((elem = elem.parentNode) && elem.nodeType === 1); - return false; - }; - }), - - // Miscellaneous - "target": function (elem) { - var hash = window.location && window.location.hash; - return hash && hash.slice(1) === elem.id; - }, - - "root": function (elem) { - return elem === docElem; - }, - - "focus": function (elem) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function (elem) { - return elem.disabled === false; - }, - - "disabled": function (elem) { - return elem.disabled === true; - }, - - "checked": function (elem) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function (elem) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if (elem.parentNode) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function (elem) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for (elem = elem.firstChild; elem; elem = elem.nextSibling) { - if (elem.nodeType < 6) { - return false; - } - } - return true; - }, - - "parent": function (elem) { - return !Expr.pseudos["empty"](elem); - }, - - // Element/input types - "header": function (elem) { - return rheader.test(elem.nodeName); - }, - - "input": function (elem) { - return rinputs.test(elem.nodeName); - }, - - "button": function (elem) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function (elem) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ((attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text"); - }, - - // Position-in-collection - "first": createPositionalPseudo(function () { - return [0]; - }), - - "last": createPositionalPseudo(function (matchIndexes, length) { - return [length - 1]; - }), - - "eq": createPositionalPseudo(function (matchIndexes, length, argument) { - return [argument < 0 ? argument + length : argument]; - }), - - "even": createPositionalPseudo(function (matchIndexes, length) { - var i = 0; - for (; i < length; i += 2) { - matchIndexes.push(i); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function (matchIndexes, length) { - var i = 1; - for (; i < length; i += 2) { - matchIndexes.push(i); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function (matchIndexes, length, argument) { - var i = argument < 0 ? argument + length : argument; - for (; --i >= 0;) { - matchIndexes.push(i); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function (matchIndexes, length, argument) { - var i = argument < 0 ? argument + length : argument; - for (; ++i < length;) { - matchIndexes.push(i); - } - return matchIndexes; - }) - } - }; - - Expr.pseudos["nth"] = Expr.pseudos["eq"]; - - // Add button/input type pseudos - for (i in { radio: true, checkbox: true, file: true, password: true, image: true }) { - Expr.pseudos[i] = createInputPseudo(i); - } - for (i in { submit: true, reset: true }) { - Expr.pseudos[i] = createButtonPseudo(i); - } - - // Easy API for creating new setFilters - function setFilters() { } - setFilters.prototype = Expr.filters = Expr.pseudos; - Expr.setFilters = new setFilters(); - - tokenize = Sizzle.tokenize = function (selector, parseOnly) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[selector + " "]; - - if (cached) { - return parseOnly ? 0 : cached.slice(0); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while (soFar) { - - // Comma and first run - if (!matched || (match = rcomma.exec(soFar))) { - if (match) { - // Don't consume trailing commas as valid - soFar = soFar.slice(match[0].length) || soFar; - } - groups.push((tokens = [])); - } - - matched = false; - - // Combinators - if ((match = rcombinators.exec(soFar))) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace(rtrim, " ") - }); - soFar = soFar.slice(matched.length); - } - - // Filters - for (type in Expr.filter) { - if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || - (match = preFilters[type](match)))) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice(matched.length); - } - } - - if (!matched) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error(selector) : - // Cache the tokens - tokenCache(selector, groups).slice(0); - }; - - function toSelector(tokens) { - var i = 0, - len = tokens.length, - selector = ""; - for (; i < len; i++) { - selector += tokens[i].value; - } - return selector; - } - - function addCombinator(matcher, combinator, base) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function (elem, context, xml) { - while ((elem = elem[dir])) { - if (elem.nodeType === 1 || checkNonElements) { - return matcher(elem, context, xml); - } - } - } : - - // Check against all ancestor/preceding elements - function (elem, context, xml) { - var oldCache, outerCache, - newCache = [dirruns, doneName]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if (xml) { - while ((elem = elem[dir])) { - if (elem.nodeType === 1 || checkNonElements) { - if (matcher(elem, context, xml)) { - return true; - } - } - } - } else { - while ((elem = elem[dir])) { - if (elem.nodeType === 1 || checkNonElements) { - outerCache = elem[expando] || (elem[expando] = {}); - if ((oldCache = outerCache[dir]) && - oldCache[0] === dirruns && oldCache[1] === doneName) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[2] = oldCache[2]); - } else { - // Reuse newcache so results back-propagate to previous elements - outerCache[dir] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ((newCache[2] = matcher(elem, context, xml))) { - return true; - } - } - } - } - } - }; - } - - function elementMatcher(matchers) { - return matchers.length > 1 ? - function (elem, context, xml) { - var i = matchers.length; - while (i--) { - if (!matchers[i](elem, context, xml)) { - return false; - } - } - return true; - } : - matchers[0]; - } - - function multipleContexts(selector, contexts, results) { - var i = 0, - len = contexts.length; - for (; i < len; i++) { - Sizzle(selector, contexts[i], results); - } - return results; - } - - function condense(unmatched, map, filter, context, xml) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for (; i < len; i++) { - if ((elem = unmatched[i])) { - if (!filter || filter(elem, context, xml)) { - newUnmatched.push(elem); - if (mapped) { - map.push(i); - } - } - } - } - - return newUnmatched; - } - - function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) { - if (postFilter && !postFilter[expando]) { - postFilter = setMatcher(postFilter); - } - if (postFinder && !postFinder[expando]) { - postFinder = setMatcher(postFinder, postSelector); - } - return markFunction(function (seed, results, context, xml) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, []), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && (seed || !selector) ? - condense(elems, preMap, preFilter, context, xml) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || (seed ? preFilter : preexisting || postFilter) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if (matcher) { - matcher(matcherIn, matcherOut, context, xml); - } - - // Apply postFilter - if (postFilter) { - temp = condense(matcherOut, postMap); - postFilter(temp, [], context, xml); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while (i--) { - if ((elem = temp[i])) { - matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem); - } - } - } - - if (seed) { - if (postFinder || preFilter) { - if (postFinder) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while (i--) { - if ((elem = matcherOut[i])) { - // Restore matcherIn since elem is not yet a final match - temp.push((matcherIn[i] = elem)); - } - } - postFinder(null, (matcherOut = []), temp, xml); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while (i--) { - if ((elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call(seed, elem) : preMap[i]) > -1) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice(preexisting, matcherOut.length) : - matcherOut - ); - if (postFinder) { - postFinder(null, results, matcherOut, xml); - } else { - push.apply(results, matcherOut); - } - } - }); - } - - function matcherFromTokens(tokens) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[tokens[0].type], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator(function (elem) { - return elem === checkContext; - }, implicitRelative, true), - matchAnyContext = addCombinator(function (elem) { - return indexOf.call(checkContext, elem) > -1; - }, implicitRelative, true), - matchers = [function (elem, context, xml) { - return (!leadingRelative && (xml || context !== outermostContext)) || ( - (checkContext = context).nodeType ? - matchContext(elem, context, xml) : - matchAnyContext(elem, context, xml)); - }]; - - for (; i < len; i++) { - if ((matcher = Expr.relative[tokens[i].type])) { - matchers = [addCombinator(elementMatcher(matchers), matcher)]; - } else { - matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches); - - // Return special upon seeing a positional matcher - if (matcher[expando]) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for (; j < len; j++) { - if (Expr.relative[tokens[j].type]) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher(matchers), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice(0, i - 1).concat({ value: tokens[i - 2].type === " " ? "*" : "" }) - ).replace(rtrim, "$1"), - matcher, - i < j && matcherFromTokens(tokens.slice(i, j)), - j < len && matcherFromTokens((tokens = tokens.slice(j))), - j < len && toSelector(tokens) - ); - } - matchers.push(matcher); - } - } - - return elementMatcher(matchers); - } - - function matcherFromGroupMatchers(elementMatchers, setMatchers) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function (seed, context, xml, results, outermost) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]("*", outermost), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if (outermost) { - outermostContext = context !== document && context; - } - - // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for (; i !== len && (elem = elems[i]) != null; i++) { - if (byElement && elem) { - j = 0; - while ((matcher = elementMatchers[j++])) { - if (matcher(elem, context, xml)) { - results.push(elem); - break; - } - } - if (outermost) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if (bySet) { - // They will have gone through all possible matchers - if ((elem = !matcher && elem)) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if (seed) { - unmatched.push(elem); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if (bySet && i !== matchedCount) { - j = 0; - while ((matcher = setMatchers[j++])) { - matcher(unmatched, setMatched, context, xml); - } - - if (seed) { - // Reintegrate element matches to eliminate the need for sorting - if (matchedCount > 0) { - while (i--) { - if (!(unmatched[i] || setMatched[i])) { - setMatched[i] = pop.call(results); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense(setMatched); - } - - // Add matches to results - push.apply(results, setMatched); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if (outermost && !seed && setMatched.length > 0 && - (matchedCount + setMatchers.length) > 1) { - - Sizzle.uniqueSort(results); - } - } - - // Override manipulation of globals by nested matchers - if (outermost) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction(superMatcher) : - superMatcher; - } - - compile = Sizzle.compile = function (selector, match /* Internal Use Only */) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[selector + " "]; - - if (!cached) { - // Generate a function of recursive functions that can be used to check each element - if (!match) { - match = tokenize(selector); - } - i = match.length; - while (i--) { - cached = matcherFromTokens(match[i]); - if (cached[expando]) { - setMatchers.push(cached); - } else { - elementMatchers.push(cached); - } - } - - // Cache the compiled function - cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers)); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; - }; - - /** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ - select = Sizzle.select = function (selector, context, results, seed) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize((selector = compiled.selector || selector)); - - results = results || []; - - // Try to minimize operations if there is no seed and only one group - if (match.length === 1) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice(0); - if (tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[tokens[1].type]) { - - context = (Expr.find["ID"](token.matches[0].replace(runescape, funescape), context) || [])[0]; - if (!context) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if (compiled) { - context = context.parentNode; - } - - selector = selector.slice(tokens.shift().value.length); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test(selector) ? 0 : tokens.length; - while (i--) { - token = tokens[i]; - - // Abort if we hit a combinator - if (Expr.relative[(type = token.type)]) { - break; - } - if ((find = Expr.find[type])) { - // Search, expanding context for leading sibling combinators - if ((seed = find( - token.matches[0].replace(runescape, funescape), - rsibling.test(tokens[0].type) && testContext(context.parentNode) || context - ))) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice(i, 1); - selector = seed.length && toSelector(tokens); - if (!selector) { - push.apply(results, seed); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - (compiled || compile(selector, match))( - seed, - context, - !documentIsHTML, - results, - rsibling.test(selector) && testContext(context.parentNode) || context - ); - return results; - }; - - // One-time assignments - - // Sort stability - support.sortStable = expando.split("").sort(sortOrder).join("") === expando; - - // Support: Chrome<14 - // Always assume duplicates if they aren't passed to the comparison function - support.detectDuplicates = !!hasDuplicate; - - // Initialize against the default document - setDocument(); - - // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) - // Detached nodes confoundingly follow *each other* - support.sortDetached = assert(function (div1) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition(document.createElement("div")) & 1; - }); - - // Support: IE<8 - // Prevent attribute/property "interpolation" - // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx - if (!assert(function (div) { - div.innerHTML = ""; - return div.firstChild.getAttribute("href") === "#"; - })) { - addHandle("type|href|height|width", function (elem, name, isXML) { - if (!isXML) { - return elem.getAttribute(name, name.toLowerCase() === "type" ? 1 : 2); - } - }); - } - - // Support: IE<9 - // Use defaultValue in place of getAttribute("value") - if (!support.attributes || !assert(function (div) { - div.innerHTML = ""; - div.firstChild.setAttribute("value", ""); - return div.firstChild.getAttribute("value") === ""; - })) { - addHandle("value", function (elem, name, isXML) { - if (!isXML && elem.nodeName.toLowerCase() === "input") { - return elem.defaultValue; - } - }); - } - - // Support: IE<9 - // Use getAttributeNode to fetch booleans when getAttribute lies - if (!assert(function (div) { - return div.getAttribute("disabled") == null; - })) { - addHandle(booleans, function (elem, name, isXML) { - var val; - if (!isXML) { - return elem[name] === true ? name.toLowerCase() : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; - } - }); - } - - return Sizzle; - - })(window); - - - - jQuery.find = Sizzle; - jQuery.expr = Sizzle.selectors; - jQuery.expr[":"] = jQuery.expr.pseudos; - jQuery.unique = Sizzle.uniqueSort; - jQuery.text = Sizzle.getText; - jQuery.isXMLDoc = Sizzle.isXML; - jQuery.contains = Sizzle.contains; - - - - var rneedsContext = jQuery.expr.match.needsContext; - - var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); - - - - var risSimple = /^.[^:#\[\.,]*$/; - - // Implement the identical functionality for filter and not - function winnow(elements, qualifier, not) { - if (jQuery.isFunction(qualifier)) { - return jQuery.grep(elements, function (elem, i) { - /* jshint -W018 */ - return !!qualifier.call(elem, i, elem) !== not; - }); - - } - - if (qualifier.nodeType) { - return jQuery.grep(elements, function (elem) { - return (elem === qualifier) !== not; - }); - - } - - if (typeof qualifier === "string") { - if (risSimple.test(qualifier)) { - return jQuery.filter(qualifier, elements, not); - } - - qualifier = jQuery.filter(qualifier, elements); - } - - return jQuery.grep(elements, function (elem) { - return (jQuery.inArray(elem, qualifier) >= 0) !== not; - }); - } - - jQuery.filter = function (expr, elems, not) { - var elem = elems[0]; - - if (not) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector(elem, expr) ? [elem] : [] : - jQuery.find.matches(expr, jQuery.grep(elems, function (elem) { - return elem.nodeType === 1; - })); - }; - - jQuery.fn.extend({ - find: function (selector) { - var i, - ret = [], - self = this, - len = self.length; - - if (typeof selector !== "string") { - return this.pushStack(jQuery(selector).filter(function () { - for (i = 0; i < len; i++) { - if (jQuery.contains(self[i], this)) { - return true; - } - } - })); - } - - for (i = 0; i < len; i++) { - jQuery.find(selector, self[i], ret); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack(len > 1 ? jQuery.unique(ret) : ret); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function (selector) { - return this.pushStack(winnow(this, selector || [], false)); - }, - not: function (selector) { - return this.pushStack(winnow(this, selector || [], true)); - }, - is: function (selector) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test(selector) ? - jQuery(selector) : - selector || [], - false - ).length; - } - }); - - - // Initialize a jQuery object - - - // A central reference to the root jQuery(document) - var rootjQuery, - - // Use the correct document accordingly with window argument (sandbox) - document = window.document, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - init = jQuery.fn.init = function (selector, context) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if (!selector) { - return this; - } - - // Handle HTML strings - if (typeof selector === "string") { - if (selector.charAt(0) === "<" && selector.charAt(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; - - // 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]); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if (elem && elem.parentNode) { - // Handle the case where IE and Opera return items - // by name instead of ID - if (elem.id !== match[2]) { - return rootjQuery.find(selector); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if (!context || context.jquery) { - return (context || rootjQuery).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.context = this[0] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if (jQuery.isFunction(selector)) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready(selector) : - // Execute immediately if ready is not present - selector(jQuery); - } - - if (selector.selector !== undefined) { - this.selector = selector.selector; - this.context = selector.context; - } - - 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); - - - var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - - jQuery.extend({ - dir: function (elem, dir, until) { - var matched = [], - cur = elem[dir]; - - while (cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery(cur).is(until))) { - if (cur.nodeType === 1) { - matched.push(cur); - } - cur = cur[dir]; - } - return matched; - }, - - sibling: function (n, elem) { - var r = []; - - for (; n; n = n.nextSibling) { - if (n.nodeType === 1 && n !== elem) { - r.push(n); - } - } - - return r; - } - }); - - jQuery.fn.extend({ - has: function (target) { - var i, - targets = jQuery(target, this), - len = targets.length; - - return this.filter(function () { - for (i = 0; i < len; i++) { - if (jQuery.contains(this, targets[i])) { - return true; - } - } - }); - }, - - closest: function (selectors, context) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test(selectors) || typeof selectors !== "string" ? - jQuery(selectors, context || this.context) : - 0; - - for (; i < l; i++) { - for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) { - // Always skip document fragments - if (cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors))) { - - matched.push(cur); - break; - } - } - } - - return this.pushStack(matched.length > 1 ? jQuery.unique(matched) : matched); - }, - - // Determine the position of an element within - // the matched set of elements - index: function (elem) { - - // No argument, return index in parent - if (!elem) { - return (this[0] && this[0].parentNode) ? this.first().prevAll().length : -1; - } - - // index in selector - if (typeof elem === "string") { - return jQuery.inArray(this[0], jQuery(elem)); - } - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this); - }, - - add: function (selector, context) { - return this.pushStack( - jQuery.unique( - jQuery.merge(this.get(), jQuery(selector, context)) - ) - ); - }, - - addBack: function (selector) { - return this.add(selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } - }); - - function sibling(cur, dir) { - do { - cur = cur[dir]; - } while (cur && cur.nodeType !== 1); - - return cur; - } - - jQuery.each({ - parent: function (elem) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function (elem) { - return jQuery.dir(elem, "parentNode"); - }, - parentsUntil: function (elem, i, until) { - return jQuery.dir(elem, "parentNode", until); - }, - next: function (elem) { - return sibling(elem, "nextSibling"); - }, - prev: function (elem) { - return sibling(elem, "previousSibling"); - }, - nextAll: function (elem) { - return jQuery.dir(elem, "nextSibling"); - }, - prevAll: function (elem) { - return jQuery.dir(elem, "previousSibling"); - }, - nextUntil: function (elem, i, until) { - return jQuery.dir(elem, "nextSibling", until); - }, - prevUntil: function (elem, i, until) { - return jQuery.dir(elem, "previousSibling", until); - }, - siblings: function (elem) { - return jQuery.sibling((elem.parentNode || {}).firstChild, elem); - }, - children: function (elem) { - return jQuery.sibling(elem.firstChild); - }, - contents: function (elem) { - return jQuery.nodeName(elem, "iframe") ? - elem.contentDocument || elem.contentWindow.document : - jQuery.merge([], elem.childNodes); - } - }, function (name, fn) { - jQuery.fn[name] = function (until, selector) { - var ret = jQuery.map(this, fn, until); - - if (name.slice(-5) !== "Until") { - selector = until; - } - - if (selector && typeof selector === "string") { - ret = jQuery.filter(selector, ret); - } - - if (this.length > 1) { - // Remove duplicates - if (!guaranteedUnique[name]) { - ret = jQuery.unique(ret); - } - - // Reverse order for parents* and prev-derivatives - if (rparentsprev.test(name)) { - ret = ret.reverse(); - } - } - - return this.pushStack(ret); - }; - }); - var rnotwhite = (/\S+/g); - - - - // String to Object options format cache - var optionsCache = {}; - - // Convert String-formatted options into Object-formatted ones and store in cache - function createOptions(options) { - var object = optionsCache[options] = {}; - jQuery.each(options.match(rnotwhite) || [], 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" ? - (optionsCache[options] || 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, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // First callback to fire (used internally by add and fireWith) - firingStart, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function (data) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for (; list && firingIndex < firingLength; firingIndex++) { - if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if (list) { - if (stack) { - if (stack.length) { - fire(stack.shift()); - } - } else if (memory) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function () { - if (list) { - // First, we save the current length - var start = list.length; - (function add(args) { - jQuery.each(args, function (_, arg) { - var type = jQuery.type(arg); - if (type === "function") { - if (!options.unique || !self.has(arg)) { - list.push(arg); - } - } else if (arg && arg.length && type !== "string") { - // Inspect recursively - add(arg); - } - }); - })(arguments); - // Do we need to add the callbacks to the - // current firing batch? - if (firing) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if (memory) { - firingStart = start; - fire(memory); - } - } - return this; - }, - // Remove a callback from the list - remove: function () { - if (list) { - jQuery.each(arguments, function (_, arg) { - var index; - while ((index = jQuery.inArray(arg, list, index)) > -1) { - list.splice(index, 1); - // Handle firing indexes - if (firing) { - if (index <= firingLength) { - firingLength--; - } - 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 && list.length); - }, - // Remove all callbacks from the list - empty: function () { - list = []; - firingLength = 0; - return this; - }, - // Have the list do nothing anymore - disable: function () { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function () { - return !list; - }, - // Lock the list in its current state - lock: function () { - stack = undefined; - if (!memory) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function () { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function (context, args) { - if (list && (!fired || stack)) { - args = args || []; - args = [context, args.slice ? args.slice() : args]; - if (firing) { - stack.push(args); - } else { - fire(args); - } - } - 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; - }; - - - jQuery.extend({ - - Deferred: function (func) { - var tuples = [ - // action, add listener, listener list, final state - ["resolve", "done", jQuery.Callbacks("once memory"), "resolved"], - ["reject", "fail", jQuery.Callbacks("once memory"), "rejected"], - ["notify", "progress", jQuery.Callbacks("memory")] - ], - state = "pending", - promise = { - state: function () { - return state; - }, - always: function () { - deferred.done(arguments).fail(arguments); - return this; - }, - then: function ( /* fnDone, fnFail, fnProgress */) { - var fns = arguments; - return jQuery.Deferred(function (newDefer) { - jQuery.each(tuples, function (i, tuple) { - var fn = jQuery.isFunction(fns[i]) && fns[i]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[tuple[1]](function () { - var returned = fn && fn.apply(this, arguments); - if (returned && jQuery.isFunction(returned.promise)) { - returned.promise() - .done(newDefer.resolve) - .fail(newDefer.reject) - .progress(newDefer.notify); - } else { - newDefer[tuple[0] + "With"](this === promise ? newDefer.promise() : this, fn ? [returned] : arguments); - } - }); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function (obj) { - return obj != null ? jQuery.extend(obj, promise) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each(tuples, function (i, tuple) { - var list = tuple[2], - stateString = tuple[3]; - - // promise[ done | fail | progress ] = list.add - promise[tuple[1]] = list.add; - - // Handle state - if (stateString) { - list.add(function () { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[i ^ 1][2].disable, tuples[2][2].lock); - } - - // deferred[ resolve | reject | notify ] - deferred[tuple[0]] = function () { - deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments); - return this; - }; - deferred[tuple[0] + "With"] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise(deferred); - - // Call given func if any - if (func) { - func.call(deferred, deferred); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function (subordinate /* , ..., subordinateN */) { - var i = 0, - resolveValues = slice.call(arguments), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || (subordinate && jQuery.isFunction(subordinate.promise)) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function (i, contexts, values) { - return function (value) { - contexts[i] = this; - values[i] = arguments.length > 1 ? slice.call(arguments) : value; - if (values === progressValues) { - deferred.notifyWith(contexts, values); - - } else if (!(--remaining)) { - deferred.resolveWith(contexts, values); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if (length > 1) { - progressValues = new Array(length); - progressContexts = new Array(length); - resolveContexts = new Array(length); - for (; i < length; i++) { - if (resolveValues[i] && jQuery.isFunction(resolveValues[i].promise)) { - resolveValues[i].promise() - .done(updateFunc(i, resolveContexts, resolveValues)) - .fail(deferred.reject) - .progress(updateFunc(i, progressContexts, progressValues)); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if (!remaining) { - deferred.resolveWith(resolveContexts, resolveValues); - } - - return deferred.promise(); - } - }); - - - // The deferred used on DOM ready - var readyList; - - jQuery.fn.ready = function (fn) { - // Add the callback - jQuery.ready.promise().done(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, - - // Hold (or release) the ready event - holdReady: function (hold) { - if (hold) { - jQuery.readyWait++; - } else { - jQuery.ready(true); - } - }, - - // 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; - } - - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if (!document.body) { - return setTimeout(jQuery.ready); - } - - // 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]); - - // Trigger any bound ready events - if (jQuery.fn.triggerHandler) { - jQuery(document).triggerHandler("ready"); - jQuery(document).off("ready"); - } - } - }); - - /** - * Clean-up method for dom ready events - */ - function detach() { - if (document.addEventListener) { - document.removeEventListener("DOMContentLoaded", completed, false); - window.removeEventListener("load", completed, false); - - } else { - document.detachEvent("onreadystatechange", completed); - window.detachEvent("onload", completed); - } - } - - /** - * The ready event handler and self cleanup method - */ - function completed() { - // readyState === "complete" is good enough for us to call the dom ready in oldIE - if (document.addEventListener || event.type === "load" || document.readyState === "complete") { - detach(); - jQuery.ready(); - } - } - - jQuery.ready.promise = function (obj) { - if (!readyList) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if (document.readyState === "complete") { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout(jQuery.ready); - - // Standards-based browsers support DOMContentLoaded - } else if (document.addEventListener) { - // Use the handy event callback - document.addEventListener("DOMContentLoaded", completed, false); - - // A fallback to window.onload, that will always work - window.addEventListener("load", completed, false); - - // If IE event model is used - } else { - // Ensure firing before onload, maybe late but safe also for iframes - document.attachEvent("onreadystatechange", completed); - - // A fallback to window.onload, that will always work - window.attachEvent("onload", completed); - - // If IE and not a frame - // continually check to see if the document is ready - var top = false; - - try { - top = window.frameElement == null && document.documentElement; - } catch (e) { } - - if (top && top.doScroll) { - (function doScrollCheck() { - if (!jQuery.isReady) { - - try { - // Use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - top.doScroll("left"); - } catch (e) { - return setTimeout(doScrollCheck, 50); - } - - // detach all dom ready events - detach(); - - // and execute any waiting functions - jQuery.ready(); - } - })(); - } - } - } - return readyList.promise(obj); - }; - - - var strundefined = typeof undefined; - - - - // Support: IE<9 - // Iteration over object's inherited properties before its own - var i; - for (i in jQuery(support)) { - break; - } - support.ownLast = i !== "0"; - - // Note: most support tests are defined in their respective modules. - // false until the test is run - support.inlineBlockNeedsLayout = false; - - // Execute ASAP in case we need to set body.style.zoom - jQuery(function () { - // Minified: var a,b,c,d - var val, div, body, container; - - body = document.getElementsByTagName("body")[0]; - if (!body || !body.style) { - // Return for frameset docs that don't have a body - return; - } - - // Setup - div = document.createElement("div"); - container = document.createElement("div"); - container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; - body.appendChild(container).appendChild(div); - - if (typeof div.style.zoom !== strundefined) { - // Support: IE<8 - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; - - support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; - if (val) { - // Prevent IE 6 from affecting layout for positioned elements #11048 - // Prevent IE from shrinking the body in IE 7 mode #12869 - // Support: IE<8 - body.style.zoom = 1; - } - } - - body.removeChild(container); - }); - - - - - (function () { - var div = document.createElement("div"); - - // Execute the test only if not already executed in another module. - if (support.deleteExpando == null) { - // Support: IE<9 - support.deleteExpando = true; - try { - delete div.test; - } catch (e) { - support.deleteExpando = false; - } - } - - // Null elements to avoid leaks in IE. - div = null; - })(); - - - /** - * Determines whether an object can have data - */ - jQuery.acceptData = function (elem) { - var noData = jQuery.noData[(elem.nodeName + " ").toLowerCase()], - nodeType = +elem.nodeType || 1; - - // Do not set data on non-element DOM nodes because it will not be cleared (#8335). - return nodeType !== 1 && nodeType !== 9 ? - false : - - // Nodes accept data unless otherwise specified; rejection can be conditional - !noData || noData !== true && elem.getAttribute("classid") === noData; - }; - - - var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; - - function dataAttr(elem, key, data) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if (data === undefined && elem.nodeType === 1) { - - var name = "data-" + key.replace(rmultiDash, "-$1").toLowerCase(); - - data = elem.getAttribute(name); - - if (typeof data === "string") { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test(data) ? jQuery.parseJSON(data) : - data; - } catch (e) { } - - // Make sure we set the data so it isn't changed later - jQuery.data(elem, key, data); - - } else { - data = undefined; - } - } - - return data; - } - - // checks a cache object for emptiness - function isEmptyDataObject(obj) { - var name; - for (name in obj) { - - // if the public data object is empty, the private is still empty - if (name === "data" && jQuery.isEmptyObject(obj[name])) { - continue; - } - if (name !== "toJSON") { - return false; - } - } - - return true; - } - - function internalData(elem, name, data, pvt /* Internal Use Only */) { - if (!jQuery.acceptData(elem)) { - return; - } - - var ret, thisCache, - internalKey = jQuery.expando, - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[internalKey] : elem[internalKey] && internalKey; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ((!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string") { - return; - } - - if (!id) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if (isNode) { - id = elem[internalKey] = deletedIds.pop() || jQuery.guid++; - } else { - id = internalKey; - } - } - - if (!cache[id]) { - // Avoid exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - cache[id] = isNode ? {} : { toJSON: jQuery.noop }; - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if (typeof name === "object" || typeof name === "function") { - if (pvt) { - cache[id] = jQuery.extend(cache[id], name); - } else { - cache[id].data = jQuery.extend(cache[id].data, name); - } - } - - thisCache = cache[id]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if (!pvt) { - if (!thisCache.data) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if (data !== undefined) { - thisCache[jQuery.camelCase(name)] = data; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if (typeof name === "string") { - - // First Try to find as-is property data - ret = thisCache[name]; - - // Test for null|undefined property data - if (ret == null) { - - // Try to find the camelCased property - ret = thisCache[jQuery.camelCase(name)]; - } - } else { - ret = thisCache; - } - - return ret; - } - - function internalRemoveData(elem, name, pvt) { - if (!jQuery.acceptData(elem)) { - return; - } - - var thisCache, i, - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - id = isNode ? elem[jQuery.expando] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if (!cache[id]) { - return; - } - - if (name) { - - thisCache = pvt ? cache[id] : cache[id].data; - - if (thisCache) { - - // Support array or space separated string names for data keys - if (!jQuery.isArray(name)) { - - // try the string as a key before any manipulation - if (name in thisCache) { - name = [name]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase(name); - if (name in thisCache) { - name = [name]; - } else { - name = name.split(" "); - } - } - } else { - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = name.concat(jQuery.map(name, jQuery.camelCase)); - } - - i = name.length; - while (i--) { - delete thisCache[name[i]]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if (pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache)) { - return; - } - } - } - - // See jQuery.data for more information - if (!pvt) { - delete cache[id].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if (!isEmptyDataObject(cache[id])) { - return; - } - } - - // Destroy the cache - if (isNode) { - jQuery.cleanData([elem], true); - - // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) - /* jshint eqeqeq: false */ - } else if (support.deleteExpando || cache != cache.window) { - /* jshint eqeqeq: true */ - delete cache[id]; - - // When all else fails, null - } else { - cache[id] = null; - } - } - - jQuery.extend({ - cache: {}, - - // The following elements (space-suffixed to avoid Object.prototype collisions) - // throw uncatchable exceptions if you attempt to set expando properties - noData: { - "applet ": true, - "embed ": true, - // ...but Flash objects (which have this classid) *can* handle expandos - "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" - }, - - hasData: function (elem) { - elem = elem.nodeType ? jQuery.cache[elem[jQuery.expando]] : elem[jQuery.expando]; - return !!elem && !isEmptyDataObject(elem); - }, - - data: function (elem, name, data) { - return internalData(elem, name, data); - }, - - removeData: function (elem, name) { - return internalRemoveData(elem, name); - }, - - // For internal use only. - _data: function (elem, name, data) { - return internalData(elem, name, data, true); - }, - - _removeData: function (elem, name) { - return internalRemoveData(elem, name, true); - } - }); - - jQuery.fn.extend({ - data: function (key, value) { - var i, name, data, - elem = this[0], - attrs = elem && elem.attributes; - - // Special expections of .data basically thwart jQuery.access, - // so implement the relevant behavior ourselves - - // Gets all values - if (key === undefined) { - if (this.length) { - data = jQuery.data(elem); - - if (elem.nodeType === 1 && !jQuery._data(elem, "parsedAttrs")) { - i = attrs.length; - while (i--) { - - // Support: IE11+ - // The attrs elements can be null (#14894) - if (attrs[i]) { - name = attrs[i].name; - if (name.indexOf("data-") === 0) { - name = jQuery.camelCase(name.slice(5)); - dataAttr(elem, name, data[name]); - } - } - } - jQuery._data(elem, "parsedAttrs", true); - } - } - - return data; - } - - // Sets multiple values - if (typeof key === "object") { - return this.each(function () { - jQuery.data(this, key); - }); - } - - return arguments.length > 1 ? - - // Sets one value - this.each(function () { - jQuery.data(this, key, value); - }) : - - // Gets one value - // Try to fetch any internally stored data first - elem ? dataAttr(elem, key, jQuery.data(elem, key)) : undefined; - }, - - removeData: function (key) { - return this.each(function () { - jQuery.removeData(this, key); - }); - } - }); - - - jQuery.extend({ - queue: function (elem, type, data) { - var queue; - - if (elem) { - type = (type || "fx") + "queue"; - queue = jQuery._data(elem, type); - - // Speed up dequeue by getting out quickly if this is just a lookup - if (data) { - if (!queue || jQuery.isArray(data)) { - queue = jQuery._data(elem, type, jQuery.makeArray(data)); - } else { - queue.push(data); - } - } - return queue || []; - } - }, - - dequeue: function (elem, type) { - type = type || "fx"; - - var queue = jQuery.queue(elem, type), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks(elem, type), - next = function () { - jQuery.dequeue(elem, type); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if (fn === "inprogress") { - fn = queue.shift(); - startLength--; - } - - if (fn) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if (type === "fx") { - queue.unshift("inprogress"); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call(elem, next, hooks); - } - - if (!startLength && hooks) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function (elem, type) { - var key = type + "queueHooks"; - return jQuery._data(elem, key) || jQuery._data(elem, key, { - empty: jQuery.Callbacks("once memory").add(function () { - jQuery._removeData(elem, type + "queue"); - jQuery._removeData(elem, key); - }) - }); - } - }); - - jQuery.fn.extend({ - queue: function (type, data) { - var setter = 2; - - if (typeof type !== "string") { - data = type; - type = "fx"; - setter--; - } - - if (arguments.length < setter) { - return jQuery.queue(this[0], type); - } - - return data === undefined ? - this : - this.each(function () { - var queue = jQuery.queue(this, type, data); - - // ensure a hooks for this queue - jQuery._queueHooks(this, type); - - if (type === "fx" && queue[0] !== "inprogress") { - jQuery.dequeue(this, type); - } - }); - }, - dequeue: function (type) { - return this.each(function () { - jQuery.dequeue(this, type); - }); - }, - clearQueue: function (type) { - return this.queue(type || "fx", []); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function (type, obj) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function () { - if (!(--count)) { - defer.resolveWith(elements, [elements]); - } - }; - - if (typeof type !== "string") { - obj = type; - type = undefined; - } - type = type || "fx"; - - while (i--) { - tmp = jQuery._data(elements[i], type + "queueHooks"); - if (tmp && tmp.empty) { - count++; - tmp.empty.add(resolve); - } - } - resolve(); - return defer.promise(obj); - } - }); - var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; - - var cssExpand = ["Top", "Right", "Bottom", "Left"]; - - var isHidden = function (elem, el) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css(elem, "display") === "none" || !jQuery.contains(elem.ownerDocument, elem); - }; - - - - // Multifunctional method to get and set values of a collection - // The value/s can optionally be executed if it's a function - var access = jQuery.access = function (elems, fn, key, value, chainable, emptyGet, raw) { - var i = 0, - length = elems.length, - bulk = key == null; - - // Sets many values - if (jQuery.type(key) === "object") { - chainable = true; - for (i in key) { - jQuery.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 < length; i++) { - fn(elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key))); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call(elems) : - length ? fn(elems[0], key) : emptyGet; - }; - var rcheckableType = (/^(?:checkbox|radio)$/i); - - - - (function () { - // Minified: var a,b,c - var input = document.createElement("input"), - div = document.createElement("div"), - fragment = document.createDocumentFragment(); - - // Setup - div.innerHTML = "
    a"; - - // IE strips leading whitespace when .innerHTML is used - support.leadingWhitespace = div.firstChild.nodeType === 3; - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - support.tbody = !div.getElementsByTagName("tbody").length; - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - support.htmlSerialize = !!div.getElementsByTagName("link").length; - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - support.html5Clone = - document.createElement("nav").cloneNode(true).outerHTML !== "<:nav>"; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - input.type = "checkbox"; - input.checked = true; - fragment.appendChild(input); - support.appendChecked = input.checked; - - // Make sure textarea (and checkbox) defaultValue is properly cloned - // Support: IE6-IE11+ - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue; - - // #11217 - WebKit loses check when the name is after the checked attribute - fragment.appendChild(div); - div.innerHTML = ""; - - // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 - // old WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked; - - // Support: IE<9 - // Opera does not clone events (and typeof div.attachEvent === undefined). - // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() - support.noCloneEvent = true; - if (div.attachEvent) { - div.attachEvent("onclick", function () { - support.noCloneEvent = false; - }); - - div.cloneNode(true).click(); - } - - // Execute the test only if not already executed in another module. - if (support.deleteExpando == null) { - // Support: IE<9 - support.deleteExpando = true; - try { - delete div.test; - } catch (e) { - support.deleteExpando = false; - } - } - })(); - - - (function () { - var i, eventName, - div = document.createElement("div"); - - // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) - for (i in { submit: true, change: true, focusin: true }) { - eventName = "on" + i; - - if (!(support[i + "Bubbles"] = eventName in window)) { - // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) - div.setAttribute(eventName, "t"); - support[i + "Bubbles"] = div.attributes[eventName].expando === false; - } - } - - // Null elements to avoid leaks in IE. - div = null; - })(); - - - var rformElems = /^(?:input|select|textarea)$/i, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; - - function returnTrue() { - return true; - } - - function returnFalse() { - return false; - } - - function safeActiveElement() { - try { - return document.activeElement; - } catch (err) { } - } - - /* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ - jQuery.event = { - - global: {}, - - add: function (elem, types, handler, data, selector) { - var tmp, events, t, handleObjIn, - special, eventHandle, handleObj, - handlers, type, namespaces, origType, - elemData = jQuery._data(elem); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if (!elemData) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if (handler.handler) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if (!handler.guid) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if (!(events = elemData.events)) { - events = elemData.events = {}; - } - if (!(eventHandle = elemData.handle)) { - eventHandle = elemData.handle = function (e) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.dispatch.apply(eventHandle.elem, arguments) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - types = (types || "").match(rnotwhite) || [""]; - t = types.length; - while (t--) { - tmp = rtypenamespace.exec(types[t]) || []; - type = origType = tmp[1]; - namespaces = (tmp[2] || "").split(".").sort(); - - // There *must* be a type, no attaching namespace-only handlers - if (!type) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[type] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = (selector ? special.delegateType : special.bindType) || type; - - // Update special based on newly reset type - special = jQuery.event.special[type] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test(selector), - namespace: namespaces.join(".") - }, handleObjIn); - - // Init the event handler queue if we're the first - if (!(handlers = events[type])) { - handlers = events[type] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) { - // Bind the global event handler to the element - if (elem.addEventListener) { - elem.addEventListener(type, eventHandle, false); - - } else if (elem.attachEvent) { - elem.attachEvent("on" + type, eventHandle); - } - } - } - - if (special.add) { - special.add.call(elem, handleObj); - - if (!handleObj.handler.guid) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if (selector) { - handlers.splice(handlers.delegateCount++, 0, handleObj); - } else { - handlers.push(handleObj); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[type] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - // Detach an event or set of events from an element - remove: function (elem, types, handler, selector, mappedTypes) { - var j, handleObj, tmp, - origCount, t, events, - special, handlers, type, - namespaces, origType, - elemData = jQuery.hasData(elem) && jQuery._data(elem); - - if (!elemData || !(events = elemData.events)) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = (types || "").match(rnotwhite) || [""]; - t = types.length; - while (t--) { - tmp = rtypenamespace.exec(types[t]) || []; - type = origType = tmp[1]; - namespaces = (tmp[2] || "").split(".").sort(); - - // Unbind all events (on this namespace, if provided) for the element - if (!type) { - for (type in events) { - jQuery.event.remove(elem, type + types[t], handler, selector, true); - } - continue; - } - - special = jQuery.event.special[type] || {}; - type = (selector ? special.delegateType : special.bindType) || type; - handlers = events[type] || []; - tmp = tmp[2] && new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)"); - - // Remove matching events - origCount = j = handlers.length; - while (j--) { - handleObj = handlers[j]; - - if ((mappedTypes || origType === handleObj.origType) && - (!handler || handler.guid === handleObj.guid) && - (!tmp || tmp.test(handleObj.namespace)) && - (!selector || selector === handleObj.selector || selector === "**" && handleObj.selector)) { - handlers.splice(j, 1); - - if (handleObj.selector) { - handlers.delegateCount--; - } - if (special.remove) { - special.remove.call(elem, handleObj); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if (origCount && !handlers.length) { - if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) { - jQuery.removeEvent(elem, type, elemData.handle); - } - - delete events[type]; - } - } - - // Remove the expando if it's no longer used - if (jQuery.isEmptyObject(events)) { - delete elemData.handle; - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery._removeData(elem, "events"); - } - }, - - trigger: function (event, data, elem, onlyHandlers) { - var handle, ontype, cur, - bubbleType, special, tmp, i, - eventPath = [elem || document], - type = hasOwn.call(event, "type") ? event.type : event, - namespaces = hasOwn.call(event, "namespace") ? event.namespace.split(".") : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if (elem.nodeType === 3 || elem.nodeType === 8) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if (rfocusMorph.test(type + jQuery.event.triggered)) { - return; - } - - if (type.indexOf(".") >= 0) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[jQuery.expando] ? - event : - new jQuery.Event(type, typeof event === "object" && event); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if (!event.target) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [event] : - jQuery.makeArray(data, [event]); - - // Allow special events to draw outside the lines - special = jQuery.event.special[type] || {}; - if (!onlyHandlers && special.trigger && special.trigger.apply(elem, data) === false) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if (!onlyHandlers && !special.noBubble && !jQuery.isWindow(elem)) { - - bubbleType = special.delegateType || type; - if (!rfocusMorph.test(bubbleType + type)) { - cur = cur.parentNode; - } - for (; cur; cur = cur.parentNode) { - eventPath.push(cur); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if (tmp === (elem.ownerDocument || document)) { - eventPath.push(tmp.defaultView || tmp.parentWindow || window); - } - } - - // Fire handlers on the event path - i = 0; - while ((cur = eventPath[i++]) && !event.isPropagationStopped()) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = (jQuery._data(cur, "events") || {})[event.type] && jQuery._data(cur, "handle"); - if (handle) { - handle.apply(cur, data); - } - - // Native handler - handle = ontype && cur[ontype]; - if (handle && handle.apply && jQuery.acceptData(cur)) { - event.result = handle.apply(cur, data); - if (event.result === false) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if (!onlyHandlers && !event.isDefaultPrevented()) { - - if ((!special._default || special._default.apply(eventPath.pop(), data) === false) && - jQuery.acceptData(elem)) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - if (ontype && elem[type] && !jQuery.isWindow(elem)) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ontype]; - - if (tmp) { - elem[ontype] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - try { - elem[type](); - } catch (e) { - // IE<9 dies on focus/blur to hidden element (#1486,#12518) - // only reproducible on winXP IE8 native, not IE9 in IE8 mode - } - jQuery.event.triggered = undefined; - - if (tmp) { - elem[ontype] = tmp; - } - } - } - } - - return event.result; - }, - - dispatch: function (event) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix(event); - - var i, ret, handleObj, matched, j, - handlerQueue = [], - args = slice.call(arguments), - handlers = (jQuery._data(this, "events") || {})[event.type] || [], - special = jQuery.event.special[event.type] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if (special.preDispatch && special.preDispatch.call(this, event) === false) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call(this, event, handlers); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) { - event.currentTarget = matched.elem; - - j = 0; - while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) { - - // Triggered event must either 1) have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if (!event.namespace_re || event.namespace_re.test(handleObj.namespace)) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler) - .apply(matched.elem, args); - - if (ret !== undefined) { - if ((event.result = ret) === false) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if (special.postDispatch) { - special.postDispatch.call(this, event); - } - - return event.result; - }, - - handlers: function (event, handlers) { - var sel, handleObj, matches, i, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - // Black-hole SVG instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if (delegateCount && cur.nodeType && (!event.button || event.type !== "click")) { - - /* jshint eqeqeq: false */ - for (; cur != this; cur = cur.parentNode || this) { - /* jshint eqeqeq: true */ - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if (cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click")) { - matches = []; - for (i = 0; i < delegateCount; i++) { - handleObj = handlers[i]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if (matches[sel] === undefined) { - matches[sel] = handleObj.needsContext ? - jQuery(sel, this).index(cur) >= 0 : - jQuery.find(sel, this, null, [cur]).length; - } - if (matches[sel]) { - matches.push(handleObj); - } - } - if (matches.length) { - handlerQueue.push({ elem: cur, handlers: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if (delegateCount < handlers.length) { - handlerQueue.push({ elem: this, handlers: handlers.slice(delegateCount) }); - } - - return handlerQueue; - }, - - fix: function (event) { - if (event[jQuery.expando]) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[type]; - - if (!fixHook) { - this.fixHooks[type] = fixHook = - rmouseEvent.test(type) ? this.mouseHooks : - rkeyEvent.test(type) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat(fixHook.props) : this.props; - - event = new jQuery.Event(originalEvent); - - i = copy.length; - while (i--) { - prop = copy[i]; - event[prop] = originalEvent[prop]; - } - - // Support: IE<9 - // Fix target property (#1925) - if (!event.target) { - event.target = originalEvent.srcElement || document; - } - - // Support: Chrome 23+, Safari? - // Target should not be a text node (#504, #13143) - if (event.target.nodeType === 3) { - event.target = event.target.parentNode; - } - - // Support: IE<9 - // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) - event.metaKey = !!event.metaKey; - - return fixHook.filter ? fixHook.filter(event, originalEvent) : event; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function (event, original) { - - // Add which for key events - if (event.which == null) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function (event, original) { - var body, eventDoc, doc, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if (event.pageX == null && original.clientX != null) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = original.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Add relatedTarget, if necessary - if (!event.relatedTarget && fromElement) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if (!event.which && button !== undefined) { - event.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); - } - - return event; - } - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - // Fire native event if possible so blur/focus sequence is correct - trigger: function () { - if (this !== safeActiveElement() && this.focus) { - try { - this.focus(); - return false; - } catch (e) { - // Support: IE<9 - // If we error on focus to hidden element (#1486, #12518), - // let .trigger() run the handlers - } - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function () { - if (this === safeActiveElement() && this.blur) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - // For checkbox, fire native event so checked state will be right - trigger: function () { - if (jQuery.nodeName(this, "input") && this.type === "checkbox" && this.click) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function (event) { - return jQuery.nodeName(event.target, "a"); - } - }, - - beforeunload: { - postDispatch: function (event) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if (event.result !== undefined && event.originalEvent) { - event.originalEvent.returnValue = event.result; - } - } - } - }, - - simulate: function (type, elem, event, bubble) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true, - originalEvent: {} - } - ); - if (bubble) { - jQuery.event.trigger(e, null, elem); - } else { - jQuery.event.dispatch.call(elem, e); - } - if (e.isDefaultPrevented()) { - event.preventDefault(); - } - } - }; - - jQuery.removeEvent = document.removeEventListener ? - function (elem, type, handle) { - if (elem.removeEventListener) { - elem.removeEventListener(type, handle, false); - } - } : - function (elem, type, handle) { - var name = "on" + type; - - if (elem.detachEvent) { - - // #8545, #7054, preventing memory leaks for custom events in IE6-8 - // detachEvent needed property on element, by name of that event, to properly expose it to GC - if (typeof elem[name] === strundefined) { - elem[name] = null; - } - - elem.detachEvent(name, handle); - } - }; - - jQuery.Event = function (src, props) { - // Allow instantiation without the 'new' keyword - if (!(this instanceof jQuery.Event)) { - return new jQuery.Event(src, props); - } - - // Event object - if (src && src.type) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - // Support: IE < 9, Android < 4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if (props) { - jQuery.extend(this, props); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[jQuery.expando] = true; - }; - - // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding - // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html - jQuery.Event.prototype = { - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - - preventDefault: function () { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - if (!e) { - return; - } - - // If preventDefault exists, run it on the original event - if (e.preventDefault) { - e.preventDefault(); - - // Support: IE - // Otherwise set the returnValue property of the original event to false - } else { - e.returnValue = false; - } - }, - stopPropagation: function () { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - if (!e) { - return; - } - // If stopPropagation exists, run it on the original event - if (e.stopPropagation) { - e.stopPropagation(); - } - - // Support: IE - // Set the cancelBubble property of the original event to true - e.cancelBubble = true; - }, - stopImmediatePropagation: function () { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if (e && e.stopImmediatePropagation) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } - }; - - // Create mouseenter/leave events using mouseover/out and event-time checks - jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" - }, function (orig, fix) { - jQuery.event.special[orig] = { - delegateType: fix, - bindType: fix, - - handle: function (event) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if (!related || (related !== target && !jQuery.contains(target, related))) { - event.type = handleObj.origType; - ret = handleObj.handler.apply(this, arguments); - event.type = fix; - } - return ret; - } - }; - }); - - // IE submit delegation - if (!support.submitBubbles) { - - jQuery.event.special.submit = { - setup: function () { - // Only need this for delegated form submit events - if (jQuery.nodeName(this, "form")) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add(this, "click._submit keypress._submit", function (e) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName(elem, "input") || jQuery.nodeName(elem, "button") ? elem.form : undefined; - if (form && !jQuery._data(form, "submitBubbles")) { - jQuery.event.add(form, "submit._submit", function (event) { - event._submit_bubble = true; - }); - jQuery._data(form, "submitBubbles", true); - } - }); - // return undefined since we don't need an event listener - }, - - postDispatch: function (event) { - // If form was submitted by the user, bubble the event up the tree - if (event._submit_bubble) { - delete event._submit_bubble; - if (this.parentNode && !event.isTrigger) { - jQuery.event.simulate("submit", this.parentNode, event, true); - } - } - }, - - teardown: function () { - // Only need this for delegated form submit events - if (jQuery.nodeName(this, "form")) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove(this, "._submit"); - } - }; - } - - // IE change delegation and checkbox/radio fix - if (!support.changeBubbles) { - - jQuery.event.special.change = { - - setup: function () { - - if (rformElems.test(this.nodeName)) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if (this.type === "checkbox" || this.type === "radio") { - jQuery.event.add(this, "propertychange._change", function (event) { - if (event.originalEvent.propertyName === "checked") { - this._just_changed = true; - } - }); - jQuery.event.add(this, "click._change", function (event) { - if (this._just_changed && !event.isTrigger) { - this._just_changed = false; - } - // Allow triggered, simulated change events (#11500) - jQuery.event.simulate("change", this, event, true); - }); - } - return false; - } - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add(this, "beforeactivate._change", function (e) { - var elem = e.target; - - if (rformElems.test(elem.nodeName) && !jQuery._data(elem, "changeBubbles")) { - jQuery.event.add(elem, "change._change", function (event) { - if (this.parentNode && !event.isSimulated && !event.isTrigger) { - jQuery.event.simulate("change", this.parentNode, event, true); - } - }); - jQuery._data(elem, "changeBubbles", true); - } - }); - }, - - handle: function (event) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if (this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox")) { - return event.handleObj.handler.apply(this, arguments); - } - }, - - teardown: function () { - jQuery.event.remove(this, "._change"); - - return !rformElems.test(this.nodeName); - } - }; - } - - // Create "bubbling" focus and blur events - if (!support.focusinBubbles) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function (orig, fix) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function (event) { - jQuery.event.simulate(fix, event.target, jQuery.event.fix(event), true); - }; - - jQuery.event.special[fix] = { - setup: function () { - var doc = this.ownerDocument || this, - attaches = jQuery._data(doc, fix); - - if (!attaches) { - doc.addEventListener(orig, handler, true); - } - jQuery._data(doc, fix, (attaches || 0) + 1); - }, - teardown: function () { - var doc = this.ownerDocument || this, - attaches = jQuery._data(doc, fix) - 1; - - if (!attaches) { - doc.removeEventListener(orig, handler, true); - jQuery._removeData(doc, fix); - } else { - jQuery._data(doc, fix, attaches); - } - } - }; - }); - } - - jQuery.fn.extend({ - - on: function (types, selector, data, fn, /*INTERNAL*/ one) { - var type, origFn; - - // Types can be a map of types/handlers - if (typeof types === "object") { - // ( types-Object, selector, data ) - if (typeof selector !== "string") { - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for (type in types) { - this.on(type, selector, data, types[type], one); - } - return this; - } - - if (data == null && fn == null) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if (fn == null) { - if (typeof selector === "string") { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if (fn === false) { - fn = returnFalse; - } else if (!fn) { - return this; - } - - if (one === 1) { - origFn = fn; - fn = function (event) { - // Can use an empty set, since event contains the info - jQuery().off(event); - return origFn.apply(this, arguments); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || (origFn.guid = jQuery.guid++); - } - return this.each(function () { - jQuery.event.add(this, types, fn, data, selector); - }); - }, - one: function (types, selector, data, fn) { - return this.on(types, selector, data, fn, 1); - }, - off: function (types, selector, fn) { - var handleObj, type; - if (types && types.preventDefault && types.handleObj) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery(types.delegateTarget).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if (typeof types === "object") { - // ( types-object [, selector] ) - for (type in types) { - this.off(type, selector, types[type]); - } - return this; - } - if (selector === false || typeof selector === "function") { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if (fn === false) { - fn = returnFalse; - } - return this.each(function () { - jQuery.event.remove(this, types, fn, selector); - }); - }, - - trigger: function (type, data) { - return this.each(function () { - jQuery.event.trigger(type, data, this); - }); - }, - triggerHandler: function (type, data) { - var elem = this[0]; - if (elem) { - return jQuery.event.trigger(type, data, elem, true); - } - } - }); - - - function createSafeFragment(document) { - var list = nodeNames.split("|"), - safeFrag = document.createDocumentFragment(); - - if (safeFrag.createElement) { - while (list.length) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; - } - - var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, - rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rtbody = /\s*$/g, - - // We have to close these tags to support XHTML (#13200) - wrapMap = { - option: [1, ""], - legend: [1, "
    ", "
    "], - area: [1, "", ""], - param: [1, "", ""], - thead: [1, "", "
    "], - tr: [2, "", "
    "], - col: [2, "", "
    "], - td: [3, "", "
    "], - - // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, - // unless wrapped in a div with non-breaking characters in front of it. - _default: support.htmlSerialize ? [0, "", ""] : [1, "X
    ", "
    "] - }, - safeFragment = createSafeFragment(document), - fragmentDiv = safeFragment.appendChild(document.createElement("div")); - - wrapMap.optgroup = wrapMap.option; - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; - wrapMap.th = wrapMap.td; - - function getAll(context, tag) { - var elems, elem, - i = 0, - found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName(tag || "*") : - typeof context.querySelectorAll !== strundefined ? context.querySelectorAll(tag || "*") : - undefined; - - if (!found) { - for (found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++) { - if (!tag || jQuery.nodeName(elem, tag)) { - found.push(elem); - } else { - jQuery.merge(found, getAll(elem, tag)); - } - } - } - - return tag === undefined || tag && jQuery.nodeName(context, tag) ? - jQuery.merge([context], found) : - found; - } - - // Used in buildFragment, fixes the defaultChecked property - function fixDefaultChecked(elem) { - if (rcheckableType.test(elem.type)) { - elem.defaultChecked = elem.checked; - } - } - - // Support: IE<8 - // Manipulating tables requires a tbody - function manipulationTarget(elem, content) { - return jQuery.nodeName(elem, "table") && - jQuery.nodeName(content.nodeType !== 11 ? content : content.firstChild, "tr") ? - - elem.getElementsByTagName("tbody")[0] || - elem.appendChild(elem.ownerDocument.createElement("tbody")) : - elem; - } - - // Replace/restore the type attribute of script elements for safe DOM manipulation - function disableScript(elem) { - elem.type = (jQuery.find.attr(elem, "type") !== null) + "/" + elem.type; - return elem; - } - function restoreScript(elem) { - var match = rscriptTypeMasked.exec(elem.type); - if (match) { - elem.type = match[1]; - } else { - elem.removeAttribute("type"); - } - return elem; - } - - // Mark scripts as having already been evaluated - function setGlobalEval(elems, refElements) { - var elem, - i = 0; - for (; (elem = elems[i]) != null; i++) { - jQuery._data(elem, "globalEval", !refElements || jQuery._data(refElements[i], "globalEval")); - } - } - - function cloneCopyEvent(src, dest) { - - if (dest.nodeType !== 1 || !jQuery.hasData(src)) { - return; - } - - var type, i, l, - oldData = jQuery._data(src), - curData = jQuery._data(dest, oldData), - events = oldData.events; - - if (events) { - delete curData.handle; - curData.events = {}; - - for (type in events) { - for (i = 0, l = events[type].length; i < l; i++) { - jQuery.event.add(dest, type, events[type][i]); - } - } - } - - // make the cloned public data object a copy from the original - if (curData.data) { - curData.data = jQuery.extend({}, curData.data); - } - } - - function fixCloneNodeIssues(src, dest) { - var nodeName, e, data; - - // We do not need to do anything for non-Elements - if (dest.nodeType !== 1) { - return; - } - - nodeName = dest.nodeName.toLowerCase(); - - // IE6-8 copies events bound via attachEvent when using cloneNode. - if (!support.noCloneEvent && dest[jQuery.expando]) { - data = jQuery._data(dest); - - for (e in data.events) { - jQuery.removeEvent(dest, e, data.handle); - } - - // Event data gets referenced instead of copied if the expando gets copied too - dest.removeAttribute(jQuery.expando); - } - - // IE blanks contents when cloning scripts, and tries to evaluate newly-set text - if (nodeName === "script" && dest.text !== src.text) { - disableScript(dest).text = src.text; - restoreScript(dest); - - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. - } else if (nodeName === "object") { - if (dest.parentNode) { - dest.outerHTML = src.outerHTML; - } - - // This path appears unavoidable for IE9. When cloning an object - // element in IE9, the outerHTML strategy above is not sufficient. - // If the src has innerHTML and the destination does not, - // copy the src.innerHTML into the dest.innerHTML. #10324 - if (support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML))) { - dest.innerHTML = src.innerHTML; - } - - } else if (nodeName === "input" && rcheckableType.test(src.type)) { - // IE6-8 fails to persist the checked state of a cloned checkbox - // or radio button. Worse, IE6-7 fail to give the cloned element - // a checked appearance if the defaultChecked value isn't also set - - dest.defaultChecked = dest.checked = src.checked; - - // IE6-7 get confused and end up setting the value of a cloned - // checkbox/radio button to an empty string instead of "on" - if (dest.value !== src.value) { - dest.value = src.value; - } - - // IE6-8 fails to return the selected option to the default selected - // state when cloning options - } else if (nodeName === "option") { - dest.defaultSelected = dest.selected = src.defaultSelected; - - // IE6-8 fails to set the defaultValue to the correct value when - // cloning other types of input fields - } else if (nodeName === "input" || nodeName === "textarea") { - dest.defaultValue = src.defaultValue; - } - } - - jQuery.extend({ - clone: function (elem, dataAndEvents, deepDataAndEvents) { - var destElements, node, clone, i, srcElements, - inPage = jQuery.contains(elem.ownerDocument, elem); - - if (support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test("<" + elem.nodeName + ">")) { - clone = elem.cloneNode(true); - - // IE<=8 does not properly clone detached, unknown element nodes - } else { - fragmentDiv.innerHTML = elem.outerHTML; - fragmentDiv.removeChild(clone = fragmentDiv.firstChild); - } - - if ((!support.noCloneEvent || !support.noCloneChecked) && - (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem)) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll(clone); - srcElements = getAll(elem); - - // Fix all IE cloning issues - for (i = 0; (node = srcElements[i]) != null; ++i) { - // Ensure that the destination node is not null; Fixes #9587 - if (destElements[i]) { - fixCloneNodeIssues(node, destElements[i]); - } - } - } - - // Copy the events from the original to the clone - if (dataAndEvents) { - if (deepDataAndEvents) { - srcElements = srcElements || getAll(elem); - destElements = destElements || getAll(clone); - - for (i = 0; (node = srcElements[i]) != null; i++) { - cloneCopyEvent(node, destElements[i]); - } - } else { - cloneCopyEvent(elem, clone); - } - } - - // Preserve script evaluation history - destElements = getAll(clone, "script"); - if (destElements.length > 0) { - setGlobalEval(destElements, !inPage && getAll(elem, "script")); - } - - destElements = srcElements = node = null; - - // Return the cloned set - return clone; - }, - - buildFragment: function (elems, context, scripts, selection) { - var j, elem, contains, - tmp, tag, tbody, wrap, - l = elems.length, - - // Ensure a safe fragment - safe = createSafeFragment(context), - - nodes = [], - i = 0; - - for (; i < l; i++) { - elem = elems[i]; - - if (elem || elem === 0) { - - // Add nodes directly - if (jQuery.type(elem) === "object") { - jQuery.merge(nodes, elem.nodeType ? [elem] : elem); - - // Convert non-html into a text node - } else if (!rhtml.test(elem)) { - nodes.push(context.createTextNode(elem)); - - // Convert html into DOM nodes - } else { - tmp = tmp || safe.appendChild(context.createElement("div")); - - // Deserialize a standard representation - tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase(); - wrap = wrapMap[tag] || wrapMap._default; - - tmp.innerHTML = wrap[1] + elem.replace(rxhtmlTag, "<$1>") + wrap[2]; - - // Descend through wrappers to the right content - j = wrap[0]; - while (j--) { - tmp = tmp.lastChild; - } - - // Manually add leading whitespace removed by IE - if (!support.leadingWhitespace && rleadingWhitespace.test(elem)) { - nodes.push(context.createTextNode(rleadingWhitespace.exec(elem)[0])); - } - - // Remove IE's autoinserted from table fragments - if (!support.tbody) { - - // String was a , *may* have spurious - elem = tag === "table" && !rtbody.test(elem) ? - tmp.firstChild : - - // String was a bare or - wrap[1] === "
    " && !rtbody.test(elem) ? - tmp : - 0; - - j = elem && elem.childNodes.length; - while (j--) { - if (jQuery.nodeName((tbody = elem.childNodes[j]), "tbody") && !tbody.childNodes.length) { - elem.removeChild(tbody); - } - } - } - - jQuery.merge(nodes, tmp.childNodes); - - // Fix #12392 for WebKit and IE > 9 - tmp.textContent = ""; - - // Fix #12392 for oldIE - while (tmp.firstChild) { - tmp.removeChild(tmp.firstChild); - } - - // Remember the top-level container for proper cleanup - tmp = safe.lastChild; - } - } - } - - // Fix #11356: Clear elements from fragment - if (tmp) { - safe.removeChild(tmp); - } - - // Reset defaultChecked for any radios and checkboxes - // about to be appended to the DOM in IE 6/7 (#8060) - if (!support.appendChecked) { - jQuery.grep(getAll(nodes, "input"), fixDefaultChecked); - } - - i = 0; - while ((elem = nodes[i++])) { - - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if (selection && jQuery.inArray(elem, selection) !== -1) { - continue; - } - - contains = jQuery.contains(elem.ownerDocument, elem); - - // Append to fragment - tmp = getAll(safe.appendChild(elem), "script"); - - // Preserve script evaluation history - if (contains) { - setGlobalEval(tmp); - } - - // Capture executables - if (scripts) { - j = 0; - while ((elem = tmp[j++])) { - if (rscriptType.test(elem.type || "")) { - scripts.push(elem); - } - } - } - } - - tmp = null; - - return safe; - }, - - cleanData: function (elems, /* internal */ acceptData) { - var elem, type, id, data, - i = 0, - internalKey = jQuery.expando, - cache = jQuery.cache, - deleteExpando = support.deleteExpando, - special = jQuery.event.special; - - for (; (elem = elems[i]) != null; i++) { - if (acceptData || jQuery.acceptData(elem)) { - - id = elem[internalKey]; - data = id && cache[id]; - - if (data) { - if (data.events) { - for (type in data.events) { - if (special[type]) { - jQuery.event.remove(elem, type); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent(elem, type, data.handle); - } - } - } - - // Remove cache only if it was not already removed by jQuery.event.remove - if (cache[id]) { - - delete cache[id]; - - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if (deleteExpando) { - delete elem[internalKey]; - - } else if (typeof elem.removeAttribute !== strundefined) { - elem.removeAttribute(internalKey); - - } else { - elem[internalKey] = null; - } - - deletedIds.push(id); - } - } - } - } - } - }); - - jQuery.fn.extend({ - text: function (value) { - return access(this, function (value) { - return value === undefined ? - jQuery.text(this) : - this.empty().append((this[0] && this[0].ownerDocument || document).createTextNode(value)); - }, null, value, arguments.length); - }, - - append: function () { - return this.domManip(arguments, function (elem) { - if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { - var target = manipulationTarget(this, elem); - target.appendChild(elem); - } - }); - }, - - prepend: function () { - return this.domManip(arguments, function (elem) { - if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { - var target = manipulationTarget(this, elem); - target.insertBefore(elem, target.firstChild); - } - }); - }, - - before: function () { - return this.domManip(arguments, function (elem) { - if (this.parentNode) { - this.parentNode.insertBefore(elem, this); - } - }); - }, - - after: function () { - return this.domManip(arguments, function (elem) { - if (this.parentNode) { - this.parentNode.insertBefore(elem, this.nextSibling); - } - }); - }, - - remove: function (selector, keepData /* Internal Use Only */) { - var elem, - elems = selector ? jQuery.filter(selector, this) : this, - i = 0; - - for (; (elem = elems[i]) != null; i++) { - - if (!keepData && elem.nodeType === 1) { - jQuery.cleanData(getAll(elem)); - } - - if (elem.parentNode) { - if (keepData && jQuery.contains(elem.ownerDocument, elem)) { - setGlobalEval(getAll(elem, "script")); - } - elem.parentNode.removeChild(elem); - } - } - - return this; - }, - - empty: function () { - var elem, - i = 0; - - for (; (elem = this[i]) != null; i++) { - // Remove element nodes and prevent memory leaks - if (elem.nodeType === 1) { - jQuery.cleanData(getAll(elem, false)); - } - - // Remove any remaining nodes - while (elem.firstChild) { - elem.removeChild(elem.firstChild); - } - - // If this is a select, ensure that it displays empty (#12336) - // Support: IE<9 - if (elem.options && jQuery.nodeName(elem, "select")) { - elem.options.length = 0; - } - } - - return this; - }, - - clone: function (dataAndEvents, deepDataAndEvents) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map(function () { - return jQuery.clone(this, dataAndEvents, deepDataAndEvents); - }); - }, - - html: function (value) { - return access(this, function (value) { - var elem = this[0] || {}, - i = 0, - l = this.length; - - if (value === undefined) { - return elem.nodeType === 1 ? - elem.innerHTML.replace(rinlinejQuery, "") : - undefined; - } - - // See if we can take a shortcut and just use innerHTML - if (typeof value === "string" && !rnoInnerhtml.test(value) && - (support.htmlSerialize || !rnoshimcache.test(value)) && - (support.leadingWhitespace || !rleadingWhitespace.test(value)) && - !wrapMap[(rtagName.exec(value) || ["", ""])[1].toLowerCase()]) { - - value = value.replace(rxhtmlTag, "<$1>"); - - try { - for (; i < l; i++) { - // Remove element nodes and prevent memory leaks - elem = this[i] || {}; - if (elem.nodeType === 1) { - jQuery.cleanData(getAll(elem, false)); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch (e) { } - } - - if (elem) { - this.empty().append(value); - } - }, null, value, arguments.length); - }, - - replaceWith: function () { - var arg = arguments[0]; - - // Make the changes, replacing each context element with the new content - this.domManip(arguments, function (elem) { - arg = this.parentNode; - - jQuery.cleanData(getAll(this)); - - if (arg) { - arg.replaceChild(elem, this); - } - }); - - // Force removal if there was no new content (e.g., from empty arguments) - return arg && (arg.length || arg.nodeType) ? this : this.remove(); - }, - - detach: function (selector) { - return this.remove(selector, true); - }, - - domManip: function (args, callback) { - - // Flatten any nested arrays - args = concat.apply([], args); - - var first, node, hasScripts, - scripts, doc, fragment, - i = 0, - l = this.length, - set = this, - iNoClone = l - 1, - value = args[0], - isFunction = jQuery.isFunction(value); - - // We can't cloneNode fragments that contain checked, in WebKit - if (isFunction || - (l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test(value))) { - return this.each(function (index) { - var self = set.eq(index); - if (isFunction) { - args[0] = value.call(this, index, self.html()); - } - self.domManip(args, callback); - }); - } - - if (l) { - fragment = jQuery.buildFragment(args, this[0].ownerDocument, false, this); - first = fragment.firstChild; - - if (fragment.childNodes.length === 1) { - fragment = first; - } - - if (first) { - scripts = jQuery.map(getAll(fragment, "script"), disableScript); - hasScripts = scripts.length; - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for (; i < l; i++) { - node = fragment; - - if (i !== iNoClone) { - node = jQuery.clone(node, true, true); - - // Keep references to cloned scripts for later restoration - if (hasScripts) { - jQuery.merge(scripts, getAll(node, "script")); - } - } - - callback.call(this[i], node, i); - } - - if (hasScripts) { - doc = scripts[scripts.length - 1].ownerDocument; - - // Reenable scripts - jQuery.map(scripts, restoreScript); - - // Evaluate executable scripts on first document insertion - for (i = 0; i < hasScripts; i++) { - node = scripts[i]; - if (rscriptType.test(node.type || "") && - !jQuery._data(node, "globalEval") && jQuery.contains(doc, node)) { - - if (node.src) { - // Optional AJAX dependency, but won't run scripts if not present - if (jQuery._evalUrl) { - jQuery._evalUrl(node.src); - } - } else { - jQuery.globalEval((node.text || node.textContent || node.innerHTML || "").replace(rcleanScript, "")); - } - } - } - } - - // Fix #11809: Avoid leaking memory - fragment = first = null; - } - } - - return this; - } - }); - - jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" - }, function (name, original) { - jQuery.fn[name] = function (selector) { - var elems, - i = 0, - ret = [], - insert = jQuery(selector), - last = insert.length - 1; - - for (; i <= last; i++) { - elems = i === last ? this : this.clone(true); - jQuery(insert[i])[original](elems); - - // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() - push.apply(ret, elems.get()); - } - - return this.pushStack(ret); - }; - }); - - - var iframe, - elemdisplay = {}; - - /** - * Retrieve the actual display of a element - * @param {String} name nodeName of the element - * @param {Object} doc Document object - */ - // Called only from within defaultDisplay - function actualDisplay(name, doc) { - var style, - elem = jQuery(doc.createElement(name)).appendTo(doc.body), - - // getDefaultComputedStyle might be reliably used only on attached element - display = window.getDefaultComputedStyle && (style = window.getDefaultComputedStyle(elem[0])) ? - - // Use of this method is a temporary fix (more like optmization) until something better comes along, - // since it was removed from specification and supported only in FF - style.display : jQuery.css(elem[0], "display"); - - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); - - return display; - } - - /** - * Try to determine the default display value of an element - * @param {String} nodeName - */ - function defaultDisplay(nodeName) { - var doc = document, - display = elemdisplay[nodeName]; - - if (!display) { - display = actualDisplay(nodeName, doc); - - // If the simple way fails, read from inside an iframe - if (display === "none" || !display) { - - // Use the already-created iframe if possible - iframe = (iframe || jQuery("