• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

moto web application


Commit MetaInfo

Revision197ef9ed3e26003b9e89f056dea744ac25968d5c (tree)
Time2014-01-31 16:34:08
Authorastoria-d <astoria-d@mail...>
Commiterastoria-d

Log Message

atmosphere test integrated

Change Summary

Incremental Difference

--- a/WEB-INF/classes/motoSample/ChatBean.java
+++ b/WEB-INF/classes/motoSample/ChatBean.java
@@ -28,8 +28,8 @@ import java.util.Date;
2828 import java.text.SimpleDateFormat;
2929 import java.util.UUID;
3030
31-import org.primefaces.push.PushContext;
32-import org.primefaces.push.PushContextFactory;
31+//import org.primefaces.push.PushContext;
32+//import org.primefaces.push.PushContextFactory;
3333
3434 @ManagedBean
3535 @ViewScoped
@@ -221,8 +221,8 @@ public class ChatBean implements Serializable {
221221 cm.setDate(dt);
222222 cm.setUname(userBean.getUid());
223223
224- PushContext pushContext = PushContextFactory.getDefault().getPushContext();
225- pushContext.push("/" + chatRoom, pm);
224+ //PushContext pushContext = PushContextFactory.getDefault().getPushContext();
225+ //pushContext.push("/" + chatRoom, pm);
226226 }
227227 catch (SQLException se) {
228228 log.severe("sql err!!!");
--- a/WEB-INF/classes/motoSample/UserBean.java
+++ b/WEB-INF/classes/motoSample/UserBean.java
@@ -18,8 +18,8 @@ import javax.servlet.http.HttpSession;
1818 import java.util.ArrayList;
1919 import javax.faces.model.SelectItem;
2020
21-import org.primefaces.push.PushContext;
22-import org.primefaces.push.PushContextFactory;
21+//import org.primefaces.push.PushContext;
22+//import org.primefaces.push.PushContextFactory;
2323
2424 @ManagedBean
2525 @SessionScoped
@@ -128,8 +128,8 @@ public class UserBean implements Serializable {
128128 lu.setUid(uid);
129129 lu.setLogin(true);
130130
131- PushContext pushContext = PushContextFactory.getDefault().getPushContext();
132- pushContext.push("/" + chatRoom, pm);
131+ //PushContext pushContext = PushContextFactory.getDefault().getPushContext();
132+ //pushContext.push("/" + chatRoom, pm);
133133 }
134134
135135 ///after login, redirect to the user specified url.
@@ -166,8 +166,8 @@ public class UserBean implements Serializable {
166166 lu.setUid(uid);
167167 lu.setLogin(false);
168168
169- PushContext pushContext = PushContextFactory.getDefault().getPushContext();
170- pushContext.push("/" + chatRoom, pm);
169+ //PushContext pushContext = PushContextFactory.getDefault().getPushContext();
170+ //pushContext.push("/" + chatRoom, pm);
171171 }
172172 loginMemberBean.login(uid, false);
173173 context.getExternalContext().invalidateSession();
--- /dev/null
+++ b/WEB-INF/classes/org/atmosphere/samples/chat/Chat.java
@@ -0,0 +1,84 @@
1+/*
2+ * Copyright 2014 Jeanfrancois Arcand
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+ * use this file except in compliance with the License. You may obtain a copy of
6+ * the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+ * License for the specific language governing permissions and limitations under
14+ * the License.
15+ */
16+package org.atmosphere.samples.chat;
17+
18+import org.atmosphere.config.service.Disconnect;
19+import org.atmosphere.config.service.ManagedService;
20+import org.atmosphere.config.service.Ready;
21+import org.atmosphere.cpr.AtmosphereResource;
22+import org.atmosphere.cpr.AtmosphereResourceEvent;
23+import org.atmosphere.samples.chat.custom.Config;
24+import org.slf4j.Logger;
25+import org.slf4j.LoggerFactory;
26+
27+import java.io.IOException;
28+
29+import static org.atmosphere.cpr.ApplicationConfig.MAX_INACTIVE;
30+
31+/**
32+ * Simple annotated class that demonstrate the power of Atmosphere. This class supports all transports, support
33+ * message length garantee, heart beat, message cache thanks to the {@link ManagedService}.
34+ */
35+@Config
36+@ManagedService(path = "/chat", atmosphereConfig = MAX_INACTIVE + "=120000")
37+public class Chat {
38+ private final Logger logger = LoggerFactory.getLogger(Chat.class);
39+
40+// Uncomment for changing response's state
41+// @Get
42+// public void init(AtmosphereResource r) {
43+// r.getResponse().setCharacterEncoding("UTF-8");
44+// }
45+
46+ /**
47+ * Invoked when the connection as been fully established and suspended, e.g ready for receiving messages.
48+ *
49+ * @param r
50+ */
51+ @Ready
52+ public void onReady(final AtmosphereResource r) {
53+ logger.info("Browser {} connected.", r.uuid());
54+ }
55+
56+ /**
57+ * Invoked when the client disconnect or when an unexpected closing of the underlying connection happens.
58+ *
59+ * @param event
60+ */
61+ @Disconnect
62+ public void onDisconnect(AtmosphereResourceEvent event) {
63+ if (event.isCancelled()) {
64+ logger.info("Browser {} unexpectedly disconnected", event.getResource().uuid());
65+ } else if (event.isClosedByClient()) {
66+ logger.info("Browser {} closed the connection", event.getResource().uuid());
67+ }
68+ }
69+
70+ /**
71+ * Simple annotated class that demonstrate how {@link org.atmosphere.config.managed.Encoder} and {@link org.atmosphere.config.managed.Decoder
72+ * can be used.
73+ *
74+ * @param message an instance of {@link Message}
75+ * @return
76+ * @throws IOException
77+ */
78+ @org.atmosphere.config.service.Message(encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class})
79+ public Message onMessage(Message message) throws IOException {
80+ logger.info("{} just send {}", message.getAuthor(), message.getMessage());
81+ return message;
82+ }
83+
84+}
\ No newline at end of file
--- /dev/null
+++ b/WEB-INF/classes/org/atmosphere/samples/chat/JacksonDecoder.java
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright 2014 Jeanfrancois Arcand
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+ * use this file except in compliance with the License. You may obtain a copy of
6+ * the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+ * License for the specific language governing permissions and limitations under
14+ * the License.
15+ */
16+package org.atmosphere.samples.chat;
17+
18+import org.atmosphere.config.managed.Decoder;
19+import org.codehaus.jackson.map.ObjectMapper;
20+
21+import java.io.IOException;
22+
23+/**
24+ * Decode a String into a {@link Message}.
25+ */
26+public class JacksonDecoder implements Decoder<String, Message> {
27+
28+ private final ObjectMapper mapper = new ObjectMapper();
29+
30+ @Override
31+ public Message decode(String s) {
32+ try {
33+ return mapper.readValue(s, Message.class);
34+ } catch (IOException e) {
35+ throw new RuntimeException(e);
36+ }
37+ }
38+}
--- /dev/null
+++ b/WEB-INF/classes/org/atmosphere/samples/chat/JacksonEncoder.java
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright 2014 Jeanfrancois Arcand
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+ * use this file except in compliance with the License. You may obtain a copy of
6+ * the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+ * License for the specific language governing permissions and limitations under
14+ * the License.
15+ */
16+package org.atmosphere.samples.chat;
17+
18+import org.atmosphere.config.managed.Encoder;
19+import org.codehaus.jackson.map.ObjectMapper;
20+
21+import java.io.IOException;
22+
23+/**
24+ * Encode a {@link Message} into a String
25+ */
26+public class JacksonEncoder implements Encoder<Message, String> {
27+
28+ private final ObjectMapper mapper = new ObjectMapper();
29+
30+ @Override
31+ public String encode(Message m) {
32+ try {
33+ return mapper.writeValueAsString(m);
34+ } catch (IOException e) {
35+ throw new RuntimeException(e);
36+ }
37+ }
38+}
--- /dev/null
+++ b/WEB-INF/classes/org/atmosphere/samples/chat/Message.java
@@ -0,0 +1,60 @@
1+/*
2+ * Copyright 2014 Jeanfrancois Arcand
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+ * use this file except in compliance with the License. You may obtain a copy of
6+ * the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+ * License for the specific language governing permissions and limitations under
14+ * the License.
15+ */
16+package org.atmosphere.samples.chat;
17+
18+import java.util.Date;
19+
20+public class Message {
21+
22+ private String message;
23+ private String author;
24+ private long time;
25+
26+ public Message() {
27+ this("", "");
28+ }
29+
30+ public Message(String author, String message) {
31+ this.author = author;
32+ this.message = message;
33+ this.time = new Date().getTime();
34+ }
35+
36+ public String getMessage() {
37+ return message;
38+ }
39+
40+ public String getAuthor() {
41+ return author;
42+ }
43+
44+ public void setAuthor(String author) {
45+ this.author = author;
46+ }
47+
48+ public void setMessage(String message) {
49+ this.message = message;
50+ }
51+
52+ public long getTime() {
53+ return time;
54+ }
55+
56+ public void setTime(long time) {
57+ this.time = time;
58+ }
59+
60+}
--- /dev/null
+++ b/WEB-INF/classes/org/atmosphere/samples/chat/custom/Config.java
@@ -0,0 +1,18 @@
1+package org.atmosphere.samples.chat.custom;
2+
3+import java.lang.annotation.Documented;
4+import java.lang.annotation.ElementType;
5+import java.lang.annotation.Retention;
6+import java.lang.annotation.RetentionPolicy;
7+import java.lang.annotation.Target;
8+
9+/**
10+ * This annotation is here to demonstrate how simple it is to write custom annotation in Atmosphere.
11+ * @author Jeanfrancois Arcand
12+ */
13+
14+@Target({ElementType.TYPE})
15+@Retention(RetentionPolicy.RUNTIME)
16+@Documented
17+public @interface Config {
18+}
--- /dev/null
+++ b/WEB-INF/classes/org/atmosphere/samples/chat/custom/SampleConfig.java
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright 2014 Jeanfrancois Arcand
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+ * use this file except in compliance with the License. You may obtain a copy of
6+ * the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+ * License for the specific language governing permissions and limitations under
14+ * the License.
15+ */
16+package org.atmosphere.samples.chat.custom;
17+
18+import org.atmosphere.annotation.Processor;
19+import org.atmosphere.config.AtmosphereAnnotation;
20+import org.atmosphere.cpr.AtmosphereFramework;
21+import org.slf4j.Logger;
22+import org.slf4j.LoggerFactory;
23+
24+/**
25+ * A Simple {@link Processor} that demonstrate how you can extend you application with custom annotation.
26+ *
27+ * @author eanfrancois Arcand
28+ */
29+@AtmosphereAnnotation(Config.class)
30+public class SampleConfig implements Processor<Object> {
31+
32+ private final Logger logger = LoggerFactory.getLogger(SampleConfig.class);
33+
34+ @Override
35+ public void handle(AtmosphereFramework framework, Class<Object> annotatedClass) {
36+ logger.info("Custom annotation {} discovered. Starting the Chat Sample", annotatedClass.getAnnotation(Config.class));
37+ }
38+}
--- a/WEB-INF/jboss-deployment-structure.xml
+++ /dev/null
@@ -1,5 +0,0 @@
1-<?xml version="1.0" encoding="UTF-8"?>
2-<jboss-deployment-structure>
3- <deployment>
4- </deployment>
5-</jboss-deployment-structure>
Binary files a/WEB-INF/lib/atmosphere-runtime-2.0.1.jar and /dev/null differ
Binary files /dev/null and b/WEB-INF/lib/atmosphere-runtime-2.1.0.jar differ
Binary files /dev/null and b/WEB-INF/lib/jackson-core-asl-1.9.3.jar differ
Binary files /dev/null and b/WEB-INF/lib/jackson-mapper-asl-1.9.3.jar differ
Binary files a/WEB-INF/lib/primefaces-4.0.jar and /dev/null differ
--- a/WEB-INF/web.xml
+++ b/WEB-INF/web.xml
@@ -44,15 +44,19 @@
4444 </auth-constraint>
4545 </security-constraint>
4646
47- <!-- primefaces push servlet -->
47+
48+ <!-- atmosphere servlet mapping. -->
4849 <servlet>
49- <servlet-name>Push Servlet</servlet-name>
50- <servlet-class>org.primefaces.push.PushServlet</servlet-class>
50+ <description>AtmosphereServlet</description>
51+ <servlet-name>AtmosphereServlet</servlet-name>
52+ <servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
53+ <!-- Use it with mvn jetty:run -->
54+ <load-on-startup>0</load-on-startup>
55+ <async-supported>true</async-supported>
5156 </servlet>
52-
5357 <servlet-mapping>
54- <servlet-name>Push Servlet</servlet-name>
55- <url-pattern>/primepush/*</url-pattern>
58+ <servlet-name>AtmosphereServlet</servlet-name>
59+ <url-pattern>/chat/*</url-pattern>
5660 </servlet-mapping>
5761
5862 </web-app>
--- /dev/null
+++ b/atmos.html
@@ -0,0 +1,29 @@
1+<!DOCTYPE html>
2+<html>
3+<head>
4+ <meta charset="utf-8">
5+ <title>Atmosphere Chat</title>
6+ <!-- Atmosphere -->
7+ <script type="text/javascript" src="javascript/atmosphere.js"></script>
8+ <!-- Application -->
9+ <script type="text/javascript" src="javascript/jquery-1.9.0.js"></script>
10+ <script type="text/javascript" src="javascript/application.js"></script>
11+ <style>
12+ * {font-family: tahoma; font-size: 12px; padding: 0px; margin: 0px;}
13+ p {line-height: 18px;}
14+ div {width: 500px; margin-left: auto; margin-right: auto;}
15+ #content {padding: 5px; background: #ddd; border-radius: 5px; border: 1px solid #CCC; margin-top: 10px;}
16+ #header {padding: 5px; background: #f5deb3; border-radius: 5px; border: 1px solid #CCC; margin-top: 10px;}
17+ #input {border-radius: 2px; border: 1px solid #ccc; margin-top: 10px; padding: 5px; width: 400px;}
18+ #status {width: 88px; display: block; float: left; margin-top: 15px;}
19+ </style>
20+</head>
21+<body>
22+ <div id="header"><h3>Atmosphere Chat. Default transport is WebSocket, fallback is long-polling</h3></div>
23+ <div id="content"></div>
24+ <div>
25+ <span id="status">Connecting...</span>
26+ <input type="text" id="input" disabled="disabled"/>
27+ </div>
28+</body>
29+</html>
\ No newline at end of file
--- a/build.xml
+++ b/build.xml
@@ -25,9 +25,9 @@
2525 <property name="inject" value="${env.JBOSS_HOME}\modules\javax\inject\api\main\javax.inject-1.jar"/>
2626 <property name="servlet" value="${env.JBOSS_HOME}\modules\javax\servlet\api\main\jboss-servlet-api_3.0_spec-1.0.0.Final.jar"/>
2727 <property name="cdi" value="${env.JBOSS_HOME}\modules\javax\enterprise\api\main\cdi-api-1.0-SP4.jar"/>
28- <property name="primefaces" value="${lib}\primefaces-4.0.jar"/>
29- <property name="atmosphere" value="${lib}\atmosphere-runtime-2.0.1.jar"/>
28+ <property name="atmosphere" value="${lib}\atmosphere-runtime-2.1.0.jar"/>
3029 <property name="slf4j" value="${lib}\slf4j-api-1.6.1.jar"/>
30+ <property name="jackson-jars" value="jackson-*.jar"/>
3131
3232 <target name="clean">
3333 <!-- Delete our the ${build} and ${dist} directory trees -->
@@ -55,7 +55,12 @@
5555 <pathelement path="${inject}" />
5656 <pathelement path="${servlet}" />
5757 <pathelement path="${cdi}" />
58- <pathelement path="${primefaces}" />
58+ <pathelement path="${atmosphere}" />
59+ <pathelement path="${slf4j}" />
60+
61+ <fileset dir="${lib}">
62+ <include name="${jackson-jars}"/>
63+ </fileset>
5964 </classpath>
6065 </javac>
6166 </target>
@@ -67,6 +72,8 @@
6772 <!-- include all facelets in root level, and all .properties files anywhere -->
6873
6974 <fileset dir="${faceletsrc}">
75+ <include name="javascript/*.js"/>
76+ <include name="**/*.html"/>
7077 <include name="**/*.xhtml"/>
7178 <include name="**/*.properties"/>
7279 </fileset>
--- /dev/null
+++ b/javascript/application.js
@@ -0,0 +1,124 @@
1+$(function () {
2+ "use strict";
3+
4+ var header = $('#header');
5+ var content = $('#content');
6+ var input = $('#input');
7+ var status = $('#status');
8+ var myName = false;
9+ var author = null;
10+ var logged = false;
11+ var socket = atmosphere;
12+ var subSocket;
13+ var transport = 'websocket';
14+
15+ // We are now ready to cut the request
16+ var request = { url: '/moto_web_app/chat',
17+ contentType : "application/json",
18+ logLevel : 'debug',
19+ transport : transport ,
20+ trackMessageLength : true,
21+ reconnectInterval : 5000,
22+ enableXDR: true,
23+ timeout : 60000 };
24+
25+
26+ request.onOpen = function(response) {
27+ content.html($('<p>', { text: 'Atmosphere connected using ' + response.transport }));
28+ input.removeAttr('disabled').focus();
29+ status.text('Choose name:');
30+ transport = response.transport;
31+
32+ // Carry the UUID. This is required if you want to call subscribe(request) again.
33+ request.uuid = response.request.uuid;
34+ };
35+
36+ request.onClientTimeout = function(r) {
37+ content.html($('<p>', { text: 'Client closed the connection after a timeout. Reconnecting in ' + request.reconnectInterval }));
38+ subSocket.push(atmosphere.util.stringifyJSON({ author: author, message: 'is inactive and closed the connection. Will reconnect in ' + request.reconnectInterval }));
39+ input.attr('disabled', 'disabled');
40+ setTimeout(function (){
41+ subSocket = socket.subscribe(request);
42+ }, request.reconnectInterval);
43+ };
44+
45+ request.onReopen = function(response) {
46+ input.removeAttr('disabled').focus();
47+ content.html($('<p>', { text: 'Atmosphere re-connected using ' + response.transport }));
48+ };
49+
50+ // For demonstration of how you can customize the fallbackTransport using the onTransportFailure function
51+ request.onTransportFailure = function(errorMsg, request) {
52+ atmosphere.util.info(errorMsg);
53+ request.fallbackTransport = "long-polling";
54+ header.html($('<h3>', { text: 'Atmosphere Chat. Default transport is WebSocket, fallback is ' + request.fallbackTransport }));
55+ };
56+
57+ request.onMessage = function (response) {
58+
59+ var message = response.responseBody;
60+ try {
61+ var json = atmosphere.util.parseJSON(message);
62+ } catch (e) {
63+ console.log('This doesn\'t look like a valid JSON: ', message);
64+ return;
65+ }
66+
67+ input.removeAttr('disabled').focus();
68+ if (!logged && myName) {
69+ logged = true;
70+ status.text(myName + ': ').css('color', 'blue');
71+ } else {
72+ var me = json.author == author;
73+ var date = typeof(json.time) == 'string' ? parseInt(json.time) : json.time;
74+ addMessage(json.author, json.message, me ? 'blue' : 'black', new Date(date));
75+ }
76+ };
77+
78+ request.onClose = function(response) {
79+ content.html($('<p>', { text: 'Server closed the connection after a timeout' }));
80+ if (subSocket) {
81+ subSocket.push(atmosphere.util.stringifyJSON({ author: author, message: 'disconnecting' }));
82+ }
83+ input.attr('disabled', 'disabled');
84+ };
85+
86+ request.onError = function(response) {
87+ content.html($('<p>', { text: 'Sorry, but there\'s some problem with your '
88+ + 'socket or the server is down' }));
89+ logged = false;
90+ };
91+
92+ request.onReconnect = function(request, response) {
93+ content.html($('<p>', { text: 'Connection lost, trying to reconnect. Trying to reconnect ' + request.reconnectInterval}));
94+ input.attr('disabled', 'disabled');
95+ };
96+
97+ subSocket = socket.subscribe(request);
98+
99+ input.keydown(function(e) {
100+ if (e.keyCode === 13) {
101+ var msg = $(this).val();
102+
103+ // First message is always the author's name
104+ if (author == null) {
105+ author = msg;
106+ }
107+
108+ subSocket.push(atmosphere.util.stringifyJSON({ author: author, message: msg }));
109+ $(this).val('');
110+
111+ input.attr('disabled', 'disabled');
112+ if (myName === false) {
113+ myName = msg;
114+ }
115+ }
116+ });
117+
118+ function addMessage(author, message, color, datetime) {
119+ content.append('<p><span style="color:' + color + '">' + author + '</span> @ ' +
120+ + (datetime.getHours() < 10 ? '0' + datetime.getHours() : datetime.getHours()) + ':'
121+ + (datetime.getMinutes() < 10 ? '0' + datetime.getMinutes() : datetime.getMinutes())
122+ + ': ' + message + '</p>');
123+ }
124+});
--- /dev/null
+++ b/javascript/atmosphere-min.js
@@ -0,0 +1,1017 @@
1+(function(a,b){if(typeof define==="function"&&define.amd){define(b)
2+}else{a.atmosphere=b()
3+}}(this,function(){var c="2.1.4-javascript",a={},d,g=[],f=[],e=0,b=Object.prototype.hasOwnProperty;
4+a={onError:function(h){},onClose:function(h){},onOpen:function(h){},onReopen:function(h){},onMessage:function(h){},onReconnect:function(i,h){},onMessagePublished:function(h){},onTransportFailure:function(i,h){},onLocalMessage:function(h){},onFailureToReconnect:function(i,h){},onClientTimeout:function(h){},AtmosphereRequest:function(M){var O={timeout:300000,method:"GET",headers:{},contentType:"",callback:null,url:"",data:"",suspend:true,maxRequest:-1,reconnect:true,maxStreamingLength:10000000,lastIndex:0,logLevel:"info",requestCount:0,fallbackMethod:"GET",fallbackTransport:"streaming",transport:"long-polling",webSocketImpl:null,webSocketBinaryType:null,dispatchUrl:null,webSocketPathDelimiter:"@@",enableXDR:false,rewriteURL:false,attachHeadersAsQueryString:true,executeCallbackBeforeReconnect:false,readyState:0,lastTimestamp:0,withCredentials:false,trackMessageLength:false,messageDelimiter:"|",connectTimeout:-1,reconnectInterval:0,dropHeaders:true,uuid:0,async:true,shared:false,readResponsesHeaders:false,maxReconnectOnClose:5,enableProtocol:true,onError:function(aA){},onClose:function(aA){},onOpen:function(aA){},onMessage:function(aA){},onReopen:function(aB,aA){},onReconnect:function(aB,aA){},onMessagePublished:function(aA){},onTransportFailure:function(aB,aA){},onLocalMessage:function(aA){},onFailureToReconnect:function(aB,aA){},onClientTimeout:function(aA){}};
5+var W={status:200,reasonPhrase:"OK",responseBody:"",messages:[],headers:[],state:"messageReceived",transport:"polling",error:null,request:null,partialMessage:"",errorHandled:false,closedByClientTimeout:false};
6+var Z=null;
7+var o=null;
8+var v=null;
9+var E=null;
10+var G=null;
11+var ak=true;
12+var l=0;
13+var aw=false;
14+var aa=null;
15+var aq;
16+var q=null;
17+var J=a.util.now();
18+var K;
19+var az;
20+ay(M);
21+function ar(){ak=true;
22+aw=false;
23+l=0;
24+Z=null;
25+o=null;
26+v=null;
27+E=null
28+}function A(){am();
29+ar()
30+}function L(aB,aA){if(W.partialMessage===""&&(aA.transport==="streaming")&&(aB.responseText.length>aA.maxStreamingLength)){W.messages=[];
31+ai(true);
32+D();
33+am();
34+R(aB,aA,0)
35+}}function D(){if(O.enableProtocol&&!O.firstMessage){var aC="X-Atmosphere-Transport=close&X-Atmosphere-tracking-id="+O.uuid;
36+a.util.each(O.headers,function(aE,aG){var aF=a.util.isFunction(aG)?aG.call(this,O,O,W):aG;
37+if(aF!=null){aC+="&"+encodeURIComponent(aE)+"="+encodeURIComponent(aF)
38+}});
39+var aA=O.url.replace(/([?&])_=[^&]*/,aC);
40+aA=aA+(aA===O.url?(/\?/.test(O.url)?"&":"?")+aC:"");
41+var aB={connected:false};
42+var aD=new a.AtmosphereRequest(aB);
43+aD.attachHeadersAsQueryString=false;
44+aD.dropHeaders=true;
45+aD.url=aA;
46+aD.contentType="text/plain";
47+aD.transport="polling";
48+aD.async=false;
49+n("",aD)
50+}}function an(){if(O.reconnectId){clearTimeout(O.reconnectId);
51+delete O.reconnectId
52+}O.reconnect=false;
53+aw=true;
54+W.request=O;
55+W.state="unsubscribe";
56+W.responseBody="";
57+W.status=408;
58+W.partialMessage="";
59+C();
60+D();
61+am()
62+}function am(){W.partialMessage="";
63+if(O.id){clearTimeout(O.id)
64+}if(E!=null){E.close();
65+E=null
66+}if(G!=null){G.abort();
67+G=null
68+}if(v!=null){v.abort();
69+v=null
70+}if(Z!=null){if(Z.webSocketOpened){Z.close()
71+}Z=null
72+}if(o!=null){o.close();
73+o=null
74+}at()
75+}function at(){if(aq!=null){clearInterval(K);
76+document.cookie=az+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
77+aq.signal("close",{reason:"",heir:!aw?J:(aq.get("children")||[])[0]});
78+aq.close()
79+}if(q!=null){q.close()
80+}}function ay(aA){A();
81+O=a.util.extend(O,aA);
82+O.mrequest=O.reconnect;
83+if(!O.reconnect){O.reconnect=true
84+}}function p(){return O.webSocketImpl!=null||window.WebSocket||window.MozWebSocket
85+}function S(){return window.EventSource
86+}function t(){if(O.shared){q=ah(O);
87+if(q!=null){if(O.logLevel==="debug"){a.util.debug("Storage service available. All communication will be local")
88+}if(q.open(O)){return
89+}}if(O.logLevel==="debug"){a.util.debug("No Storage service available.")
90+}q=null
91+}O.firstMessage=e==0?true:false;
92+O.isOpen=false;
93+O.ctime=a.util.now();
94+if(O.uuid===0){O.uuid=e
95+}W.closedByClientTimeout=false;
96+if(O.transport!=="websocket"&&O.transport!=="sse"){s(O)
97+}else{if(O.transport==="websocket"){if(!p()){Q("Websocket is not supported, using request.fallbackTransport ("+O.fallbackTransport+")")
98+}else{aj(false)
99+}}else{if(O.transport==="sse"){if(!S()){Q("Server Side Events(SSE) is not supported, using request.fallbackTransport ("+O.fallbackTransport+")")
100+}else{I(false)
101+}}}}}function ah(aE){var aF,aD,aI,aA="atmosphere-"+aE.url,aB={storage:function(){function aJ(aN){if(aN.key===aA&&aN.newValue){aC(aN.newValue)
102+}}if(!a.util.storage){return
103+}var aM=window.localStorage,aK=function(aN){return a.util.parseJSON(aM.getItem(aA+"-"+aN))
104+},aL=function(aN,aO){aM.setItem(aA+"-"+aN,a.util.stringifyJSON(aO))
105+};
106+return{init:function(){aL("children",aK("children").concat([J]));
107+a.util.on(window,"storage",aJ);
108+return aK("opened")
109+},signal:function(aN,aO){aM.setItem(aA,a.util.stringifyJSON({target:"p",type:aN,data:aO}))
110+},close:function(){var aN=aK("children");
111+a.util.off(window,"storage",aJ);
112+if(aN){if(aG(aN,aE.id)){aL("children",aN)
113+}}}}
114+},windowref:function(){var aJ=window.open("",aA.replace(/\W/g,""));
115+if(!aJ||aJ.closed||!aJ.callbacks){return
116+}return{init:function(){aJ.callbacks.push(aC);
117+aJ.children.push(J);
118+return aJ.opened
119+},signal:function(aK,aL){if(!aJ.closed&&aJ.fire){aJ.fire(a.util.stringifyJSON({target:"p",type:aK,data:aL}))
120+}},close:function(){if(!aI){aG(aJ.callbacks,aC);
121+aG(aJ.children,J)
122+}}}
123+}};
124+function aG(aM,aL){var aJ,aK=aM.length;
125+for(aJ=0;
126+aJ<aK;
127+aJ++){if(aM[aJ]===aL){aM.splice(aJ,1)
128+}}return aK!==aM.length
129+}function aC(aJ){var aL=a.util.parseJSON(aJ),aK=aL.data;
130+if(aL.target==="c"){switch(aL.type){case"open":N("opening","local",O);
131+break;
132+case"close":if(!aI){aI=true;
133+if(aK.reason==="aborted"){an()
134+}else{if(aK.heir===J){t()
135+}else{setTimeout(function(){t()
136+},100)
137+}}}break;
138+case"message":F(aK,"messageReceived",200,aE.transport);
139+break;
140+case"localMessage":ac(aK);
141+break
142+}}}function aH(){var aJ=new RegExp("(?:^|; )("+encodeURIComponent(aA)+")=([^;]*)").exec(document.cookie);
143+if(aJ){return a.util.parseJSON(decodeURIComponent(aJ[2]))
144+}}aF=aH();
145+if(!aF||a.util.now()-aF.ts>1000){return
146+}aD=aB.storage()||aB.windowref();
147+if(!aD){return
148+}return{open:function(){var aJ;
149+K=setInterval(function(){var aK=aF;
150+aF=aH();
151+if(!aF||aK.ts===aF.ts){aC(a.util.stringifyJSON({target:"c",type:"close",data:{reason:"error",heir:aK.heir}}))
152+}},1000);
153+aJ=aD.init();
154+if(aJ){setTimeout(function(){N("opening","local",aE)
155+},50)
156+}return aJ
157+},send:function(aJ){aD.signal("send",aJ)
158+},localSend:function(aJ){aD.signal("localSend",a.util.stringifyJSON({id:J,event:aJ}))
159+},close:function(){if(!aw){clearInterval(K);
160+aD.signal("close");
161+aD.close()
162+}}}
163+}function ad(){var aB,aA="atmosphere-"+O.url,aF={storage:function(){function aG(aI){if(aI.key===aA&&aI.newValue){aC(aI.newValue)
164+}}if(!a.util.storage){return
165+}var aH=window.localStorage;
166+return{init:function(){a.util.on(window,"storage",aG)
167+},signal:function(aI,aJ){aH.setItem(aA,a.util.stringifyJSON({target:"c",type:aI,data:aJ}))
168+},get:function(aI){return a.util.parseJSON(aH.getItem(aA+"-"+aI))
169+},set:function(aI,aJ){aH.setItem(aA+"-"+aI,a.util.stringifyJSON(aJ))
170+},close:function(){a.util.off(window,"storage",aG);
171+aH.removeItem(aA);
172+aH.removeItem(aA+"-opened");
173+aH.removeItem(aA+"-children")
174+}}
175+},windowref:function(){var aH=aA.replace(/\W/g,""),aG=document.getElementById(aH),aI;
176+if(!aG){aG=document.createElement("div");
177+aG.id=aH;
178+aG.style.display="none";
179+aG.innerHTML='<iframe name="'+aH+'" />';
180+document.body.appendChild(aG)
181+}aI=aG.firstChild.contentWindow;
182+return{init:function(){aI.callbacks=[aC];
183+aI.fire=function(aJ){var aK;
184+for(aK=0;
185+aK<aI.callbacks.length;
186+aK++){aI.callbacks[aK](aJ)
187+}}
188+},signal:function(aJ,aK){if(!aI.closed&&aI.fire){aI.fire(a.util.stringifyJSON({target:"c",type:aJ,data:aK}))
189+}},get:function(aJ){return !aI.closed?aI[aJ]:null
190+},set:function(aJ,aK){if(!aI.closed){aI[aJ]=aK
191+}},close:function(){}}
192+}};
193+function aC(aG){var aI=a.util.parseJSON(aG),aH=aI.data;
194+if(aI.target==="p"){switch(aI.type){case"send":al(aH);
195+break;
196+case"localSend":ac(aH);
197+break;
198+case"close":an();
199+break
200+}}}aa=function aE(aG){aB.signal("message",aG)
201+};
202+function aD(){document.cookie=az+"="+encodeURIComponent(a.util.stringifyJSON({ts:a.util.now()+1,heir:(aB.get("children")||[])[0]}))+"; path=/"
203+}aB=aF.storage()||aF.windowref();
204+aB.init();
205+if(O.logLevel==="debug"){a.util.debug("Installed StorageService "+aB)
206+}aB.set("children",[]);
207+if(aB.get("opened")!=null&&!aB.get("opened")){aB.set("opened",false)
208+}az=encodeURIComponent(aA);
209+aD();
210+K=setInterval(aD,1000);
211+aq=aB
212+}function N(aC,aF,aB){if(O.shared&&aF!=="local"){ad()
213+}if(aq!=null){aq.set("opened",true)
214+}aB.close=function(){an()
215+};
216+if(l>0&&aC==="re-connecting"){aB.isReopen=true;
217+ae(W)
218+}else{if(W.error==null){W.request=aB;
219+var aD=W.state;
220+W.state=aC;
221+var aA=W.transport;
222+W.transport=aF;
223+var aE=W.responseBody;
224+C();
225+W.responseBody=aE;
226+W.state=aD;
227+W.transport=aA
228+}}}function z(aC){aC.transport="jsonp";
229+var aB=O,aA;
230+if((aC!=null)&&(typeof(aC)!=="undefined")){aB=aC
231+}G={open:function(){var aE="atmosphere"+(++J);
232+function aD(){var aF=aB.url;
233+if(aB.dispatchUrl!=null){aF+=aB.dispatchUrl
234+}var aH=aB.data;
235+if(aB.attachHeadersAsQueryString){aF=X(aB);
236+if(aH!==""){aF+="&X-Atmosphere-Post-Body="+encodeURIComponent(aH)
237+}aH=""
238+}var aG=document.head||document.getElementsByTagName("head")[0]||document.documentElement;
239+aA=document.createElement("script");
240+aA.src=aF+"&jsonpTransport="+aE;
241+aA.clean=function(){aA.clean=aA.onerror=aA.onload=aA.onreadystatechange=null;
242+if(aA.parentNode){aA.parentNode.removeChild(aA)
243+}};
244+aA.onload=aA.onreadystatechange=function(){if(!aA.readyState||/loaded|complete/.test(aA.readyState)){aA.clean()
245+}};
246+aA.onerror=function(){aA.clean();
247+aB.lastIndex=0;
248+if(aB.openId){clearTimeout(aB.openId)
249+}if(aB.reconnect&&l++<aB.maxReconnectOnClose){N("re-connecting",aB.transport,aB);
250+R(G,aB,aC.reconnectInterval);
251+aB.openId=setTimeout(function(){ao(aB)
252+},aB.reconnectInterval+1000)
253+}else{af(0,"maxReconnectOnClose reached")
254+}};
255+aG.insertBefore(aA,aG.firstChild)
256+}window[aE]=function(aH){if(aB.reconnect){if(aB.maxRequest===-1||aB.requestCount++<aB.maxRequest){if(!aB.executeCallbackBeforeReconnect){R(G,aB,0)
257+}if(aH!=null&&typeof aH!=="string"){try{aH=aH.message
258+}catch(aG){}}var aF=x(aH,aB,W);
259+if(!aF){F(W.responseBody,"messageReceived",200,aB.transport)
260+}if(aB.executeCallbackBeforeReconnect){R(G,aB,0)
261+}}else{a.util.log(O.logLevel,["JSONP reconnect maximum try reached "+O.requestCount]);
262+af(0,"maxRequest reached")
263+}}};
264+setTimeout(function(){aD()
265+},50)
266+},abort:function(){if(aA.clean){aA.clean()
267+}}};
268+G.open()
269+}function j(aA){if(O.webSocketImpl!=null){return O.webSocketImpl
270+}else{if(window.WebSocket){return new WebSocket(aA)
271+}else{return new MozWebSocket(aA)
272+}}}function k(){return a.util.getAbsoluteURL(X(O)).replace(/^http/,"ws")
273+}function ax(){var aA=X(O);
274+return aA
275+}function I(aB){W.transport="sse";
276+var aA=ax();
277+if(O.logLevel==="debug"){a.util.debug("Invoking executeSSE");
278+a.util.debug("Using URL: "+aA)
279+}if(O.enableProtocol&&aB){var aD=a.util.now()-O.ctime;
280+O.lastTimestamp=Number(O.stime)+Number(aD)
281+}if(aB&&!O.reconnect){if(o!=null){am()
282+}return
283+}try{o=new EventSource(aA,{withCredentials:O.withCredentials})
284+}catch(aC){af(0,aC);
285+Q("SSE failed. Downgrading to fallback transport and resending");
286+return
287+}if(O.connectTimeout>0){O.id=setTimeout(function(){if(!aB){am()
288+}},O.connectTimeout)
289+}o.onopen=function(aE){y(O);
290+if(O.logLevel==="debug"){a.util.debug("SSE successfully opened")
291+}if(!O.enableProtocol){if(!aB){N("opening","sse",O)
292+}else{N("re-opening","sse",O)
293+}}else{if(O.isReopen){O.isReopen=false;
294+N("re-opening",O.transport,O)
295+}}aB=true;
296+if(O.method==="POST"){W.state="messageReceived";
297+o.send(O.data)
298+}};
299+o.onmessage=function(aF){y(O);
300+if(!O.enableXDR&&aF.origin&&aF.origin!==window.location.protocol+"//"+window.location.host){a.util.log(O.logLevel,["Origin was not "+window.location.protocol+"//"+window.location.host]);
301+return
302+}W.state="messageReceived";
303+W.status=200;
304+aF=aF.data;
305+var aE=x(aF,O,W);
306+if(!aE){C();
307+W.responseBody="";
308+W.messages=[]
309+}};
310+o.onerror=function(aE){clearTimeout(O.id);
311+if(W.closedByClientTimeout){return
312+}ai(aB);
313+am();
314+if(aw){a.util.log(O.logLevel,["SSE closed normally"])
315+}else{if(!aB){Q("SSE failed. Downgrading to fallback transport and resending")
316+}else{if(O.reconnect&&(W.transport==="sse")){if(l++<O.maxReconnectOnClose){N("re-connecting",O.transport,O);
317+if(O.reconnectInterval>0){O.reconnectId=setTimeout(function(){I(true)
318+},O.reconnectInterval)
319+}else{I(true)
320+}W.responseBody="";
321+W.messages=[]
322+}else{a.util.log(O.logLevel,["SSE reconnect maximum try reached "+l]);
323+af(0,"maxReconnectOnClose reached")
324+}}}}}
325+}function aj(aB){W.transport="websocket";
326+if(O.enableProtocol&&aB){var aC=a.util.now()-O.ctime;
327+O.lastTimestamp=Number(O.stime)+Number(aC)
328+}var aA=k(O.url);
329+if(O.logLevel==="debug"){a.util.debug("Invoking executeWebSocket");
330+a.util.debug("Using URL: "+aA)
331+}if(aB&&!O.reconnect){if(Z!=null){am()
332+}return
333+}Z=j(aA);
334+if(O.webSocketBinaryType!=null){Z.binaryType=O.webSocketBinaryType
335+}if(O.connectTimeout>0){O.id=setTimeout(function(){if(!aB){var aD={code:1002,reason:"",wasClean:false};
336+Z.onclose(aD);
337+try{am()
338+}catch(aE){}return
339+}},O.connectTimeout)
340+}Z.onopen=function(aE){y(O);
341+if(O.logLevel==="debug"){a.util.debug("Websocket successfully opened")
342+}var aD=aB;
343+aB=true;
344+if(Z!=null){Z.webSocketOpened=aB
345+}if(!O.enableProtocol){if(aD){N("re-opening","websocket",O)
346+}else{N("opening","websocket",O)
347+}}if(Z!=null){if(O.method==="POST"){W.state="messageReceived";
348+Z.send(O.data)
349+}}};
350+Z.onmessage=function(aF){y(O);
351+W.state="messageReceived";
352+W.status=200;
353+aF=aF.data;
354+var aD=typeof(aF)==="string";
355+if(aD){var aE=x(aF,O,W);
356+if(!aE){C();
357+W.responseBody="";
358+W.messages=[]
359+}}else{if(!u(O,aF)){return
360+}W.responseBody=aF;
361+C();
362+W.responseBody=null
363+}};
364+Z.onerror=function(aD){clearTimeout(O.id)
365+};
366+Z.onclose=function(aD){clearTimeout(O.id);
367+if(W.state==="closed"){return
368+}var aE=aD.reason;
369+if(aE===""){switch(aD.code){case 1000:aE="Normal closure; the connection successfully completed whatever purpose for which it was created.";
370+break;
371+case 1001:aE="The endpoint is going away, either because of a server failure or because the browser is navigating away from the page that opened the connection.";
372+break;
373+case 1002:aE="The endpoint is terminating the connection due to a protocol error.";
374+break;
375+case 1003:aE="The connection is being terminated because the endpoint received data of a type it cannot accept (for example, a text-only endpoint received binary data).";
376+break;
377+case 1004:aE="The endpoint is terminating the connection because a data frame was received that is too large.";
378+break;
379+case 1005:aE="Unknown: no status code was provided even though one was expected.";
380+break;
381+case 1006:aE="Connection was closed abnormally (that is, with no close frame being sent).";
382+break
383+}}if(O.logLevel==="warn"){a.util.warn("Websocket closed, reason: "+aE);
384+a.util.warn("Websocket closed, wasClean: "+aD.wasClean)
385+}if(W.closedByClientTimeout){return
386+}ai(aB);
387+W.state="closed";
388+if(aw){a.util.log(O.logLevel,["Websocket closed normally"])
389+}else{if(!aB){Q("Websocket failed. Downgrading to Comet and resending")
390+}else{if(O.reconnect&&W.transport==="websocket"){am();
391+if(l++<O.maxReconnectOnClose){N("re-connecting",O.transport,O);
392+if(O.reconnectInterval>0){O.reconnectId=setTimeout(function(){W.responseBody="";
393+W.messages=[];
394+aj(true)
395+},O.reconnectInterval)
396+}else{W.responseBody="";
397+W.messages=[];
398+aj(true)
399+}}else{a.util.log(O.logLevel,["Websocket reconnect maximum try reached "+O.requestCount]);
400+if(O.logLevel==="warn"){a.util.warn("Websocket error, reason: "+aD.reason)
401+}af(0,"maxReconnectOnClose reached")
402+}}}}};
403+if(Z.url===undefined){Z.onclose({reason:"Android 4.1 does not support websockets.",wasClean:false})
404+}}function u(aD,aC){var aA=true;
405+if(aD.transport==="polling"){return aA
406+}if(a.util.trim(aC).length!==0&&aD.enableProtocol&&aD.firstMessage){aD.firstMessage=false;
407+var aB=aC.split(aD.messageDelimiter);
408+var aE=aB.length===2?0:1;
409+aD.uuid=a.util.trim(aB[aE]);
410+aD.stime=a.util.trim(aB[aE+1]);
411+aA=false;
412+if(aD.transport!=="long-polling"){ao(aD)
413+}e=aD.uuid
414+}else{if(aD.enableProtocol&&aD.firstMessage){aA=false
415+}else{ao(aD)
416+}}return aA
417+}function y(aA){clearTimeout(aA.id);
418+if(aA.timeout>0&&aA.transport!=="polling"){aA.id=setTimeout(function(){r(aA);
419+D();
420+am()
421+},aA.timeout)
422+}}function r(aA){W.closedByClientTimeout=true;
423+W.state="closedByClient";
424+W.responseBody="";
425+W.status=408;
426+W.messages=[];
427+C()
428+}function af(aA,aB){am();
429+clearTimeout(O.id);
430+W.state="error";
431+W.reasonPhrase=aB;
432+W.responseBody="";
433+W.status=aA;
434+W.messages=[];
435+C()
436+}function x(aE,aD,aA){if(!u(aD,aE)){return true
437+}if(aE.length===0){return true
438+}if(aD.trackMessageLength){aE=aA.partialMessage+aE;
439+var aC=[];
440+var aB=aE.indexOf(aD.messageDelimiter);
441+while(aB!==-1){var aG=a.util.trim(aE.substring(0,aB));
442+var aF=+aG;
443+if(isNaN(aF)){throw new Error('message length "'+aG+'" is not a number')
444+}aB+=aD.messageDelimiter.length;
445+if(aB+aF>aE.length){aB=-1
446+}else{aC.push(aE.substring(aB,aB+aF));
447+aE=aE.substring(aB+aF,aE.length);
448+aB=aE.indexOf(aD.messageDelimiter)
449+}}aA.partialMessage=aE;
450+if(aC.length!==0){aA.responseBody=aC.join(aD.messageDelimiter);
451+aA.messages=aC;
452+return false
453+}else{aA.responseBody="";
454+aA.messages=[];
455+return true
456+}}else{aA.responseBody=aE
457+}return false
458+}function Q(aA){a.util.log(O.logLevel,[aA]);
459+if(typeof(O.onTransportFailure)!=="undefined"){O.onTransportFailure(aA,O)
460+}else{if(typeof(a.util.onTransportFailure)!=="undefined"){a.util.onTransportFailure(aA,O)
461+}}O.transport=O.fallbackTransport;
462+var aB=O.connectTimeout===-1?0:O.connectTimeout;
463+if(O.reconnect&&O.transport!=="none"||O.transport==null){O.method=O.fallbackMethod;
464+W.transport=O.fallbackTransport;
465+O.fallbackTransport="none";
466+if(aB>0){O.reconnectId=setTimeout(function(){t()
467+},aB)
468+}else{t()
469+}}else{af(500,"Unable to reconnect with fallback transport")
470+}}function X(aC,aA){var aB=O;
471+if((aC!=null)&&(typeof(aC)!=="undefined")){aB=aC
472+}if(aA==null){aA=aB.url
473+}if(!aB.attachHeadersAsQueryString){return aA
474+}if(aA.indexOf("X-Atmosphere-Framework")!==-1){return aA
475+}aA+=(aA.indexOf("?")!==-1)?"&":"?";
476+aA+="X-Atmosphere-tracking-id="+aB.uuid;
477+aA+="&X-Atmosphere-Framework="+c;
478+aA+="&X-Atmosphere-Transport="+aB.transport;
479+if(aB.trackMessageLength){aA+="&X-Atmosphere-TrackMessageSize=true"
480+}if(aB.lastTimestamp!=null){aA+="&X-Cache-Date="+aB.lastTimestamp
481+}else{aA+="&X-Cache-Date="+0
482+}if(aB.contentType!==""){aA+="&Content-Type="+(aB.transport==="websocket"?aB.contentType:encodeURIComponent(aB.contentType))
483+}if(aB.enableProtocol){aA+="&X-atmo-protocol=true"
484+}a.util.each(aB.headers,function(aD,aF){var aE=a.util.isFunction(aF)?aF.call(this,aB,aC,W):aF;
485+if(aE!=null){aA+="&"+encodeURIComponent(aD)+"="+encodeURIComponent(aE)
486+}});
487+return aA
488+}function ao(aA){if(!aA.isOpen){aA.isOpen=true;
489+N("opening",aA.transport,aA)
490+}else{if(aA.isReopen){aA.isReopen=false;
491+N("re-opening",aA.transport,aA)
492+}}}function s(aC){var aA=O;
493+if((aC!=null)||(typeof(aC)!=="undefined")){aA=aC
494+}aA.lastIndex=0;
495+aA.readyState=0;
496+if((aA.transport==="jsonp")||((aA.enableXDR)&&(a.util.checkCORSSupport()))){z(aA);
497+return
498+}if(a.util.browser.msie&&+a.util.browser.version.split(".")[0]<10){if((aA.transport==="streaming")){if(aA.enableXDR&&window.XDomainRequest){P(aA)
499+}else{av(aA)
500+}return
501+}if((aA.enableXDR)&&(window.XDomainRequest)){P(aA);
502+return
503+}}var aD=function(){aA.lastIndex=0;
504+if(aA.reconnect&&l++<aA.maxReconnectOnClose){N("re-connecting",aC.transport,aC);
505+R(aB,aA,aC.reconnectInterval)
506+}else{af(0,"maxReconnectOnClose reached")
507+}};
508+if(aA.force||(aA.reconnect&&(aA.maxRequest===-1||aA.requestCount++<aA.maxRequest))){aA.force=false;
509+var aB=a.util.xhr();
510+aB.hasData=false;
511+h(aB,aA,true);
512+if(aA.suspend){v=aB
513+}if(aA.transport!=="polling"){W.transport=aA.transport;
514+aB.onabort=function(){ai(true)
515+};
516+aB.onerror=function(){W.error=true;
517+try{W.status=XMLHttpRequest.status
518+}catch(aF){W.status=500
519+}if(!W.status){W.status=500
520+}if(!W.errorHandled){am();
521+aD()
522+}}
523+}aB.onreadystatechange=function(){if(aw){return
524+}W.error=null;
525+var aG=false;
526+var aL=false;
527+if(aA.transport==="streaming"&&aA.readyState>2&&aB.readyState===4){am();
528+aD();
529+return
530+}aA.readyState=aB.readyState;
531+if(aA.transport==="streaming"&&aB.readyState>=3){aL=true
532+}else{if(aA.transport==="long-polling"&&aB.readyState===4){aL=true
533+}}y(O);
534+if(aA.transport!=="polling"){var aF=200;
535+if(aB.readyState===4){aF=aB.status>1000?0:aB.status
536+}if(aF>=300||aF===0){W.errorHandled=true;
537+am();
538+aD();
539+return
540+}if((!aA.enableProtocol||!aC.firstMessage)&&aB.readyState===2){ao(aA)
541+}}else{if(aB.readyState===4){aL=true
542+}}if(aL){var aJ=aB.responseText;
543+if(a.util.trim(aJ).length===0&&aA.transport==="long-polling"){if(!aB.hasData){R(aB,aA,0)
544+}else{aB.hasData=false
545+}return
546+}aB.hasData=true;
547+ag(aB,O);
548+if(aA.transport==="streaming"){if(!a.util.browser.opera){var aI=aJ.substring(aA.lastIndex,aJ.length);
549+aG=x(aI,aA,W);
550+aA.lastIndex=aJ.length;
551+if(aG){return
552+}}else{a.util.iterate(function(){if(W.status!==500&&aB.responseText.length>aA.lastIndex){try{W.status=aB.status;
553+W.headers=a.util.parseHeaders(aB.getAllResponseHeaders());
554+ag(aB,O)
555+}catch(aN){W.status=404
556+}y(O);
557+W.state="messageReceived";
558+var aM=aB.responseText.substring(aA.lastIndex);
559+aA.lastIndex=aB.responseText.length;
560+aG=x(aM,aA,W);
561+if(!aG){C()
562+}L(aB,aA)
563+}else{if(W.status>400){aA.lastIndex=aB.responseText.length;
564+return false
565+}}},0)
566+}}else{aG=x(aJ,aA,W)
567+}try{W.status=aB.status;
568+W.headers=a.util.parseHeaders(aB.getAllResponseHeaders());
569+ag(aB,aA)
570+}catch(aK){W.status=404
571+}if(aA.suspend){W.state=W.status===0?"closed":"messageReceived"
572+}else{W.state="messagePublished"
573+}var aH=aC.transport!=="streaming"&&aC.transport!=="polling";
574+if(aH&&!aA.executeCallbackBeforeReconnect){R(aB,aA,0)
575+}if(W.responseBody.length!==0&&!aG){C()
576+}if(aH&&aA.executeCallbackBeforeReconnect){R(aB,aA,0)
577+}L(aB,aA)
578+}};
579+try{aB.send(aA.data);
580+ak=true
581+}catch(aE){a.util.log(aA.logLevel,["Unable to connect to "+aA.url])
582+}}else{if(aA.logLevel==="debug"){a.util.log(aA.logLevel,["Max re-connection reached."])
583+}af(0,"maxRequest reached")
584+}}function h(aC,aD,aB){var aA=aD.url;
585+if(aD.dispatchUrl!=null&&aD.method==="POST"){aA+=aD.dispatchUrl
586+}aA=X(aD,aA);
587+aA=a.util.prepareURL(aA);
588+if(aB){aC.open(aD.method,aA,aD.async);
589+if(aD.connectTimeout>0){aD.id=setTimeout(function(){if(aD.requestCount===0){am();
590+F("Connect timeout","closed",200,aD.transport)
591+}},aD.connectTimeout)
592+}}if(O.withCredentials){if("withCredentials" in aC){aC.withCredentials=true
593+}}if(!O.dropHeaders){aC.setRequestHeader("X-Atmosphere-Framework",a.util.version);
594+aC.setRequestHeader("X-Atmosphere-Transport",aD.transport);
595+if(aD.lastTimestamp!=null){aC.setRequestHeader("X-Cache-Date",aD.lastTimestamp)
596+}else{aC.setRequestHeader("X-Cache-Date",0)
597+}if(aD.trackMessageLength){aC.setRequestHeader("X-Atmosphere-TrackMessageSize","true")
598+}aC.setRequestHeader("X-Atmosphere-tracking-id",aD.uuid);
599+a.util.each(aD.headers,function(aE,aG){var aF=a.util.isFunction(aG)?aG.call(this,aC,aD,aB,W):aG;
600+if(aF!=null){aC.setRequestHeader(aE,aF)
601+}})
602+}if(aD.contentType!==""){aC.setRequestHeader("Content-Type",aD.contentType)
603+}}function R(aB,aC,aD){if(aC.reconnect||(aC.suspend&&ak)){var aA=0;
604+if(aB&&aB.readyState>1){aA=aB.status>1000?0:aB.status
605+}W.status=aA===0?204:aA;
606+W.reason=aA===0?"Server resumed the connection or down.":"OK";
607+clearTimeout(aC.id);
608+if(aC.reconnectId){clearTimeout(aC.reconnectId);
609+delete aC.reconnectId
610+}if(aD>0){O.reconnectId=setTimeout(function(){s(aC)
611+},aD)
612+}else{s(aC)
613+}}}function ae(aA){aA.state="re-connecting";
614+ab(aA)
615+}function P(aA){if(aA.transport!=="polling"){E=V(aA);
616+E.open()
617+}else{V(aA).open()
618+}}function V(aC){var aB=O;
619+if((aC!=null)&&(typeof(aC)!=="undefined")){aB=aC
620+}var aH=aB.transport;
621+var aG=0;
622+var aA=new window.XDomainRequest();
623+var aE=function(){if(aB.transport==="long-polling"&&(aB.reconnect&&(aB.maxRequest===-1||aB.requestCount++<aB.maxRequest))){aA.status=200;
624+P(aB)
625+}};
626+var aF=aB.rewriteURL||function(aJ){var aI=/(?:^|;\s*)(JSESSIONID|PHPSESSID)=([^;]*)/.exec(document.cookie);
627+switch(aI&&aI[1]){case"JSESSIONID":return aJ.replace(/;jsessionid=[^\?]*|(\?)|$/,";jsessionid="+aI[2]+"$1");
628+case"PHPSESSID":return aJ.replace(/\?PHPSESSID=[^&]*&?|\?|$/,"?PHPSESSID="+aI[2]+"&").replace(/&$/,"")
629+}return aJ
630+};
631+aA.onprogress=function(){aD(aA)
632+};
633+aA.onerror=function(){if(aB.transport!=="polling"){am();
634+if(l++<aB.maxReconnectOnClose){if(aB.reconnectInterval>0){aB.reconnectId=setTimeout(function(){N("re-connecting",aC.transport,aC);
635+P(aB)
636+},aB.reconnectInterval)
637+}else{N("re-connecting",aC.transport,aC);
638+P(aB)
639+}}else{af(0,"maxReconnectOnClose reached")
640+}}};
641+aA.onload=function(){};
642+var aD=function(aI){clearTimeout(aB.id);
643+var aK=aI.responseText;
644+aK=aK.substring(aG);
645+aG+=aK.length;
646+if(aH!=="polling"){y(aB);
647+var aJ=x(aK,aB,W);
648+if(aH==="long-polling"&&a.util.trim(aK).length===0){return
649+}if(aB.executeCallbackBeforeReconnect){aE()
650+}if(!aJ){F(W.responseBody,"messageReceived",200,aH)
651+}if(!aB.executeCallbackBeforeReconnect){aE()
652+}}};
653+return{open:function(){var aI=aB.url;
654+if(aB.dispatchUrl!=null){aI+=aB.dispatchUrl
655+}aI=X(aB,aI);
656+aA.open(aB.method,aF(aI));
657+if(aB.method==="GET"){aA.send()
658+}else{aA.send(aB.data)
659+}if(aB.connectTimeout>0){aB.id=setTimeout(function(){if(aB.requestCount===0){am();
660+F("Connect timeout","closed",200,aB.transport)
661+}},aB.connectTimeout)
662+}},close:function(){aA.abort()
663+}}
664+}function av(aA){E=w(aA);
665+E.open()
666+}function w(aD){var aC=O;
667+if((aD!=null)&&(typeof(aD)!=="undefined")){aC=aD
668+}var aB;
669+var aE=new window.ActiveXObject("htmlfile");
670+aE.open();
671+aE.close();
672+var aA=aC.url;
673+if(aC.dispatchUrl!=null){aA+=aC.dispatchUrl
674+}if(aC.transport!=="polling"){W.transport=aC.transport
675+}return{open:function(){var aF=aE.createElement("iframe");
676+aA=X(aC);
677+if(aC.data!==""){aA+="&X-Atmosphere-Post-Body="+encodeURIComponent(aC.data)
678+}aA=a.util.prepareURL(aA);
679+aF.src=aA;
680+aE.body.appendChild(aF);
681+var aG=aF.contentDocument||aF.contentWindow.document;
682+aB=a.util.iterate(function(){try{if(!aG.firstChild){return
683+}var aJ=aG.body?aG.body.lastChild:aG;
684+var aL=function(){var aN=aJ.cloneNode(true);
685+aN.appendChild(aG.createTextNode("."));
686+var aM=aN.innerText;
687+aM=aM.substring(0,aM.length-1);
688+return aM
689+};
690+if(!aG.body||!aG.body.firstChild||aG.body.firstChild.nodeName.toLowerCase()!=="pre"){var aI=aG.head||aG.getElementsByTagName("head")[0]||aG.documentElement||aG;
691+var aH=aG.createElement("script");
692+aH.text="document.write('<plaintext>')";
693+aI.insertBefore(aH,aI.firstChild);
694+aI.removeChild(aH);
695+aJ=aG.body.lastChild
696+}if(aC.closed){aC.isReopen=true
697+}aB=a.util.iterate(function(){var aN=aL();
698+if(aN.length>aC.lastIndex){y(O);
699+W.status=200;
700+W.error=null;
701+aJ.innerText="";
702+var aM=x(aN,aC,W);
703+if(aM){return""
704+}F(W.responseBody,"messageReceived",200,aC.transport)
705+}aC.lastIndex=0;
706+if(aG.readyState==="complete"){ai(true);
707+N("re-connecting",aC.transport,aC);
708+if(aC.reconnectInterval>0){aC.reconnectId=setTimeout(function(){av(aC)
709+},aC.reconnectInterval)
710+}else{av(aC)
711+}return false
712+}},null);
713+return false
714+}catch(aK){W.error=true;
715+N("re-connecting",aC.transport,aC);
716+if(l++<aC.maxReconnectOnClose){if(aC.reconnectInterval>0){aC.reconnectId=setTimeout(function(){av(aC)
717+},aC.reconnectInterval)
718+}else{av(aC)
719+}}else{af(0,"maxReconnectOnClose reached")
720+}aE.execCommand("Stop");
721+aE.close();
722+return false
723+}})
724+},close:function(){if(aB){aB()
725+}aE.execCommand("Stop");
726+ai(true)
727+}}
728+}function al(aA){if(q!=null){m(aA)
729+}else{if(v!=null||o!=null){i(aA)
730+}else{if(E!=null){Y(aA)
731+}else{if(G!=null){U(aA)
732+}else{if(Z!=null){H(aA)
733+}else{af(0,"No suspended connection available");
734+a.util.error("No suspended connection available. Make sure atmosphere.subscribe has been called and request.onOpen invoked before invoking this method")
735+}}}}}}function n(aB,aA){if(!aA){aA=ap(aB)
736+}aA.transport="polling";
737+aA.method="GET";
738+aA.async=false;
739+aA.withCredentials=false;
740+aA.reconnect=false;
741+aA.force=true;
742+aA.suspend=false;
743+aA.timeout=1000;
744+s(aA)
745+}function m(aA){q.send(aA)
746+}function B(aB){if(aB.length===0){return
747+}try{if(q){q.localSend(aB)
748+}else{if(aq){aq.signal("localMessage",a.util.stringifyJSON({id:J,event:aB}))
749+}}}catch(aA){a.util.error(aA)
750+}}function i(aB){var aA=ap(aB);
751+s(aA)
752+}function Y(aB){if(O.enableXDR&&a.util.checkCORSSupport()){var aA=ap(aB);
753+aA.reconnect=false;
754+z(aA)
755+}else{i(aB)
756+}}function U(aA){i(aA)
757+}function T(aA){var aB=aA;
758+if(typeof(aB)==="object"){aB=aA.data
759+}return aB
760+}function ap(aB){var aC=T(aB);
761+var aA={connected:false,timeout:60000,method:"POST",url:O.url,contentType:O.contentType,headers:O.headers,reconnect:true,callback:null,data:aC,suspend:false,maxRequest:-1,logLevel:"info",requestCount:0,withCredentials:O.withCredentials,async:O.async,transport:"polling",isOpen:true,attachHeadersAsQueryString:true,enableXDR:O.enableXDR,uuid:O.uuid,dispatchUrl:O.dispatchUrl,enableProtocol:false,messageDelimiter:"|",maxReconnectOnClose:O.maxReconnectOnClose};
762+if(typeof(aB)==="object"){aA=a.util.extend(aA,aB)
763+}return aA
764+}function H(aA){var aD=a.util.isBinary(aA)?aA:T(aA);
765+var aB;
766+try{if(O.dispatchUrl!=null){aB=O.webSocketPathDelimiter+O.dispatchUrl+O.webSocketPathDelimiter+aD
767+}else{aB=aD
768+}if(!Z.webSocketOpened){a.util.error("WebSocket not connected.");
769+return
770+}Z.send(aB)
771+}catch(aC){Z.onclose=function(aE){};
772+am();
773+Q("Websocket failed. Downgrading to Comet and resending "+aA);
774+i(aA)
775+}}function ac(aB){var aA=a.util.parseJSON(aB);
776+if(aA.id!==J){if(typeof(O.onLocalMessage)!=="undefined"){O.onLocalMessage(aA.event)
777+}else{if(typeof(a.util.onLocalMessage)!=="undefined"){a.util.onLocalMessage(aA.event)
778+}}}}function F(aD,aA,aB,aC){W.responseBody=aD;
779+W.transport=aC;
780+W.status=aB;
781+W.state=aA;
782+C()
783+}function ag(aA,aD){if(!aD.readResponsesHeaders){if(!aD.enableProtocol){aD.lastTimestamp=a.util.now();
784+aD.uuid=J
785+}}else{try{var aC=aA.getResponseHeader("X-Cache-Date");
786+if(aC&&aC!=null&&aC.length>0){aD.lastTimestamp=aC.split(" ").pop()
787+}var aB=aA.getResponseHeader("X-Atmosphere-tracking-id");
788+if(aB&&aB!=null){aD.uuid=aB.split(" ").pop()
789+}}catch(aE){}}}function ab(aA){au(aA,O);
790+au(aA,a.util)
791+}function au(aB,aC){switch(aB.state){case"messageReceived":l=0;
792+if(typeof(aC.onMessage)!=="undefined"){aC.onMessage(aB)
793+}break;
794+case"error":if(typeof(aC.onError)!=="undefined"){aC.onError(aB)
795+}break;
796+case"opening":delete O.closed;
797+if(typeof(aC.onOpen)!=="undefined"){aC.onOpen(aB)
798+}break;
799+case"messagePublished":if(typeof(aC.onMessagePublished)!=="undefined"){aC.onMessagePublished(aB)
800+}break;
801+case"re-connecting":if(typeof(aC.onReconnect)!=="undefined"){aC.onReconnect(O,aB)
802+}break;
803+case"closedByClient":if(typeof(aC.onClientTimeout)!=="undefined"){aC.onClientTimeout(O)
804+}break;
805+case"re-opening":delete O.closed;
806+if(typeof(aC.onReopen)!=="undefined"){aC.onReopen(O,aB)
807+}break;
808+case"fail-to-reconnect":if(typeof(aC.onFailureToReconnect)!=="undefined"){aC.onFailureToReconnect(O,aB)
809+}break;
810+case"unsubscribe":case"closed":var aA=typeof(O.closed)!=="undefined"?O.closed:false;
811+if(typeof(aC.onClose)!=="undefined"&&!aA){aC.onClose(aB)
812+}O.closed=true;
813+break
814+}}function ai(aA){if(W.state!=="closed"){W.state="closed";
815+W.responseBody="";
816+W.messages=[];
817+W.status=!aA?501:200;
818+C()
819+}}function C(){var aC=function(aF,aG){aG(W)
820+};
821+if(q==null&&aa!=null){aa(W.responseBody)
822+}O.reconnect=O.mrequest;
823+var aA=typeof(W.responseBody)==="string";
824+var aD=(aA&&O.trackMessageLength)?(W.messages.length>0?W.messages:[""]):new Array(W.responseBody);
825+for(var aB=0;
826+aB<aD.length;
827+aB++){if(aD.length>1&&aD[aB].length===0){continue
828+}W.responseBody=(aA)?a.util.trim(aD[aB]):aD[aB];
829+if(q==null&&aa!=null){aa(W.responseBody)
830+}if(W.responseBody.length===0&&W.state==="messageReceived"){continue
831+}ab(W);
832+if(f.length>0){if(O.logLevel==="debug"){a.util.debug("Invoking "+f.length+" global callbacks: "+W.state)
833+}try{a.util.each(f,aC)
834+}catch(aE){a.util.log(O.logLevel,["Callback exception"+aE])
835+}}if(typeof(O.callback)==="function"){if(O.logLevel==="debug"){a.util.debug("Invoking request callbacks")
836+}try{O.callback(W)
837+}catch(aE){a.util.log(O.logLevel,["Callback exception"+aE])
838+}}}}this.subscribe=function(aA){ay(aA);
839+t()
840+};
841+this.execute=function(){t()
842+};
843+this.close=function(){an()
844+};
845+this.disconnect=function(){D()
846+};
847+this.getUrl=function(){return O.url
848+};
849+this.push=function(aC,aB){if(aB!=null){var aA=O.dispatchUrl;
850+O.dispatchUrl=aB;
851+al(aC);
852+O.dispatchUrl=aA
853+}else{al(aC)
854+}};
855+this.getUUID=function(){return O.uuid
856+};
857+this.pushLocal=function(aA){B(aA)
858+};
859+this.enableProtocol=function(aA){return O.enableProtocol
860+};
861+this.request=O;
862+this.response=W
863+}};
864+a.subscribe=function(h,k,j){if(typeof(k)==="function"){a.addCallback(k)
865+}e=0;
866+if(typeof(h)!=="string"){j=h
867+}else{j.url=h
868+}var i=new a.AtmosphereRequest(j);
869+i.execute();
870+g[g.length]=i;
871+return i
872+};
873+a.unsubscribe=function(){if(g.length>0){var h=[].concat(g);
874+for(var k=0;
875+k<h.length;
876+k++){var j=h[k];
877+j.close();
878+clearTimeout(j.response.request.id)
879+}}g=[];
880+f=[]
881+};
882+a.unsubscribeUrl=function(j){var h=-1;
883+if(g.length>0){for(var l=0;
884+l<g.length;
885+l++){var k=g[l];
886+if(k.getUrl()===j){k.close();
887+clearTimeout(k.response.request.id);
888+h=l;
889+break
890+}}}if(h>=0){g.splice(h,1)
891+}};
892+a.addCallback=function(h){if(a.util.inArray(h,f)===-1){f.push(h)
893+}};
894+a.removeCallback=function(i){var h=a.util.inArray(i,f);
895+if(h!==-1){f.splice(h,1)
896+}};
897+a.util={browser:{},parseHeaders:function(i){var h,k=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,j={};
898+while(h=k.exec(i)){j[h[1]]=h[2]
899+}return j
900+},now:function(){return new Date().getTime()
901+},isArray:function(h){return Object.prototype.toString.call(h)==="[object Array]"
902+},inArray:function(k,l){if(!Array.prototype.indexOf){var h=l.length;
903+for(var j=0;
904+j<h;
905+++j){if(l[j]===k){return j
906+}}return -1
907+}return l.indexOf(k)
908+},isBinary:function(h){return/^\[object\s(?:Blob|ArrayBuffer|.+Array)\]$/.test(Object.prototype.toString.call(h))
909+},isFunction:function(h){return Object.prototype.toString.call(h)==="[object Function]"
910+},getAbsoluteURL:function(h){var i=document.createElement("div");
911+i.innerHTML='<a href="'+h+'"/>';
912+return encodeURI(decodeURI(i.firstChild.href))
913+},prepareURL:function(i){var j=a.util.now();
914+var h=i.replace(/([?&])_=[^&]*/,"$1_="+j);
915+return h+(h===i?(/\?/.test(i)?"&":"?")+"_="+j:"")
916+},trim:function(h){if(!String.prototype.trim){return h.toString().replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g,"").replace(/\s+/g," ")
917+}else{return h.toString().trim()
918+}},param:function(l){var j,h=[];
919+function k(m,n){n=a.util.isFunction(n)?n():(n==null?"":n);
920+h.push(encodeURIComponent(m)+"="+encodeURIComponent(n))
921+}function i(n,o){var m;
922+if(a.util.isArray(o)){a.util.each(o,function(q,p){if(/\[\]$/.test(n)){k(n,p)
923+}else{i(n+"["+(typeof p==="object"?q:"")+"]",p)
924+}})
925+}else{if(Object.prototype.toString.call(o)==="[object Object]"){for(m in o){i(n+"["+m+"]",o[m])
926+}}else{k(n,o)
927+}}}for(j in l){i(j,l[j])
928+}return h.join("&").replace(/%20/g,"+")
929+},storage:!!(window.localStorage&&window.StorageEvent),iterate:function(j,i){var k;
930+i=i||0;
931+(function h(){k=setTimeout(function(){if(j()===false){return
932+}h()
933+},i)
934+})();
935+return function(){clearTimeout(k)
936+}
937+},each:function(n,o,j){if(!n){return
938+}var m,k=0,l=n.length,h=a.util.isArray(n);
939+if(j){if(h){for(;
940+k<l;
941+k++){m=o.apply(n[k],j);
942+if(m===false){break
943+}}}else{for(k in n){m=o.apply(n[k],j);
944+if(m===false){break
945+}}}}else{if(h){for(;
946+k<l;
947+k++){m=o.call(n[k],k,n[k]);
948+if(m===false){break
949+}}}else{for(k in n){m=o.call(n[k],k,n[k]);
950+if(m===false){break
951+}}}}return n
952+},extend:function(l){var k,j,h;
953+for(k=1;
954+k<arguments.length;
955+k++){if((j=arguments[k])!=null){for(h in j){l[h]=j[h]
956+}}}return l
957+},on:function(j,i,h){if(j.addEventListener){j.addEventListener(i,h,false)
958+}else{if(j.attachEvent){j.attachEvent("on"+i,h)
959+}}},off:function(j,i,h){if(j.removeEventListener){j.removeEventListener(i,h,false)
960+}else{if(j.detachEvent){j.detachEvent("on"+i,h)
961+}}},log:function(j,i){if(window.console){var h=window.console[j];
962+if(typeof h==="function"){h.apply(window.console,i)
963+}}},warn:function(){a.util.log("warn",arguments)
964+},info:function(){a.util.log("info",arguments)
965+},debug:function(){a.util.log("debug",arguments)
966+},error:function(){a.util.log("error",arguments)
967+},xhr:function(){try{return new window.XMLHttpRequest()
968+}catch(i){try{return new window.ActiveXObject("Microsoft.XMLHTTP")
969+}catch(h){}}},parseJSON:function(h){return !h?null:window.JSON&&window.JSON.parse?window.JSON.parse(h):new Function("return "+h)()
970+},stringifyJSON:function(j){var m=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,k={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};
971+function h(n){return'"'+n.replace(m,function(o){var p=k[o];
972+return typeof p==="string"?p:"\\u"+("0000"+o.charCodeAt(0).toString(16)).slice(-4)
973+})+'"'
974+}function i(o){return o<10?"0"+o:o
975+}return window.JSON&&window.JSON.stringify?window.JSON.stringify(j):(function l(s,r){var q,p,n,o,u=r[s],t=typeof u;
976+if(u&&typeof u==="object"&&typeof u.toJSON==="function"){u=u.toJSON(s);
977+t=typeof u
978+}switch(t){case"string":return h(u);
979+case"number":return isFinite(u)?String(u):"null";
980+case"boolean":return String(u);
981+case"object":if(!u){return"null"
982+}switch(Object.prototype.toString.call(u)){case"[object Date]":return isFinite(u.valueOf())?'"'+u.getUTCFullYear()+"-"+i(u.getUTCMonth()+1)+"-"+i(u.getUTCDate())+"T"+i(u.getUTCHours())+":"+i(u.getUTCMinutes())+":"+i(u.getUTCSeconds())+'Z"':"null";
983+case"[object Array]":n=u.length;
984+o=[];
985+for(q=0;
986+q<n;
987+q++){o.push(l(q,u)||"null")
988+}return"["+o.join(",")+"]";
989+default:o=[];
990+for(q in u){if(b.call(u,q)){p=l(q,u);
991+if(p){o.push(h(q)+":"+p)
992+}}}return"{"+o.join(",")+"}"
993+}}})("",{"":j})
994+},checkCORSSupport:function(){if(a.util.browser.msie&&!window.XDomainRequest){return true
995+}else{if(a.util.browser.opera&&a.util.browser.version<12){return true
996+}else{if(a.util.trim(navigator.userAgent).slice(0,16)==="KreaTVWebKit/531"){return true
997+}else{if(a.util.trim(navigator.userAgent).slice(-7).toLowerCase()==="kreatel"){return true
998+}}}}var h=navigator.userAgent.toLowerCase();
999+var i=h.indexOf("android")>-1;
1000+if(i){return true
1001+}return false
1002+}};
1003+d=a.util.now();
1004+(function(){var i=navigator.userAgent.toLowerCase(),h=/(chrome)[ \/]([\w.]+)/.exec(i)||/(webkit)[ \/]([\w.]+)/.exec(i)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(i)||/(msie) ([\w.]+)/.exec(i)||/(trident)(?:.*? rv:([\w.]+)|)/.exec(i)||i.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(i)||[];
1005+a.util.browser[h[1]||""]=true;
1006+a.util.browser.version=h[2]||"0";
1007+if(a.util.browser.trident){a.util.browser.msie=true
1008+}if(a.util.browser.msie||(a.util.browser.mozilla&&a.util.browser.version.split(".")[0]==="1")){a.util.storage=false
1009+}})();
1010+a.util.on(window,"unload",function(h){a.unsubscribe()
1011+});
1012+a.util.on(window,"keypress",function(h){if(h.charCode===27||h.keyCode===27){if(h.preventDefault){h.preventDefault()
1013+}}});
1014+a.util.on(window,"offline",function(){a.unsubscribe()
1015+});
1016+return a
1017+}));
\ No newline at end of file
--- /dev/null
+++ b/javascript/atmosphere.js
@@ -0,0 +1,3056 @@
1+/*
2+ * Copyright 2013 Jeanfrancois Arcand
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+/**
17+ * Atmosphere.js
18+ * https://github.com/Atmosphere/atmosphere-javascript
19+ *
20+ * API reference
21+ * https://github.com/Atmosphere/atmosphere/wiki/jQuery.atmosphere.js-API
22+ *
23+ * Highly inspired by
24+ * - Portal by Donghwan Kim http://flowersinthesand.github.io/portal/
25+ */
26+(function(root, factory) {
27+ if (typeof define === "function" && define.amd) {
28+ // AMD
29+ define(factory);
30+ } else {
31+ // Browser globals, Window
32+ root.atmosphere = factory();
33+ }
34+}(this, function() {
35+
36+ "use strict";
37+
38+ var version = "2.1.4-javascript",
39+ atmosphere = {},
40+ guid,
41+ requests = [],
42+ callbacks = [],
43+ uuid = 0,
44+ hasOwn = Object.prototype.hasOwnProperty;
45+
46+ atmosphere = {
47+
48+ onError: function (response) {
49+ },
50+ onClose: function (response) {
51+ },
52+ onOpen: function (response) {
53+ },
54+ onReopen: function (response) {
55+ },
56+ onMessage: function (response) {
57+ },
58+ onReconnect: function (request, response) {
59+ },
60+ onMessagePublished: function (response) {
61+ },
62+ onTransportFailure: function (errorMessage, _request) {
63+ },
64+ onLocalMessage: function (response) {
65+ },
66+ onFailureToReconnect: function (request, response) {
67+ },
68+ onClientTimeout: function(request){
69+ },
70+
71+ AtmosphereRequest: function (options) {
72+
73+ /**
74+ * {Object} Request parameters.
75+ *
76+ * @private
77+ */
78+ var _request = {
79+ timeout: 300000,
80+ method: 'GET',
81+ headers: {},
82+ contentType: '',
83+ callback: null,
84+ url: '',
85+ data: '',
86+ suspend: true,
87+ maxRequest: -1,
88+ reconnect: true,
89+ maxStreamingLength: 10000000,
90+ lastIndex: 0,
91+ logLevel: 'info',
92+ requestCount: 0,
93+ fallbackMethod: 'GET',
94+ fallbackTransport: 'streaming',
95+ transport: 'long-polling',
96+ webSocketImpl: null,
97+ webSocketBinaryType: null,
98+ dispatchUrl: null,
99+ webSocketPathDelimiter: "@@",
100+ enableXDR: false,
101+ rewriteURL: false,
102+ attachHeadersAsQueryString: true,
103+ executeCallbackBeforeReconnect: false,
104+ readyState: 0,
105+ lastTimestamp: 0,
106+ withCredentials: false,
107+ trackMessageLength: false,
108+ messageDelimiter: '|',
109+ connectTimeout: -1,
110+ reconnectInterval: 0,
111+ dropHeaders: true,
112+ uuid: 0,
113+ async: true,
114+ shared: false,
115+ readResponsesHeaders: false,
116+ maxReconnectOnClose: 5,
117+ enableProtocol: true,
118+ onError: function (response) {
119+ },
120+ onClose: function (response) {
121+ },
122+ onOpen: function (response) {
123+ },
124+ onMessage: function (response) {
125+ },
126+ onReopen: function (request, response) {
127+ },
128+ onReconnect: function (request, response) {
129+ },
130+ onMessagePublished: function (response) {
131+ },
132+ onTransportFailure: function (reason, request) {
133+ },
134+ onLocalMessage: function (request) {
135+ },
136+ onFailureToReconnect: function (request, response) {
137+ },
138+ onClientTimeout: function(request){
139+ }
140+ };
141+
142+ /**
143+ * {Object} Request's last response.
144+ *
145+ * @private
146+ */
147+ var _response = {
148+ status: 200,
149+ reasonPhrase: "OK",
150+ responseBody: '',
151+ messages: [],
152+ headers: [],
153+ state: "messageReceived",
154+ transport: "polling",
155+ error: null,
156+ request: null,
157+ partialMessage: "",
158+ errorHandled: false,
159+ closedByClientTimeout: false
160+ };
161+
162+ /**
163+ * {websocket} Opened web socket.
164+ *
165+ * @private
166+ */
167+ var _websocket = null;
168+
169+ /**
170+ * {SSE} Opened SSE.
171+ *
172+ * @private
173+ */
174+ var _sse = null;
175+
176+ /**
177+ * {XMLHttpRequest, ActiveXObject} Opened ajax request (in case of http-streaming or long-polling)
178+ *
179+ * @private
180+ */
181+ var _activeRequest = null;
182+
183+ /**
184+ * {Object} Object use for streaming with IE.
185+ *
186+ * @private
187+ */
188+ var _ieStream = null;
189+
190+ /**
191+ * {Object} Object use for jsonp transport.
192+ *
193+ * @private
194+ */
195+ var _jqxhr = null;
196+
197+ /**
198+ * {boolean} If request has been subscribed or not.
199+ *
200+ * @private
201+ */
202+ var _subscribed = true;
203+
204+ /**
205+ * {number} Number of test reconnection.
206+ *
207+ * @private
208+ */
209+ var _requestCount = 0;
210+
211+ /**
212+ * {boolean} If request is currently aborded.
213+ *
214+ * @private
215+ */
216+ var _abordingConnection = false;
217+
218+ /**
219+ * A local "channel' of communication.
220+ *
221+ * @private
222+ */
223+ var _localSocketF = null;
224+
225+ /**
226+ * The storage used.
227+ *
228+ * @private
229+ */
230+ var _storageService;
231+
232+ /**
233+ * Local communication
234+ *
235+ * @private
236+ */
237+ var _localStorageService = null;
238+
239+ /**
240+ * A Unique ID
241+ *
242+ * @private
243+ */
244+ var guid = atmosphere.util.now();
245+
246+ /** Trace time */
247+ var _traceTimer;
248+
249+ /** Key for connection sharing */
250+ var _sharingKey;
251+
252+ // Automatic call to subscribe
253+ _subscribe(options);
254+
255+ /**
256+ * Initialize atmosphere request object.
257+ *
258+ * @private
259+ */
260+ function _init() {
261+ _subscribed = true;
262+ _abordingConnection = false;
263+ _requestCount = 0;
264+
265+ _websocket = null;
266+ _sse = null;
267+ _activeRequest = null;
268+ _ieStream = null;
269+ }
270+
271+ /**
272+ * Re-initialize atmosphere object.
273+ *
274+ * @private
275+ */
276+ function _reinit() {
277+ _clearState();
278+ _init();
279+ }
280+
281+ /**
282+ *
283+ * @private
284+ */
285+ function _verifyStreamingLength(ajaxRequest, rq) {
286+ // Wait to be sure we have the full message before closing.
287+ if (_response.partialMessage === "" && (rq.transport === 'streaming') && (ajaxRequest.responseText.length > rq.maxStreamingLength)) {
288+ _response.messages = [];
289+ _invokeClose(true);
290+ _disconnect();
291+ _clearState();
292+ _reconnect(ajaxRequest, rq, 0);
293+ }
294+ }
295+
296+ /**
297+ * Disconnect
298+ *
299+ * @private
300+ */
301+ function _disconnect() {
302+ if (_request.enableProtocol && !_request.firstMessage) {
303+ var query = "X-Atmosphere-Transport=close&X-Atmosphere-tracking-id=" + _request.uuid;
304+
305+ atmosphere.util.each(_request.headers, function (name, value) {
306+ var h = atmosphere.util.isFunction(value) ? value.call(this, _request, _request, _response) : value;
307+ if (h != null) {
308+ query += "&" + encodeURIComponent(name) + "=" + encodeURIComponent(h);
309+ }
310+ });
311+
312+ var url = _request.url.replace(/([?&])_=[^&]*/, query);
313+ url = url + (url === _request.url ? (/\?/.test(_request.url) ? "&" : "?") + query : "");
314+
315+ var rq = {
316+ connected: false
317+ };
318+ var closeR = new atmosphere.AtmosphereRequest(rq);
319+ closeR.attachHeadersAsQueryString = false;
320+ closeR.dropHeaders = true;
321+ closeR.url = url;
322+ closeR.contentType = "text/plain";
323+ closeR.transport = 'polling';
324+ closeR.async = false;
325+ _pushOnClose("", closeR);
326+ }
327+ }
328+
329+ /**
330+ * Close request.
331+ *
332+ * @private
333+ */
334+ function _close() {
335+ if (_request.reconnectId) {
336+ clearTimeout(_request.reconnectId);
337+ delete _request.reconnectId;
338+ }
339+ _request.reconnect = false;
340+ _abordingConnection = true;
341+ _response.request = _request;
342+ _response.state = 'unsubscribe';
343+ _response.responseBody = "";
344+ _response.status = 408;
345+ _response.partialMessage = "";
346+ _invokeCallback();
347+ _disconnect();
348+ _clearState();
349+ }
350+
351+ function _clearState() {
352+ _response.partialMessage = "";
353+ if (_request.id) {
354+ clearTimeout(_request.id);
355+ }
356+
357+ if (_ieStream != null) {
358+ _ieStream.close();
359+ _ieStream = null;
360+ }
361+ if (_jqxhr != null) {
362+ _jqxhr.abort();
363+ _jqxhr = null;
364+ }
365+ if (_activeRequest != null) {
366+ _activeRequest.abort();
367+ _activeRequest = null;
368+ }
369+ if (_websocket != null) {
370+ if (_websocket.webSocketOpened) {
371+ _websocket.close();
372+ }
373+ _websocket = null;
374+ }
375+ if (_sse != null) {
376+ _sse.close();
377+ _sse = null;
378+ }
379+ _clearStorage();
380+ }
381+
382+ function _clearStorage() {
383+ // Stop sharing a connection
384+ if (_storageService != null) {
385+ // Clears trace timer
386+ clearInterval(_traceTimer);
387+ // Removes the trace
388+ document.cookie = _sharingKey + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
389+ // The heir is the parent unless unloading
390+ _storageService.signal("close", {
391+ reason: "",
392+ heir: !_abordingConnection ? guid : (_storageService.get("children") || [])[0]
393+ });
394+ _storageService.close();
395+ }
396+ if (_localStorageService != null) {
397+ _localStorageService.close();
398+ }
399+ }
400+
401+ /**
402+ * Subscribe request using request transport. <br>
403+ * If request is currently opened, this one will be closed.
404+ *
405+ * @param {Object} Request parameters.
406+ * @private
407+ */
408+ function _subscribe(options) {
409+ _reinit();
410+
411+ _request = atmosphere.util.extend(_request, options);
412+ // Allow at least 1 request
413+ _request.mrequest = _request.reconnect;
414+ if (!_request.reconnect) {
415+ _request.reconnect = true;
416+ }
417+ }
418+
419+ /**
420+ * Check if web socket is supported (check for custom implementation provided by request object or browser implementation).
421+ *
422+ * @returns {boolean} True if web socket is supported, false otherwise.
423+ * @private
424+ */
425+ function _supportWebsocket() {
426+ return _request.webSocketImpl != null || window.WebSocket || window.MozWebSocket;
427+ }
428+
429+ /**
430+ * Check if server side events (SSE) is supported (check for custom implementation provided by request object or browser implementation).
431+ *
432+ * @returns {boolean} True if web socket is supported, false otherwise.
433+ * @private
434+ */
435+ function _supportSSE() {
436+ return window.EventSource;
437+ }
438+
439+ /**
440+ * Open request using request transport. <br>
441+ * If request transport is 'websocket' but websocket can't be opened, request will automatically reconnect using fallback transport.
442+ *
443+ * @private
444+ */
445+ function _execute() {
446+ // Shared across multiple tabs/windows.
447+ if (_request.shared) {
448+ _localStorageService = _local(_request);
449+ if (_localStorageService != null) {
450+ if (_request.logLevel === 'debug') {
451+ atmosphere.util.debug("Storage service available. All communication will be local");
452+ }
453+
454+ if (_localStorageService.open(_request)) {
455+ // Local connection.
456+ return;
457+ }
458+ }
459+
460+ if (_request.logLevel === 'debug') {
461+ atmosphere.util.debug("No Storage service available.");
462+ }
463+ // Wasn't local or an error occurred
464+ _localStorageService = null;
465+ }
466+
467+ // Protocol
468+ _request.firstMessage = uuid == 0 ? true : false;
469+ _request.isOpen = false;
470+ _request.ctime = atmosphere.util.now();
471+
472+ // We carry any UUID set by the user or from a previous connection.
473+ if (_request.uuid === 0) {
474+ _request.uuid = uuid;
475+ }
476+ _response.closedByClientTimeout = false;
477+
478+ if (_request.transport !== 'websocket' && _request.transport !== 'sse') {
479+ _executeRequest(_request);
480+
481+ } else if (_request.transport === 'websocket') {
482+ if (!_supportWebsocket()) {
483+ _reconnectWithFallbackTransport("Websocket is not supported, using request.fallbackTransport (" + _request.fallbackTransport
484+ + ")");
485+ } else {
486+ _executeWebSocket(false);
487+ }
488+ } else if (_request.transport === 'sse') {
489+ if (!_supportSSE()) {
490+ _reconnectWithFallbackTransport("Server Side Events(SSE) is not supported, using request.fallbackTransport ("
491+ + _request.fallbackTransport + ")");
492+ } else {
493+ _executeSSE(false);
494+ }
495+ }
496+ }
497+
498+ function _local(request) {
499+ var trace, connector, orphan, name = "atmosphere-" + request.url, connectors = {
500+ storage: function () {
501+ function onstorage(event) {
502+ if (event.key === name && event.newValue) {
503+ listener(event.newValue);
504+ }
505+ }
506+
507+ if (!atmosphere.util.storage) {
508+ return;
509+ }
510+
511+ var storage = window.localStorage,
512+ get = function (key) {
513+ return atmosphere.util.parseJSON(storage.getItem(name + "-" + key));
514+ },
515+ set = function (key, value) {
516+ storage.setItem(name + "-" + key, atmosphere.util.stringifyJSON(value));
517+ };
518+
519+ return {
520+ init: function () {
521+ set("children", get("children").concat([guid]));
522+ atmosphere.util.on(window, "storage", onstorage);
523+ return get("opened");
524+ },
525+ signal: function (type, data) {
526+ storage.setItem(name, atmosphere.util.stringifyJSON({
527+ target: "p",
528+ type: type,
529+ data: data
530+ }));
531+ },
532+ close: function () {
533+ var children = get("children");
534+
535+ atmosphere.util.off(window, "storage", onstorage);
536+ if (children) {
537+ if (removeFromArray(children, request.id)) {
538+ set("children", children);
539+ }
540+ }
541+ }
542+ };
543+ },
544+ windowref: function () {
545+ var win = window.open("", name.replace(/\W/g, ""));
546+
547+ if (!win || win.closed || !win.callbacks) {
548+ return;
549+ }
550+
551+ return {
552+ init: function () {
553+ win.callbacks.push(listener);
554+ win.children.push(guid);
555+ return win.opened;
556+ },
557+ signal: function (type, data) {
558+ if (!win.closed && win.fire) {
559+ win.fire(atmosphere.util.stringifyJSON({
560+ target: "p",
561+ type: type,
562+ data: data
563+ }));
564+ }
565+ },
566+ close: function () {
567+ // Removes traces only if the parent is alive
568+ if (!orphan) {
569+ removeFromArray(win.callbacks, listener);
570+ removeFromArray(win.children, guid);
571+ }
572+ }
573+
574+ };
575+ }
576+ };
577+
578+ function removeFromArray(array, val) {
579+ var i, length = array.length;
580+
581+ for (i = 0; i < length; i++) {
582+ if (array[i] === val) {
583+ array.splice(i, 1);
584+ }
585+ }
586+
587+ return length !== array.length;
588+ }
589+
590+ // Receives open, close and message command from the parent
591+ function listener(string) {
592+ var command = atmosphere.util.parseJSON(string), data = command.data;
593+
594+ if (command.target === "c") {
595+ switch (command.type) {
596+ case "open":
597+ _open("opening", 'local', _request);
598+ break;
599+ case "close":
600+ if (!orphan) {
601+ orphan = true;
602+ if (data.reason === "aborted") {
603+ _close();
604+ } else {
605+ // Gives the heir some time to reconnect
606+ if (data.heir === guid) {
607+ _execute();
608+ } else {
609+ setTimeout(function () {
610+ _execute();
611+ }, 100);
612+ }
613+ }
614+ }
615+ break;
616+ case "message":
617+ _prepareCallback(data, "messageReceived", 200, request.transport);
618+ break;
619+ case "localMessage":
620+ _localMessage(data);
621+ break;
622+ }
623+ }
624+ }
625+
626+ function findTrace() {
627+ var matcher = new RegExp("(?:^|; )(" + encodeURIComponent(name) + ")=([^;]*)").exec(document.cookie);
628+ if (matcher) {
629+ return atmosphere.util.parseJSON(decodeURIComponent(matcher[2]));
630+ }
631+ }
632+
633+ // Finds and validates the parent socket's trace from the cookie
634+ trace = findTrace();
635+ if (!trace || atmosphere.util.now() - trace.ts > 1000) {
636+ return;
637+ }
638+
639+ // Chooses a connector
640+ connector = connectors.storage() || connectors.windowref();
641+ if (!connector) {
642+ return;
643+ }
644+
645+ return {
646+ open: function () {
647+ var parentOpened;
648+
649+ // Checks the shared one is alive
650+ _traceTimer = setInterval(function () {
651+ var oldTrace = trace;
652+ trace = findTrace();
653+ if (!trace || oldTrace.ts === trace.ts) {
654+ // Simulates a close signal
655+ listener(atmosphere.util.stringifyJSON({
656+ target: "c",
657+ type: "close",
658+ data: {
659+ reason: "error",
660+ heir: oldTrace.heir
661+ }
662+ }));
663+ }
664+ }, 1000);
665+
666+ parentOpened = connector.init();
667+ if (parentOpened) {
668+ // Firing the open event without delay robs the user of the opportunity to bind connecting event handlers
669+ setTimeout(function () {
670+ _open("opening", 'local', request);
671+ }, 50);
672+ }
673+ return parentOpened;
674+ },
675+ send: function (event) {
676+ connector.signal("send", event);
677+ },
678+ localSend: function (event) {
679+ connector.signal("localSend", atmosphere.util.stringifyJSON({
680+ id: guid,
681+ event: event
682+ }));
683+ },
684+ close: function () {
685+ // Do not signal the parent if this method is executed by the unload event handler
686+ if (!_abordingConnection) {
687+ clearInterval(_traceTimer);
688+ connector.signal("close");
689+ connector.close();
690+ }
691+ }
692+ };
693+ }
694+
695+ function share() {
696+ var storageService, name = "atmosphere-" + _request.url, servers = {
697+ // Powered by the storage event and the localStorage
698+ // http://www.w3.org/TR/webstorage/#event-storage
699+ storage: function () {
700+ function onstorage(event) {
701+ // When a deletion, newValue initialized to null
702+ if (event.key === name && event.newValue) {
703+ listener(event.newValue);
704+ }
705+ }
706+
707+ if (!atmosphere.util.storage) {
708+ return;
709+ }
710+
711+ var storage = window.localStorage;
712+
713+ return {
714+ init: function () {
715+ // Handles the storage event
716+ atmosphere.util.on(window, "storage", onstorage);
717+ },
718+ signal: function (type, data) {
719+ storage.setItem(name, atmosphere.util.stringifyJSON({
720+ target: "c",
721+ type: type,
722+ data: data
723+ }));
724+ },
725+ get: function (key) {
726+ return atmosphere.util.parseJSON(storage.getItem(name + "-" + key));
727+ },
728+ set: function (key, value) {
729+ storage.setItem(name + "-" + key, atmosphere.util.stringifyJSON(value));
730+ },
731+ close: function () {
732+ atmosphere.util.off(window, "storage", onstorage);
733+ storage.removeItem(name);
734+ storage.removeItem(name + "-opened");
735+ storage.removeItem(name + "-children");
736+ }
737+
738+ };
739+ },
740+ // Powered by the window.open method
741+ // https://developer.mozilla.org/en/DOM/window.open
742+ windowref: function () {
743+ // Internet Explorer raises an invalid argument error
744+ // when calling the window.open method with the name containing non-word characters
745+ var neim = name.replace(/\W/g, ""), container = document.getElementById(neim), win;
746+
747+ if (!container) {
748+ container = document.createElement("div");
749+ container.id = neim;
750+ container.style.display = "none";
751+ container.innerHTML = '<iframe name="' + neim + '" />';
752+ document.body.appendChild(container);
753+ }
754+
755+ win = container.firstChild.contentWindow;
756+
757+ return {
758+ init: function () {
759+ // Callbacks from different windows
760+ win.callbacks = [listener];
761+ // In IE 8 and less, only string argument can be safely passed to the function in other window
762+ win.fire = function (string) {
763+ var i;
764+
765+ for (i = 0; i < win.callbacks.length; i++) {
766+ win.callbacks[i](string);
767+ }
768+ };
769+ },
770+ signal: function (type, data) {
771+ if (!win.closed && win.fire) {
772+ win.fire(atmosphere.util.stringifyJSON({
773+ target: "c",
774+ type: type,
775+ data: data
776+ }));
777+ }
778+ },
779+ get: function (key) {
780+ return !win.closed ? win[key] : null;
781+ },
782+ set: function (key, value) {
783+ if (!win.closed) {
784+ win[key] = value;
785+ }
786+ },
787+ close: function () {
788+ }
789+ };
790+ }
791+ };
792+
793+ // Receives send and close command from the children
794+ function listener(string) {
795+ var command = atmosphere.util.parseJSON(string), data = command.data;
796+
797+ if (command.target === "p") {
798+ switch (command.type) {
799+ case "send":
800+ _push(data);
801+ break;
802+ case "localSend":
803+ _localMessage(data);
804+ break;
805+ case "close":
806+ _close();
807+ break;
808+ }
809+ }
810+ }
811+
812+ _localSocketF = function propagateMessageEvent(context) {
813+ storageService.signal("message", context);
814+ };
815+
816+ function leaveTrace() {
817+ document.cookie = _sharingKey + "=" +
818+ // Opera's JSON implementation ignores a number whose a last digit of 0 strangely
819+ // but has no problem with a number whose a last digit of 9 + 1
820+ encodeURIComponent(atmosphere.util.stringifyJSON({
821+ ts: atmosphere.util.now() + 1,
822+ heir: (storageService.get("children") || [])[0]
823+ })) + "; path=/";
824+ }
825+
826+ // Chooses a storageService
827+ storageService = servers.storage() || servers.windowref();
828+ storageService.init();
829+
830+ if (_request.logLevel === 'debug') {
831+ atmosphere.util.debug("Installed StorageService " + storageService);
832+ }
833+
834+ // List of children sockets
835+ storageService.set("children", []);
836+
837+ if (storageService.get("opened") != null && !storageService.get("opened")) {
838+ // Flag indicating the parent socket is opened
839+ storageService.set("opened", false);
840+ }
841+ // Leaves traces
842+ _sharingKey = encodeURIComponent(name);
843+ leaveTrace();
844+ _traceTimer = setInterval(leaveTrace, 1000);
845+
846+ _storageService = storageService;
847+ }
848+
849+ /**
850+ * @private
851+ */
852+ function _open(state, transport, request) {
853+ if (_request.shared && transport !== 'local') {
854+ share();
855+ }
856+
857+ if (_storageService != null) {
858+ _storageService.set("opened", true);
859+ }
860+
861+ request.close = function () {
862+ _close();
863+ };
864+
865+ if (_requestCount > 0 && state === 're-connecting') {
866+ request.isReopen = true;
867+ _tryingToReconnect(_response);
868+ } else if (_response.error == null) {
869+ _response.request = request;
870+ var prevState = _response.state;
871+ _response.state = state;
872+ var prevTransport = _response.transport;
873+ _response.transport = transport;
874+
875+ var _body = _response.responseBody;
876+ _invokeCallback();
877+ _response.responseBody = _body;
878+
879+ _response.state = prevState;
880+ _response.transport = prevTransport;
881+ }
882+ }
883+
884+ /**
885+ * Execute request using jsonp transport.
886+ *
887+ * @param request {Object} request Request parameters, if undefined _request object will be used.
888+ * @private
889+ */
890+ function _jsonp(request) {
891+ // When CORS is enabled, make sure we force the proper transport.
892+ request.transport = "jsonp";
893+
894+ var rq = _request, script;
895+ if ((request != null) && (typeof (request) !== 'undefined')) {
896+ rq = request;
897+ }
898+
899+ _jqxhr = {
900+ open: function () {
901+ var callback = "atmosphere" + (++guid);
902+
903+ function poll() {
904+ var url = rq.url;
905+ if (rq.dispatchUrl != null) {
906+ url += rq.dispatchUrl;
907+ }
908+
909+ var data = rq.data;
910+ if (rq.attachHeadersAsQueryString) {
911+ url = _attachHeaders(rq);
912+ if (data !== '') {
913+ url += "&X-Atmosphere-Post-Body=" + encodeURIComponent(data);
914+ }
915+ data = '';
916+ }
917+
918+ var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
919+
920+ script = document.createElement("script");
921+ script.src = url + "&jsonpTransport=" + callback;
922+ script.clean = function () {
923+ script.clean = script.onerror = script.onload = script.onreadystatechange = null;
924+ if (script.parentNode) {
925+ script.parentNode.removeChild(script);
926+ }
927+ };
928+ script.onload = script.onreadystatechange = function () {
929+ if (!script.readyState || /loaded|complete/.test(script.readyState)) {
930+ script.clean();
931+ }
932+ };
933+ script.onerror = function () {
934+ script.clean();
935+ rq.lastIndex = 0;
936+
937+ if (rq.openId) {
938+ clearTimeout(rq.openId);
939+ }
940+
941+ if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {
942+ _open('re-connecting', rq.transport, rq);
943+ _reconnect(_jqxhr, rq, request.reconnectInterval);
944+ rq.openId = setTimeout(function() {
945+ _triggerOpen(rq);
946+ }, rq.reconnectInterval + 1000);
947+ } else {
948+ _onError(0, "maxReconnectOnClose reached");
949+ }
950+ };
951+
952+ head.insertBefore(script, head.firstChild);
953+ }
954+
955+ // Attaches callback
956+ window[callback] = function (msg) {
957+ if (rq.reconnect) {
958+ if (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest) {
959+ // _readHeaders(_jqxhr, rq);
960+
961+ if (!rq.executeCallbackBeforeReconnect) {
962+ _reconnect(_jqxhr, rq, 0);
963+ }
964+
965+ if (msg != null && typeof msg !== 'string') {
966+ try {
967+ msg = msg.message;
968+ } catch (err) {
969+ // The message was partial
970+ }
971+ }
972+
973+ var skipCallbackInvocation = _trackMessageSize(msg, rq, _response);
974+ if (!skipCallbackInvocation) {
975+ _prepareCallback(_response.responseBody, "messageReceived", 200, rq.transport);
976+ }
977+
978+ if (rq.executeCallbackBeforeReconnect) {
979+ _reconnect(_jqxhr, rq, 0);
980+ }
981+ } else {
982+ atmosphere.util.log(_request.logLevel, ["JSONP reconnect maximum try reached " + _request.requestCount]);
983+ _onError(0, "maxRequest reached");
984+ }
985+ }
986+ };
987+ setTimeout(function () {
988+ poll();
989+ }, 50);
990+ },
991+ abort: function () {
992+ if (script.clean) {
993+ script.clean();
994+ }
995+ }
996+ };
997+
998+ _jqxhr.open();
999+ }
1000+
1001+ /**
1002+ * Build websocket object.
1003+ *
1004+ * @param location {string} Web socket url.
1005+ * @returns {websocket} Web socket object.
1006+ * @private
1007+ */
1008+ function _getWebSocket(location) {
1009+ if (_request.webSocketImpl != null) {
1010+ return _request.webSocketImpl;
1011+ } else {
1012+ if (window.WebSocket) {
1013+ return new WebSocket(location);
1014+ } else {
1015+ return new MozWebSocket(location);
1016+ }
1017+ }
1018+ }
1019+
1020+ /**
1021+ * Build web socket url from request url.
1022+ *
1023+ * @return {string} Web socket url (start with "ws" or "wss" for secure web socket).
1024+ * @private
1025+ */
1026+ function _buildWebSocketUrl() {
1027+ return atmosphere.util.getAbsoluteURL(_attachHeaders(_request)).replace(/^http/, "ws");
1028+ }
1029+
1030+ /**
1031+ * Build SSE url from request url.
1032+ *
1033+ * @return a url with Atmosphere's headers
1034+ * @private
1035+ */
1036+ function _buildSSEUrl() {
1037+ var url = _attachHeaders(_request);
1038+ return url;
1039+ }
1040+
1041+ /**
1042+ * Open SSE. <br>
1043+ * Automatically use fallback transport if SSE can't be opened.
1044+ *
1045+ * @private
1046+ */
1047+ function _executeSSE(sseOpened) {
1048+
1049+ _response.transport = "sse";
1050+
1051+ var location = _buildSSEUrl();
1052+
1053+ if (_request.logLevel === 'debug') {
1054+ atmosphere.util.debug("Invoking executeSSE");
1055+ atmosphere.util.debug("Using URL: " + location);
1056+ }
1057+
1058+ if (_request.enableProtocol && sseOpened) {
1059+ var time = atmosphere.util.now() - _request.ctime;
1060+ _request.lastTimestamp = Number(_request.stime) + Number(time);
1061+ }
1062+
1063+ if (sseOpened && !_request.reconnect) {
1064+ if (_sse != null) {
1065+ _clearState();
1066+ }
1067+ return;
1068+ }
1069+
1070+ try {
1071+ _sse = new EventSource(location, {
1072+ withCredentials: _request.withCredentials
1073+ });
1074+ } catch (e) {
1075+ _onError(0, e);
1076+ _reconnectWithFallbackTransport("SSE failed. Downgrading to fallback transport and resending");
1077+ return;
1078+ }
1079+
1080+ if (_request.connectTimeout > 0) {
1081+ _request.id = setTimeout(function () {
1082+ if (!sseOpened) {
1083+ _clearState();
1084+ }
1085+ }, _request.connectTimeout);
1086+ }
1087+
1088+ _sse.onopen = function (event) {
1089+ _timeout(_request);
1090+ if (_request.logLevel === 'debug') {
1091+ atmosphere.util.debug("SSE successfully opened");
1092+ }
1093+
1094+ if (!_request.enableProtocol) {
1095+ if (!sseOpened) {
1096+ _open('opening', "sse", _request);
1097+ } else {
1098+ _open('re-opening', "sse", _request);
1099+ }
1100+ } else if (_request.isReopen) {
1101+ _request.isReopen = false;
1102+ _open('re-opening', _request.transport, _request);
1103+ }
1104+
1105+ sseOpened = true;
1106+
1107+ if (_request.method === 'POST') {
1108+ _response.state = "messageReceived";
1109+ _sse.send(_request.data);
1110+ }
1111+ };
1112+
1113+ _sse.onmessage = function (message) {
1114+ _timeout(_request);
1115+
1116+ if (!_request.enableXDR && message.origin && message.origin !== window.location.protocol + "//" + window.location.host) {
1117+ atmosphere.util.log(_request.logLevel, ["Origin was not " + window.location.protocol + "//" + window.location.host]);
1118+ return;
1119+ }
1120+
1121+ _response.state = 'messageReceived';
1122+ _response.status = 200;
1123+
1124+ message = message.data;
1125+ var skipCallbackInvocation = _trackMessageSize(message, _request, _response);
1126+
1127+ // https://github.com/remy/polyfills/blob/master/EventSource.js
1128+ // Since we polling.
1129+ /* if (_sse.URL) {
1130+ _sse.interval = 100;
1131+ _sse.URL = _buildSSEUrl();
1132+ } */
1133+
1134+ if (!skipCallbackInvocation) {
1135+ _invokeCallback();
1136+ _response.responseBody = '';
1137+ _response.messages = [];
1138+ }
1139+ };
1140+
1141+ _sse.onerror = function (message) {
1142+ clearTimeout(_request.id);
1143+
1144+ if (_response.closedByClientTimeout) return;
1145+
1146+ _invokeClose(sseOpened);
1147+ _clearState();
1148+
1149+ if (_abordingConnection) {
1150+ atmosphere.util.log(_request.logLevel, ["SSE closed normally"]);
1151+ } else if (!sseOpened) {
1152+ _reconnectWithFallbackTransport("SSE failed. Downgrading to fallback transport and resending");
1153+ } else if (_request.reconnect && (_response.transport === 'sse')) {
1154+ if (_requestCount++ < _request.maxReconnectOnClose) {
1155+ _open('re-connecting', _request.transport, _request);
1156+ if (_request.reconnectInterval > 0) {
1157+ _request.reconnectId = setTimeout(function () {
1158+ _executeSSE(true);
1159+ }, _request.reconnectInterval);
1160+ } else {
1161+ _executeSSE(true);
1162+ }
1163+ _response.responseBody = "";
1164+ _response.messages = [];
1165+ } else {
1166+ atmosphere.util.log(_request.logLevel, ["SSE reconnect maximum try reached " + _requestCount]);
1167+ _onError(0, "maxReconnectOnClose reached");
1168+ }
1169+ }
1170+ };
1171+ }
1172+
1173+ /**
1174+ * Open web socket. <br>
1175+ * Automatically use fallback transport if web socket can't be opened.
1176+ *
1177+ * @private
1178+ */
1179+ function _executeWebSocket(webSocketOpened) {
1180+
1181+ _response.transport = "websocket";
1182+
1183+ if (_request.enableProtocol && webSocketOpened) {
1184+ var time = atmosphere.util.now() - _request.ctime;
1185+ _request.lastTimestamp = Number(_request.stime) + Number(time);
1186+ }
1187+
1188+ var location = _buildWebSocketUrl(_request.url);
1189+ if (_request.logLevel === 'debug') {
1190+ atmosphere.util.debug("Invoking executeWebSocket");
1191+ atmosphere.util.debug("Using URL: " + location);
1192+ }
1193+
1194+ if (webSocketOpened && !_request.reconnect) {
1195+ if (_websocket != null) {
1196+ _clearState();
1197+ }
1198+ return;
1199+ }
1200+
1201+ _websocket = _getWebSocket(location);
1202+ if (_request.webSocketBinaryType != null) {
1203+ _websocket.binaryType = _request.webSocketBinaryType;
1204+ }
1205+
1206+ if (_request.connectTimeout > 0) {
1207+ _request.id = setTimeout(function () {
1208+ if (!webSocketOpened) {
1209+ var _message = {
1210+ code: 1002,
1211+ reason: "",
1212+ wasClean: false
1213+ };
1214+ _websocket.onclose(_message);
1215+ // Close it anyway
1216+ try {
1217+ _clearState();
1218+ } catch (e) {
1219+ }
1220+ return;
1221+ }
1222+
1223+ }, _request.connectTimeout);
1224+ }
1225+
1226+ _websocket.onopen = function (message) {
1227+ _timeout(_request);
1228+
1229+ if (_request.logLevel === 'debug') {
1230+ atmosphere.util.debug("Websocket successfully opened");
1231+ }
1232+
1233+ var reopening = webSocketOpened;
1234+
1235+ webSocketOpened = true;
1236+ if(_websocket != null) {
1237+ _websocket.webSocketOpened = webSocketOpened;
1238+ }
1239+
1240+ if (!_request.enableProtocol) {
1241+ if (reopening) {
1242+ _open('re-opening', "websocket", _request);
1243+ } else {
1244+ _open('opening', "websocket", _request);
1245+ }
1246+ }
1247+
1248+ if (_websocket != null) {
1249+ if (_request.method === 'POST') {
1250+ _response.state = "messageReceived";
1251+ _websocket.send(_request.data);
1252+ }
1253+ }
1254+ };
1255+
1256+ _websocket.onmessage = function (message) {
1257+ _timeout(_request);
1258+
1259+ _response.state = 'messageReceived';
1260+ _response.status = 200;
1261+
1262+ message = message.data;
1263+ var isString = typeof (message) === 'string';
1264+ if (isString) {
1265+ var skipCallbackInvocation = _trackMessageSize(message, _request, _response);
1266+ if (!skipCallbackInvocation) {
1267+ _invokeCallback();
1268+ _response.responseBody = '';
1269+ _response.messages = [];
1270+ }
1271+ } else {
1272+ if (!_handleProtocol(_request, message))
1273+ return;
1274+
1275+ _response.responseBody = message;
1276+ _invokeCallback();
1277+ _response.responseBody = null;
1278+ }
1279+ };
1280+
1281+ _websocket.onerror = function (message) {
1282+ clearTimeout(_request.id);
1283+ };
1284+
1285+ _websocket.onclose = function (message) {
1286+ clearTimeout(_request.id);
1287+ if (_response.state === 'closed')
1288+ return;
1289+
1290+ var reason = message.reason;
1291+ if (reason === "") {
1292+ switch (message.code) {
1293+ case 1000:
1294+ reason = "Normal closure; the connection successfully completed whatever purpose for which " + "it was created.";
1295+ break;
1296+ case 1001:
1297+ reason = "The endpoint is going away, either because of a server failure or because the "
1298+ + "browser is navigating away from the page that opened the connection.";
1299+ break;
1300+ case 1002:
1301+ reason = "The endpoint is terminating the connection due to a protocol error.";
1302+ break;
1303+ case 1003:
1304+ reason = "The connection is being terminated because the endpoint received data of a type it "
1305+ + "cannot accept (for example, a text-only endpoint received binary data).";
1306+ break;
1307+ case 1004:
1308+ reason = "The endpoint is terminating the connection because a data frame was received that " + "is too large.";
1309+ break;
1310+ case 1005:
1311+ reason = "Unknown: no status code was provided even though one was expected.";
1312+ break;
1313+ case 1006:
1314+ reason = "Connection was closed abnormally (that is, with no close frame being sent).";
1315+ break;
1316+ }
1317+ }
1318+
1319+ if (_request.logLevel === 'warn') {
1320+ atmosphere.util.warn("Websocket closed, reason: " + reason);
1321+ atmosphere.util.warn("Websocket closed, wasClean: " + message.wasClean);
1322+ }
1323+
1324+ if (_response.closedByClientTimeout) {
1325+ return;
1326+ }
1327+
1328+ _invokeClose(webSocketOpened);
1329+
1330+ _response.state = 'closed';
1331+
1332+ if (_abordingConnection) {
1333+ atmosphere.util.log(_request.logLevel, ["Websocket closed normally"]);
1334+ } else if (!webSocketOpened) {
1335+ _reconnectWithFallbackTransport("Websocket failed. Downgrading to Comet and resending");
1336+
1337+ } else if (_request.reconnect && _response.transport === 'websocket') {
1338+ _clearState();
1339+ if (_requestCount++ < _request.maxReconnectOnClose) {
1340+ _open('re-connecting', _request.transport, _request);
1341+ if (_request.reconnectInterval > 0) {
1342+ _request.reconnectId = setTimeout(function () {
1343+ _response.responseBody = "";
1344+ _response.messages = [];
1345+ _executeWebSocket(true);
1346+ }, _request.reconnectInterval);
1347+ } else {
1348+ _response.responseBody = "";
1349+ _response.messages = [];
1350+ _executeWebSocket(true);
1351+ }
1352+ } else {
1353+ atmosphere.util.log(_request.logLevel, ["Websocket reconnect maximum try reached " + _request.requestCount]);
1354+ if (_request.logLevel === 'warn') {
1355+ atmosphere.util.warn("Websocket error, reason: " + message.reason);
1356+ }
1357+ _onError(0, "maxReconnectOnClose reached");
1358+ }
1359+ }
1360+ };
1361+
1362+ if (_websocket.url === undefined) {
1363+ // Android 4.1 does not really support websockets and fails silently
1364+ _websocket.onclose({
1365+ reason: "Android 4.1 does not support websockets.",
1366+ wasClean: false
1367+ });
1368+ }
1369+ }
1370+
1371+ function _handleProtocol(request, message) {
1372+
1373+ // The first messages is always the uuid.
1374+ var b = true;
1375+
1376+ if (request.transport === 'polling') return b;
1377+
1378+ if (atmosphere.util.trim(message).length !== 0 && request.enableProtocol && request.firstMessage) {
1379+ request.firstMessage = false;
1380+ var messages = message.split(request.messageDelimiter);
1381+ var pos = messages.length === 2 ? 0 : 1;
1382+ request.uuid = atmosphere.util.trim(messages[pos]);
1383+ request.stime = atmosphere.util.trim(messages[pos + 1]);
1384+ b = false;
1385+ if (request.transport !== 'long-polling') {
1386+ _triggerOpen(request);
1387+ }
1388+ uuid = request.uuid;
1389+ } else if (request.enableProtocol && request.firstMessage) {
1390+ // In case we are getting some junk from IE
1391+ b = false;
1392+ } else {
1393+ _triggerOpen(request);
1394+ }
1395+ return b;
1396+ }
1397+
1398+ function _timeout(_request) {
1399+ clearTimeout(_request.id);
1400+ if (_request.timeout > 0 && _request.transport !== 'polling') {
1401+ _request.id = setTimeout(function () {
1402+ _onClientTimeout(_request);
1403+ _disconnect();
1404+ _clearState();
1405+ }, _request.timeout);
1406+ }
1407+ }
1408+
1409+ function _onClientTimeout(_request) {
1410+ _response.closedByClientTimeout = true;
1411+ _response.state = 'closedByClient';
1412+ _response.responseBody = "";
1413+ _response.status = 408;
1414+ _response.messages = [];
1415+ _invokeCallback();
1416+ }
1417+
1418+ function _onError(code, reason) {
1419+ _clearState();
1420+ clearTimeout(_request.id);
1421+ _response.state = 'error';
1422+ _response.reasonPhrase = reason;
1423+ _response.responseBody = "";
1424+ _response.status = code;
1425+ _response.messages = [];
1426+ _invokeCallback();
1427+ }
1428+
1429+ /**
1430+ * Track received message and make sure callbacks/functions are only invoked when the complete message has been received.
1431+ *
1432+ * @param message
1433+ * @param request
1434+ * @param response
1435+ */
1436+ function _trackMessageSize(message, request, response) {
1437+ if (!_handleProtocol(request, message))
1438+ return true;
1439+ if (message.length === 0)
1440+ return true;
1441+
1442+ if (request.trackMessageLength) {
1443+ // prepend partialMessage if any
1444+ message = response.partialMessage + message;
1445+
1446+ var messages = [];
1447+ var messageStart = message.indexOf(request.messageDelimiter);
1448+ while (messageStart !== -1) {
1449+ var str = atmosphere.util.trim(message.substring(0, messageStart));
1450+ var messageLength = +str;
1451+ if (isNaN(messageLength))
1452+ throw new Error('message length "' + str + '" is not a number');
1453+ messageStart += request.messageDelimiter.length;
1454+ if (messageStart + messageLength > message.length) {
1455+ // message not complete, so there is no trailing messageDelimiter
1456+ messageStart = -1;
1457+ } else {
1458+ // message complete, so add it
1459+ messages.push(message.substring(messageStart, messageStart + messageLength));
1460+ // remove consumed characters
1461+ message = message.substring(messageStart + messageLength, message.length);
1462+ messageStart = message.indexOf(request.messageDelimiter);
1463+ }
1464+ }
1465+
1466+ /* keep any remaining data */
1467+ response.partialMessage = message;
1468+
1469+ if (messages.length !== 0) {
1470+ response.responseBody = messages.join(request.messageDelimiter);
1471+ response.messages = messages;
1472+ return false;
1473+ } else {
1474+ response.responseBody = "";
1475+ response.messages = [];
1476+ return true;
1477+ }
1478+ } else {
1479+ response.responseBody = message;
1480+ }
1481+ return false;
1482+ }
1483+
1484+ /**
1485+ * Reconnect request with fallback transport. <br>
1486+ * Used in case websocket can't be opened.
1487+ *
1488+ * @private
1489+ */
1490+ function _reconnectWithFallbackTransport(errorMessage) {
1491+ atmosphere.util.log(_request.logLevel, [errorMessage]);
1492+
1493+ if (typeof (_request.onTransportFailure) !== 'undefined') {
1494+ _request.onTransportFailure(errorMessage, _request);
1495+ } else if (typeof (atmosphere.util.onTransportFailure) !== 'undefined') {
1496+ atmosphere.util.onTransportFailure(errorMessage, _request);
1497+ }
1498+
1499+ _request.transport = _request.fallbackTransport;
1500+ var reconnectInterval = _request.connectTimeout === -1 ? 0 : _request.connectTimeout;
1501+ if (_request.reconnect && _request.transport !== 'none' || _request.transport == null) {
1502+ _request.method = _request.fallbackMethod;
1503+ _response.transport = _request.fallbackTransport;
1504+ _request.fallbackTransport = 'none';
1505+ if (reconnectInterval > 0) {
1506+ _request.reconnectId = setTimeout(function () {
1507+ _execute();
1508+ }, reconnectInterval);
1509+ } else {
1510+ _execute();
1511+ }
1512+ } else {
1513+ _onError(500, "Unable to reconnect with fallback transport");
1514+ }
1515+ }
1516+
1517+ /**
1518+ * Get url from request and attach headers to it.
1519+ *
1520+ * @param request {Object} request Request parameters, if undefined _request object will be used.
1521+ *
1522+ * @returns {Object} Request object, if undefined, _request object will be used.
1523+ * @private
1524+ */
1525+ function _attachHeaders(request, url) {
1526+ var rq = _request;
1527+ if ((request != null) && (typeof (request) !== 'undefined')) {
1528+ rq = request;
1529+ }
1530+
1531+ if (url == null) {
1532+ url = rq.url;
1533+ }
1534+
1535+ // If not enabled
1536+ if (!rq.attachHeadersAsQueryString)
1537+ return url;
1538+
1539+ // If already added
1540+ if (url.indexOf("X-Atmosphere-Framework") !== -1) {
1541+ return url;
1542+ }
1543+
1544+ url += (url.indexOf('?') !== -1) ? '&' : '?';
1545+ url += "X-Atmosphere-tracking-id=" + rq.uuid;
1546+ url += "&X-Atmosphere-Framework=" + version;
1547+ url += "&X-Atmosphere-Transport=" + rq.transport;
1548+
1549+ if (rq.trackMessageLength) {
1550+ url += "&X-Atmosphere-TrackMessageSize=" + "true";
1551+ }
1552+
1553+ if (rq.lastTimestamp != null) {
1554+ url += "&X-Cache-Date=" + rq.lastTimestamp;
1555+ } else {
1556+ url += "&X-Cache-Date=" + 0;
1557+ }
1558+
1559+ if (rq.contentType !== '') {
1560+ //Eurk!
1561+ url += "&Content-Type=" + (rq.transport === 'websocket' ? rq.contentType : encodeURIComponent(rq.contentType));
1562+ }
1563+
1564+ if (rq.enableProtocol) {
1565+ url += "&X-atmo-protocol=true";
1566+ }
1567+
1568+ atmosphere.util.each(rq.headers, function (name, value) {
1569+ var h = atmosphere.util.isFunction(value) ? value.call(this, rq, request, _response) : value;
1570+ if (h != null) {
1571+ url += "&" + encodeURIComponent(name) + "=" + encodeURIComponent(h);
1572+ }
1573+ });
1574+
1575+ return url;
1576+ }
1577+
1578+ function _triggerOpen(rq) {
1579+ if (!rq.isOpen) {
1580+ rq.isOpen = true;
1581+ _open('opening', rq.transport, rq);
1582+ } else if (rq.isReopen) {
1583+ rq.isReopen = false;
1584+ _open('re-opening', rq.transport, rq);
1585+ }
1586+ }
1587+
1588+ /**
1589+ * Execute ajax request. <br>
1590+ *
1591+ * @param request {Object} request Request parameters, if undefined _request object will be used.
1592+ * @private
1593+ */
1594+ function _executeRequest(request) {
1595+ var rq = _request;
1596+ if ((request != null) || (typeof (request) !== 'undefined')) {
1597+ rq = request;
1598+ }
1599+
1600+ rq.lastIndex = 0;
1601+ rq.readyState = 0;
1602+
1603+ // CORS fake using JSONP
1604+ if ((rq.transport === 'jsonp') || ((rq.enableXDR) && (atmosphere.util.checkCORSSupport()))) {
1605+ _jsonp(rq);
1606+ return;
1607+ }
1608+
1609+ if (atmosphere.util.browser.msie && +atmosphere.util.browser.version.split(".")[0] < 10) {
1610+ if ((rq.transport === 'streaming')) {
1611+ if (rq.enableXDR && window.XDomainRequest) {
1612+ _ieXDR(rq);
1613+ } else {
1614+ _ieStreaming(rq);
1615+ }
1616+ return;
1617+ }
1618+
1619+ if ((rq.enableXDR) && (window.XDomainRequest)) {
1620+ _ieXDR(rq);
1621+ return;
1622+ }
1623+ }
1624+
1625+ var reconnectF = function () {
1626+ rq.lastIndex = 0;
1627+ if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {
1628+ _open('re-connecting', request.transport, request);
1629+ _reconnect(ajaxRequest, rq, request.reconnectInterval);
1630+ } else {
1631+ _onError(0, "maxReconnectOnClose reached");
1632+ }
1633+ };
1634+
1635+ if (rq.force || (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest))) {
1636+ rq.force = false;
1637+
1638+ var ajaxRequest = atmosphere.util.xhr();
1639+ ajaxRequest.hasData = false;
1640+
1641+ _doRequest(ajaxRequest, rq, true);
1642+
1643+ if (rq.suspend) {
1644+ _activeRequest = ajaxRequest;
1645+ }
1646+
1647+ if (rq.transport !== 'polling') {
1648+ _response.transport = rq.transport;
1649+
1650+ ajaxRequest.onabort = function () {
1651+ _invokeClose(true);
1652+ };
1653+
1654+ ajaxRequest.onerror = function () {
1655+ _response.error = true;
1656+ try {
1657+ _response.status = XMLHttpRequest.status;
1658+ } catch (e) {
1659+ _response.status = 500;
1660+ }
1661+
1662+ if (!_response.status) {
1663+ _response.status = 500;
1664+ }
1665+ if (!_response.errorHandled) {
1666+ _clearState();
1667+ reconnectF();
1668+ }
1669+ };
1670+ }
1671+
1672+ ajaxRequest.onreadystatechange = function () {
1673+ if (_abordingConnection) {
1674+ return;
1675+ }
1676+
1677+ _response.error = null;
1678+ var skipCallbackInvocation = false;
1679+ var update = false;
1680+
1681+ if (rq.transport === 'streaming' && rq.readyState > 2 && ajaxRequest.readyState === 4) {
1682+ _clearState();
1683+ reconnectF();
1684+ return;
1685+ }
1686+
1687+ rq.readyState = ajaxRequest.readyState;
1688+
1689+ if (rq.transport === 'streaming' && ajaxRequest.readyState >= 3) {
1690+ update = true;
1691+ } else if (rq.transport === 'long-polling' && ajaxRequest.readyState === 4) {
1692+ update = true;
1693+ }
1694+ _timeout(_request);
1695+
1696+ if (rq.transport !== 'polling') {
1697+ // MSIE 9 and lower status can be higher than 1000, Chrome can be 0
1698+ var status = 200;
1699+ if (ajaxRequest.readyState === 4) {
1700+ status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;
1701+ }
1702+
1703+ if (status >= 300 || status === 0) {
1704+ // Prevent onerror callback to be called
1705+ _response.errorHandled = true;
1706+ _clearState();
1707+ reconnectF();
1708+ return;
1709+ }
1710+
1711+ // Firefox incorrectly send statechange 0->2 when a reconnect attempt fails. The above checks ensure that onopen is not called for these
1712+ if ((!rq.enableProtocol || !request.firstMessage) && ajaxRequest.readyState === 2) {
1713+ _triggerOpen(rq);
1714+ }
1715+
1716+ } else if (ajaxRequest.readyState === 4) {
1717+ update = true;
1718+ }
1719+
1720+ if (update) {
1721+ var responseText = ajaxRequest.responseText;
1722+
1723+ if (atmosphere.util.trim(responseText).length === 0 && rq.transport === 'long-polling') {
1724+ // For browser that aren't support onabort
1725+ if (!ajaxRequest.hasData) {
1726+ _reconnect(ajaxRequest, rq, 0);
1727+ } else {
1728+ ajaxRequest.hasData = false;
1729+ }
1730+ return;
1731+ }
1732+ ajaxRequest.hasData = true;
1733+
1734+ _readHeaders(ajaxRequest, _request);
1735+
1736+ if (rq.transport === 'streaming') {
1737+ if (!atmosphere.util.browser.opera) {
1738+ var message = responseText.substring(rq.lastIndex, responseText.length);
1739+ skipCallbackInvocation = _trackMessageSize(message, rq, _response);
1740+
1741+ rq.lastIndex = responseText.length;
1742+ if (skipCallbackInvocation) {
1743+ return;
1744+ }
1745+ } else {
1746+ atmosphere.util.iterate(function () {
1747+ if (_response.status !== 500 && ajaxRequest.responseText.length > rq.lastIndex) {
1748+ try {
1749+ _response.status = ajaxRequest.status;
1750+ _response.headers = atmosphere.util.parseHeaders(ajaxRequest.getAllResponseHeaders());
1751+
1752+ _readHeaders(ajaxRequest, _request);
1753+
1754+ } catch (e) {
1755+ _response.status = 404;
1756+ }
1757+ _timeout(_request);
1758+
1759+ _response.state = "messageReceived";
1760+ var message = ajaxRequest.responseText.substring(rq.lastIndex);
1761+ rq.lastIndex = ajaxRequest.responseText.length;
1762+
1763+ skipCallbackInvocation = _trackMessageSize(message, rq, _response);
1764+ if (!skipCallbackInvocation) {
1765+ _invokeCallback();
1766+ }
1767+
1768+ _verifyStreamingLength(ajaxRequest, rq);
1769+ } else if (_response.status > 400) {
1770+ // Prevent replaying the last message.
1771+ rq.lastIndex = ajaxRequest.responseText.length;
1772+ return false;
1773+ }
1774+ }, 0);
1775+ }
1776+ } else {
1777+ skipCallbackInvocation = _trackMessageSize(responseText, rq, _response);
1778+ }
1779+
1780+ try {
1781+ _response.status = ajaxRequest.status;
1782+ _response.headers = atmosphere.util.parseHeaders(ajaxRequest.getAllResponseHeaders());
1783+
1784+ _readHeaders(ajaxRequest, rq);
1785+ } catch (e) {
1786+ _response.status = 404;
1787+ }
1788+
1789+ if (rq.suspend) {
1790+ _response.state = _response.status === 0 ? "closed" : "messageReceived";
1791+ } else {
1792+ _response.state = "messagePublished";
1793+ }
1794+
1795+ var isAllowedToReconnect = request.transport !== 'streaming' && request.transport !== 'polling';
1796+ if (isAllowedToReconnect && !rq.executeCallbackBeforeReconnect) {
1797+ _reconnect(ajaxRequest, rq, 0);
1798+ }
1799+
1800+ if (_response.responseBody.length !== 0 && !skipCallbackInvocation)
1801+ _invokeCallback();
1802+
1803+ if (isAllowedToReconnect && rq.executeCallbackBeforeReconnect) {
1804+ _reconnect(ajaxRequest, rq, 0);
1805+ }
1806+
1807+ _verifyStreamingLength(ajaxRequest, rq);
1808+ }
1809+ };
1810+
1811+ try {
1812+ ajaxRequest.send(rq.data);
1813+ _subscribed = true;
1814+ } catch (e) {
1815+ atmosphere.util.log(rq.logLevel, ["Unable to connect to " + rq.url]);
1816+ }
1817+
1818+ } else {
1819+ if (rq.logLevel === 'debug') {
1820+ atmosphere.util.log(rq.logLevel, ["Max re-connection reached."]);
1821+ }
1822+ _onError(0, "maxRequest reached");
1823+ }
1824+ }
1825+
1826+ /**
1827+ * Do ajax request.
1828+ *
1829+ * @param ajaxRequest Ajax request.
1830+ * @param request Request parameters.
1831+ * @param create If ajax request has to be open.
1832+ */
1833+ function _doRequest(ajaxRequest, request, create) {
1834+ // Prevent Android to cache request
1835+ var url = request.url;
1836+ if (request.dispatchUrl != null && request.method === 'POST') {
1837+ url += request.dispatchUrl;
1838+ }
1839+ url = _attachHeaders(request, url);
1840+ url = atmosphere.util.prepareURL(url);
1841+
1842+ if (create) {
1843+ ajaxRequest.open(request.method, url, request.async);
1844+ if (request.connectTimeout > 0) {
1845+ request.id = setTimeout(function () {
1846+ if (request.requestCount === 0) {
1847+ _clearState();
1848+ _prepareCallback("Connect timeout", "closed", 200, request.transport);
1849+ }
1850+ }, request.connectTimeout);
1851+ }
1852+ }
1853+
1854+ if (_request.withCredentials) {
1855+ if ("withCredentials" in ajaxRequest) {
1856+ ajaxRequest.withCredentials = true;
1857+ }
1858+ }
1859+
1860+ if (!_request.dropHeaders) {
1861+ ajaxRequest.setRequestHeader("X-Atmosphere-Framework", atmosphere.util.version);
1862+ ajaxRequest.setRequestHeader("X-Atmosphere-Transport", request.transport);
1863+ if (request.lastTimestamp != null) {
1864+ ajaxRequest.setRequestHeader("X-Cache-Date", request.lastTimestamp);
1865+ } else {
1866+ ajaxRequest.setRequestHeader("X-Cache-Date", 0);
1867+ }
1868+
1869+ if (request.trackMessageLength) {
1870+ ajaxRequest.setRequestHeader("X-Atmosphere-TrackMessageSize", "true");
1871+ }
1872+ ajaxRequest.setRequestHeader("X-Atmosphere-tracking-id", request.uuid);
1873+
1874+ atmosphere.util.each(request.headers, function (name, value) {
1875+ var h = atmosphere.util.isFunction(value) ? value.call(this, ajaxRequest, request, create, _response) : value;
1876+ if (h != null) {
1877+ ajaxRequest.setRequestHeader(name, h);
1878+ }
1879+ });
1880+ }
1881+
1882+ if (request.contentType !== '') {
1883+ ajaxRequest.setRequestHeader("Content-Type", request.contentType);
1884+ }
1885+ }
1886+
1887+ function _reconnect(ajaxRequest, request, reconnectInterval) {
1888+ if (request.reconnect || (request.suspend && _subscribed)) {
1889+ var status = 0;
1890+ if (ajaxRequest && ajaxRequest.readyState > 1) {
1891+ status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;
1892+ }
1893+ _response.status = status === 0 ? 204 : status;
1894+ _response.reason = status === 0 ? "Server resumed the connection or down." : "OK";
1895+
1896+ clearTimeout(request.id);
1897+ if (request.reconnectId) {
1898+ clearTimeout(request.reconnectId);
1899+ delete request.reconnectId;
1900+ }
1901+
1902+ if (reconnectInterval > 0) {
1903+ // For whatever reason, never cancel a reconnect timeout as it is mandatory to reconnect.
1904+ _request.reconnectId = setTimeout(function () {
1905+ _executeRequest(request);
1906+ }, reconnectInterval);
1907+ } else {
1908+ _executeRequest(request);
1909+ }
1910+ }
1911+ }
1912+
1913+ function _tryingToReconnect(response) {
1914+ response.state = 're-connecting';
1915+ _invokeFunction(response);
1916+ }
1917+
1918+ function _ieXDR(request) {
1919+ if (request.transport !== "polling") {
1920+ _ieStream = _configureXDR(request);
1921+ _ieStream.open();
1922+ } else {
1923+ _configureXDR(request).open();
1924+ }
1925+ }
1926+
1927+ function _configureXDR(request) {
1928+ var rq = _request;
1929+ if ((request != null) && (typeof (request) !== 'undefined')) {
1930+ rq = request;
1931+ }
1932+
1933+ var transport = rq.transport;
1934+ var lastIndex = 0;
1935+ var xdr = new window.XDomainRequest();
1936+
1937+ var reconnect = function () {
1938+ if (rq.transport === "long-polling" && (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest))) {
1939+ xdr.status = 200;
1940+ _ieXDR(rq);
1941+ }
1942+ };
1943+
1944+ var rewriteURL = rq.rewriteURL || function (url) {
1945+ // Maintaining session by rewriting URL
1946+ // http://stackoverflow.com/questions/6453779/maintaining-session-by-rewriting-url
1947+ var match = /(?:^|;\s*)(JSESSIONID|PHPSESSID)=([^;]*)/.exec(document.cookie);
1948+
1949+ switch (match && match[1]) {
1950+ case "JSESSIONID":
1951+ return url.replace(/;jsessionid=[^\?]*|(\?)|$/, ";jsessionid=" + match[2] + "$1");
1952+ case "PHPSESSID":
1953+ return url.replace(/\?PHPSESSID=[^&]*&?|\?|$/, "?PHPSESSID=" + match[2] + "&").replace(/&$/, "");
1954+ }
1955+ return url;
1956+ };
1957+
1958+ // Handles open and message event
1959+ xdr.onprogress = function () {
1960+ handle(xdr);
1961+ };
1962+ // Handles error event
1963+ xdr.onerror = function () {
1964+ // If the server doesn't send anything back to XDR will fail with polling
1965+ if (rq.transport !== 'polling') {
1966+ _clearState();
1967+ if (_requestCount++ < rq.maxReconnectOnClose) {
1968+ if (rq.reconnectInterval > 0) {
1969+ rq.reconnectId = setTimeout(function () {
1970+ _open('re-connecting', request.transport, request);
1971+ _ieXDR(rq);
1972+ }, rq.reconnectInterval);
1973+ } else {
1974+ _open('re-connecting', request.transport, request);
1975+ _ieXDR(rq);
1976+ }
1977+ } else {
1978+ _onError(0, "maxReconnectOnClose reached");
1979+ }
1980+ }
1981+ };
1982+
1983+ // Handles close event
1984+ xdr.onload = function () {
1985+ };
1986+
1987+ var handle = function (xdr) {
1988+ clearTimeout(rq.id);
1989+ var message = xdr.responseText;
1990+
1991+ message = message.substring(lastIndex);
1992+ lastIndex += message.length;
1993+
1994+ if (transport !== 'polling') {
1995+ _timeout(rq);
1996+
1997+ var skipCallbackInvocation = _trackMessageSize(message, rq, _response);
1998+
1999+ if (transport === 'long-polling' && atmosphere.util.trim(message).length === 0)
2000+ return;
2001+
2002+ if (rq.executeCallbackBeforeReconnect) {
2003+ reconnect();
2004+ }
2005+
2006+ if (!skipCallbackInvocation) {
2007+ _prepareCallback(_response.responseBody, "messageReceived", 200, transport);
2008+ }
2009+
2010+ if (!rq.executeCallbackBeforeReconnect) {
2011+ reconnect();
2012+ }
2013+ }
2014+ };
2015+
2016+ return {
2017+ open: function () {
2018+ var url = rq.url;
2019+ if (rq.dispatchUrl != null) {
2020+ url += rq.dispatchUrl;
2021+ }
2022+ url = _attachHeaders(rq, url);
2023+ xdr.open(rq.method, rewriteURL(url));
2024+ if (rq.method === 'GET') {
2025+ xdr.send();
2026+ } else {
2027+ xdr.send(rq.data);
2028+ }
2029+
2030+ if (rq.connectTimeout > 0) {
2031+ rq.id = setTimeout(function () {
2032+ if (rq.requestCount === 0) {
2033+ _clearState();
2034+ _prepareCallback("Connect timeout", "closed", 200, rq.transport);
2035+ }
2036+ }, rq.connectTimeout);
2037+ }
2038+ },
2039+ close: function () {
2040+ xdr.abort();
2041+ }
2042+ };
2043+ }
2044+
2045+ function _ieStreaming(request) {
2046+ _ieStream = _configureIE(request);
2047+ _ieStream.open();
2048+ }
2049+
2050+ function _configureIE(request) {
2051+ var rq = _request;
2052+ if ((request != null) && (typeof (request) !== 'undefined')) {
2053+ rq = request;
2054+ }
2055+
2056+ var stop;
2057+ var doc = new window.ActiveXObject("htmlfile");
2058+
2059+ doc.open();
2060+ doc.close();
2061+
2062+ var url = rq.url;
2063+ if (rq.dispatchUrl != null) {
2064+ url += rq.dispatchUrl;
2065+ }
2066+
2067+ if (rq.transport !== 'polling') {
2068+ _response.transport = rq.transport;
2069+ }
2070+
2071+ return {
2072+ open: function () {
2073+ var iframe = doc.createElement("iframe");
2074+
2075+ url = _attachHeaders(rq);
2076+ if (rq.data !== '') {
2077+ url += "&X-Atmosphere-Post-Body=" + encodeURIComponent(rq.data);
2078+ }
2079+
2080+ // Finally attach a timestamp to prevent Android and IE caching.
2081+ url = atmosphere.util.prepareURL(url);
2082+
2083+ iframe.src = url;
2084+ doc.body.appendChild(iframe);
2085+
2086+ // For the server to respond in a consistent format regardless of user agent, we polls response text
2087+ var cdoc = iframe.contentDocument || iframe.contentWindow.document;
2088+
2089+ stop = atmosphere.util.iterate(function () {
2090+ try {
2091+ if (!cdoc.firstChild) {
2092+ return;
2093+ }
2094+
2095+ var res = cdoc.body ? cdoc.body.lastChild : cdoc;
2096+ var readResponse = function () {
2097+ // Clones the element not to disturb the original one
2098+ var clone = res.cloneNode(true);
2099+
2100+ // If the last character is a carriage return or a line feed, IE ignores it in the innerText property
2101+ // therefore, we add another non-newline character to preserve it
2102+ clone.appendChild(cdoc.createTextNode("."));
2103+
2104+ var text = clone.innerText;
2105+
2106+ text = text.substring(0, text.length - 1);
2107+ return text;
2108+
2109+ };
2110+
2111+ // To support text/html content type
2112+ if (!cdoc.body || !cdoc.body.firstChild || cdoc.body.firstChild.nodeName.toLowerCase() !== "pre") {
2113+ // Injects a plaintext element which renders text without interpreting the HTML and cannot be stopped
2114+ // it is deprecated in HTML5, but still works
2115+ var head = cdoc.head || cdoc.getElementsByTagName("head")[0] || cdoc.documentElement || cdoc;
2116+ var script = cdoc.createElement("script");
2117+
2118+ script.text = "document.write('<plaintext>')";
2119+
2120+ head.insertBefore(script, head.firstChild);
2121+ head.removeChild(script);
2122+
2123+ // The plaintext element will be the response container
2124+ res = cdoc.body.lastChild;
2125+ }
2126+
2127+ if (rq.closed) {
2128+ rq.isReopen = true;
2129+ }
2130+
2131+ // Handles message and close event
2132+ stop = atmosphere.util.iterate(function () {
2133+ var text = readResponse();
2134+ if (text.length > rq.lastIndex) {
2135+ _timeout(_request);
2136+
2137+ _response.status = 200;
2138+ _response.error = null;
2139+
2140+ // Empties response every time that it is handled
2141+ res.innerText = "";
2142+ var skipCallbackInvocation = _trackMessageSize(text, rq, _response);
2143+ if (skipCallbackInvocation) {
2144+ return "";
2145+ }
2146+
2147+ _prepareCallback(_response.responseBody, "messageReceived", 200, rq.transport);
2148+ }
2149+
2150+ rq.lastIndex = 0;
2151+
2152+ if (cdoc.readyState === "complete") {
2153+ _invokeClose(true);
2154+ _open('re-connecting', rq.transport, rq);
2155+ if (rq.reconnectInterval > 0) {
2156+ rq.reconnectId = setTimeout(function () {
2157+ _ieStreaming(rq);
2158+ }, rq.reconnectInterval);
2159+ } else {
2160+ _ieStreaming(rq);
2161+ }
2162+ return false;
2163+ }
2164+ }, null);
2165+
2166+ return false;
2167+ } catch (err) {
2168+ _response.error = true;
2169+ _open('re-connecting', rq.transport, rq);
2170+ if (_requestCount++ < rq.maxReconnectOnClose) {
2171+ if (rq.reconnectInterval > 0) {
2172+ rq.reconnectId = setTimeout(function () {
2173+ _ieStreaming(rq);
2174+ }, rq.reconnectInterval);
2175+ } else {
2176+ _ieStreaming(rq);
2177+ }
2178+ } else {
2179+ _onError(0, "maxReconnectOnClose reached");
2180+ }
2181+ doc.execCommand("Stop");
2182+ doc.close();
2183+ return false;
2184+ }
2185+ });
2186+ },
2187+
2188+ close: function () {
2189+ if (stop) {
2190+ stop();
2191+ }
2192+
2193+ doc.execCommand("Stop");
2194+ _invokeClose(true);
2195+ }
2196+ };
2197+ }
2198+
2199+ /**
2200+ * Send message. <br>
2201+ * Will be automatically dispatch to other connected.
2202+ *
2203+ * @param {Object, string} Message to send.
2204+ * @private
2205+ */
2206+ function _push(message) {
2207+
2208+ if (_localStorageService != null) {
2209+ _pushLocal(message);
2210+ } else if (_activeRequest != null || _sse != null) {
2211+ _pushAjaxMessage(message);
2212+ } else if (_ieStream != null) {
2213+ _pushIE(message);
2214+ } else if (_jqxhr != null) {
2215+ _pushJsonp(message);
2216+ } else if (_websocket != null) {
2217+ _pushWebSocket(message);
2218+ } else {
2219+ _onError(0, "No suspended connection available");
2220+ atmosphere.util.error("No suspended connection available. Make sure atmosphere.subscribe has been called and request.onOpen invoked before invoking this method");
2221+ }
2222+ }
2223+
2224+ function _pushOnClose(message, rq) {
2225+ if (!rq) {
2226+ rq = _getPushRequest(message);
2227+ }
2228+ rq.transport = "polling";
2229+ rq.method = "GET";
2230+ rq.async = false;
2231+ rq.withCredentials = false;
2232+ rq.reconnect = false;
2233+ rq.force = true;
2234+ rq.suspend = false;
2235+ rq.timeout = 1000;
2236+ _executeRequest(rq);
2237+ }
2238+
2239+ function _pushLocal(message) {
2240+ _localStorageService.send(message);
2241+ }
2242+
2243+ function _intraPush(message) {
2244+ // IE 9 will crash if not.
2245+ if (message.length === 0)
2246+ return;
2247+
2248+ try {
2249+ if (_localStorageService) {
2250+ _localStorageService.localSend(message);
2251+ } else if (_storageService) {
2252+ _storageService.signal("localMessage", atmosphere.util.stringifyJSON({
2253+ id: guid,
2254+ event: message
2255+ }));
2256+ }
2257+ } catch (err) {
2258+ atmosphere.util.error(err);
2259+ }
2260+ }
2261+
2262+ /**
2263+ * Send a message using currently opened ajax request (using http-streaming or long-polling). <br>
2264+ *
2265+ * @param {string, Object} Message to send. This is an object, string message is saved in data member.
2266+ * @private
2267+ */
2268+ function _pushAjaxMessage(message) {
2269+ var rq = _getPushRequest(message);
2270+ _executeRequest(rq);
2271+ }
2272+
2273+ /**
2274+ * Send a message using currently opened ie streaming (using http-streaming or long-polling). <br>
2275+ *
2276+ * @param {string, Object} Message to send. This is an object, string message is saved in data member.
2277+ * @private
2278+ */
2279+ function _pushIE(message) {
2280+ if (_request.enableXDR && atmosphere.util.checkCORSSupport()) {
2281+ var rq = _getPushRequest(message);
2282+ // Do not reconnect since we are pushing.
2283+ rq.reconnect = false;
2284+ _jsonp(rq);
2285+ } else {
2286+ _pushAjaxMessage(message);
2287+ }
2288+ }
2289+
2290+ /**
2291+ * Send a message using jsonp transport. <br>
2292+ *
2293+ * @param {string, Object} Message to send. This is an object, string message is saved in data member.
2294+ * @private
2295+ */
2296+ function _pushJsonp(message) {
2297+ _pushAjaxMessage(message);
2298+ }
2299+
2300+ function _getStringMessage(message) {
2301+ var msg = message;
2302+ if (typeof (msg) === 'object') {
2303+ msg = message.data;
2304+ }
2305+ return msg;
2306+ }
2307+
2308+ /**
2309+ * Build request use to push message using method 'POST' <br>. Transport is defined as 'polling' and 'suspend' is set to false.
2310+ *
2311+ * @return {Object} Request object use to push message.
2312+ * @private
2313+ */
2314+ function _getPushRequest(message) {
2315+ var msg = _getStringMessage(message);
2316+
2317+ var rq = {
2318+ connected: false,
2319+ timeout: 60000,
2320+ method: 'POST',
2321+ url: _request.url,
2322+ contentType: _request.contentType,
2323+ headers: _request.headers,
2324+ reconnect: true,
2325+ callback: null,
2326+ data: msg,
2327+ suspend: false,
2328+ maxRequest: -1,
2329+ logLevel: 'info',
2330+ requestCount: 0,
2331+ withCredentials: _request.withCredentials,
2332+ async: _request.async,
2333+ transport: 'polling',
2334+ isOpen: true,
2335+ attachHeadersAsQueryString: true,
2336+ enableXDR: _request.enableXDR,
2337+ uuid: _request.uuid,
2338+ dispatchUrl: _request.dispatchUrl,
2339+ enableProtocol: false,
2340+ messageDelimiter: '|',
2341+ maxReconnectOnClose: _request.maxReconnectOnClose
2342+ };
2343+
2344+ if (typeof (message) === 'object') {
2345+ rq = atmosphere.util.extend(rq, message);
2346+ }
2347+
2348+ return rq;
2349+ }
2350+
2351+ /**
2352+ * Send a message using currently opened websocket. <br>
2353+ *
2354+ */
2355+ function _pushWebSocket(message) {
2356+ var msg = atmosphere.util.isBinary(message) ? message : _getStringMessage(message);
2357+ var data;
2358+ try {
2359+ if (_request.dispatchUrl != null) {
2360+ data = _request.webSocketPathDelimiter + _request.dispatchUrl + _request.webSocketPathDelimiter + msg;
2361+ } else {
2362+ data = msg;
2363+ }
2364+
2365+ if (!_websocket.webSocketOpened) {
2366+ atmosphere.util.error("WebSocket not connected.");
2367+ return;
2368+ }
2369+
2370+ _websocket.send(data);
2371+
2372+ } catch (e) {
2373+ _websocket.onclose = function (message) {
2374+ };
2375+ _clearState();
2376+
2377+ _reconnectWithFallbackTransport("Websocket failed. Downgrading to Comet and resending " + message);
2378+ _pushAjaxMessage(message);
2379+ }
2380+ }
2381+
2382+ function _localMessage(message) {
2383+ var m = atmosphere.util.parseJSON(message);
2384+ if (m.id !== guid) {
2385+ if (typeof (_request.onLocalMessage) !== 'undefined') {
2386+ _request.onLocalMessage(m.event);
2387+ } else if (typeof (atmosphere.util.onLocalMessage) !== 'undefined') {
2388+ atmosphere.util.onLocalMessage(m.event);
2389+ }
2390+ }
2391+ }
2392+
2393+ function _prepareCallback(messageBody, state, errorCode, transport) {
2394+
2395+ _response.responseBody = messageBody;
2396+ _response.transport = transport;
2397+ _response.status = errorCode;
2398+ _response.state = state;
2399+
2400+ _invokeCallback();
2401+ }
2402+
2403+ function _readHeaders(xdr, request) {
2404+ if (!request.readResponsesHeaders) {
2405+ if (!request.enableProtocol) {
2406+ request.lastTimestamp = atmosphere.util.now();
2407+ request.uuid = guid;
2408+ }
2409+ }
2410+ else {
2411+ try {
2412+ var tempDate = xdr.getResponseHeader('X-Cache-Date');
2413+ if (tempDate && tempDate != null && tempDate.length > 0) {
2414+ request.lastTimestamp = tempDate.split(" ").pop();
2415+ }
2416+
2417+ var tempUUID = xdr.getResponseHeader('X-Atmosphere-tracking-id');
2418+ if (tempUUID && tempUUID != null) {
2419+ request.uuid = tempUUID.split(" ").pop();
2420+ }
2421+ } catch (e) {
2422+ }
2423+ }
2424+ }
2425+
2426+ function _invokeFunction(response) {
2427+ _f(response, _request);
2428+ // Global
2429+ _f(response, atmosphere.util);
2430+ }
2431+
2432+ function _f(response, f) {
2433+ switch (response.state) {
2434+ case "messageReceived":
2435+ _requestCount = 0;
2436+ if (typeof (f.onMessage) !== 'undefined')
2437+ f.onMessage(response);
2438+ break;
2439+ case "error":
2440+ if (typeof (f.onError) !== 'undefined')
2441+ f.onError(response);
2442+ break;
2443+ case "opening":
2444+ delete _request.closed;
2445+ if (typeof (f.onOpen) !== 'undefined')
2446+ f.onOpen(response);
2447+ break;
2448+ case "messagePublished":
2449+ if (typeof (f.onMessagePublished) !== 'undefined')
2450+ f.onMessagePublished(response);
2451+ break;
2452+ case "re-connecting":
2453+ if (typeof (f.onReconnect) !== 'undefined')
2454+ f.onReconnect(_request, response);
2455+ break;
2456+ case "closedByClient":
2457+ if (typeof (f.onClientTimeout) !== 'undefined')
2458+ f.onClientTimeout(_request);
2459+ break;
2460+ case "re-opening":
2461+ delete _request.closed;
2462+ if (typeof (f.onReopen) !== 'undefined')
2463+ f.onReopen(_request, response);
2464+ break;
2465+ case "fail-to-reconnect":
2466+ if (typeof (f.onFailureToReconnect) !== 'undefined')
2467+ f.onFailureToReconnect(_request, response);
2468+ break;
2469+ case "unsubscribe":
2470+ case "closed":
2471+ var closed = typeof (_request.closed) !== 'undefined' ? _request.closed : false;
2472+ if (typeof (f.onClose) !== 'undefined' && !closed)
2473+ f.onClose(response);
2474+ _request.closed = true;
2475+ break;
2476+ }
2477+ }
2478+
2479+ function _invokeClose(wasOpen) {
2480+ if (_response.state !== 'closed') {
2481+ _response.state = 'closed';
2482+ _response.responseBody = "";
2483+ _response.messages = [];
2484+ _response.status = !wasOpen ? 501 : 200;
2485+ _invokeCallback();
2486+ }
2487+ }
2488+
2489+ /**
2490+ * Invoke request callbacks.
2491+ *
2492+ * @private
2493+ */
2494+ function _invokeCallback() {
2495+ var call = function (index, func) {
2496+ func(_response);
2497+ };
2498+
2499+ if (_localStorageService == null && _localSocketF != null) {
2500+ _localSocketF(_response.responseBody);
2501+ }
2502+
2503+ _request.reconnect = _request.mrequest;
2504+
2505+ var isString = typeof (_response.responseBody) === 'string';
2506+ var messages = (isString && _request.trackMessageLength) ? (_response.messages.length > 0 ? _response.messages : ['']) : new Array(
2507+ _response.responseBody);
2508+ for (var i = 0; i < messages.length; i++) {
2509+
2510+ if (messages.length > 1 && messages[i].length === 0) {
2511+ continue;
2512+ }
2513+ _response.responseBody = (isString) ? atmosphere.util.trim(messages[i]) : messages[i];
2514+
2515+ if (_localStorageService == null && _localSocketF != null) {
2516+ _localSocketF(_response.responseBody);
2517+ }
2518+
2519+ if (_response.responseBody.length === 0 && _response.state === "messageReceived") {
2520+ continue;
2521+ }
2522+
2523+ _invokeFunction(_response);
2524+
2525+ // Invoke global callbacks
2526+ if (callbacks.length > 0) {
2527+ if (_request.logLevel === 'debug') {
2528+ atmosphere.util.debug("Invoking " + callbacks.length + " global callbacks: " + _response.state);
2529+ }
2530+ try {
2531+ atmosphere.util.each(callbacks, call);
2532+ } catch (e) {
2533+ atmosphere.util.log(_request.logLevel, ["Callback exception" + e]);
2534+ }
2535+ }
2536+
2537+ // Invoke request callback
2538+ if (typeof (_request.callback) === 'function') {
2539+ if (_request.logLevel === 'debug') {
2540+ atmosphere.util.debug("Invoking request callbacks");
2541+ }
2542+ try {
2543+ _request.callback(_response);
2544+ } catch (e) {
2545+ atmosphere.util.log(_request.logLevel, ["Callback exception" + e]);
2546+ }
2547+ }
2548+ }
2549+ }
2550+
2551+ this.subscribe = function (options) {
2552+ _subscribe(options);
2553+ _execute();
2554+ };
2555+
2556+ this.execute = function () {
2557+ _execute();
2558+ };
2559+
2560+ this.close = function () {
2561+ _close();
2562+ };
2563+
2564+ this.disconnect = function () {
2565+ _disconnect();
2566+ };
2567+
2568+ this.getUrl = function () {
2569+ return _request.url;
2570+ };
2571+
2572+ this.push = function (message, dispatchUrl) {
2573+ if (dispatchUrl != null) {
2574+ var originalDispatchUrl = _request.dispatchUrl;
2575+ _request.dispatchUrl = dispatchUrl;
2576+ _push(message);
2577+ _request.dispatchUrl = originalDispatchUrl;
2578+ } else {
2579+ _push(message);
2580+ }
2581+ };
2582+
2583+ this.getUUID = function () {
2584+ return _request.uuid;
2585+ };
2586+
2587+ this.pushLocal = function (message) {
2588+ _intraPush(message);
2589+ };
2590+
2591+ this.enableProtocol = function (message) {
2592+ return _request.enableProtocol;
2593+ };
2594+
2595+ this.request = _request;
2596+ this.response = _response;
2597+ }
2598+ };
2599+
2600+ atmosphere.subscribe = function (url, callback, request) {
2601+ if (typeof (callback) === 'function') {
2602+ atmosphere.addCallback(callback);
2603+ }
2604+
2605+ // https://github.com/Atmosphere/atmosphere-javascript/issues/58
2606+ uuid = 0;
2607+
2608+ if (typeof (url) !== "string") {
2609+ request = url;
2610+ } else {
2611+ request.url = url;
2612+ }
2613+
2614+ var rq = new atmosphere.AtmosphereRequest(request);
2615+ rq.execute();
2616+
2617+ requests[requests.length] = rq;
2618+ return rq;
2619+ };
2620+
2621+ atmosphere.unsubscribe = function () {
2622+ if (requests.length > 0) {
2623+ var requestsClone = [].concat(requests);
2624+ for (var i = 0; i < requestsClone.length; i++) {
2625+ var rq = requestsClone[i];
2626+ rq.close();
2627+ clearTimeout(rq.response.request.id);
2628+ }
2629+ }
2630+ requests = [];
2631+ callbacks = [];
2632+ };
2633+
2634+ atmosphere.unsubscribeUrl = function (url) {
2635+ var idx = -1;
2636+ if (requests.length > 0) {
2637+ for (var i = 0; i < requests.length; i++) {
2638+ var rq = requests[i];
2639+
2640+ // Suppose you can subscribe once to an url
2641+ if (rq.getUrl() === url) {
2642+ rq.close();
2643+ clearTimeout(rq.response.request.id);
2644+ idx = i;
2645+ break;
2646+ }
2647+ }
2648+ }
2649+ if (idx >= 0) {
2650+ requests.splice(idx, 1);
2651+ }
2652+ };
2653+
2654+ atmosphere.addCallback = function (func) {
2655+ if (atmosphere.util.inArray(func, callbacks) === -1) {
2656+ callbacks.push(func);
2657+ }
2658+ };
2659+
2660+ atmosphere.removeCallback = function (func) {
2661+ var index = atmosphere.util.inArray(func, callbacks);
2662+ if (index !== -1) {
2663+ callbacks.splice(index, 1);
2664+ }
2665+ };
2666+
2667+ atmosphere.util = {
2668+ browser: {},
2669+
2670+ parseHeaders: function (headerString) {
2671+ var match, rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, headers = {};
2672+ while (match = rheaders.exec(headerString)) {
2673+ headers[match[1]] = match[2];
2674+ }
2675+ return headers;
2676+ },
2677+
2678+ now: function () {
2679+ return new Date().getTime();
2680+ },
2681+
2682+ isArray: function (array) {
2683+ return Object.prototype.toString.call(array) === "[object Array]";
2684+ },
2685+
2686+ inArray: function (elem, array) {
2687+ if (!Array.prototype.indexOf) {
2688+ var len = array.length;
2689+ for (var i = 0; i < len; ++i) {
2690+ if (array[i] === elem) {
2691+ return i;
2692+ }
2693+ }
2694+ return -1;
2695+ }
2696+ return array.indexOf(elem);
2697+ },
2698+
2699+ isBinary: function (data) {
2700+ // True if data is an instance of Blob, ArrayBuffer or ArrayBufferView
2701+ return /^\[object\s(?:Blob|ArrayBuffer|.+Array)\]$/.test(Object.prototype.toString.call(data));
2702+ },
2703+
2704+ isFunction: function (fn) {
2705+ return Object.prototype.toString.call(fn) === "[object Function]";
2706+ },
2707+
2708+ getAbsoluteURL: function (url) {
2709+ var div = document.createElement("div");
2710+
2711+ // Uses an innerHTML property to obtain an absolute URL
2712+ div.innerHTML = '<a href="' + url + '"/>';
2713+
2714+ // encodeURI and decodeURI are needed to normalize URL between IE and non-IE,
2715+ // since IE doesn't encode the href property value and return it - http://jsfiddle.net/Yq9M8/1/
2716+ return encodeURI(decodeURI(div.firstChild.href));
2717+ },
2718+
2719+ prepareURL: function (url) {
2720+ // Attaches a time stamp to prevent caching
2721+ var ts = atmosphere.util.now();
2722+ var ret = url.replace(/([?&])_=[^&]*/, "$1_=" + ts);
2723+
2724+ return ret + (ret === url ? (/\?/.test(url) ? "&" : "?") + "_=" + ts : "");
2725+ },
2726+
2727+ trim: function (str) {
2728+ if (!String.prototype.trim) {
2729+ return str.toString().replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g, "").replace(/\s+/g, " ");
2730+ } else {
2731+ return str.toString().trim();
2732+ }
2733+ },
2734+
2735+ param: function (params) {
2736+ var prefix, s = [];
2737+
2738+ function add(key, value) {
2739+ value = atmosphere.util.isFunction(value) ? value() : (value == null ? "" : value);
2740+ s.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
2741+ }
2742+
2743+ function buildParams(prefix, obj) {
2744+ var name;
2745+
2746+ if (atmosphere.util.isArray(obj)) {
2747+ atmosphere.util.each(obj, function (i, v) {
2748+ if (/\[\]$/.test(prefix)) {
2749+ add(prefix, v);
2750+ } else {
2751+ buildParams(prefix + "[" + (typeof v === "object" ? i : "") + "]", v);
2752+ }
2753+ });
2754+ } else if (Object.prototype.toString.call(obj) === "[object Object]") {
2755+ for (name in obj) {
2756+ buildParams(prefix + "[" + name + "]", obj[name]);
2757+ }
2758+ } else {
2759+ add(prefix, obj);
2760+ }
2761+ }
2762+
2763+ for (prefix in params) {
2764+ buildParams(prefix, params[prefix]);
2765+ }
2766+
2767+ return s.join("&").replace(/%20/g, "+");
2768+ },
2769+
2770+ storage: !!(window.localStorage && window.StorageEvent),
2771+
2772+ iterate: function (fn, interval) {
2773+ var timeoutId;
2774+
2775+ // Though the interval is 0 for real-time application, there is a delay between setTimeout calls
2776+ // For detail, see https://developer.mozilla.org/en/window.setTimeout#Minimum_delay_and_timeout_nesting
2777+ interval = interval || 0;
2778+
2779+ (function loop() {
2780+ timeoutId = setTimeout(function () {
2781+ if (fn() === false) {
2782+ return;
2783+ }
2784+
2785+ loop();
2786+ }, interval);
2787+ })();
2788+
2789+ return function () {
2790+ clearTimeout(timeoutId);
2791+ };
2792+ },
2793+
2794+ each: function (obj, callback, args) {
2795+ if (!obj) return;
2796+ var value, i = 0, length = obj.length, isArray = atmosphere.util.isArray(obj);
2797+
2798+ if (args) {
2799+ if (isArray) {
2800+ for (; i < length; i++) {
2801+ value = callback.apply(obj[i], args);
2802+
2803+ if (value === false) {
2804+ break;
2805+ }
2806+ }
2807+ } else {
2808+ for (i in obj) {
2809+ value = callback.apply(obj[i], args);
2810+
2811+ if (value === false) {
2812+ break;
2813+ }
2814+ }
2815+ }
2816+
2817+ // A special, fast, case for the most common use of each
2818+ } else {
2819+ if (isArray) {
2820+ for (; i < length; i++) {
2821+ value = callback.call(obj[i], i, obj[i]);
2822+
2823+ if (value === false) {
2824+ break;
2825+ }
2826+ }
2827+ } else {
2828+ for (i in obj) {
2829+ value = callback.call(obj[i], i, obj[i]);
2830+
2831+ if (value === false) {
2832+ break;
2833+ }
2834+ }
2835+ }
2836+ }
2837+
2838+ return obj;
2839+ },
2840+
2841+ extend: function (target) {
2842+ var i, options, name;
2843+
2844+ for (i = 1; i < arguments.length; i++) {
2845+ if ((options = arguments[i]) != null) {
2846+ for (name in options) {
2847+ target[name] = options[name];
2848+ }
2849+ }
2850+ }
2851+
2852+ return target;
2853+ },
2854+ on: function (elem, type, fn) {
2855+ if (elem.addEventListener) {
2856+ elem.addEventListener(type, fn, false);
2857+ } else if (elem.attachEvent) {
2858+ elem.attachEvent("on" + type, fn);
2859+ }
2860+ },
2861+ off: function (elem, type, fn) {
2862+ if (elem.removeEventListener) {
2863+ elem.removeEventListener(type, fn, false);
2864+ } else if (elem.detachEvent) {
2865+ elem.detachEvent("on" + type, fn);
2866+ }
2867+ },
2868+
2869+ log: function (level, args) {
2870+ if (window.console) {
2871+ var logger = window.console[level];
2872+ if (typeof logger === 'function') {
2873+ logger.apply(window.console, args);
2874+ }
2875+ }
2876+ },
2877+
2878+ warn: function () {
2879+ atmosphere.util.log('warn', arguments);
2880+ },
2881+
2882+ info: function () {
2883+ atmosphere.util.log('info', arguments);
2884+ },
2885+
2886+ debug: function () {
2887+ atmosphere.util.log('debug', arguments);
2888+ },
2889+
2890+ error: function () {
2891+ atmosphere.util.log('error', arguments);
2892+ },
2893+ xhr: function () {
2894+ try {
2895+ return new window.XMLHttpRequest();
2896+ } catch (e1) {
2897+ try {
2898+ return new window.ActiveXObject("Microsoft.XMLHTTP");
2899+ } catch (e2) {
2900+ }
2901+ }
2902+ },
2903+ parseJSON: function (data) {
2904+ return !data ? null : window.JSON && window.JSON.parse ? window.JSON.parse(data) : new Function("return " + data)();
2905+ },
2906+ // http://github.com/flowersinthesand/stringifyJSON
2907+ stringifyJSON: function (value) {
2908+ var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, meta = {
2909+ '\b': '\\b',
2910+ '\t': '\\t',
2911+ '\n': '\\n',
2912+ '\f': '\\f',
2913+ '\r': '\\r',
2914+ '"': '\\"',
2915+ '\\': '\\\\'
2916+ };
2917+
2918+ function quote(string) {
2919+ return '"' + string.replace(escapable, function (a) {
2920+ var c = meta[a];
2921+ return typeof c === "string" ? c : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
2922+ }) + '"';
2923+ }
2924+
2925+ function f(n) {
2926+ return n < 10 ? "0" + n : n;
2927+ }
2928+
2929+ return window.JSON && window.JSON.stringify ? window.JSON.stringify(value) : (function str(key, holder) {
2930+ var i, v, len, partial, value = holder[key], type = typeof value;
2931+
2932+ if (value && typeof value === "object" && typeof value.toJSON === "function") {
2933+ value = value.toJSON(key);
2934+ type = typeof value;
2935+ }
2936+
2937+ switch (type) {
2938+ case "string":
2939+ return quote(value);
2940+ case "number":
2941+ return isFinite(value) ? String(value) : "null";
2942+ case "boolean":
2943+ return String(value);
2944+ case "object":
2945+ if (!value) {
2946+ return "null";
2947+ }
2948+
2949+ switch (Object.prototype.toString.call(value)) {
2950+ case "[object Date]":
2951+ return isFinite(value.valueOf()) ? '"' + value.getUTCFullYear() + "-" + f(value.getUTCMonth() + 1) + "-"
2952+ + f(value.getUTCDate()) + "T" + f(value.getUTCHours()) + ":" + f(value.getUTCMinutes()) + ":" + f(value.getUTCSeconds())
2953+ + "Z" + '"' : "null";
2954+ case "[object Array]":
2955+ len = value.length;
2956+ partial = [];
2957+ for (i = 0; i < len; i++) {
2958+ partial.push(str(i, value) || "null");
2959+ }
2960+
2961+ return "[" + partial.join(",") + "]";
2962+ default:
2963+ partial = [];
2964+ for (i in value) {
2965+ if (hasOwn.call(value, i)) {
2966+ v = str(i, value);
2967+ if (v) {
2968+ partial.push(quote(i) + ":" + v);
2969+ }
2970+ }
2971+ }
2972+
2973+ return "{" + partial.join(",") + "}";
2974+ }
2975+ }
2976+ })("", {
2977+ "": value
2978+ });
2979+ },
2980+
2981+ checkCORSSupport: function () {
2982+ if (atmosphere.util.browser.msie && !window.XDomainRequest) {
2983+ return true;
2984+ } else if (atmosphere.util.browser.opera && atmosphere.util.browser.version < 12.0) {
2985+ return true;
2986+ }
2987+
2988+ // KreaTV 4.1 -> 4.4
2989+ else if (atmosphere.util.trim(navigator.userAgent).slice(0, 16) === "KreaTVWebKit/531") {
2990+ return true;
2991+ }
2992+ // KreaTV 3.8
2993+ else if (atmosphere.util.trim(navigator.userAgent).slice(-7).toLowerCase() === "kreatel") {
2994+ return true;
2995+ }
2996+
2997+ // Force Android to use CORS as some version like 2.2.3 fail otherwise
2998+ var ua = navigator.userAgent.toLowerCase();
2999+ var isAndroid = ua.indexOf("android") > -1;
3000+ if (isAndroid) {
3001+ return true;
3002+ }
3003+ return false;
3004+ }
3005+ };
3006+
3007+ guid = atmosphere.util.now();
3008+
3009+ // Browser sniffing
3010+ (function () {
3011+ var ua = navigator.userAgent.toLowerCase(),
3012+ match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
3013+ /(webkit)[ \/]([\w.]+)/.exec(ua) ||
3014+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
3015+ /(msie) ([\w.]+)/.exec(ua) ||
3016+ /(trident)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
3017+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
3018+ [];
3019+
3020+ atmosphere.util.browser[match[1] || ""] = true;
3021+ atmosphere.util.browser.version = match[2] || "0";
3022+
3023+ // Trident is the layout engine of the Internet Explorer
3024+ // IE 11 has no "MSIE: 11.0" token
3025+ if (atmosphere.util.browser.trident) {
3026+ atmosphere.util.browser.msie = true;
3027+ }
3028+
3029+ // The storage event of Internet Explorer and Firefox 3 works strangely
3030+ if (atmosphere.util.browser.msie || (atmosphere.util.browser.mozilla && atmosphere.util.browser.version.split(".")[0] === "1")) {
3031+ atmosphere.util.storage = false;
3032+ }
3033+ })();
3034+
3035+ atmosphere.util.on(window, "unload", function (event) {
3036+ atmosphere.unsubscribe();
3037+ });
3038+
3039+ // Pressing ESC key in Firefox kills the connection
3040+ // for your information, this is fixed in Firefox 20
3041+ // https://bugzilla.mozilla.org/show_bug.cgi?id=614304
3042+ atmosphere.util.on(window, "keypress", function (event) {
3043+ if (event.charCode === 27 || event.keyCode === 27) {
3044+ if (event.preventDefault) {
3045+ event.preventDefault();
3046+ }
3047+ }
3048+ });
3049+
3050+ atmosphere.util.on(window, "offline", function () {
3051+ atmosphere.unsubscribe();
3052+ });
3053+
3054+ return atmosphere;
3055+}));
3056+/* jshint eqnull:true, noarg:true, noempty:true, eqeqeq:true, evil:true, laxbreak:true, undef:true, browser:true, indent:false, maxerr:50 */
--- /dev/null
+++ b/javascript/jquery-1.9.0.js
@@ -0,0 +1,9555 @@
1+/*!
2+ * jQuery JavaScript Library v1.9.0
3+ * http://jquery.com/
4+ *
5+ * Includes Sizzle.js
6+ * http://sizzlejs.com/
7+ *
8+ * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
9+ * Released under the MIT license
10+ * http://jquery.org/license
11+ *
12+ * Date: 2013-1-14
13+ */
14+(function( window, undefined ) {
15+"use strict";
16+var
17+ // A central reference to the root jQuery(document)
18+ rootjQuery,
19+
20+ // The deferred used on DOM ready
21+ readyList,
22+
23+ // Use the correct document accordingly with window argument (sandbox)
24+ document = window.document,
25+ location = window.location,
26+
27+ // Map over jQuery in case of overwrite
28+ _jQuery = window.jQuery,
29+
30+ // Map over the $ in case of overwrite
31+ _$ = window.$,
32+
33+ // [[Class]] -> type pairs
34+ class2type = {},
35+
36+ // List of deleted data cache ids, so we can reuse them
37+ core_deletedIds = [],
38+
39+ core_version = "1.9.0",
40+
41+ // Save a reference to some core methods
42+ core_concat = core_deletedIds.concat,
43+ core_push = core_deletedIds.push,
44+ core_slice = core_deletedIds.slice,
45+ core_indexOf = core_deletedIds.indexOf,
46+ core_toString = class2type.toString,
47+ core_hasOwn = class2type.hasOwnProperty,
48+ core_trim = core_version.trim,
49+
50+ // Define a local copy of jQuery
51+ jQuery = function( selector, context ) {
52+ // The jQuery object is actually just the init constructor 'enhanced'
53+ return new jQuery.fn.init( selector, context, rootjQuery );
54+ },
55+
56+ // Used for matching numbers
57+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
58+
59+ // Used for splitting on whitespace
60+ core_rnotwhite = /\S+/g,
61+
62+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
63+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
64+
65+ // A simple way to check for HTML strings
66+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
67+ // Strict HTML recognition (#11290: must start with <)
68+ rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
69+
70+ // Match a standalone tag
71+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
72+
73+ // JSON RegExp
74+ rvalidchars = /^[\],:{}\s]*$/,
75+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
76+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
77+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
78+
79+ // Matches dashed string for camelizing
80+ rmsPrefix = /^-ms-/,
81+ rdashAlpha = /-([\da-z])/gi,
82+
83+ // Used by jQuery.camelCase as callback to replace()
84+ fcamelCase = function( all, letter ) {
85+ return letter.toUpperCase();
86+ },
87+
88+ // The ready event handler and self cleanup method
89+ DOMContentLoaded = function() {
90+ if ( document.addEventListener ) {
91+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
92+ jQuery.ready();
93+ } else if ( document.readyState === "complete" ) {
94+ // we're here because readyState === "complete" in oldIE
95+ // which is good enough for us to call the dom ready!
96+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
97+ jQuery.ready();
98+ }
99+ };
100+
101+jQuery.fn = jQuery.prototype = {
102+ // The current version of jQuery being used
103+ jquery: core_version,
104+
105+ constructor: jQuery,
106+ init: function( selector, context, rootjQuery ) {
107+ var match, elem;
108+
109+ // HANDLE: $(""), $(null), $(undefined), $(false)
110+ if ( !selector ) {
111+ return this;
112+ }
113+
114+ // Handle HTML strings
115+ if ( typeof selector === "string" ) {
116+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
117+ // Assume that strings that start and end with <> are HTML and skip the regex check
118+ match = [ null, selector, null ];
119+
120+ } else {
121+ match = rquickExpr.exec( selector );
122+ }
123+
124+ // Match html or make sure no context is specified for #id
125+ if ( match && (match[1] || !context) ) {
126+
127+ // HANDLE: $(html) -> $(array)
128+ if ( match[1] ) {
129+ context = context instanceof jQuery ? context[0] : context;
130+
131+ // scripts is true for back-compat
132+ jQuery.merge( this, jQuery.parseHTML(
133+ match[1],
134+ context && context.nodeType ? context.ownerDocument || context : document,
135+ true
136+ ) );
137+
138+ // HANDLE: $(html, props)
139+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
140+ for ( match in context ) {
141+ // Properties of context are called as methods if possible
142+ if ( jQuery.isFunction( this[ match ] ) ) {
143+ this[ match ]( context[ match ] );
144+
145+ // ...and otherwise set as attributes
146+ } else {
147+ this.attr( match, context[ match ] );
148+ }
149+ }
150+ }
151+
152+ return this;
153+
154+ // HANDLE: $(#id)
155+ } else {
156+ elem = document.getElementById( match[2] );
157+
158+ // Check parentNode to catch when Blackberry 4.6 returns
159+ // nodes that are no longer in the document #6963
160+ if ( elem && elem.parentNode ) {
161+ // Handle the case where IE and Opera return items
162+ // by name instead of ID
163+ if ( elem.id !== match[2] ) {
164+ return rootjQuery.find( selector );
165+ }
166+
167+ // Otherwise, we inject the element directly into the jQuery object
168+ this.length = 1;
169+ this[0] = elem;
170+ }
171+
172+ this.context = document;
173+ this.selector = selector;
174+ return this;
175+ }
176+
177+ // HANDLE: $(expr, $(...))
178+ } else if ( !context || context.jquery ) {
179+ return ( context || rootjQuery ).find( selector );
180+
181+ // HANDLE: $(expr, context)
182+ // (which is just equivalent to: $(context).find(expr)
183+ } else {
184+ return this.constructor( context ).find( selector );
185+ }
186+
187+ // HANDLE: $(DOMElement)
188+ } else if ( selector.nodeType ) {
189+ this.context = this[0] = selector;
190+ this.length = 1;
191+ return this;
192+
193+ // HANDLE: $(function)
194+ // Shortcut for document ready
195+ } else if ( jQuery.isFunction( selector ) ) {
196+ return rootjQuery.ready( selector );
197+ }
198+
199+ if ( selector.selector !== undefined ) {
200+ this.selector = selector.selector;
201+ this.context = selector.context;
202+ }
203+
204+ return jQuery.makeArray( selector, this );
205+ },
206+
207+ // Start with an empty selector
208+ selector: "",
209+
210+ // The default length of a jQuery object is 0
211+ length: 0,
212+
213+ // The number of elements contained in the matched element set
214+ size: function() {
215+ return this.length;
216+ },
217+
218+ toArray: function() {
219+ return core_slice.call( this );
220+ },
221+
222+ // Get the Nth element in the matched element set OR
223+ // Get the whole matched element set as a clean array
224+ get: function( num ) {
225+ return num == null ?
226+
227+ // Return a 'clean' array
228+ this.toArray() :
229+
230+ // Return just the object
231+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
232+ },
233+
234+ // Take an array of elements and push it onto the stack
235+ // (returning the new matched element set)
236+ pushStack: function( elems ) {
237+
238+ // Build a new jQuery matched element set
239+ var ret = jQuery.merge( this.constructor(), elems );
240+
241+ // Add the old object onto the stack (as a reference)
242+ ret.prevObject = this;
243+ ret.context = this.context;
244+
245+ // Return the newly-formed element set
246+ return ret;
247+ },
248+
249+ // Execute a callback for every element in the matched set.
250+ // (You can seed the arguments with an array of args, but this is
251+ // only used internally.)
252+ each: function( callback, args ) {
253+ return jQuery.each( this, callback, args );
254+ },
255+
256+ ready: function( fn ) {
257+ // Add the callback
258+ jQuery.ready.promise().done( fn );
259+
260+ return this;
261+ },
262+
263+ slice: function() {
264+ return this.pushStack( core_slice.apply( this, arguments ) );
265+ },
266+
267+ first: function() {
268+ return this.eq( 0 );
269+ },
270+
271+ last: function() {
272+ return this.eq( -1 );
273+ },
274+
275+ eq: function( i ) {
276+ var len = this.length,
277+ j = +i + ( i < 0 ? len : 0 );
278+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
279+ },
280+
281+ map: function( callback ) {
282+ return this.pushStack( jQuery.map(this, function( elem, i ) {
283+ return callback.call( elem, i, elem );
284+ }));
285+ },
286+
287+ end: function() {
288+ return this.prevObject || this.constructor(null);
289+ },
290+
291+ // For internal use only.
292+ // Behaves like an Array's method, not like a jQuery method.
293+ push: core_push,
294+ sort: [].sort,
295+ splice: [].splice
296+};
297+
298+// Give the init function the jQuery prototype for later instantiation
299+jQuery.fn.init.prototype = jQuery.fn;
300+
301+jQuery.extend = jQuery.fn.extend = function() {
302+ var options, name, src, copy, copyIsArray, clone,
303+ target = arguments[0] || {},
304+ i = 1,
305+ length = arguments.length,
306+ deep = false;
307+
308+ // Handle a deep copy situation
309+ if ( typeof target === "boolean" ) {
310+ deep = target;
311+ target = arguments[1] || {};
312+ // skip the boolean and the target
313+ i = 2;
314+ }
315+
316+ // Handle case when target is a string or something (possible in deep copy)
317+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
318+ target = {};
319+ }
320+
321+ // extend jQuery itself if only one argument is passed
322+ if ( length === i ) {
323+ target = this;
324+ --i;
325+ }
326+
327+ for ( ; i < length; i++ ) {
328+ // Only deal with non-null/undefined values
329+ if ( (options = arguments[ i ]) != null ) {
330+ // Extend the base object
331+ for ( name in options ) {
332+ src = target[ name ];
333+ copy = options[ name ];
334+
335+ // Prevent never-ending loop
336+ if ( target === copy ) {
337+ continue;
338+ }
339+
340+ // Recurse if we're merging plain objects or arrays
341+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
342+ if ( copyIsArray ) {
343+ copyIsArray = false;
344+ clone = src && jQuery.isArray(src) ? src : [];
345+
346+ } else {
347+ clone = src && jQuery.isPlainObject(src) ? src : {};
348+ }
349+
350+ // Never move original objects, clone them
351+ target[ name ] = jQuery.extend( deep, clone, copy );
352+
353+ // Don't bring in undefined values
354+ } else if ( copy !== undefined ) {
355+ target[ name ] = copy;
356+ }
357+ }
358+ }
359+ }
360+
361+ // Return the modified object
362+ return target;
363+};
364+
365+jQuery.extend({
366+ noConflict: function( deep ) {
367+ if ( window.$ === jQuery ) {
368+ window.$ = _$;
369+ }
370+
371+ if ( deep && window.jQuery === jQuery ) {
372+ window.jQuery = _jQuery;
373+ }
374+
375+ return jQuery;
376+ },
377+
378+ // Is the DOM ready to be used? Set to true once it occurs.
379+ isReady: false,
380+
381+ // A counter to track how many items to wait for before
382+ // the ready event fires. See #6781
383+ readyWait: 1,
384+
385+ // Hold (or release) the ready event
386+ holdReady: function( hold ) {
387+ if ( hold ) {
388+ jQuery.readyWait++;
389+ } else {
390+ jQuery.ready( true );
391+ }
392+ },
393+
394+ // Handle when the DOM is ready
395+ ready: function( wait ) {
396+
397+ // Abort if there are pending holds or we're already ready
398+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
399+ return;
400+ }
401+
402+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
403+ if ( !document.body ) {
404+ return setTimeout( jQuery.ready );
405+ }
406+
407+ // Remember that the DOM is ready
408+ jQuery.isReady = true;
409+
410+ // If a normal DOM Ready event fired, decrement, and wait if need be
411+ if ( wait !== true && --jQuery.readyWait > 0 ) {
412+ return;
413+ }
414+
415+ // If there are functions bound, to execute
416+ readyList.resolveWith( document, [ jQuery ] );
417+
418+ // Trigger any bound ready events
419+ if ( jQuery.fn.trigger ) {
420+ jQuery( document ).trigger("ready").off("ready");
421+ }
422+ },
423+
424+ // See test/unit/core.js for details concerning isFunction.
425+ // Since version 1.3, DOM methods and functions like alert
426+ // aren't supported. They return false on IE (#2968).
427+ isFunction: function( obj ) {
428+ return jQuery.type(obj) === "function";
429+ },
430+
431+ isArray: Array.isArray || function( obj ) {
432+ return jQuery.type(obj) === "array";
433+ },
434+
435+ isWindow: function( obj ) {
436+ return obj != null && obj == obj.window;
437+ },
438+
439+ isNumeric: function( obj ) {
440+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
441+ },
442+
443+ type: function( obj ) {
444+ if ( obj == null ) {
445+ return String( obj );
446+ }
447+ return typeof obj === "object" || typeof obj === "function" ?
448+ class2type[ core_toString.call(obj) ] || "object" :
449+ typeof obj;
450+ },
451+
452+ isPlainObject: function( obj ) {
453+ // Must be an Object.
454+ // Because of IE, we also have to check the presence of the constructor property.
455+ // Make sure that DOM nodes and window objects don't pass through, as well
456+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
457+ return false;
458+ }
459+
460+ try {
461+ // Not own constructor property must be Object
462+ if ( obj.constructor &&
463+ !core_hasOwn.call(obj, "constructor") &&
464+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
465+ return false;
466+ }
467+ } catch ( e ) {
468+ // IE8,9 Will throw exceptions on certain host objects #9897
469+ return false;
470+ }
471+
472+ // Own properties are enumerated firstly, so to speed up,
473+ // if last one is own, then all properties are own.
474+
475+ var key;
476+ for ( key in obj ) {}
477+
478+ return key === undefined || core_hasOwn.call( obj, key );
479+ },
480+
481+ isEmptyObject: function( obj ) {
482+ var name;
483+ for ( name in obj ) {
484+ return false;
485+ }
486+ return true;
487+ },
488+
489+ error: function( msg ) {
490+ throw new Error( msg );
491+ },
492+
493+ // data: string of html
494+ // context (optional): If specified, the fragment will be created in this context, defaults to document
495+ // keepScripts (optional): If true, will include scripts passed in the html string
496+ parseHTML: function( data, context, keepScripts ) {
497+ if ( !data || typeof data !== "string" ) {
498+ return null;
499+ }
500+ if ( typeof context === "boolean" ) {
501+ keepScripts = context;
502+ context = false;
503+ }
504+ context = context || document;
505+
506+ var parsed = rsingleTag.exec( data ),
507+ scripts = !keepScripts && [];
508+
509+ // Single tag
510+ if ( parsed ) {
511+ return [ context.createElement( parsed[1] ) ];
512+ }
513+
514+ parsed = jQuery.buildFragment( [ data ], context, scripts );
515+ if ( scripts ) {
516+ jQuery( scripts ).remove();
517+ }
518+ return jQuery.merge( [], parsed.childNodes );
519+ },
520+
521+ parseJSON: function( data ) {
522+ // Attempt to parse using the native JSON parser first
523+ if ( window.JSON && window.JSON.parse ) {
524+ return window.JSON.parse( data );
525+ }
526+
527+ if ( data === null ) {
528+ return data;
529+ }
530+
531+ if ( typeof data === "string" ) {
532+
533+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
534+ data = jQuery.trim( data );
535+
536+ if ( data ) {
537+ // Make sure the incoming data is actual JSON
538+ // Logic borrowed from http://json.org/json2.js
539+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
540+ .replace( rvalidtokens, "]" )
541+ .replace( rvalidbraces, "")) ) {
542+
543+ return ( new Function( "return " + data ) )();
544+ }
545+ }
546+ }
547+
548+ jQuery.error( "Invalid JSON: " + data );
549+ },
550+
551+ // Cross-browser xml parsing
552+ parseXML: function( data ) {
553+ var xml, tmp;
554+ if ( !data || typeof data !== "string" ) {
555+ return null;
556+ }
557+ try {
558+ if ( window.DOMParser ) { // Standard
559+ tmp = new DOMParser();
560+ xml = tmp.parseFromString( data , "text/xml" );
561+ } else { // IE
562+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
563+ xml.async = "false";
564+ xml.loadXML( data );
565+ }
566+ } catch( e ) {
567+ xml = undefined;
568+ }
569+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
570+ jQuery.error( "Invalid XML: " + data );
571+ }
572+ return xml;
573+ },
574+
575+ noop: function() {},
576+
577+ // Evaluates a script in a global context
578+ // Workarounds based on findings by Jim Driscoll
579+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
580+ globalEval: function( data ) {
581+ if ( data && jQuery.trim( data ) ) {
582+ // We use execScript on Internet Explorer
583+ // We use an anonymous function so that context is window
584+ // rather than jQuery in Firefox
585+ ( window.execScript || function( data ) {
586+ window[ "eval" ].call( window, data );
587+ } )( data );
588+ }
589+ },
590+
591+ // Convert dashed to camelCase; used by the css and data modules
592+ // Microsoft forgot to hump their vendor prefix (#9572)
593+ camelCase: function( string ) {
594+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
595+ },
596+
597+ nodeName: function( elem, name ) {
598+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
599+ },
600+
601+ // args is for internal usage only
602+ each: function( obj, callback, args ) {
603+ var value,
604+ i = 0,
605+ length = obj.length,
606+ isArray = isArraylike( obj );
607+
608+ if ( args ) {
609+ if ( isArray ) {
610+ for ( ; i < length; i++ ) {
611+ value = callback.apply( obj[ i ], args );
612+
613+ if ( value === false ) {
614+ break;
615+ }
616+ }
617+ } else {
618+ for ( i in obj ) {
619+ value = callback.apply( obj[ i ], args );
620+
621+ if ( value === false ) {
622+ break;
623+ }
624+ }
625+ }
626+
627+ // A special, fast, case for the most common use of each
628+ } else {
629+ if ( isArray ) {
630+ for ( ; i < length; i++ ) {
631+ value = callback.call( obj[ i ], i, obj[ i ] );
632+
633+ if ( value === false ) {
634+ break;
635+ }
636+ }
637+ } else {
638+ for ( i in obj ) {
639+ value = callback.call( obj[ i ], i, obj[ i ] );
640+
641+ if ( value === false ) {
642+ break;
643+ }
644+ }
645+ }
646+ }
647+
648+ return obj;
649+ },
650+
651+ // Use native String.trim function wherever possible
652+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
653+ function( text ) {
654+ return text == null ?
655+ "" :
656+ core_trim.call( text );
657+ } :
658+
659+ // Otherwise use our own trimming functionality
660+ function( text ) {
661+ return text == null ?
662+ "" :
663+ ( text + "" ).replace( rtrim, "" );
664+ },
665+
666+ // results is for internal usage only
667+ makeArray: function( arr, results ) {
668+ var ret = results || [];
669+
670+ if ( arr != null ) {
671+ if ( isArraylike( Object(arr) ) ) {
672+ jQuery.merge( ret,
673+ typeof arr === "string" ?
674+ [ arr ] : arr
675+ );
676+ } else {
677+ core_push.call( ret, arr );
678+ }
679+ }
680+
681+ return ret;
682+ },
683+
684+ inArray: function( elem, arr, i ) {
685+ var len;
686+
687+ if ( arr ) {
688+ if ( core_indexOf ) {
689+ return core_indexOf.call( arr, elem, i );
690+ }
691+
692+ len = arr.length;
693+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
694+
695+ for ( ; i < len; i++ ) {
696+ // Skip accessing in sparse arrays
697+ if ( i in arr && arr[ i ] === elem ) {
698+ return i;
699+ }
700+ }
701+ }
702+
703+ return -1;
704+ },
705+
706+ merge: function( first, second ) {
707+ var l = second.length,
708+ i = first.length,
709+ j = 0;
710+
711+ if ( typeof l === "number" ) {
712+ for ( ; j < l; j++ ) {
713+ first[ i++ ] = second[ j ];
714+ }
715+ } else {
716+ while ( second[j] !== undefined ) {
717+ first[ i++ ] = second[ j++ ];
718+ }
719+ }
720+
721+ first.length = i;
722+
723+ return first;
724+ },
725+
726+ grep: function( elems, callback, inv ) {
727+ var retVal,
728+ ret = [],
729+ i = 0,
730+ length = elems.length;
731+ inv = !!inv;
732+
733+ // Go through the array, only saving the items
734+ // that pass the validator function
735+ for ( ; i < length; i++ ) {
736+ retVal = !!callback( elems[ i ], i );
737+ if ( inv !== retVal ) {
738+ ret.push( elems[ i ] );
739+ }
740+ }
741+
742+ return ret;
743+ },
744+
745+ // arg is for internal usage only
746+ map: function( elems, callback, arg ) {
747+ var value,
748+ i = 0,
749+ length = elems.length,
750+ isArray = isArraylike( elems ),
751+ ret = [];
752+
753+ // Go through the array, translating each of the items to their
754+ if ( isArray ) {
755+ for ( ; i < length; i++ ) {
756+ value = callback( elems[ i ], i, arg );
757+
758+ if ( value != null ) {
759+ ret[ ret.length ] = value;
760+ }
761+ }
762+
763+ // Go through every key on the object,
764+ } else {
765+ for ( i in elems ) {
766+ value = callback( elems[ i ], i, arg );
767+
768+ if ( value != null ) {
769+ ret[ ret.length ] = value;
770+ }
771+ }
772+ }
773+
774+ // Flatten any nested arrays
775+ return core_concat.apply( [], ret );
776+ },
777+
778+ // A global GUID counter for objects
779+ guid: 1,
780+
781+ // Bind a function to a context, optionally partially applying any
782+ // arguments.
783+ proxy: function( fn, context ) {
784+ var tmp, args, proxy;
785+
786+ if ( typeof context === "string" ) {
787+ tmp = fn[ context ];
788+ context = fn;
789+ fn = tmp;
790+ }
791+
792+ // Quick check to determine if target is callable, in the spec
793+ // this throws a TypeError, but we will just return undefined.
794+ if ( !jQuery.isFunction( fn ) ) {
795+ return undefined;
796+ }
797+
798+ // Simulated bind
799+ args = core_slice.call( arguments, 2 );
800+ proxy = function() {
801+ return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
802+ };
803+
804+ // Set the guid of unique handler to the same of original handler, so it can be removed
805+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
806+
807+ return proxy;
808+ },
809+
810+ // Multifunctional method to get and set values of a collection
811+ // The value/s can optionally be executed if it's a function
812+ access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
813+ var i = 0,
814+ length = elems.length,
815+ bulk = key == null;
816+
817+ // Sets many values
818+ if ( jQuery.type( key ) === "object" ) {
819+ chainable = true;
820+ for ( i in key ) {
821+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
822+ }
823+
824+ // Sets one value
825+ } else if ( value !== undefined ) {
826+ chainable = true;
827+
828+ if ( !jQuery.isFunction( value ) ) {
829+ raw = true;
830+ }
831+
832+ if ( bulk ) {
833+ // Bulk operations run against the entire set
834+ if ( raw ) {
835+ fn.call( elems, value );
836+ fn = null;
837+
838+ // ...except when executing function values
839+ } else {
840+ bulk = fn;
841+ fn = function( elem, key, value ) {
842+ return bulk.call( jQuery( elem ), value );
843+ };
844+ }
845+ }
846+
847+ if ( fn ) {
848+ for ( ; i < length; i++ ) {
849+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
850+ }
851+ }
852+ }
853+
854+ return chainable ?
855+ elems :
856+
857+ // Gets
858+ bulk ?
859+ fn.call( elems ) :
860+ length ? fn( elems[0], key ) : emptyGet;
861+ },
862+
863+ now: function() {
864+ return ( new Date() ).getTime();
865+ }
866+});
867+
868+jQuery.ready.promise = function( obj ) {
869+ if ( !readyList ) {
870+
871+ readyList = jQuery.Deferred();
872+
873+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
874+ // we once tried to use readyState "interactive" here, but it caused issues like the one
875+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
876+ if ( document.readyState === "complete" ) {
877+ // Handle it asynchronously to allow scripts the opportunity to delay ready
878+ setTimeout( jQuery.ready );
879+
880+ // Standards-based browsers support DOMContentLoaded
881+ } else if ( document.addEventListener ) {
882+ // Use the handy event callback
883+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
884+
885+ // A fallback to window.onload, that will always work
886+ window.addEventListener( "load", jQuery.ready, false );
887+
888+ // If IE event model is used
889+ } else {
890+ // Ensure firing before onload, maybe late but safe also for iframes
891+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
892+
893+ // A fallback to window.onload, that will always work
894+ window.attachEvent( "onload", jQuery.ready );
895+
896+ // If IE and not a frame
897+ // continually check to see if the document is ready
898+ var top = false;
899+
900+ try {
901+ top = window.frameElement == null && document.documentElement;
902+ } catch(e) {}
903+
904+ if ( top && top.doScroll ) {
905+ (function doScrollCheck() {
906+ if ( !jQuery.isReady ) {
907+
908+ try {
909+ // Use the trick by Diego Perini
910+ // http://javascript.nwbox.com/IEContentLoaded/
911+ top.doScroll("left");
912+ } catch(e) {
913+ return setTimeout( doScrollCheck, 50 );
914+ }
915+
916+ // and execute any waiting functions
917+ jQuery.ready();
918+ }
919+ })();
920+ }
921+ }
922+ }
923+ return readyList.promise( obj );
924+};
925+
926+// Populate the class2type map
927+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
928+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
929+});
930+
931+function isArraylike( obj ) {
932+ var length = obj.length,
933+ type = jQuery.type( obj );
934+
935+ if ( jQuery.isWindow( obj ) ) {
936+ return false;
937+ }
938+
939+ if ( obj.nodeType === 1 && length ) {
940+ return true;
941+ }
942+
943+ return type === "array" || type !== "function" &&
944+ ( length === 0 ||
945+ typeof length === "number" && length > 0 && ( length - 1 ) in obj );
946+}
947+
948+// All jQuery objects should point back to these
949+rootjQuery = jQuery(document);
950+// String to Object options format cache
951+var optionsCache = {};
952+
953+// Convert String-formatted options into Object-formatted ones and store in cache
954+function createOptions( options ) {
955+ var object = optionsCache[ options ] = {};
956+ jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
957+ object[ flag ] = true;
958+ });
959+ return object;
960+}
961+
962+/*
963+ * Create a callback list using the following parameters:
964+ *
965+ * options: an optional list of space-separated options that will change how
966+ * the callback list behaves or a more traditional option object
967+ *
968+ * By default a callback list will act like an event callback list and can be
969+ * "fired" multiple times.
970+ *
971+ * Possible options:
972+ *
973+ * once: will ensure the callback list can only be fired once (like a Deferred)
974+ *
975+ * memory: will keep track of previous values and will call any callback added
976+ * after the list has been fired right away with the latest "memorized"
977+ * values (like a Deferred)
978+ *
979+ * unique: will ensure a callback can only be added once (no duplicate in the list)
980+ *
981+ * stopOnFalse: interrupt callings when a callback returns false
982+ *
983+ */
984+jQuery.Callbacks = function( options ) {
985+
986+ // Convert options from String-formatted to Object-formatted if needed
987+ // (we check in cache first)
988+ options = typeof options === "string" ?
989+ ( optionsCache[ options ] || createOptions( options ) ) :
990+ jQuery.extend( {}, options );
991+
992+ var // Last fire value (for non-forgettable lists)
993+ memory,
994+ // Flag to know if list was already fired
995+ fired,
996+ // Flag to know if list is currently firing
997+ firing,
998+ // First callback to fire (used internally by add and fireWith)
999+ firingStart,
1000+ // End of the loop when firing
1001+ firingLength,
1002+ // Index of currently firing callback (modified by remove if needed)
1003+ firingIndex,
1004+ // Actual callback list
1005+ list = [],
1006+ // Stack of fire calls for repeatable lists
1007+ stack = !options.once && [],
1008+ // Fire callbacks
1009+ fire = function( data ) {
1010+ memory = options.memory && data;
1011+ fired = true;
1012+ firingIndex = firingStart || 0;
1013+ firingStart = 0;
1014+ firingLength = list.length;
1015+ firing = true;
1016+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
1017+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
1018+ memory = false; // To prevent further calls using add
1019+ break;
1020+ }
1021+ }
1022+ firing = false;
1023+ if ( list ) {
1024+ if ( stack ) {
1025+ if ( stack.length ) {
1026+ fire( stack.shift() );
1027+ }
1028+ } else if ( memory ) {
1029+ list = [];
1030+ } else {
1031+ self.disable();
1032+ }
1033+ }
1034+ },
1035+ // Actual Callbacks object
1036+ self = {
1037+ // Add a callback or a collection of callbacks to the list
1038+ add: function() {
1039+ if ( list ) {
1040+ // First, we save the current length
1041+ var start = list.length;
1042+ (function add( args ) {
1043+ jQuery.each( args, function( _, arg ) {
1044+ var type = jQuery.type( arg );
1045+ if ( type === "function" ) {
1046+ if ( !options.unique || !self.has( arg ) ) {
1047+ list.push( arg );
1048+ }
1049+ } else if ( arg && arg.length && type !== "string" ) {
1050+ // Inspect recursively
1051+ add( arg );
1052+ }
1053+ });
1054+ })( arguments );
1055+ // Do we need to add the callbacks to the
1056+ // current firing batch?
1057+ if ( firing ) {
1058+ firingLength = list.length;
1059+ // With memory, if we're not firing then
1060+ // we should call right away
1061+ } else if ( memory ) {
1062+ firingStart = start;
1063+ fire( memory );
1064+ }
1065+ }
1066+ return this;
1067+ },
1068+ // Remove a callback from the list
1069+ remove: function() {
1070+ if ( list ) {
1071+ jQuery.each( arguments, function( _, arg ) {
1072+ var index;
1073+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1074+ list.splice( index, 1 );
1075+ // Handle firing indexes
1076+ if ( firing ) {
1077+ if ( index <= firingLength ) {
1078+ firingLength--;
1079+ }
1080+ if ( index <= firingIndex ) {
1081+ firingIndex--;
1082+ }
1083+ }
1084+ }
1085+ });
1086+ }
1087+ return this;
1088+ },
1089+ // Control if a given callback is in the list
1090+ has: function( fn ) {
1091+ return jQuery.inArray( fn, list ) > -1;
1092+ },
1093+ // Remove all callbacks from the list
1094+ empty: function() {
1095+ list = [];
1096+ return this;
1097+ },
1098+ // Have the list do nothing anymore
1099+ disable: function() {
1100+ list = stack = memory = undefined;
1101+ return this;
1102+ },
1103+ // Is it disabled?
1104+ disabled: function() {
1105+ return !list;
1106+ },
1107+ // Lock the list in its current state
1108+ lock: function() {
1109+ stack = undefined;
1110+ if ( !memory ) {
1111+ self.disable();
1112+ }
1113+ return this;
1114+ },
1115+ // Is it locked?
1116+ locked: function() {
1117+ return !stack;
1118+ },
1119+ // Call all callbacks with the given context and arguments
1120+ fireWith: function( context, args ) {
1121+ args = args || [];
1122+ args = [ context, args.slice ? args.slice() : args ];
1123+ if ( list && ( !fired || stack ) ) {
1124+ if ( firing ) {
1125+ stack.push( args );
1126+ } else {
1127+ fire( args );
1128+ }
1129+ }
1130+ return this;
1131+ },
1132+ // Call all the callbacks with the given arguments
1133+ fire: function() {
1134+ self.fireWith( this, arguments );
1135+ return this;
1136+ },
1137+ // To know if the callbacks have already been called at least once
1138+ fired: function() {
1139+ return !!fired;
1140+ }
1141+ };
1142+
1143+ return self;
1144+};
1145+jQuery.extend({
1146+
1147+ Deferred: function( func ) {
1148+ var tuples = [
1149+ // action, add listener, listener list, final state
1150+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1151+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1152+ [ "notify", "progress", jQuery.Callbacks("memory") ]
1153+ ],
1154+ state = "pending",
1155+ promise = {
1156+ state: function() {
1157+ return state;
1158+ },
1159+ always: function() {
1160+ deferred.done( arguments ).fail( arguments );
1161+ return this;
1162+ },
1163+ then: function( /* fnDone, fnFail, fnProgress */ ) {
1164+ var fns = arguments;
1165+ return jQuery.Deferred(function( newDefer ) {
1166+ jQuery.each( tuples, function( i, tuple ) {
1167+ var action = tuple[ 0 ],
1168+ fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
1169+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
1170+ deferred[ tuple[1] ](function() {
1171+ var returned = fn && fn.apply( this, arguments );
1172+ if ( returned && jQuery.isFunction( returned.promise ) ) {
1173+ returned.promise()
1174+ .done( newDefer.resolve )
1175+ .fail( newDefer.reject )
1176+ .progress( newDefer.notify );
1177+ } else {
1178+ newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
1179+ }
1180+ });
1181+ });
1182+ fns = null;
1183+ }).promise();
1184+ },
1185+ // Get a promise for this deferred
1186+ // If obj is provided, the promise aspect is added to the object
1187+ promise: function( obj ) {
1188+ return obj != null ? jQuery.extend( obj, promise ) : promise;
1189+ }
1190+ },
1191+ deferred = {};
1192+
1193+ // Keep pipe for back-compat
1194+ promise.pipe = promise.then;
1195+
1196+ // Add list-specific methods
1197+ jQuery.each( tuples, function( i, tuple ) {
1198+ var list = tuple[ 2 ],
1199+ stateString = tuple[ 3 ];
1200+
1201+ // promise[ done | fail | progress ] = list.add
1202+ promise[ tuple[1] ] = list.add;
1203+
1204+ // Handle state
1205+ if ( stateString ) {
1206+ list.add(function() {
1207+ // state = [ resolved | rejected ]
1208+ state = stateString;
1209+
1210+ // [ reject_list | resolve_list ].disable; progress_list.lock
1211+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1212+ }
1213+
1214+ // deferred[ resolve | reject | notify ]
1215+ deferred[ tuple[0] ] = function() {
1216+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
1217+ return this;
1218+ };
1219+ deferred[ tuple[0] + "With" ] = list.fireWith;
1220+ });
1221+
1222+ // Make the deferred a promise
1223+ promise.promise( deferred );
1224+
1225+ // Call given func if any
1226+ if ( func ) {
1227+ func.call( deferred, deferred );
1228+ }
1229+
1230+ // All done!
1231+ return deferred;
1232+ },
1233+
1234+ // Deferred helper
1235+ when: function( subordinate /* , ..., subordinateN */ ) {
1236+ var i = 0,
1237+ resolveValues = core_slice.call( arguments ),
1238+ length = resolveValues.length,
1239+
1240+ // the count of uncompleted subordinates
1241+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1242+
1243+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1244+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1245+
1246+ // Update function for both resolve and progress values
1247+ updateFunc = function( i, contexts, values ) {
1248+ return function( value ) {
1249+ contexts[ i ] = this;
1250+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1251+ if( values === progressValues ) {
1252+ deferred.notifyWith( contexts, values );
1253+ } else if ( !( --remaining ) ) {
1254+ deferred.resolveWith( contexts, values );
1255+ }
1256+ };
1257+ },
1258+
1259+ progressValues, progressContexts, resolveContexts;
1260+
1261+ // add listeners to Deferred subordinates; treat others as resolved
1262+ if ( length > 1 ) {
1263+ progressValues = new Array( length );
1264+ progressContexts = new Array( length );
1265+ resolveContexts = new Array( length );
1266+ for ( ; i < length; i++ ) {
1267+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1268+ resolveValues[ i ].promise()
1269+ .done( updateFunc( i, resolveContexts, resolveValues ) )
1270+ .fail( deferred.reject )
1271+ .progress( updateFunc( i, progressContexts, progressValues ) );
1272+ } else {
1273+ --remaining;
1274+ }
1275+ }
1276+ }
1277+
1278+ // if we're not waiting on anything, resolve the master
1279+ if ( !remaining ) {
1280+ deferred.resolveWith( resolveContexts, resolveValues );
1281+ }
1282+
1283+ return deferred.promise();
1284+ }
1285+});
1286+jQuery.support = (function() {
1287+
1288+ var support, all, a, select, opt, input, fragment, eventName, isSupported, i,
1289+ div = document.createElement("div");
1290+
1291+ // Setup
1292+ div.setAttribute( "className", "t" );
1293+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1294+
1295+ // Support tests won't run in some limited or non-browser environments
1296+ all = div.getElementsByTagName("*");
1297+ a = div.getElementsByTagName("a")[ 0 ];
1298+ if ( !all || !a || !all.length ) {
1299+ return {};
1300+ }
1301+
1302+ // First batch of tests
1303+ select = document.createElement("select");
1304+ opt = select.appendChild( document.createElement("option") );
1305+ input = div.getElementsByTagName("input")[ 0 ];
1306+
1307+ a.style.cssText = "top:1px;float:left;opacity:.5";
1308+ support = {
1309+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1310+ getSetAttribute: div.className !== "t",
1311+
1312+ // IE strips leading whitespace when .innerHTML is used
1313+ leadingWhitespace: div.firstChild.nodeType === 3,
1314+
1315+ // Make sure that tbody elements aren't automatically inserted
1316+ // IE will insert them into empty tables
1317+ tbody: !div.getElementsByTagName("tbody").length,
1318+
1319+ // Make sure that link elements get serialized correctly by innerHTML
1320+ // This requires a wrapper element in IE
1321+ htmlSerialize: !!div.getElementsByTagName("link").length,
1322+
1323+ // Get the style information from getAttribute
1324+ // (IE uses .cssText instead)
1325+ style: /top/.test( a.getAttribute("style") ),
1326+
1327+ // Make sure that URLs aren't manipulated
1328+ // (IE normalizes it by default)
1329+ hrefNormalized: a.getAttribute("href") === "/a",
1330+
1331+ // Make sure that element opacity exists
1332+ // (IE uses filter instead)
1333+ // Use a regex to work around a WebKit issue. See #5145
1334+ opacity: /^0.5/.test( a.style.opacity ),
1335+
1336+ // Verify style float existence
1337+ // (IE uses styleFloat instead of cssFloat)
1338+ cssFloat: !!a.style.cssFloat,
1339+
1340+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
1341+ checkOn: !!input.value,
1342+
1343+ // Make sure that a selected-by-default option has a working selected property.
1344+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1345+ optSelected: opt.selected,
1346+
1347+ // Tests for enctype support on a form (#6743)
1348+ enctype: !!document.createElement("form").enctype,
1349+
1350+ // Makes sure cloning an html5 element does not cause problems
1351+ // Where outerHTML is undefined, this still works
1352+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1353+
1354+ // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1355+ boxModel: document.compatMode === "CSS1Compat",
1356+
1357+ // Will be defined later
1358+ deleteExpando: true,
1359+ noCloneEvent: true,
1360+ inlineBlockNeedsLayout: false,
1361+ shrinkWrapBlocks: false,
1362+ reliableMarginRight: true,
1363+ boxSizingReliable: true,
1364+ pixelPosition: false
1365+ };
1366+
1367+ // Make sure checked status is properly cloned
1368+ input.checked = true;
1369+ support.noCloneChecked = input.cloneNode( true ).checked;
1370+
1371+ // Make sure that the options inside disabled selects aren't marked as disabled
1372+ // (WebKit marks them as disabled)
1373+ select.disabled = true;
1374+ support.optDisabled = !opt.disabled;
1375+
1376+ // Support: IE<9
1377+ try {
1378+ delete div.test;
1379+ } catch( e ) {
1380+ support.deleteExpando = false;
1381+ }
1382+
1383+ // Check if we can trust getAttribute("value")
1384+ input = document.createElement("input");
1385+ input.setAttribute( "value", "" );
1386+ support.input = input.getAttribute( "value" ) === "";
1387+
1388+ // Check if an input maintains its value after becoming a radio
1389+ input.value = "t";
1390+ input.setAttribute( "type", "radio" );
1391+ support.radioValue = input.value === "t";
1392+
1393+ // #11217 - WebKit loses check when the name is after the checked attribute
1394+ input.setAttribute( "checked", "t" );
1395+ input.setAttribute( "name", "t" );
1396+
1397+ fragment = document.createDocumentFragment();
1398+ fragment.appendChild( input );
1399+
1400+ // Check if a disconnected checkbox will retain its checked
1401+ // value of true after appended to the DOM (IE6/7)
1402+ support.appendChecked = input.checked;
1403+
1404+ // WebKit doesn't clone checked state correctly in fragments
1405+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1406+
1407+ // Support: IE<9
1408+ // Opera does not clone events (and typeof div.attachEvent === undefined).
1409+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
1410+ if ( div.attachEvent ) {
1411+ div.attachEvent( "onclick", function() {
1412+ support.noCloneEvent = false;
1413+ });
1414+
1415+ div.cloneNode( true ).click();
1416+ }
1417+
1418+ // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
1419+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
1420+ for ( i in { submit: true, change: true, focusin: true }) {
1421+ div.setAttribute( eventName = "on" + i, "t" );
1422+
1423+ support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
1424+ }
1425+
1426+ div.style.backgroundClip = "content-box";
1427+ div.cloneNode( true ).style.backgroundClip = "";
1428+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
1429+
1430+ // Run tests that need a body at doc ready
1431+ jQuery(function() {
1432+ var container, marginDiv, tds,
1433+ divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
1434+ body = document.getElementsByTagName("body")[0];
1435+
1436+ if ( !body ) {
1437+ // Return for frameset docs that don't have a body
1438+ return;
1439+ }
1440+
1441+ container = document.createElement("div");
1442+ container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
1443+
1444+ body.appendChild( container ).appendChild( div );
1445+
1446+ // Support: IE8
1447+ // Check if table cells still have offsetWidth/Height when they are set
1448+ // to display:none and there are still other visible table cells in a
1449+ // table row; if so, offsetWidth/Height are not reliable for use when
1450+ // determining if an element has been hidden directly using
1451+ // display:none (it is still safe to use offsets if a parent element is
1452+ // hidden; don safety goggles and see bug #4512 for more information).
1453+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1454+ tds = div.getElementsByTagName("td");
1455+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1456+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
1457+
1458+ tds[ 0 ].style.display = "";
1459+ tds[ 1 ].style.display = "none";
1460+
1461+ // Support: IE8
1462+ // Check if empty table cells still have offsetWidth/Height
1463+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1464+
1465+ // Check box-sizing and margin behavior
1466+ div.innerHTML = "";
1467+ div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
1468+ support.boxSizing = ( div.offsetWidth === 4 );
1469+ support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1470+
1471+ // Use window.getComputedStyle because jsdom on node.js will break without it.
1472+ if ( window.getComputedStyle ) {
1473+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1474+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
1475+
1476+ // Check if div with explicit width and no margin-right incorrectly
1477+ // gets computed margin-right based on width of container. (#3333)
1478+ // Fails in WebKit before Feb 2011 nightlies
1479+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1480+ marginDiv = div.appendChild( document.createElement("div") );
1481+ marginDiv.style.cssText = div.style.cssText = divReset;
1482+ marginDiv.style.marginRight = marginDiv.style.width = "0";
1483+ div.style.width = "1px";
1484+
1485+ support.reliableMarginRight =
1486+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
1487+ }
1488+
1489+ if ( typeof div.style.zoom !== "undefined" ) {
1490+ // Support: IE<8
1491+ // Check if natively block-level elements act like inline-block
1492+ // elements when setting their display to 'inline' and giving
1493+ // them layout
1494+ div.innerHTML = "";
1495+ div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
1496+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
1497+
1498+ // Support: IE6
1499+ // Check if elements with layout shrink-wrap their children
1500+ div.style.display = "block";
1501+ div.innerHTML = "<div></div>";
1502+ div.firstChild.style.width = "5px";
1503+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
1504+
1505+ // Prevent IE 6 from affecting layout for positioned elements #11048
1506+ // Prevent IE from shrinking the body in IE 7 mode #12869
1507+ body.style.zoom = 1;
1508+ }
1509+
1510+ body.removeChild( container );
1511+
1512+ // Null elements to avoid leaks in IE
1513+ container = div = tds = marginDiv = null;
1514+ });
1515+
1516+ // Null elements to avoid leaks in IE
1517+ all = select = fragment = opt = a = input = null;
1518+
1519+ return support;
1520+})();
1521+
1522+var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
1523+ rmultiDash = /([A-Z])/g;
1524+
1525+function internalData( elem, name, data, pvt /* Internal Use Only */ ){
1526+ if ( !jQuery.acceptData( elem ) ) {
1527+ return;
1528+ }
1529+
1530+ var thisCache, ret,
1531+ internalKey = jQuery.expando,
1532+ getByName = typeof name === "string",
1533+
1534+ // We have to handle DOM nodes and JS objects differently because IE6-7
1535+ // can't GC object references properly across the DOM-JS boundary
1536+ isNode = elem.nodeType,
1537+
1538+ // Only DOM nodes need the global jQuery cache; JS object data is
1539+ // attached directly to the object so GC can occur automatically
1540+ cache = isNode ? jQuery.cache : elem,
1541+
1542+ // Only defining an ID for JS objects if its cache already exists allows
1543+ // the code to shortcut on the same path as a DOM node with no cache
1544+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
1545+
1546+ // Avoid doing any more work than we need to when trying to get data on an
1547+ // object that has no data at all
1548+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
1549+ return;
1550+ }
1551+
1552+ if ( !id ) {
1553+ // Only DOM nodes need a new unique ID for each element since their data
1554+ // ends up in the global cache
1555+ if ( isNode ) {
1556+ elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
1557+ } else {
1558+ id = internalKey;
1559+ }
1560+ }
1561+
1562+ if ( !cache[ id ] ) {
1563+ cache[ id ] = {};
1564+
1565+ // Avoids exposing jQuery metadata on plain JS objects when the object
1566+ // is serialized using JSON.stringify
1567+ if ( !isNode ) {
1568+ cache[ id ].toJSON = jQuery.noop;
1569+ }
1570+ }
1571+
1572+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
1573+ // shallow copied over onto the existing cache
1574+ if ( typeof name === "object" || typeof name === "function" ) {
1575+ if ( pvt ) {
1576+ cache[ id ] = jQuery.extend( cache[ id ], name );
1577+ } else {
1578+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1579+ }
1580+ }
1581+
1582+ thisCache = cache[ id ];
1583+
1584+ // jQuery data() is stored in a separate object inside the object's internal data
1585+ // cache in order to avoid key collisions between internal data and user-defined
1586+ // data.
1587+ if ( !pvt ) {
1588+ if ( !thisCache.data ) {
1589+ thisCache.data = {};
1590+ }
1591+
1592+ thisCache = thisCache.data;
1593+ }
1594+
1595+ if ( data !== undefined ) {
1596+ thisCache[ jQuery.camelCase( name ) ] = data;
1597+ }
1598+
1599+ // Check for both converted-to-camel and non-converted data property names
1600+ // If a data property was specified
1601+ if ( getByName ) {
1602+
1603+ // First Try to find as-is property data
1604+ ret = thisCache[ name ];
1605+
1606+ // Test for null|undefined property data
1607+ if ( ret == null ) {
1608+
1609+ // Try to find the camelCased property
1610+ ret = thisCache[ jQuery.camelCase( name ) ];
1611+ }
1612+ } else {
1613+ ret = thisCache;
1614+ }
1615+
1616+ return ret;
1617+}
1618+
1619+function internalRemoveData( elem, name, pvt /* For internal use only */ ){
1620+ if ( !jQuery.acceptData( elem ) ) {
1621+ return;
1622+ }
1623+
1624+ var thisCache, i, l,
1625+
1626+ isNode = elem.nodeType,
1627+
1628+ // See jQuery.data for more information
1629+ cache = isNode ? jQuery.cache : elem,
1630+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1631+
1632+ // If there is already no cache entry for this object, there is no
1633+ // purpose in continuing
1634+ if ( !cache[ id ] ) {
1635+ return;
1636+ }
1637+
1638+ if ( name ) {
1639+
1640+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
1641+
1642+ if ( thisCache ) {
1643+
1644+ // Support array or space separated string names for data keys
1645+ if ( !jQuery.isArray( name ) ) {
1646+
1647+ // try the string as a key before any manipulation
1648+ if ( name in thisCache ) {
1649+ name = [ name ];
1650+ } else {
1651+
1652+ // split the camel cased version by spaces unless a key with the spaces exists
1653+ name = jQuery.camelCase( name );
1654+ if ( name in thisCache ) {
1655+ name = [ name ];
1656+ } else {
1657+ name = name.split(" ");
1658+ }
1659+ }
1660+ } else {
1661+ // If "name" is an array of keys...
1662+ // When data is initially created, via ("key", "val") signature,
1663+ // keys will be converted to camelCase.
1664+ // Since there is no way to tell _how_ a key was added, remove
1665+ // both plain key and camelCase key. #12786
1666+ // This will only penalize the array argument path.
1667+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
1668+ }
1669+
1670+ for ( i = 0, l = name.length; i < l; i++ ) {
1671+ delete thisCache[ name[i] ];
1672+ }
1673+
1674+ // If there is no data left in the cache, we want to continue
1675+ // and let the cache object itself get destroyed
1676+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1677+ return;
1678+ }
1679+ }
1680+ }
1681+
1682+ // See jQuery.data for more information
1683+ if ( !pvt ) {
1684+ delete cache[ id ].data;
1685+
1686+ // Don't destroy the parent cache unless the internal data object
1687+ // had been the only thing left in it
1688+ if ( !isEmptyDataObject( cache[ id ] ) ) {
1689+ return;
1690+ }
1691+ }
1692+
1693+ // Destroy the cache
1694+ if ( isNode ) {
1695+ jQuery.cleanData( [ elem ], true );
1696+
1697+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
1698+ } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
1699+ delete cache[ id ];
1700+
1701+ // When all else fails, null
1702+ } else {
1703+ cache[ id ] = null;
1704+ }
1705+}
1706+
1707+jQuery.extend({
1708+ cache: {},
1709+
1710+ // Unique for each copy of jQuery on the page
1711+ // Non-digits removed to match rinlinejQuery
1712+ expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
1713+
1714+ // The following elements throw uncatchable exceptions if you
1715+ // attempt to add expando properties to them.
1716+ noData: {
1717+ "embed": true,
1718+ // Ban all objects except for Flash (which handle expandos)
1719+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1720+ "applet": true
1721+ },
1722+
1723+ hasData: function( elem ) {
1724+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1725+ return !!elem && !isEmptyDataObject( elem );
1726+ },
1727+
1728+ data: function( elem, name, data ) {
1729+ return internalData( elem, name, data, false );
1730+ },
1731+
1732+ removeData: function( elem, name ) {
1733+ return internalRemoveData( elem, name, false );
1734+ },
1735+
1736+ // For internal use only.
1737+ _data: function( elem, name, data ) {
1738+ return internalData( elem, name, data, true );
1739+ },
1740+
1741+ _removeData: function( elem, name ) {
1742+ return internalRemoveData( elem, name, true );
1743+ },
1744+
1745+ // A method for determining if a DOM node can handle the data expando
1746+ acceptData: function( elem ) {
1747+ var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
1748+
1749+ // nodes accept data unless otherwise specified; rejection can be conditional
1750+ return !noData || noData !== true && elem.getAttribute("classid") === noData;
1751+ }
1752+});
1753+
1754+jQuery.fn.extend({
1755+ data: function( key, value ) {
1756+ var attrs, name,
1757+ elem = this[0],
1758+ i = 0,
1759+ data = null;
1760+
1761+ // Gets all values
1762+ if ( key === undefined ) {
1763+ if ( this.length ) {
1764+ data = jQuery.data( elem );
1765+
1766+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
1767+ attrs = elem.attributes;
1768+ for ( ; i < attrs.length; i++ ) {
1769+ name = attrs[i].name;
1770+
1771+ if ( !name.indexOf( "data-" ) ) {
1772+ name = jQuery.camelCase( name.substring(5) );
1773+
1774+ dataAttr( elem, name, data[ name ] );
1775+ }
1776+ }
1777+ jQuery._data( elem, "parsedAttrs", true );
1778+ }
1779+ }
1780+
1781+ return data;
1782+ }
1783+
1784+ // Sets multiple values
1785+ if ( typeof key === "object" ) {
1786+ return this.each(function() {
1787+ jQuery.data( this, key );
1788+ });
1789+ }
1790+
1791+ return jQuery.access( this, function( value ) {
1792+
1793+ if ( value === undefined ) {
1794+ // Try to fetch any internally stored data first
1795+ return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
1796+ }
1797+
1798+ this.each(function() {
1799+ jQuery.data( this, key, value );
1800+ });
1801+ }, null, value, arguments.length > 1, null, true );
1802+ },
1803+
1804+ removeData: function( key ) {
1805+ return this.each(function() {
1806+ jQuery.removeData( this, key );
1807+ });
1808+ }
1809+});
1810+
1811+function dataAttr( elem, key, data ) {
1812+ // If nothing was found internally, try to fetch any
1813+ // data from the HTML5 data-* attribute
1814+ if ( data === undefined && elem.nodeType === 1 ) {
1815+
1816+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1817+
1818+ data = elem.getAttribute( name );
1819+
1820+ if ( typeof data === "string" ) {
1821+ try {
1822+ data = data === "true" ? true :
1823+ data === "false" ? false :
1824+ data === "null" ? null :
1825+ // Only convert to a number if it doesn't change the string
1826+ +data + "" === data ? +data :
1827+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
1828+ data;
1829+ } catch( e ) {}
1830+
1831+ // Make sure we set the data so it isn't changed later
1832+ jQuery.data( elem, key, data );
1833+
1834+ } else {
1835+ data = undefined;
1836+ }
1837+ }
1838+
1839+ return data;
1840+}
1841+
1842+// checks a cache object for emptiness
1843+function isEmptyDataObject( obj ) {
1844+ var name;
1845+ for ( name in obj ) {
1846+
1847+ // if the public data object is empty, the private is still empty
1848+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1849+ continue;
1850+ }
1851+ if ( name !== "toJSON" ) {
1852+ return false;
1853+ }
1854+ }
1855+
1856+ return true;
1857+}
1858+jQuery.extend({
1859+ queue: function( elem, type, data ) {
1860+ var queue;
1861+
1862+ if ( elem ) {
1863+ type = ( type || "fx" ) + "queue";
1864+ queue = jQuery._data( elem, type );
1865+
1866+ // Speed up dequeue by getting out quickly if this is just a lookup
1867+ if ( data ) {
1868+ if ( !queue || jQuery.isArray(data) ) {
1869+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
1870+ } else {
1871+ queue.push( data );
1872+ }
1873+ }
1874+ return queue || [];
1875+ }
1876+ },
1877+
1878+ dequeue: function( elem, type ) {
1879+ type = type || "fx";
1880+
1881+ var queue = jQuery.queue( elem, type ),
1882+ startLength = queue.length,
1883+ fn = queue.shift(),
1884+ hooks = jQuery._queueHooks( elem, type ),
1885+ next = function() {
1886+ jQuery.dequeue( elem, type );
1887+ };
1888+
1889+ // If the fx queue is dequeued, always remove the progress sentinel
1890+ if ( fn === "inprogress" ) {
1891+ fn = queue.shift();
1892+ startLength--;
1893+ }
1894+
1895+ hooks.cur = fn;
1896+ if ( fn ) {
1897+
1898+ // Add a progress sentinel to prevent the fx queue from being
1899+ // automatically dequeued
1900+ if ( type === "fx" ) {
1901+ queue.unshift( "inprogress" );
1902+ }
1903+
1904+ // clear up the last queue stop function
1905+ delete hooks.stop;
1906+ fn.call( elem, next, hooks );
1907+ }
1908+
1909+ if ( !startLength && hooks ) {
1910+ hooks.empty.fire();
1911+ }
1912+ },
1913+
1914+ // not intended for public consumption - generates a queueHooks object, or returns the current one
1915+ _queueHooks: function( elem, type ) {
1916+ var key = type + "queueHooks";
1917+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
1918+ empty: jQuery.Callbacks("once memory").add(function() {
1919+ jQuery._removeData( elem, type + "queue" );
1920+ jQuery._removeData( elem, key );
1921+ })
1922+ });
1923+ }
1924+});
1925+
1926+jQuery.fn.extend({
1927+ queue: function( type, data ) {
1928+ var setter = 2;
1929+
1930+ if ( typeof type !== "string" ) {
1931+ data = type;
1932+ type = "fx";
1933+ setter--;
1934+ }
1935+
1936+ if ( arguments.length < setter ) {
1937+ return jQuery.queue( this[0], type );
1938+ }
1939+
1940+ return data === undefined ?
1941+ this :
1942+ this.each(function() {
1943+ var queue = jQuery.queue( this, type, data );
1944+
1945+ // ensure a hooks for this queue
1946+ jQuery._queueHooks( this, type );
1947+
1948+ if ( type === "fx" && queue[0] !== "inprogress" ) {
1949+ jQuery.dequeue( this, type );
1950+ }
1951+ });
1952+ },
1953+ dequeue: function( type ) {
1954+ return this.each(function() {
1955+ jQuery.dequeue( this, type );
1956+ });
1957+ },
1958+ // Based off of the plugin by Clint Helfers, with permission.
1959+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
1960+ delay: function( time, type ) {
1961+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
1962+ type = type || "fx";
1963+
1964+ return this.queue( type, function( next, hooks ) {
1965+ var timeout = setTimeout( next, time );
1966+ hooks.stop = function() {
1967+ clearTimeout( timeout );
1968+ };
1969+ });
1970+ },
1971+ clearQueue: function( type ) {
1972+ return this.queue( type || "fx", [] );
1973+ },
1974+ // Get a promise resolved when queues of a certain type
1975+ // are emptied (fx is the type by default)
1976+ promise: function( type, obj ) {
1977+ var tmp,
1978+ count = 1,
1979+ defer = jQuery.Deferred(),
1980+ elements = this,
1981+ i = this.length,
1982+ resolve = function() {
1983+ if ( !( --count ) ) {
1984+ defer.resolveWith( elements, [ elements ] );
1985+ }
1986+ };
1987+
1988+ if ( typeof type !== "string" ) {
1989+ obj = type;
1990+ type = undefined;
1991+ }
1992+ type = type || "fx";
1993+
1994+ while( i-- ) {
1995+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
1996+ if ( tmp && tmp.empty ) {
1997+ count++;
1998+ tmp.empty.add( resolve );
1999+ }
2000+ }
2001+ resolve();
2002+ return defer.promise( obj );
2003+ }
2004+});
2005+var nodeHook, boolHook,
2006+ rclass = /[\t\r\n]/g,
2007+ rreturn = /\r/g,
2008+ rfocusable = /^(?:input|select|textarea|button|object)$/i,
2009+ rclickable = /^(?:a|area)$/i,
2010+ rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
2011+ ruseDefault = /^(?:checked|selected)$/i,
2012+ getSetAttribute = jQuery.support.getSetAttribute,
2013+ getSetInput = jQuery.support.input;
2014+
2015+jQuery.fn.extend({
2016+ attr: function( name, value ) {
2017+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
2018+ },
2019+
2020+ removeAttr: function( name ) {
2021+ return this.each(function() {
2022+ jQuery.removeAttr( this, name );
2023+ });
2024+ },
2025+
2026+ prop: function( name, value ) {
2027+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2028+ },
2029+
2030+ removeProp: function( name ) {
2031+ name = jQuery.propFix[ name ] || name;
2032+ return this.each(function() {
2033+ // try/catch handles cases where IE balks (such as removing a property on window)
2034+ try {
2035+ this[ name ] = undefined;
2036+ delete this[ name ];
2037+ } catch( e ) {}
2038+ });
2039+ },
2040+
2041+ addClass: function( value ) {
2042+ var classes, elem, cur, clazz, j,
2043+ i = 0,
2044+ len = this.length,
2045+ proceed = typeof value === "string" && value;
2046+
2047+ if ( jQuery.isFunction( value ) ) {
2048+ return this.each(function( j ) {
2049+ jQuery( this ).addClass( value.call( this, j, this.className ) );
2050+ });
2051+ }
2052+
2053+ if ( proceed ) {
2054+ // The disjunction here is for better compressibility (see removeClass)
2055+ classes = ( value || "" ).match( core_rnotwhite ) || [];
2056+
2057+ for ( ; i < len; i++ ) {
2058+ elem = this[ i ];
2059+ cur = elem.nodeType === 1 && ( elem.className ?
2060+ ( " " + elem.className + " " ).replace( rclass, " " ) :
2061+ " "
2062+ );
2063+
2064+ if ( cur ) {
2065+ j = 0;
2066+ while ( (clazz = classes[j++]) ) {
2067+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
2068+ cur += clazz + " ";
2069+ }
2070+ }
2071+ elem.className = jQuery.trim( cur );
2072+
2073+ }
2074+ }
2075+ }
2076+
2077+ return this;
2078+ },
2079+
2080+ removeClass: function( value ) {
2081+ var classes, elem, cur, clazz, j,
2082+ i = 0,
2083+ len = this.length,
2084+ proceed = arguments.length === 0 || typeof value === "string" && value;
2085+
2086+ if ( jQuery.isFunction( value ) ) {
2087+ return this.each(function( j ) {
2088+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
2089+ });
2090+ }
2091+ if ( proceed ) {
2092+ classes = ( value || "" ).match( core_rnotwhite ) || [];
2093+
2094+ for ( ; i < len; i++ ) {
2095+ elem = this[ i ];
2096+ // This expression is here for better compressibility (see addClass)
2097+ cur = elem.nodeType === 1 && ( elem.className ?
2098+ ( " " + elem.className + " " ).replace( rclass, " " ) :
2099+ ""
2100+ );
2101+
2102+ if ( cur ) {
2103+ j = 0;
2104+ while ( (clazz = classes[j++]) ) {
2105+ // Remove *all* instances
2106+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
2107+ cur = cur.replace( " " + clazz + " ", " " );
2108+ }
2109+ }
2110+ elem.className = value ? jQuery.trim( cur ) : "";
2111+ }
2112+ }
2113+ }
2114+
2115+ return this;
2116+ },
2117+
2118+ toggleClass: function( value, stateVal ) {
2119+ var type = typeof value,
2120+ isBool = typeof stateVal === "boolean";
2121+
2122+ if ( jQuery.isFunction( value ) ) {
2123+ return this.each(function( i ) {
2124+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2125+ });
2126+ }
2127+
2128+ return this.each(function() {
2129+ if ( type === "string" ) {
2130+ // toggle individual class names
2131+ var className,
2132+ i = 0,
2133+ self = jQuery( this ),
2134+ state = stateVal,
2135+ classNames = value.match( core_rnotwhite ) || [];
2136+
2137+ while ( (className = classNames[ i++ ]) ) {
2138+ // check each className given, space separated list
2139+ state = isBool ? state : !self.hasClass( className );
2140+ self[ state ? "addClass" : "removeClass" ]( className );
2141+ }
2142+
2143+ // Toggle whole class name
2144+ } else if ( type === "undefined" || type === "boolean" ) {
2145+ if ( this.className ) {
2146+ // store className if set
2147+ jQuery._data( this, "__className__", this.className );
2148+ }
2149+
2150+ // If the element has a class name or if we're passed "false",
2151+ // then remove the whole classname (if there was one, the above saved it).
2152+ // Otherwise bring back whatever was previously saved (if anything),
2153+ // falling back to the empty string if nothing was stored.
2154+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2155+ }
2156+ });
2157+ },
2158+
2159+ hasClass: function( selector ) {
2160+ var className = " " + selector + " ",
2161+ i = 0,
2162+ l = this.length;
2163+ for ( ; i < l; i++ ) {
2164+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
2165+ return true;
2166+ }
2167+ }
2168+
2169+ return false;
2170+ },
2171+
2172+ val: function( value ) {
2173+ var hooks, ret, isFunction,
2174+ elem = this[0];
2175+
2176+ if ( !arguments.length ) {
2177+ if ( elem ) {
2178+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
2179+
2180+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2181+ return ret;
2182+ }
2183+
2184+ ret = elem.value;
2185+
2186+ return typeof ret === "string" ?
2187+ // handle most common string cases
2188+ ret.replace(rreturn, "") :
2189+ // handle cases where value is null/undef or number
2190+ ret == null ? "" : ret;
2191+ }
2192+
2193+ return;
2194+ }
2195+
2196+ isFunction = jQuery.isFunction( value );
2197+
2198+ return this.each(function( i ) {
2199+ var val,
2200+ self = jQuery(this);
2201+
2202+ if ( this.nodeType !== 1 ) {
2203+ return;
2204+ }
2205+
2206+ if ( isFunction ) {
2207+ val = value.call( this, i, self.val() );
2208+ } else {
2209+ val = value;
2210+ }
2211+
2212+ // Treat null/undefined as ""; convert numbers to string
2213+ if ( val == null ) {
2214+ val = "";
2215+ } else if ( typeof val === "number" ) {
2216+ val += "";
2217+ } else if ( jQuery.isArray( val ) ) {
2218+ val = jQuery.map(val, function ( value ) {
2219+ return value == null ? "" : value + "";
2220+ });
2221+ }
2222+
2223+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
2224+
2225+ // If set returns undefined, fall back to normal setting
2226+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2227+ this.value = val;
2228+ }
2229+ });
2230+ }
2231+});
2232+
2233+jQuery.extend({
2234+ valHooks: {
2235+ option: {
2236+ get: function( elem ) {
2237+ // attributes.value is undefined in Blackberry 4.7 but
2238+ // uses .value. See #6932
2239+ var val = elem.attributes.value;
2240+ return !val || val.specified ? elem.value : elem.text;
2241+ }
2242+ },
2243+ select: {
2244+ get: function( elem ) {
2245+ var value, option,
2246+ options = elem.options,
2247+ index = elem.selectedIndex,
2248+ one = elem.type === "select-one" || index < 0,
2249+ values = one ? null : [],
2250+ max = one ? index + 1 : options.length,
2251+ i = index < 0 ?
2252+ max :
2253+ one ? index : 0;
2254+
2255+ // Loop through all the selected options
2256+ for ( ; i < max; i++ ) {
2257+ option = options[ i ];
2258+
2259+ // oldIE doesn't update selected after form reset (#2551)
2260+ if ( ( option.selected || i === index ) &&
2261+ // Don't return options that are disabled or in a disabled optgroup
2262+ ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
2263+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
2264+
2265+ // Get the specific value for the option
2266+ value = jQuery( option ).val();
2267+
2268+ // We don't need an array for one selects
2269+ if ( one ) {
2270+ return value;
2271+ }
2272+
2273+ // Multi-Selects return an array
2274+ values.push( value );
2275+ }
2276+ }
2277+
2278+ return values;
2279+ },
2280+
2281+ set: function( elem, value ) {
2282+ var values = jQuery.makeArray( value );
2283+
2284+ jQuery(elem).find("option").each(function() {
2285+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2286+ });
2287+
2288+ if ( !values.length ) {
2289+ elem.selectedIndex = -1;
2290+ }
2291+ return values;
2292+ }
2293+ }
2294+ },
2295+
2296+ attr: function( elem, name, value ) {
2297+ var ret, hooks, notxml,
2298+ nType = elem.nodeType;
2299+
2300+ // don't get/set attributes on text, comment and attribute nodes
2301+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2302+ return;
2303+ }
2304+
2305+ // Fallback to prop when attributes are not supported
2306+ if ( typeof elem.getAttribute === "undefined" ) {
2307+ return jQuery.prop( elem, name, value );
2308+ }
2309+
2310+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2311+
2312+ // All attributes are lowercase
2313+ // Grab necessary hook if one is defined
2314+ if ( notxml ) {
2315+ name = name.toLowerCase();
2316+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2317+ }
2318+
2319+ if ( value !== undefined ) {
2320+
2321+ if ( value === null ) {
2322+ jQuery.removeAttr( elem, name );
2323+
2324+ } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2325+ return ret;
2326+
2327+ } else {
2328+ elem.setAttribute( name, value + "" );
2329+ return value;
2330+ }
2331+
2332+ } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2333+ return ret;
2334+
2335+ } else {
2336+
2337+ // In IE9+, Flash objects don't have .getAttribute (#12945)
2338+ // Support: IE9+
2339+ if ( typeof elem.getAttribute !== "undefined" ) {
2340+ ret = elem.getAttribute( name );
2341+ }
2342+
2343+ // Non-existent attributes return null, we normalize to undefined
2344+ return ret == null ?
2345+ undefined :
2346+ ret;
2347+ }
2348+ },
2349+
2350+ removeAttr: function( elem, value ) {
2351+ var name, propName,
2352+ i = 0,
2353+ attrNames = value && value.match( core_rnotwhite );
2354+
2355+ if ( attrNames && elem.nodeType === 1 ) {
2356+ while ( (name = attrNames[i++]) ) {
2357+ propName = jQuery.propFix[ name ] || name;
2358+
2359+ // Boolean attributes get special treatment (#10870)
2360+ if ( rboolean.test( name ) ) {
2361+ // Set corresponding property to false for boolean attributes
2362+ // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
2363+ if ( !getSetAttribute && ruseDefault.test( name ) ) {
2364+ elem[ jQuery.camelCase( "default-" + name ) ] =
2365+ elem[ propName ] = false;
2366+ } else {
2367+ elem[ propName ] = false;
2368+ }
2369+
2370+ // See #9699 for explanation of this approach (setting first, then removal)
2371+ } else {
2372+ jQuery.attr( elem, name, "" );
2373+ }
2374+
2375+ elem.removeAttribute( getSetAttribute ? name : propName );
2376+ }
2377+ }
2378+ },
2379+
2380+ attrHooks: {
2381+ type: {
2382+ set: function( elem, value ) {
2383+ if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2384+ // Setting the type on a radio button after the value resets the value in IE6-9
2385+ // Reset value to default in case type is set after value during creation
2386+ var val = elem.value;
2387+ elem.setAttribute( "type", value );
2388+ if ( val ) {
2389+ elem.value = val;
2390+ }
2391+ return value;
2392+ }
2393+ }
2394+ }
2395+ },
2396+
2397+ propFix: {
2398+ tabindex: "tabIndex",
2399+ readonly: "readOnly",
2400+ "for": "htmlFor",
2401+ "class": "className",
2402+ maxlength: "maxLength",
2403+ cellspacing: "cellSpacing",
2404+ cellpadding: "cellPadding",
2405+ rowspan: "rowSpan",
2406+ colspan: "colSpan",
2407+ usemap: "useMap",
2408+ frameborder: "frameBorder",
2409+ contenteditable: "contentEditable"
2410+ },
2411+
2412+ prop: function( elem, name, value ) {
2413+ var ret, hooks, notxml,
2414+ nType = elem.nodeType;
2415+
2416+ // don't get/set properties on text, comment and attribute nodes
2417+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2418+ return;
2419+ }
2420+
2421+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2422+
2423+ if ( notxml ) {
2424+ // Fix name and attach hooks
2425+ name = jQuery.propFix[ name ] || name;
2426+ hooks = jQuery.propHooks[ name ];
2427+ }
2428+
2429+ if ( value !== undefined ) {
2430+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2431+ return ret;
2432+
2433+ } else {
2434+ return ( elem[ name ] = value );
2435+ }
2436+
2437+ } else {
2438+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2439+ return ret;
2440+
2441+ } else {
2442+ return elem[ name ];
2443+ }
2444+ }
2445+ },
2446+
2447+ propHooks: {
2448+ tabIndex: {
2449+ get: function( elem ) {
2450+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2451+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2452+ var attributeNode = elem.getAttributeNode("tabindex");
2453+
2454+ return attributeNode && attributeNode.specified ?
2455+ parseInt( attributeNode.value, 10 ) :
2456+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2457+ 0 :
2458+ undefined;
2459+ }
2460+ }
2461+ }
2462+});
2463+
2464+// Hook for boolean attributes
2465+boolHook = {
2466+ get: function( elem, name ) {
2467+ var
2468+ // Use .prop to determine if this attribute is understood as boolean
2469+ prop = jQuery.prop( elem, name ),
2470+
2471+ // Fetch it accordingly
2472+ attr = typeof prop === "boolean" && elem.getAttribute( name ),
2473+ detail = typeof prop === "boolean" ?
2474+
2475+ getSetInput && getSetAttribute ?
2476+ attr != null :
2477+ // oldIE fabricates an empty string for missing boolean attributes
2478+ // and conflates checked/selected into attroperties
2479+ ruseDefault.test( name ) ?
2480+ elem[ jQuery.camelCase( "default-" + name ) ] :
2481+ !!attr :
2482+
2483+ // fetch an attribute node for properties not recognized as boolean
2484+ elem.getAttributeNode( name );
2485+
2486+ return detail && detail.value !== false ?
2487+ name.toLowerCase() :
2488+ undefined;
2489+ },
2490+ set: function( elem, value, name ) {
2491+ if ( value === false ) {
2492+ // Remove boolean attributes when set to false
2493+ jQuery.removeAttr( elem, name );
2494+ } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
2495+ // IE<8 needs the *property* name
2496+ elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
2497+
2498+ // Use defaultChecked and defaultSelected for oldIE
2499+ } else {
2500+ elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
2501+ }
2502+
2503+ return name;
2504+ }
2505+};
2506+
2507+// fix oldIE value attroperty
2508+if ( !getSetInput || !getSetAttribute ) {
2509+ jQuery.attrHooks.value = {
2510+ get: function( elem, name ) {
2511+ var ret = elem.getAttributeNode( name );
2512+ return jQuery.nodeName( elem, "input" ) ?
2513+
2514+ // Ignore the value *property* by using defaultValue
2515+ elem.defaultValue :
2516+
2517+ ret && ret.specified ? ret.value : undefined;
2518+ },
2519+ set: function( elem, value, name ) {
2520+ if ( jQuery.nodeName( elem, "input" ) ) {
2521+ // Does not return so that setAttribute is also used
2522+ elem.defaultValue = value;
2523+ } else {
2524+ // Use nodeHook if defined (#1954); otherwise setAttribute is fine
2525+ return nodeHook && nodeHook.set( elem, value, name );
2526+ }
2527+ }
2528+ };
2529+}
2530+
2531+// IE6/7 do not support getting/setting some attributes with get/setAttribute
2532+if ( !getSetAttribute ) {
2533+
2534+ // Use this for any attribute in IE6/7
2535+ // This fixes almost every IE6/7 issue
2536+ nodeHook = jQuery.valHooks.button = {
2537+ get: function( elem, name ) {
2538+ var ret = elem.getAttributeNode( name );
2539+ return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
2540+ ret.value :
2541+ undefined;
2542+ },
2543+ set: function( elem, value, name ) {
2544+ // Set the existing or create a new attribute node
2545+ var ret = elem.getAttributeNode( name );
2546+ if ( !ret ) {
2547+ elem.setAttributeNode(
2548+ (ret = elem.ownerDocument.createAttribute( name ))
2549+ );
2550+ }
2551+
2552+ ret.value = value += "";
2553+
2554+ // Break association with cloned elements by also using setAttribute (#9646)
2555+ return name === "value" || value === elem.getAttribute( name ) ?
2556+ value :
2557+ undefined;
2558+ }
2559+ };
2560+
2561+ // Set contenteditable to false on removals(#10429)
2562+ // Setting to empty string throws an error as an invalid value
2563+ jQuery.attrHooks.contenteditable = {
2564+ get: nodeHook.get,
2565+ set: function( elem, value, name ) {
2566+ nodeHook.set( elem, value === "" ? false : value, name );
2567+ }
2568+ };
2569+
2570+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2571+ // This is for removals
2572+ jQuery.each([ "width", "height" ], function( i, name ) {
2573+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2574+ set: function( elem, value ) {
2575+ if ( value === "" ) {
2576+ elem.setAttribute( name, "auto" );
2577+ return value;
2578+ }
2579+ }
2580+ });
2581+ });
2582+}
2583+
2584+
2585+// Some attributes require a special call on IE
2586+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2587+if ( !jQuery.support.hrefNormalized ) {
2588+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2589+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2590+ get: function( elem ) {
2591+ var ret = elem.getAttribute( name, 2 );
2592+ return ret == null ? undefined : ret;
2593+ }
2594+ });
2595+ });
2596+
2597+ // href/src property should get the full normalized URL (#10299/#12915)
2598+ jQuery.each([ "href", "src" ], function( i, name ) {
2599+ jQuery.propHooks[ name ] = {
2600+ get: function( elem ) {
2601+ return elem.getAttribute( name, 4 );
2602+ }
2603+ };
2604+ });
2605+}
2606+
2607+if ( !jQuery.support.style ) {
2608+ jQuery.attrHooks.style = {
2609+ get: function( elem ) {
2610+ // Return undefined in the case of empty string
2611+ // Note: IE uppercases css property names, but if we were to .toLowerCase()
2612+ // .cssText, that would destroy case senstitivity in URL's, like in "background"
2613+ return elem.style.cssText || undefined;
2614+ },
2615+ set: function( elem, value ) {
2616+ return ( elem.style.cssText = value + "" );
2617+ }
2618+ };
2619+}
2620+
2621+// Safari mis-reports the default selected property of an option
2622+// Accessing the parent's selectedIndex property fixes it
2623+if ( !jQuery.support.optSelected ) {
2624+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2625+ get: function( elem ) {
2626+ var parent = elem.parentNode;
2627+
2628+ if ( parent ) {
2629+ parent.selectedIndex;
2630+
2631+ // Make sure that it also works with optgroups, see #5701
2632+ if ( parent.parentNode ) {
2633+ parent.parentNode.selectedIndex;
2634+ }
2635+ }
2636+ return null;
2637+ }
2638+ });
2639+}
2640+
2641+// IE6/7 call enctype encoding
2642+if ( !jQuery.support.enctype ) {
2643+ jQuery.propFix.enctype = "encoding";
2644+}
2645+
2646+// Radios and checkboxes getter/setter
2647+if ( !jQuery.support.checkOn ) {
2648+ jQuery.each([ "radio", "checkbox" ], function() {
2649+ jQuery.valHooks[ this ] = {
2650+ get: function( elem ) {
2651+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2652+ return elem.getAttribute("value") === null ? "on" : elem.value;
2653+ }
2654+ };
2655+ });
2656+}
2657+jQuery.each([ "radio", "checkbox" ], function() {
2658+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2659+ set: function( elem, value ) {
2660+ if ( jQuery.isArray( value ) ) {
2661+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2662+ }
2663+ }
2664+ });
2665+});
2666+var rformElems = /^(?:input|select|textarea)$/i,
2667+ rkeyEvent = /^key/,
2668+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
2669+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2670+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
2671+
2672+function returnTrue() {
2673+ return true;
2674+}
2675+
2676+function returnFalse() {
2677+ return false;
2678+}
2679+
2680+/*
2681+ * Helper functions for managing events -- not part of the public interface.
2682+ * Props to Dean Edwards' addEvent library for many of the ideas.
2683+ */
2684+jQuery.event = {
2685+
2686+ global: {},
2687+
2688+ add: function( elem, types, handler, data, selector ) {
2689+
2690+ var handleObjIn, eventHandle, tmp,
2691+ events, t, handleObj,
2692+ special, handlers, type, namespaces, origType,
2693+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
2694+ elemData = elem.nodeType !== 3 && elem.nodeType !== 8 && jQuery._data( elem );
2695+
2696+ if ( !elemData ) {
2697+ return;
2698+ }
2699+
2700+ // Caller can pass in an object of custom data in lieu of the handler
2701+ if ( handler.handler ) {
2702+ handleObjIn = handler;
2703+ handler = handleObjIn.handler;
2704+ selector = handleObjIn.selector;
2705+ }
2706+
2707+ // Make sure that the handler has a unique ID, used to find/remove it later
2708+ if ( !handler.guid ) {
2709+ handler.guid = jQuery.guid++;
2710+ }
2711+
2712+ // Init the element's event structure and main handler, if this is the first
2713+ if ( !(events = elemData.events) ) {
2714+ events = elemData.events = {};
2715+ }
2716+ if ( !(eventHandle = elemData.handle) ) {
2717+ eventHandle = elemData.handle = function( e ) {
2718+ // Discard the second event of a jQuery.event.trigger() and
2719+ // when an event is called after a page has unloaded
2720+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
2721+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2722+ undefined;
2723+ };
2724+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2725+ eventHandle.elem = elem;
2726+ }
2727+
2728+ // Handle multiple events separated by a space
2729+ // jQuery(...).bind("mouseover mouseout", fn);
2730+ types = ( types || "" ).match( core_rnotwhite ) || [""];
2731+ t = types.length;
2732+ while ( t-- ) {
2733+ tmp = rtypenamespace.exec( types[t] ) || [];
2734+ type = origType = tmp[1];
2735+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
2736+
2737+ // If event changes its type, use the special event handlers for the changed type
2738+ special = jQuery.event.special[ type ] || {};
2739+
2740+ // If selector defined, determine special event api type, otherwise given type
2741+ type = ( selector ? special.delegateType : special.bindType ) || type;
2742+
2743+ // Update special based on newly reset type
2744+ special = jQuery.event.special[ type ] || {};
2745+
2746+ // handleObj is passed to all event handlers
2747+ handleObj = jQuery.extend({
2748+ type: type,
2749+ origType: origType,
2750+ data: data,
2751+ handler: handler,
2752+ guid: handler.guid,
2753+ selector: selector,
2754+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
2755+ namespace: namespaces.join(".")
2756+ }, handleObjIn );
2757+
2758+ // Init the event handler queue if we're the first
2759+ if ( !(handlers = events[ type ]) ) {
2760+ handlers = events[ type ] = [];
2761+ handlers.delegateCount = 0;
2762+
2763+ // Only use addEventListener/attachEvent if the special events handler returns false
2764+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2765+ // Bind the global event handler to the element
2766+ if ( elem.addEventListener ) {
2767+ elem.addEventListener( type, eventHandle, false );
2768+
2769+ } else if ( elem.attachEvent ) {
2770+ elem.attachEvent( "on" + type, eventHandle );
2771+ }
2772+ }
2773+ }
2774+
2775+ if ( special.add ) {
2776+ special.add.call( elem, handleObj );
2777+
2778+ if ( !handleObj.handler.guid ) {
2779+ handleObj.handler.guid = handler.guid;
2780+ }
2781+ }
2782+
2783+ // Add to the element's handler list, delegates in front
2784+ if ( selector ) {
2785+ handlers.splice( handlers.delegateCount++, 0, handleObj );
2786+ } else {
2787+ handlers.push( handleObj );
2788+ }
2789+
2790+ // Keep track of which events have ever been used, for event optimization
2791+ jQuery.event.global[ type ] = true;
2792+ }
2793+
2794+ // Nullify elem to prevent memory leaks in IE
2795+ elem = null;
2796+ },
2797+
2798+ // Detach an event or set of events from an element
2799+ remove: function( elem, types, handler, selector, mappedTypes ) {
2800+
2801+ var j, origCount, tmp,
2802+ events, t, handleObj,
2803+ special, handlers, type, namespaces, origType,
2804+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
2805+
2806+ if ( !elemData || !(events = elemData.events) ) {
2807+ return;
2808+ }
2809+
2810+ // Once for each type.namespace in types; type may be omitted
2811+ types = ( types || "" ).match( core_rnotwhite ) || [""];
2812+ t = types.length;
2813+ while ( t-- ) {
2814+ tmp = rtypenamespace.exec( types[t] ) || [];
2815+ type = origType = tmp[1];
2816+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
2817+
2818+ // Unbind all events (on this namespace, if provided) for the element
2819+ if ( !type ) {
2820+ for ( type in events ) {
2821+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
2822+ }
2823+ continue;
2824+ }
2825+
2826+ special = jQuery.event.special[ type ] || {};
2827+ type = ( selector ? special.delegateType : special.bindType ) || type;
2828+ handlers = events[ type ] || [];
2829+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
2830+
2831+ // Remove matching events
2832+ origCount = j = handlers.length;
2833+ while ( j-- ) {
2834+ handleObj = handlers[ j ];
2835+
2836+ if ( ( mappedTypes || origType === handleObj.origType ) &&
2837+ ( !handler || handler.guid === handleObj.guid ) &&
2838+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
2839+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
2840+ handlers.splice( j, 1 );
2841+
2842+ if ( handleObj.selector ) {
2843+ handlers.delegateCount--;
2844+ }
2845+ if ( special.remove ) {
2846+ special.remove.call( elem, handleObj );
2847+ }
2848+ }
2849+ }
2850+
2851+ // Remove generic event handler if we removed something and no more handlers exist
2852+ // (avoids potential for endless recursion during removal of special event handlers)
2853+ if ( origCount && !handlers.length ) {
2854+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
2855+ jQuery.removeEvent( elem, type, elemData.handle );
2856+ }
2857+
2858+ delete events[ type ];
2859+ }
2860+ }
2861+
2862+ // Remove the expando if it's no longer used
2863+ if ( jQuery.isEmptyObject( events ) ) {
2864+ delete elemData.handle;
2865+
2866+ // removeData also checks for emptiness and clears the expando if empty
2867+ // so use it instead of delete
2868+ jQuery._removeData( elem, "events" );
2869+ }
2870+ },
2871+
2872+ trigger: function( event, data, elem, onlyHandlers ) {
2873+
2874+ var i, cur, tmp, bubbleType, ontype, handle, special,
2875+ eventPath = [ elem || document ],
2876+ type = event.type || event,
2877+ namespaces = event.namespace ? event.namespace.split(".") : [];
2878+
2879+ cur = tmp = elem = elem || document;
2880+
2881+ // Don't do events on text and comment nodes
2882+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2883+ return;
2884+ }
2885+
2886+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
2887+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
2888+ return;
2889+ }
2890+
2891+ if ( type.indexOf(".") >= 0 ) {
2892+ // Namespaced trigger; create a regexp to match event type in handle()
2893+ namespaces = type.split(".");
2894+ type = namespaces.shift();
2895+ namespaces.sort();
2896+ }
2897+ ontype = type.indexOf(":") < 0 && "on" + type;
2898+
2899+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
2900+ event = event[ jQuery.expando ] ?
2901+ event :
2902+ new jQuery.Event( type, typeof event === "object" && event );
2903+
2904+ event.isTrigger = true;
2905+ event.namespace = namespaces.join(".");
2906+ event.namespace_re = event.namespace ?
2907+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
2908+ null;
2909+
2910+ // Clean up the event in case it is being reused
2911+ event.result = undefined;
2912+ if ( !event.target ) {
2913+ event.target = elem;
2914+ }
2915+
2916+ // Clone any incoming data and prepend the event, creating the handler arg list
2917+ data = data == null ?
2918+ [ event ] :
2919+ jQuery.makeArray( data, [ event ] );
2920+
2921+ // Allow special events to draw outside the lines
2922+ special = jQuery.event.special[ type ] || {};
2923+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
2924+ return;
2925+ }
2926+
2927+ // Determine event propagation path in advance, per W3C events spec (#9951)
2928+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
2929+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
2930+
2931+ bubbleType = special.delegateType || type;
2932+ if ( !rfocusMorph.test( bubbleType + type ) ) {
2933+ cur = cur.parentNode;
2934+ }
2935+ for ( ; cur; cur = cur.parentNode ) {
2936+ eventPath.push( cur );
2937+ tmp = cur;
2938+ }
2939+
2940+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
2941+ if ( tmp === (elem.ownerDocument || document) ) {
2942+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
2943+ }
2944+ }
2945+
2946+ // Fire handlers on the event path
2947+ i = 0;
2948+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
2949+
2950+ event.type = i > 1 ?
2951+ bubbleType :
2952+ special.bindType || type;
2953+
2954+ // jQuery handler
2955+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
2956+ if ( handle ) {
2957+ handle.apply( cur, data );
2958+ }
2959+
2960+ // Native handler
2961+ handle = ontype && cur[ ontype ];
2962+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
2963+ event.preventDefault();
2964+ }
2965+ }
2966+ event.type = type;
2967+
2968+ // If nobody prevented the default action, do it now
2969+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
2970+
2971+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
2972+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
2973+
2974+ // Call a native DOM method on the target with the same name name as the event.
2975+ // Can't use an .isFunction() check here because IE6/7 fails that test.
2976+ // Don't do default actions on window, that's where global variables be (#6170)
2977+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
2978+
2979+ // Don't re-trigger an onFOO event when we call its FOO() method
2980+ tmp = elem[ ontype ];
2981+
2982+ if ( tmp ) {
2983+ elem[ ontype ] = null;
2984+ }
2985+
2986+ // Prevent re-triggering of the same event, since we already bubbled it above
2987+ jQuery.event.triggered = type;
2988+ try {
2989+ elem[ type ]();
2990+ } catch ( e ) {
2991+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
2992+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
2993+ }
2994+ jQuery.event.triggered = undefined;
2995+
2996+ if ( tmp ) {
2997+ elem[ ontype ] = tmp;
2998+ }
2999+ }
3000+ }
3001+ }
3002+
3003+ return event.result;
3004+ },
3005+
3006+ dispatch: function( event ) {
3007+
3008+ // Make a writable jQuery.Event from the native event object
3009+ event = jQuery.event.fix( event );
3010+
3011+ var i, j, ret, matched, handleObj,
3012+ handlerQueue = [],
3013+ args = core_slice.call( arguments ),
3014+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
3015+ special = jQuery.event.special[ event.type ] || {};
3016+
3017+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
3018+ args[0] = event;
3019+ event.delegateTarget = this;
3020+
3021+ // Call the preDispatch hook for the mapped type, and let it bail if desired
3022+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
3023+ return;
3024+ }
3025+
3026+ // Determine handlers
3027+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
3028+
3029+ // Run delegates first; they may want to stop propagation beneath us
3030+ i = 0;
3031+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
3032+ event.currentTarget = matched.elem;
3033+
3034+ j = 0;
3035+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
3036+
3037+ // Triggered event must either 1) have no namespace, or
3038+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3039+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
3040+
3041+ event.handleObj = handleObj;
3042+ event.data = handleObj.data;
3043+
3044+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
3045+ .apply( matched.elem, args );
3046+
3047+ if ( ret !== undefined ) {
3048+ if ( (event.result = ret) === false ) {
3049+ event.preventDefault();
3050+ event.stopPropagation();
3051+ }
3052+ }
3053+ }
3054+ }
3055+ }
3056+
3057+ // Call the postDispatch hook for the mapped type
3058+ if ( special.postDispatch ) {
3059+ special.postDispatch.call( this, event );
3060+ }
3061+
3062+ return event.result;
3063+ },
3064+
3065+ handlers: function( event, handlers ) {
3066+ var i, matches, sel, handleObj,
3067+ handlerQueue = [],
3068+ delegateCount = handlers.delegateCount,
3069+ cur = event.target;
3070+
3071+ // Find delegate handlers
3072+ // Black-hole SVG <use> instance trees (#13180)
3073+ // Avoid non-left-click bubbling in Firefox (#3861)
3074+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
3075+
3076+ for ( ; cur != this; cur = cur.parentNode || this ) {
3077+
3078+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
3079+ if ( cur.disabled !== true || event.type !== "click" ) {
3080+ matches = [];
3081+ for ( i = 0; i < delegateCount; i++ ) {
3082+ handleObj = handlers[ i ];
3083+
3084+ // Don't conflict with Object.prototype properties (#13203)
3085+ sel = handleObj.selector + " ";
3086+
3087+ if ( matches[ sel ] === undefined ) {
3088+ matches[ sel ] = handleObj.needsContext ?
3089+ jQuery( sel, this ).index( cur ) >= 0 :
3090+ jQuery.find( sel, this, null, [ cur ] ).length;
3091+ }
3092+ if ( matches[ sel ] ) {
3093+ matches.push( handleObj );
3094+ }
3095+ }
3096+ if ( matches.length ) {
3097+ handlerQueue.push({ elem: cur, handlers: matches });
3098+ }
3099+ }
3100+ }
3101+ }
3102+
3103+ // Add the remaining (directly-bound) handlers
3104+ if ( delegateCount < handlers.length ) {
3105+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
3106+ }
3107+
3108+ return handlerQueue;
3109+ },
3110+
3111+ fix: function( event ) {
3112+ if ( event[ jQuery.expando ] ) {
3113+ return event;
3114+ }
3115+
3116+ // Create a writable copy of the event object and normalize some properties
3117+ var i, prop,
3118+ originalEvent = event,
3119+ fixHook = jQuery.event.fixHooks[ event.type ] || {},
3120+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3121+
3122+ event = new jQuery.Event( originalEvent );
3123+
3124+ i = copy.length;
3125+ while ( i-- ) {
3126+ prop = copy[ i ];
3127+ event[ prop ] = originalEvent[ prop ];
3128+ }
3129+
3130+ // Support: IE<9
3131+ // Fix target property (#1925)
3132+ if ( !event.target ) {
3133+ event.target = originalEvent.srcElement || document;
3134+ }
3135+
3136+ // Support: Chrome 23+, Safari?
3137+ // Target should not be a text node (#504, #13143)
3138+ if ( event.target.nodeType === 3 ) {
3139+ event.target = event.target.parentNode;
3140+ }
3141+
3142+ // Support: IE<9
3143+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
3144+ event.metaKey = !!event.metaKey;
3145+
3146+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
3147+ },
3148+
3149+ // Includes some event props shared by KeyEvent and MouseEvent
3150+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3151+
3152+ fixHooks: {},
3153+
3154+ keyHooks: {
3155+ props: "char charCode key keyCode".split(" "),
3156+ filter: function( event, original ) {
3157+
3158+ // Add which for key events
3159+ if ( event.which == null ) {
3160+ event.which = original.charCode != null ? original.charCode : original.keyCode;
3161+ }
3162+
3163+ return event;
3164+ }
3165+ },
3166+
3167+ mouseHooks: {
3168+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3169+ filter: function( event, original ) {
3170+ var eventDoc, doc, body,
3171+ button = original.button,
3172+ fromElement = original.fromElement;
3173+
3174+ // Calculate pageX/Y if missing and clientX/Y available
3175+ if ( event.pageX == null && original.clientX != null ) {
3176+ eventDoc = event.target.ownerDocument || document;
3177+ doc = eventDoc.documentElement;
3178+ body = eventDoc.body;
3179+
3180+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3181+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3182+ }
3183+
3184+ // Add relatedTarget, if necessary
3185+ if ( !event.relatedTarget && fromElement ) {
3186+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3187+ }
3188+
3189+ // Add which for click: 1 === left; 2 === middle; 3 === right
3190+ // Note: button is not normalized, so don't use it
3191+ if ( !event.which && button !== undefined ) {
3192+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3193+ }
3194+
3195+ return event;
3196+ }
3197+ },
3198+
3199+ special: {
3200+ load: {
3201+ // Prevent triggered image.load events from bubbling to window.load
3202+ noBubble: true
3203+ },
3204+ click: {
3205+ // For checkbox, fire native event so checked state will be right
3206+ trigger: function() {
3207+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
3208+ this.click();
3209+ return false;
3210+ }
3211+ }
3212+ },
3213+ focus: {
3214+ // Fire native event if possible so blur/focus sequence is correct
3215+ trigger: function() {
3216+ if ( this !== document.activeElement && this.focus ) {
3217+ try {
3218+ this.focus();
3219+ return false;
3220+ } catch ( e ) {
3221+ // Support: IE<9
3222+ // If we error on focus to hidden element (#1486, #12518),
3223+ // let .trigger() run the handlers
3224+ }
3225+ }
3226+ },
3227+ delegateType: "focusin"
3228+ },
3229+ blur: {
3230+ trigger: function() {
3231+ if ( this === document.activeElement && this.blur ) {
3232+ this.blur();
3233+ return false;
3234+ }
3235+ },
3236+ delegateType: "focusout"
3237+ },
3238+
3239+ beforeunload: {
3240+ postDispatch: function( event ) {
3241+
3242+ // Even when returnValue equals to undefined Firefox will still show alert
3243+ if ( event.result !== undefined ) {
3244+ event.originalEvent.returnValue = event.result;
3245+ }
3246+ }
3247+ }
3248+ },
3249+
3250+ simulate: function( type, elem, event, bubble ) {
3251+ // Piggyback on a donor event to simulate a different one.
3252+ // Fake originalEvent to avoid donor's stopPropagation, but if the
3253+ // simulated event prevents default then we do the same on the donor.
3254+ var e = jQuery.extend(
3255+ new jQuery.Event(),
3256+ event,
3257+ { type: type,
3258+ isSimulated: true,
3259+ originalEvent: {}
3260+ }
3261+ );
3262+ if ( bubble ) {
3263+ jQuery.event.trigger( e, null, elem );
3264+ } else {
3265+ jQuery.event.dispatch.call( elem, e );
3266+ }
3267+ if ( e.isDefaultPrevented() ) {
3268+ event.preventDefault();
3269+ }
3270+ }
3271+};
3272+
3273+jQuery.removeEvent = document.removeEventListener ?
3274+ function( elem, type, handle ) {
3275+ if ( elem.removeEventListener ) {
3276+ elem.removeEventListener( type, handle, false );
3277+ }
3278+ } :
3279+ function( elem, type, handle ) {
3280+ var name = "on" + type;
3281+
3282+ if ( elem.detachEvent ) {
3283+
3284+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
3285+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
3286+ if ( typeof elem[ name ] === "undefined" ) {
3287+ elem[ name ] = null;
3288+ }
3289+
3290+ elem.detachEvent( name, handle );
3291+ }
3292+ };
3293+
3294+jQuery.Event = function( src, props ) {
3295+ // Allow instantiation without the 'new' keyword
3296+ if ( !(this instanceof jQuery.Event) ) {
3297+ return new jQuery.Event( src, props );
3298+ }
3299+
3300+ // Event object
3301+ if ( src && src.type ) {
3302+ this.originalEvent = src;
3303+ this.type = src.type;
3304+
3305+ // Events bubbling up the document may have been marked as prevented
3306+ // by a handler lower down the tree; reflect the correct value.
3307+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3308+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3309+
3310+ // Event type
3311+ } else {
3312+ this.type = src;
3313+ }
3314+
3315+ // Put explicitly provided properties onto the event object
3316+ if ( props ) {
3317+ jQuery.extend( this, props );
3318+ }
3319+
3320+ // Create a timestamp if incoming event doesn't have one
3321+ this.timeStamp = src && src.timeStamp || jQuery.now();
3322+
3323+ // Mark it as fixed
3324+ this[ jQuery.expando ] = true;
3325+};
3326+
3327+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3328+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3329+jQuery.Event.prototype = {
3330+ isDefaultPrevented: returnFalse,
3331+ isPropagationStopped: returnFalse,
3332+ isImmediatePropagationStopped: returnFalse,
3333+
3334+ preventDefault: function() {
3335+ var e = this.originalEvent;
3336+
3337+ this.isDefaultPrevented = returnTrue;
3338+ if ( !e ) {
3339+ return;
3340+ }
3341+
3342+ // If preventDefault exists, run it on the original event
3343+ if ( e.preventDefault ) {
3344+ e.preventDefault();
3345+
3346+ // Support: IE
3347+ // Otherwise set the returnValue property of the original event to false
3348+ } else {
3349+ e.returnValue = false;
3350+ }
3351+ },
3352+ stopPropagation: function() {
3353+ var e = this.originalEvent;
3354+
3355+ this.isPropagationStopped = returnTrue;
3356+ if ( !e ) {
3357+ return;
3358+ }
3359+ // If stopPropagation exists, run it on the original event
3360+ if ( e.stopPropagation ) {
3361+ e.stopPropagation();
3362+ }
3363+
3364+ // Support: IE
3365+ // Set the cancelBubble property of the original event to true
3366+ e.cancelBubble = true;
3367+ },
3368+ stopImmediatePropagation: function() {
3369+ this.isImmediatePropagationStopped = returnTrue;
3370+ this.stopPropagation();
3371+ }
3372+};
3373+
3374+// Create mouseenter/leave events using mouseover/out and event-time checks
3375+jQuery.each({
3376+ mouseenter: "mouseover",
3377+ mouseleave: "mouseout"
3378+}, function( orig, fix ) {
3379+ jQuery.event.special[ orig ] = {
3380+ delegateType: fix,
3381+ bindType: fix,
3382+
3383+ handle: function( event ) {
3384+ var ret,
3385+ target = this,
3386+ related = event.relatedTarget,
3387+ handleObj = event.handleObj;
3388+
3389+ // For mousenter/leave call the handler if related is outside the target.
3390+ // NB: No relatedTarget if the mouse left/entered the browser window
3391+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3392+ event.type = handleObj.origType;
3393+ ret = handleObj.handler.apply( this, arguments );
3394+ event.type = fix;
3395+ }
3396+ return ret;
3397+ }
3398+ };
3399+});
3400+
3401+// IE submit delegation
3402+if ( !jQuery.support.submitBubbles ) {
3403+
3404+ jQuery.event.special.submit = {
3405+ setup: function() {
3406+ // Only need this for delegated form submit events
3407+ if ( jQuery.nodeName( this, "form" ) ) {
3408+ return false;
3409+ }
3410+
3411+ // Lazy-add a submit handler when a descendant form may potentially be submitted
3412+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
3413+ // Node name check avoids a VML-related crash in IE (#9807)
3414+ var elem = e.target,
3415+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
3416+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
3417+ jQuery.event.add( form, "submit._submit", function( event ) {
3418+ event._submit_bubble = true;
3419+ });
3420+ jQuery._data( form, "submitBubbles", true );
3421+ }
3422+ });
3423+ // return undefined since we don't need an event listener
3424+ },
3425+
3426+ postDispatch: function( event ) {
3427+ // If form was submitted by the user, bubble the event up the tree
3428+ if ( event._submit_bubble ) {
3429+ delete event._submit_bubble;
3430+ if ( this.parentNode && !event.isTrigger ) {
3431+ jQuery.event.simulate( "submit", this.parentNode, event, true );
3432+ }
3433+ }
3434+ },
3435+
3436+ teardown: function() {
3437+ // Only need this for delegated form submit events
3438+ if ( jQuery.nodeName( this, "form" ) ) {
3439+ return false;
3440+ }
3441+
3442+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
3443+ jQuery.event.remove( this, "._submit" );
3444+ }
3445+ };
3446+}
3447+
3448+// IE change delegation and checkbox/radio fix
3449+if ( !jQuery.support.changeBubbles ) {
3450+
3451+ jQuery.event.special.change = {
3452+
3453+ setup: function() {
3454+
3455+ if ( rformElems.test( this.nodeName ) ) {
3456+ // IE doesn't fire change on a check/radio until blur; trigger it on click
3457+ // after a propertychange. Eat the blur-change in special.change.handle.
3458+ // This still fires onchange a second time for check/radio after blur.
3459+ if ( this.type === "checkbox" || this.type === "radio" ) {
3460+ jQuery.event.add( this, "propertychange._change", function( event ) {
3461+ if ( event.originalEvent.propertyName === "checked" ) {
3462+ this._just_changed = true;
3463+ }
3464+ });
3465+ jQuery.event.add( this, "click._change", function( event ) {
3466+ if ( this._just_changed && !event.isTrigger ) {
3467+ this._just_changed = false;
3468+ }
3469+ // Allow triggered, simulated change events (#11500)
3470+ jQuery.event.simulate( "change", this, event, true );
3471+ });
3472+ }
3473+ return false;
3474+ }
3475+ // Delegated event; lazy-add a change handler on descendant inputs
3476+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
3477+ var elem = e.target;
3478+
3479+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
3480+ jQuery.event.add( elem, "change._change", function( event ) {
3481+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
3482+ jQuery.event.simulate( "change", this.parentNode, event, true );
3483+ }
3484+ });
3485+ jQuery._data( elem, "changeBubbles", true );
3486+ }
3487+ });
3488+ },
3489+
3490+ handle: function( event ) {
3491+ var elem = event.target;
3492+
3493+ // Swallow native change events from checkbox/radio, we already triggered them above
3494+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
3495+ return event.handleObj.handler.apply( this, arguments );
3496+ }
3497+ },
3498+
3499+ teardown: function() {
3500+ jQuery.event.remove( this, "._change" );
3501+
3502+ return !rformElems.test( this.nodeName );
3503+ }
3504+ };
3505+}
3506+
3507+// Create "bubbling" focus and blur events
3508+if ( !jQuery.support.focusinBubbles ) {
3509+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
3510+
3511+ // Attach a single capturing handler while someone wants focusin/focusout
3512+ var attaches = 0,
3513+ handler = function( event ) {
3514+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
3515+ };
3516+
3517+ jQuery.event.special[ fix ] = {
3518+ setup: function() {
3519+ if ( attaches++ === 0 ) {
3520+ document.addEventListener( orig, handler, true );
3521+ }
3522+ },
3523+ teardown: function() {
3524+ if ( --attaches === 0 ) {
3525+ document.removeEventListener( orig, handler, true );
3526+ }
3527+ }
3528+ };
3529+ });
3530+}
3531+
3532+jQuery.fn.extend({
3533+
3534+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
3535+ var origFn, type;
3536+
3537+ // Types can be a map of types/handlers
3538+ if ( typeof types === "object" ) {
3539+ // ( types-Object, selector, data )
3540+ if ( typeof selector !== "string" ) {
3541+ // ( types-Object, data )
3542+ data = data || selector;
3543+ selector = undefined;
3544+ }
3545+ for ( type in types ) {
3546+ this.on( type, selector, data, types[ type ], one );
3547+ }
3548+ return this;
3549+ }
3550+
3551+ if ( data == null && fn == null ) {
3552+ // ( types, fn )
3553+ fn = selector;
3554+ data = selector = undefined;
3555+ } else if ( fn == null ) {
3556+ if ( typeof selector === "string" ) {
3557+ // ( types, selector, fn )
3558+ fn = data;
3559+ data = undefined;
3560+ } else {
3561+ // ( types, data, fn )
3562+ fn = data;
3563+ data = selector;
3564+ selector = undefined;
3565+ }
3566+ }
3567+ if ( fn === false ) {
3568+ fn = returnFalse;
3569+ } else if ( !fn ) {
3570+ return this;
3571+ }
3572+
3573+ if ( one === 1 ) {
3574+ origFn = fn;
3575+ fn = function( event ) {
3576+ // Can use an empty set, since event contains the info
3577+ jQuery().off( event );
3578+ return origFn.apply( this, arguments );
3579+ };
3580+ // Use same guid so caller can remove using origFn
3581+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
3582+ }
3583+ return this.each( function() {
3584+ jQuery.event.add( this, types, fn, data, selector );
3585+ });
3586+ },
3587+ one: function( types, selector, data, fn ) {
3588+ return this.on( types, selector, data, fn, 1 );
3589+ },
3590+ off: function( types, selector, fn ) {
3591+ var handleObj, type;
3592+ if ( types && types.preventDefault && types.handleObj ) {
3593+ // ( event ) dispatched jQuery.Event
3594+ handleObj = types.handleObj;
3595+ jQuery( types.delegateTarget ).off(
3596+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
3597+ handleObj.selector,
3598+ handleObj.handler
3599+ );
3600+ return this;
3601+ }
3602+ if ( typeof types === "object" ) {
3603+ // ( types-object [, selector] )
3604+ for ( type in types ) {
3605+ this.off( type, selector, types[ type ] );
3606+ }
3607+ return this;
3608+ }
3609+ if ( selector === false || typeof selector === "function" ) {
3610+ // ( types [, fn] )
3611+ fn = selector;
3612+ selector = undefined;
3613+ }
3614+ if ( fn === false ) {
3615+ fn = returnFalse;
3616+ }
3617+ return this.each(function() {
3618+ jQuery.event.remove( this, types, fn, selector );
3619+ });
3620+ },
3621+
3622+ bind: function( types, data, fn ) {
3623+ return this.on( types, null, data, fn );
3624+ },
3625+ unbind: function( types, fn ) {
3626+ return this.off( types, null, fn );
3627+ },
3628+
3629+ delegate: function( selector, types, data, fn ) {
3630+ return this.on( types, selector, data, fn );
3631+ },
3632+ undelegate: function( selector, types, fn ) {
3633+ // ( namespace ) or ( selector, types [, fn] )
3634+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3635+ },
3636+
3637+ trigger: function( type, data ) {
3638+ return this.each(function() {
3639+ jQuery.event.trigger( type, data, this );
3640+ });
3641+ },
3642+ triggerHandler: function( type, data ) {
3643+ var elem = this[0];
3644+ if ( elem ) {
3645+ return jQuery.event.trigger( type, data, elem, true );
3646+ }
3647+ },
3648+
3649+ hover: function( fnOver, fnOut ) {
3650+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
3651+ }
3652+});
3653+
3654+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
3655+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
3656+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
3657+
3658+ // Handle event binding
3659+ jQuery.fn[ name ] = function( data, fn ) {
3660+ return arguments.length > 0 ?
3661+ this.on( name, null, data, fn ) :
3662+ this.trigger( name );
3663+ };
3664+
3665+ if ( rkeyEvent.test( name ) ) {
3666+ jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
3667+ }
3668+
3669+ if ( rmouseEvent.test( name ) ) {
3670+ jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
3671+ }
3672+});
3673+/*!
3674+ * Sizzle CSS Selector Engine
3675+ * Copyright 2012 jQuery Foundation and other contributors
3676+ * Released under the MIT license
3677+ * http://sizzlejs.com/
3678+ */
3679+(function( window, undefined ) {
3680+
3681+var i,
3682+ cachedruns,
3683+ Expr,
3684+ getText,
3685+ isXML,
3686+ compile,
3687+ hasDuplicate,
3688+ outermostContext,
3689+
3690+ // Local document vars
3691+ setDocument,
3692+ document,
3693+ docElem,
3694+ documentIsXML,
3695+ rbuggyQSA,
3696+ rbuggyMatches,
3697+ matches,
3698+ contains,
3699+ sortOrder,
3700+
3701+ // Instance-specific data
3702+ expando = "sizzle" + -(new Date()),
3703+ preferredDoc = window.document,
3704+ support = {},
3705+ dirruns = 0,
3706+ done = 0,
3707+ classCache = createCache(),
3708+ tokenCache = createCache(),
3709+ compilerCache = createCache(),
3710+
3711+ // General-purpose constants
3712+ strundefined = typeof undefined,
3713+ MAX_NEGATIVE = 1 << 31,
3714+
3715+ // Array methods
3716+ arr = [],
3717+ pop = arr.pop,
3718+ push = arr.push,
3719+ slice = arr.slice,
3720+ // Use a stripped-down indexOf if we can't use a native one
3721+ indexOf = arr.indexOf || function( elem ) {
3722+ var i = 0,
3723+ len = this.length;
3724+ for ( ; i < len; i++ ) {
3725+ if ( this[i] === elem ) {
3726+ return i;
3727+ }
3728+ }
3729+ return -1;
3730+ },
3731+
3732+
3733+ // Regular expressions
3734+
3735+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
3736+ whitespace = "[\\x20\\t\\r\\n\\f]",
3737+ // http://www.w3.org/TR/css3-syntax/#characters
3738+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
3739+
3740+ // Loosely modeled on CSS identifier characters
3741+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
3742+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
3743+ identifier = characterEncoding.replace( "w", "w#" ),
3744+
3745+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
3746+ operators = "([*^$|!~]?=)",
3747+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
3748+ "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
3749+
3750+ // Prefer arguments quoted,
3751+ // then not containing pseudos/brackets,
3752+ // then attribute selectors/non-parenthetical expressions,
3753+ // then anything else
3754+ // These preferences are here to reduce the number of selectors
3755+ // needing tokenize in the PSEUDO preFilter
3756+ pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
3757+
3758+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
3759+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
3760+
3761+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
3762+ rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
3763+ rpseudo = new RegExp( pseudos ),
3764+ ridentifier = new RegExp( "^" + identifier + "$" ),
3765+
3766+ matchExpr = {
3767+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
3768+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
3769+ "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
3770+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
3771+ "ATTR": new RegExp( "^" + attributes ),
3772+ "PSEUDO": new RegExp( "^" + pseudos ),
3773+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
3774+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
3775+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
3776+ // For use in libraries implementing .is()
3777+ // We use this for POS matching in `select`
3778+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
3779+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
3780+ },
3781+
3782+ rsibling = /[\x20\t\r\n\f]*[+~]/,
3783+
3784+ rnative = /\{\s*\[native code\]\s*\}/,
3785+
3786+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
3787+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
3788+
3789+ rinputs = /^(?:input|select|textarea|button)$/i,
3790+ rheader = /^h\d$/i,
3791+
3792+ rescape = /'|\\/g,
3793+ rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
3794+
3795+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
3796+ runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
3797+ funescape = function( _, escaped ) {
3798+ var high = "0x" + escaped - 0x10000;
3799+ // NaN means non-codepoint
3800+ return high !== high ?
3801+ escaped :
3802+ // BMP codepoint
3803+ high < 0 ?
3804+ String.fromCharCode( high + 0x10000 ) :
3805+ // Supplemental Plane codepoint (surrogate pair)
3806+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
3807+ };
3808+
3809+// Use a stripped-down slice if we can't use a native one
3810+try {
3811+ slice.call( docElem.childNodes, 0 )[0].nodeType;
3812+} catch ( e ) {
3813+ slice = function( i ) {
3814+ var elem,
3815+ results = [];
3816+ for ( ; (elem = this[i]); i++ ) {
3817+ results.push( elem );
3818+ }
3819+ return results;
3820+ };
3821+}
3822+
3823+/**
3824+ * For feature detection
3825+ * @param {Function} fn The function to test for native support
3826+ */
3827+function isNative( fn ) {
3828+ return rnative.test( fn + "" );
3829+}
3830+
3831+/**
3832+ * Create key-value caches of limited size
3833+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
3834+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
3835+ * deleting the oldest entry
3836+ */
3837+function createCache() {
3838+ var cache,
3839+ keys = [];
3840+
3841+ return (cache = function( key, value ) {
3842+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
3843+ if ( keys.push( key += " " ) > Expr.cacheLength ) {
3844+ // Only keep the most recent entries
3845+ delete cache[ keys.shift() ];
3846+ }
3847+ return (cache[ key ] = value);
3848+ });
3849+}
3850+
3851+/**
3852+ * Mark a function for special use by Sizzle
3853+ * @param {Function} fn The function to mark
3854+ */
3855+function markFunction( fn ) {
3856+ fn[ expando ] = true;
3857+ return fn;
3858+}
3859+
3860+/**
3861+ * Support testing using an element
3862+ * @param {Function} fn Passed the created div and expects a boolean result
3863+ */
3864+function assert( fn ) {
3865+ var div = document.createElement("div");
3866+
3867+ try {
3868+ return fn( div );
3869+ } catch (e) {
3870+ return false;
3871+ } finally {
3872+ // release memory in IE
3873+ div = null;
3874+ }
3875+}
3876+
3877+function Sizzle( selector, context, results, seed ) {
3878+ var match, elem, m, nodeType,
3879+ // QSA vars
3880+ i, groups, old, nid, newContext, newSelector;
3881+
3882+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
3883+ setDocument( context );
3884+ }
3885+
3886+ context = context || document;
3887+ results = results || [];
3888+
3889+ if ( !selector || typeof selector !== "string" ) {
3890+ return results;
3891+ }
3892+
3893+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
3894+ return [];
3895+ }
3896+
3897+ if ( !documentIsXML && !seed ) {
3898+
3899+ // Shortcuts
3900+ if ( (match = rquickExpr.exec( selector )) ) {
3901+ // Speed-up: Sizzle("#ID")
3902+ if ( (m = match[1]) ) {
3903+ if ( nodeType === 9 ) {
3904+ elem = context.getElementById( m );
3905+ // Check parentNode to catch when Blackberry 4.6 returns
3906+ // nodes that are no longer in the document #6963
3907+ if ( elem && elem.parentNode ) {
3908+ // Handle the case where IE, Opera, and Webkit return items
3909+ // by name instead of ID
3910+ if ( elem.id === m ) {
3911+ results.push( elem );
3912+ return results;
3913+ }
3914+ } else {
3915+ return results;
3916+ }
3917+ } else {
3918+ // Context is not a document
3919+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
3920+ contains( context, elem ) && elem.id === m ) {
3921+ results.push( elem );
3922+ return results;
3923+ }
3924+ }
3925+
3926+ // Speed-up: Sizzle("TAG")
3927+ } else if ( match[2] ) {
3928+ push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
3929+ return results;
3930+
3931+ // Speed-up: Sizzle(".CLASS")
3932+ } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
3933+ push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
3934+ return results;
3935+ }
3936+ }
3937+
3938+ // QSA path
3939+ if ( support.qsa && !rbuggyQSA.test(selector) ) {
3940+ old = true;
3941+ nid = expando;
3942+ newContext = context;
3943+ newSelector = nodeType === 9 && selector;
3944+
3945+ // qSA works strangely on Element-rooted queries
3946+ // We can work around this by specifying an extra ID on the root
3947+ // and working up from there (Thanks to Andrew Dupont for the technique)
3948+ // IE 8 doesn't work on object elements
3949+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
3950+ groups = tokenize( selector );
3951+
3952+ if ( (old = context.getAttribute("id")) ) {
3953+ nid = old.replace( rescape, "\\$&" );
3954+ } else {
3955+ context.setAttribute( "id", nid );
3956+ }
3957+ nid = "[id='" + nid + "'] ";
3958+
3959+ i = groups.length;
3960+ while ( i-- ) {
3961+ groups[i] = nid + toSelector( groups[i] );
3962+ }
3963+ newContext = rsibling.test( selector ) && context.parentNode || context;
3964+ newSelector = groups.join(",");
3965+ }
3966+
3967+ if ( newSelector ) {
3968+ try {
3969+ push.apply( results, slice.call( newContext.querySelectorAll(
3970+ newSelector
3971+ ), 0 ) );
3972+ return results;
3973+ } catch(qsaError) {
3974+ } finally {
3975+ if ( !old ) {
3976+ context.removeAttribute("id");
3977+ }
3978+ }
3979+ }
3980+ }
3981+ }
3982+
3983+ // All others
3984+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
3985+}
3986+
3987+/**
3988+ * Detect xml
3989+ * @param {Element|Object} elem An element or a document
3990+ */
3991+isXML = Sizzle.isXML = function( elem ) {
3992+ // documentElement is verified for cases where it doesn't yet exist
3993+ // (such as loading iframes in IE - #4833)
3994+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
3995+ return documentElement ? documentElement.nodeName !== "HTML" : false;
3996+};
3997+
3998+/**
3999+ * Sets document-related variables once based on the current document
4000+ * @param {Element|Object} [doc] An element or document object to use to set the document
4001+ * @returns {Object} Returns the current document
4002+ */
4003+setDocument = Sizzle.setDocument = function( node ) {
4004+ var doc = node ? node.ownerDocument || node : preferredDoc;
4005+
4006+ // If no document and documentElement is available, return
4007+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4008+ return document;
4009+ }
4010+
4011+ // Set our document
4012+ document = doc;
4013+ docElem = doc.documentElement;
4014+
4015+ // Support tests
4016+ documentIsXML = isXML( doc );
4017+
4018+ // Check if getElementsByTagName("*") returns only elements
4019+ support.tagNameNoComments = assert(function( div ) {
4020+ div.appendChild( doc.createComment("") );
4021+ return !div.getElementsByTagName("*").length;
4022+ });
4023+
4024+ // Check if attributes should be retrieved by attribute nodes
4025+ support.attributes = assert(function( div ) {
4026+ div.innerHTML = "<select></select>";
4027+ var type = typeof div.lastChild.getAttribute("multiple");
4028+ // IE8 returns a string for some attributes even when not present
4029+ return type !== "boolean" && type !== "string";
4030+ });
4031+
4032+ // Check if getElementsByClassName can be trusted
4033+ support.getByClassName = assert(function( div ) {
4034+ // Opera can't find a second classname (in 9.6)
4035+ div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
4036+ if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
4037+ return false;
4038+ }
4039+
4040+ // Safari 3.2 caches class attributes and doesn't catch changes
4041+ div.lastChild.className = "e";
4042+ return div.getElementsByClassName("e").length === 2;
4043+ });
4044+
4045+ // Check if getElementById returns elements by name
4046+ // Check if getElementsByName privileges form controls or returns elements by ID
4047+ support.getByName = assert(function( div ) {
4048+ // Inject content
4049+ div.id = expando + 0;
4050+ div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
4051+ docElem.insertBefore( div, docElem.firstChild );
4052+
4053+ // Test
4054+ var pass = doc.getElementsByName &&
4055+ // buggy browsers will return fewer than the correct 2
4056+ doc.getElementsByName( expando ).length === 2 +
4057+ // buggy browsers will return more than the correct 0
4058+ doc.getElementsByName( expando + 0 ).length;
4059+ support.getIdNotName = !doc.getElementById( expando );
4060+
4061+ // Cleanup
4062+ docElem.removeChild( div );
4063+
4064+ return pass;
4065+ });
4066+
4067+ // IE6/7 return modified attributes
4068+ Expr.attrHandle = assert(function( div ) {
4069+ div.innerHTML = "<a href='#'></a>";
4070+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
4071+ div.firstChild.getAttribute("href") === "#";
4072+ }) ?
4073+ {} :
4074+ {
4075+ "href": function( elem ) {
4076+ return elem.getAttribute( "href", 2 );
4077+ },
4078+ "type": function( elem ) {
4079+ return elem.getAttribute("type");
4080+ }
4081+ };
4082+
4083+ // ID find and filter
4084+ if ( support.getIdNotName ) {
4085+ Expr.find["ID"] = function( id, context ) {
4086+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4087+ var m = context.getElementById( id );
4088+ // Check parentNode to catch when Blackberry 4.6 returns
4089+ // nodes that are no longer in the document #6963
4090+ return m && m.parentNode ? [m] : [];
4091+ }
4092+ };
4093+ Expr.filter["ID"] = function( id ) {
4094+ var attrId = id.replace( runescape, funescape );
4095+ return function( elem ) {
4096+ return elem.getAttribute("id") === attrId;
4097+ };
4098+ };
4099+ } else {
4100+ Expr.find["ID"] = function( id, context ) {
4101+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4102+ var m = context.getElementById( id );
4103+
4104+ return m ?
4105+ m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
4106+ [m] :
4107+ undefined :
4108+ [];
4109+ }
4110+ };
4111+ Expr.filter["ID"] = function( id ) {
4112+ var attrId = id.replace( runescape, funescape );
4113+ return function( elem ) {
4114+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
4115+ return node && node.value === attrId;
4116+ };
4117+ };
4118+ }
4119+
4120+ // Tag
4121+ Expr.find["TAG"] = support.tagNameNoComments ?
4122+ function( tag, context ) {
4123+ if ( typeof context.getElementsByTagName !== strundefined ) {
4124+ return context.getElementsByTagName( tag );
4125+ }
4126+ } :
4127+ function( tag, context ) {
4128+ var elem,
4129+ tmp = [],
4130+ i = 0,
4131+ results = context.getElementsByTagName( tag );
4132+
4133+ // Filter out possible comments
4134+ if ( tag === "*" ) {
4135+ for ( ; (elem = results[i]); i++ ) {
4136+ if ( elem.nodeType === 1 ) {
4137+ tmp.push( elem );
4138+ }
4139+ }
4140+
4141+ return tmp;
4142+ }
4143+ return results;
4144+ };
4145+
4146+ // Name
4147+ Expr.find["NAME"] = support.getByName && function( tag, context ) {
4148+ if ( typeof context.getElementsByName !== strundefined ) {
4149+ return context.getElementsByName( name );
4150+ }
4151+ };
4152+
4153+ // Class
4154+ Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
4155+ if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
4156+ return context.getElementsByClassName( className );
4157+ }
4158+ };
4159+
4160+ // QSA and matchesSelector support
4161+
4162+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
4163+ rbuggyMatches = [];
4164+
4165+ // qSa(:focus) reports false when true (Chrome 21),
4166+ // no need to also add to buggyMatches since matches checks buggyQSA
4167+ // A support test would require too much code (would include document ready)
4168+ rbuggyQSA = [ ":focus" ];
4169+
4170+ if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
4171+ // Build QSA regex
4172+ // Regex strategy adopted from Diego Perini
4173+ assert(function( div ) {
4174+ // Select is set to empty string on purpose
4175+ // This is to test IE's treatment of not explictly
4176+ // setting a boolean content attribute,
4177+ // since its presence should be enough
4178+ // http://bugs.jquery.com/ticket/12359
4179+ div.innerHTML = "<select><option selected=''></option></select>";
4180+
4181+ // IE8 - Some boolean attributes are not treated correctly
4182+ if ( !div.querySelectorAll("[selected]").length ) {
4183+ rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
4184+ }
4185+
4186+ // Webkit/Opera - :checked should return selected option elements
4187+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4188+ // IE8 throws error here and will not see later tests
4189+ if ( !div.querySelectorAll(":checked").length ) {
4190+ rbuggyQSA.push(":checked");
4191+ }
4192+ });
4193+
4194+ assert(function( div ) {
4195+
4196+ // Opera 10-12/IE8 - ^= $= *= and empty values
4197+ // Should not select anything
4198+ div.innerHTML = "<input type='hidden' i=''/>";
4199+ if ( div.querySelectorAll("[i^='']").length ) {
4200+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
4201+ }
4202+
4203+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
4204+ // IE8 throws error here and will not see later tests
4205+ if ( !div.querySelectorAll(":enabled").length ) {
4206+ rbuggyQSA.push( ":enabled", ":disabled" );
4207+ }
4208+
4209+ // Opera 10-11 does not throw on post-comma invalid pseudos
4210+ div.querySelectorAll("*,:x");
4211+ rbuggyQSA.push(",.*:");
4212+ });
4213+ }
4214+
4215+ if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
4216+ docElem.mozMatchesSelector ||
4217+ docElem.webkitMatchesSelector ||
4218+ docElem.oMatchesSelector ||
4219+ docElem.msMatchesSelector) )) ) {
4220+
4221+ assert(function( div ) {
4222+ // Check to see if it's possible to do matchesSelector
4223+ // on a disconnected node (IE 9)
4224+ support.disconnectedMatch = matches.call( div, "div" );
4225+
4226+ // This should fail with an exception
4227+ // Gecko does not error, returns false instead
4228+ matches.call( div, "[s!='']:x" );
4229+ rbuggyMatches.push( "!=", pseudos );
4230+ });
4231+ }
4232+
4233+ rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
4234+ rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
4235+
4236+ // Element contains another
4237+ // Purposefully does not implement inclusive descendent
4238+ // As in, an element does not contain itself
4239+ contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
4240+ function( a, b ) {
4241+ var adown = a.nodeType === 9 ? a.documentElement : a,
4242+ bup = b && b.parentNode;
4243+ return a === bup || !!( bup && bup.nodeType === 1 && (
4244+ adown.contains ?
4245+ adown.contains( bup ) :
4246+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
4247+ ));
4248+ } :
4249+ function( a, b ) {
4250+ if ( b ) {
4251+ while ( (b = b.parentNode) ) {
4252+ if ( b === a ) {
4253+ return true;
4254+ }
4255+ }
4256+ }
4257+ return false;
4258+ };
4259+
4260+ // Document order sorting
4261+ sortOrder = docElem.compareDocumentPosition ?
4262+ function( a, b ) {
4263+ var compare;
4264+
4265+ if ( a === b ) {
4266+ hasDuplicate = true;
4267+ return 0;
4268+ }
4269+
4270+ if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
4271+ if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
4272+ if ( a === doc || contains( preferredDoc, a ) ) {
4273+ return -1;
4274+ }
4275+ if ( b === doc || contains( preferredDoc, b ) ) {
4276+ return 1;
4277+ }
4278+ return 0;
4279+ }
4280+ return compare & 4 ? -1 : 1;
4281+ }
4282+
4283+ return a.compareDocumentPosition ? -1 : 1;
4284+ } :
4285+ function( a, b ) {
4286+ var cur,
4287+ i = 0,
4288+ aup = a.parentNode,
4289+ bup = b.parentNode,
4290+ ap = [ a ],
4291+ bp = [ b ];
4292+
4293+ // The nodes are identical, we can exit early
4294+ if ( a === b ) {
4295+ hasDuplicate = true;
4296+ return 0;
4297+
4298+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
4299+ } else if ( a.sourceIndex && b.sourceIndex ) {
4300+ return ( ~b.sourceIndex || MAX_NEGATIVE ) - ( contains( preferredDoc, a ) && ~a.sourceIndex || MAX_NEGATIVE );
4301+
4302+ // Parentless nodes are either documents or disconnected
4303+ } else if ( !aup || !bup ) {
4304+ return a === doc ? -1 :
4305+ b === doc ? 1 :
4306+ aup ? -1 :
4307+ bup ? 1 :
4308+ 0;
4309+
4310+ // If the nodes are siblings, we can do a quick check
4311+ } else if ( aup === bup ) {
4312+ return siblingCheck( a, b );
4313+ }
4314+
4315+ // Otherwise we need full lists of their ancestors for comparison
4316+ cur = a;
4317+ while ( (cur = cur.parentNode) ) {
4318+ ap.unshift( cur );
4319+ }
4320+ cur = b;
4321+ while ( (cur = cur.parentNode) ) {
4322+ bp.unshift( cur );
4323+ }
4324+
4325+ // Walk down the tree looking for a discrepancy
4326+ while ( ap[i] === bp[i] ) {
4327+ i++;
4328+ }
4329+
4330+ return i ?
4331+ // Do a sibling check if the nodes have a common ancestor
4332+ siblingCheck( ap[i], bp[i] ) :
4333+
4334+ // Otherwise nodes in our document sort first
4335+ ap[i] === preferredDoc ? -1 :
4336+ bp[i] === preferredDoc ? 1 :
4337+ 0;
4338+ };
4339+
4340+ // Always assume the presence of duplicates if sort doesn't
4341+ // pass them to our comparison function (as in Google Chrome).
4342+ hasDuplicate = false;
4343+ [0, 0].sort( sortOrder );
4344+ support.detectDuplicates = hasDuplicate;
4345+
4346+ return document;
4347+};
4348+
4349+Sizzle.matches = function( expr, elements ) {
4350+ return Sizzle( expr, null, null, elements );
4351+};
4352+
4353+Sizzle.matchesSelector = function( elem, expr ) {
4354+ // Set document vars if needed
4355+ if ( ( elem.ownerDocument || elem ) !== document ) {
4356+ setDocument( elem );
4357+ }
4358+
4359+ // Make sure that attribute selectors are quoted
4360+ expr = expr.replace( rattributeQuotes, "='$1']" );
4361+
4362+ // rbuggyQSA always contains :focus, so no need for an existence check
4363+ if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
4364+ try {
4365+ var ret = matches.call( elem, expr );
4366+
4367+ // IE 9's matchesSelector returns false on disconnected nodes
4368+ if ( ret || support.disconnectedMatch ||
4369+ // As well, disconnected nodes are said to be in a document
4370+ // fragment in IE 9
4371+ elem.document && elem.document.nodeType !== 11 ) {
4372+ return ret;
4373+ }
4374+ } catch(e) {}
4375+ }
4376+
4377+ return Sizzle( expr, document, null, [elem] ).length > 0;
4378+};
4379+
4380+Sizzle.contains = function( context, elem ) {
4381+ // Set document vars if needed
4382+ if ( ( context.ownerDocument || context ) !== document ) {
4383+ setDocument( context );
4384+ }
4385+ return contains( context, elem );
4386+};
4387+
4388+Sizzle.attr = function( elem, name ) {
4389+ var val;
4390+
4391+ // Set document vars if needed
4392+ if ( ( elem.ownerDocument || elem ) !== document ) {
4393+ setDocument( elem );
4394+ }
4395+
4396+ if ( !documentIsXML ) {
4397+ name = name.toLowerCase();
4398+ }
4399+ if ( (val = Expr.attrHandle[ name ]) ) {
4400+ return val( elem );
4401+ }
4402+ if ( documentIsXML || support.attributes ) {
4403+ return elem.getAttribute( name );
4404+ }
4405+ return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
4406+ name :
4407+ val && val.specified ? val.value : null;
4408+};
4409+
4410+Sizzle.error = function( msg ) {
4411+ throw new Error( "Syntax error, unrecognized expression: " + msg );
4412+};
4413+
4414+// Document sorting and removing duplicates
4415+Sizzle.uniqueSort = function( results ) {
4416+ var elem,
4417+ duplicates = [],
4418+ i = 1,
4419+ j = 0;
4420+
4421+ // Unless we *know* we can detect duplicates, assume their presence
4422+ hasDuplicate = !support.detectDuplicates;
4423+ results.sort( sortOrder );
4424+
4425+ if ( hasDuplicate ) {
4426+ for ( ; (elem = results[i]); i++ ) {
4427+ if ( elem === results[ i - 1 ] ) {
4428+ j = duplicates.push( i );
4429+ }
4430+ }
4431+ while ( j-- ) {
4432+ results.splice( duplicates[ j ], 1 );
4433+ }
4434+ }
4435+
4436+ return results;
4437+};
4438+
4439+function siblingCheck( a, b ) {
4440+ var cur = a && b && a.nextSibling;
4441+
4442+ for ( ; cur; cur = cur.nextSibling ) {
4443+ if ( cur === b ) {
4444+ return -1;
4445+ }
4446+ }
4447+
4448+ return a ? 1 : -1;
4449+}
4450+
4451+// Returns a function to use in pseudos for input types
4452+function createInputPseudo( type ) {
4453+ return function( elem ) {
4454+ var name = elem.nodeName.toLowerCase();
4455+ return name === "input" && elem.type === type;
4456+ };
4457+}
4458+
4459+// Returns a function to use in pseudos for buttons
4460+function createButtonPseudo( type ) {
4461+ return function( elem ) {
4462+ var name = elem.nodeName.toLowerCase();
4463+ return (name === "input" || name === "button") && elem.type === type;
4464+ };
4465+}
4466+
4467+// Returns a function to use in pseudos for positionals
4468+function createPositionalPseudo( fn ) {
4469+ return markFunction(function( argument ) {
4470+ argument = +argument;
4471+ return markFunction(function( seed, matches ) {
4472+ var j,
4473+ matchIndexes = fn( [], seed.length, argument ),
4474+ i = matchIndexes.length;
4475+
4476+ // Match elements found at the specified indexes
4477+ while ( i-- ) {
4478+ if ( seed[ (j = matchIndexes[i]) ] ) {
4479+ seed[j] = !(matches[j] = seed[j]);
4480+ }
4481+ }
4482+ });
4483+ });
4484+}
4485+
4486+/**
4487+ * Utility function for retrieving the text value of an array of DOM nodes
4488+ * @param {Array|Element} elem
4489+ */
4490+getText = Sizzle.getText = function( elem ) {
4491+ var node,
4492+ ret = "",
4493+ i = 0,
4494+ nodeType = elem.nodeType;
4495+
4496+ if ( !nodeType ) {
4497+ // If no nodeType, this is expected to be an array
4498+ for ( ; (node = elem[i]); i++ ) {
4499+ // Do not traverse comment nodes
4500+ ret += getText( node );
4501+ }
4502+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
4503+ // Use textContent for elements
4504+ // innerText usage removed for consistency of new lines (see #11153)
4505+ if ( typeof elem.textContent === "string" ) {
4506+ return elem.textContent;
4507+ } else {
4508+ // Traverse its children
4509+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4510+ ret += getText( elem );
4511+ }
4512+ }
4513+ } else if ( nodeType === 3 || nodeType === 4 ) {
4514+ return elem.nodeValue;
4515+ }
4516+ // Do not include comment or processing instruction nodes
4517+
4518+ return ret;
4519+};
4520+
4521+Expr = Sizzle.selectors = {
4522+
4523+ // Can be adjusted by the user
4524+ cacheLength: 50,
4525+
4526+ createPseudo: markFunction,
4527+
4528+ match: matchExpr,
4529+
4530+ find: {},
4531+
4532+ relative: {
4533+ ">": { dir: "parentNode", first: true },
4534+ " ": { dir: "parentNode" },
4535+ "+": { dir: "previousSibling", first: true },
4536+ "~": { dir: "previousSibling" }
4537+ },
4538+
4539+ preFilter: {
4540+ "ATTR": function( match ) {
4541+ match[1] = match[1].replace( runescape, funescape );
4542+
4543+ // Move the given value to match[3] whether quoted or unquoted
4544+ match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
4545+
4546+ if ( match[2] === "~=" ) {
4547+ match[3] = " " + match[3] + " ";
4548+ }
4549+
4550+ return match.slice( 0, 4 );
4551+ },
4552+
4553+ "CHILD": function( match ) {
4554+ /* matches from matchExpr["CHILD"]
4555+ 1 type (only|nth|...)
4556+ 2 what (child|of-type)
4557+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4558+ 4 xn-component of xn+y argument ([+-]?\d*n|)
4559+ 5 sign of xn-component
4560+ 6 x of xn-component
4561+ 7 sign of y-component
4562+ 8 y of y-component
4563+ */
4564+ match[1] = match[1].toLowerCase();
4565+
4566+ if ( match[1].slice( 0, 3 ) === "nth" ) {
4567+ // nth-* requires argument
4568+ if ( !match[3] ) {
4569+ Sizzle.error( match[0] );
4570+ }
4571+
4572+ // numeric x and y parameters for Expr.filter.CHILD
4573+ // remember that false/true cast respectively to 0/1
4574+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
4575+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
4576+
4577+ // other types prohibit arguments
4578+ } else if ( match[3] ) {
4579+ Sizzle.error( match[0] );
4580+ }
4581+
4582+ return match;
4583+ },
4584+
4585+ "PSEUDO": function( match ) {
4586+ var excess,
4587+ unquoted = !match[5] && match[2];
4588+
4589+ if ( matchExpr["CHILD"].test( match[0] ) ) {
4590+ return null;
4591+ }
4592+
4593+ // Accept quoted arguments as-is
4594+ if ( match[4] ) {
4595+ match[2] = match[4];
4596+
4597+ // Strip excess characters from unquoted arguments
4598+ } else if ( unquoted && rpseudo.test( unquoted ) &&
4599+ // Get excess from tokenize (recursively)
4600+ (excess = tokenize( unquoted, true )) &&
4601+ // advance to the next closing parenthesis
4602+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
4603+
4604+ // excess is a negative index
4605+ match[0] = match[0].slice( 0, excess );
4606+ match[2] = unquoted.slice( 0, excess );
4607+ }
4608+
4609+ // Return only captures needed by the pseudo filter method (type and argument)
4610+ return match.slice( 0, 3 );
4611+ }
4612+ },
4613+
4614+ filter: {
4615+
4616+ "TAG": function( nodeName ) {
4617+ if ( nodeName === "*" ) {
4618+ return function() { return true; };
4619+ }
4620+
4621+ nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
4622+ return function( elem ) {
4623+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
4624+ };
4625+ },
4626+
4627+ "CLASS": function( className ) {
4628+ var pattern = classCache[ className + " " ];
4629+
4630+ return pattern ||
4631+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
4632+ classCache( className, function( elem ) {
4633+ return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
4634+ });
4635+ },
4636+
4637+ "ATTR": function( name, operator, check ) {
4638+ return function( elem ) {
4639+ var result = Sizzle.attr( elem, name );
4640+
4641+ if ( result == null ) {
4642+ return operator === "!=";
4643+ }
4644+ if ( !operator ) {
4645+ return true;
4646+ }
4647+
4648+ result += "";
4649+
4650+ return operator === "=" ? result === check :
4651+ operator === "!=" ? result !== check :
4652+ operator === "^=" ? check && result.indexOf( check ) === 0 :
4653+ operator === "*=" ? check && result.indexOf( check ) > -1 :
4654+ operator === "$=" ? check && result.substr( result.length - check.length ) === check :
4655+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
4656+ operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" :
4657+ false;
4658+ };
4659+ },
4660+
4661+ "CHILD": function( type, what, argument, first, last ) {
4662+ var simple = type.slice( 0, 3 ) !== "nth",
4663+ forward = type.slice( -4 ) !== "last",
4664+ ofType = what === "of-type";
4665+
4666+ return first === 1 && last === 0 ?
4667+
4668+ // Shortcut for :nth-*(n)
4669+ function( elem ) {
4670+ return !!elem.parentNode;
4671+ } :
4672+
4673+ function( elem, context, xml ) {
4674+ var cache, outerCache, node, diff, nodeIndex, start,
4675+ dir = simple !== forward ? "nextSibling" : "previousSibling",
4676+ parent = elem.parentNode,
4677+ name = ofType && elem.nodeName.toLowerCase(),
4678+ useCache = !xml && !ofType;
4679+
4680+ if ( parent ) {
4681+
4682+ // :(first|last|only)-(child|of-type)
4683+ if ( simple ) {
4684+ while ( dir ) {
4685+ node = elem;
4686+ while ( (node = node[ dir ]) ) {
4687+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
4688+ return false;
4689+ }
4690+ }
4691+ // Reverse direction for :only-* (if we haven't yet done so)
4692+ start = dir = type === "only" && !start && "nextSibling";
4693+ }
4694+ return true;
4695+ }
4696+
4697+ start = [ forward ? parent.firstChild : parent.lastChild ];
4698+
4699+ // non-xml :nth-child(...) stores cache data on `parent`
4700+ if ( forward && useCache ) {
4701+ // Seek `elem` from a previously-cached index
4702+ outerCache = parent[ expando ] || (parent[ expando ] = {});
4703+ cache = outerCache[ type ] || [];
4704+ nodeIndex = cache[0] === dirruns && cache[1];
4705+ diff = cache[0] === dirruns && cache[2];
4706+ node = nodeIndex && parent.childNodes[ nodeIndex ];
4707+
4708+ while ( (node = ++nodeIndex && node && node[ dir ] ||
4709+
4710+ // Fallback to seeking `elem` from the start
4711+ (diff = nodeIndex = 0) || start.pop()) ) {
4712+
4713+ // When found, cache indexes on `parent` and break
4714+ if ( node.nodeType === 1 && ++diff && node === elem ) {
4715+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
4716+ break;
4717+ }
4718+ }
4719+
4720+ // Use previously-cached element index if available
4721+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
4722+ diff = cache[1];
4723+
4724+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
4725+ } else {
4726+ // Use the same loop as above to seek `elem` from the start
4727+ while ( (node = ++nodeIndex && node && node[ dir ] ||
4728+ (diff = nodeIndex = 0) || start.pop()) ) {
4729+
4730+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
4731+ // Cache the index of each encountered element
4732+ if ( useCache ) {
4733+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
4734+ }
4735+
4736+ if ( node === elem ) {
4737+ break;
4738+ }
4739+ }
4740+ }
4741+ }
4742+
4743+ // Incorporate the offset, then check against cycle size
4744+ diff -= last;
4745+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
4746+ }
4747+ };
4748+ },
4749+
4750+ "PSEUDO": function( pseudo, argument ) {
4751+ // pseudo-class names are case-insensitive
4752+ // http://www.w3.org/TR/selectors/#pseudo-classes
4753+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
4754+ // Remember that setFilters inherits from pseudos
4755+ var args,
4756+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
4757+ Sizzle.error( "unsupported pseudo: " + pseudo );
4758+
4759+ // The user may use createPseudo to indicate that
4760+ // arguments are needed to create the filter function
4761+ // just as Sizzle does
4762+ if ( fn[ expando ] ) {
4763+ return fn( argument );
4764+ }
4765+
4766+ // But maintain support for old signatures
4767+ if ( fn.length > 1 ) {
4768+ args = [ pseudo, pseudo, "", argument ];
4769+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
4770+ markFunction(function( seed, matches ) {
4771+ var idx,
4772+ matched = fn( seed, argument ),
4773+ i = matched.length;
4774+ while ( i-- ) {
4775+ idx = indexOf.call( seed, matched[i] );
4776+ seed[ idx ] = !( matches[ idx ] = matched[i] );
4777+ }
4778+ }) :
4779+ function( elem ) {
4780+ return fn( elem, 0, args );
4781+ };
4782+ }
4783+
4784+ return fn;
4785+ }
4786+ },
4787+
4788+ pseudos: {
4789+ // Potentially complex pseudos
4790+ "not": markFunction(function( selector ) {
4791+ // Trim the selector passed to compile
4792+ // to avoid treating leading and trailing
4793+ // spaces as combinators
4794+ var input = [],
4795+ results = [],
4796+ matcher = compile( selector.replace( rtrim, "$1" ) );
4797+
4798+ return matcher[ expando ] ?
4799+ markFunction(function( seed, matches, context, xml ) {
4800+ var elem,
4801+ unmatched = matcher( seed, null, xml, [] ),
4802+ i = seed.length;
4803+
4804+ // Match elements unmatched by `matcher`
4805+ while ( i-- ) {
4806+ if ( (elem = unmatched[i]) ) {
4807+ seed[i] = !(matches[i] = elem);
4808+ }
4809+ }
4810+ }) :
4811+ function( elem, context, xml ) {
4812+ input[0] = elem;
4813+ matcher( input, null, xml, results );
4814+ return !results.pop();
4815+ };
4816+ }),
4817+
4818+ "has": markFunction(function( selector ) {
4819+ return function( elem ) {
4820+ return Sizzle( selector, elem ).length > 0;
4821+ };
4822+ }),
4823+
4824+ "contains": markFunction(function( text ) {
4825+ return function( elem ) {
4826+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
4827+ };
4828+ }),
4829+
4830+ // "Whether an element is represented by a :lang() selector
4831+ // is based solely on the element's language value
4832+ // being equal to the identifier C,
4833+ // or beginning with the identifier C immediately followed by "-".
4834+ // The matching of C against the element's language value is performed case-insensitively.
4835+ // The identifier C does not have to be a valid language name."
4836+ // http://www.w3.org/TR/selectors/#lang-pseudo
4837+ "lang": markFunction( function( lang ) {
4838+ // lang value must be a valid identifider
4839+ if ( !ridentifier.test(lang || "") ) {
4840+ Sizzle.error( "unsupported lang: " + lang );
4841+ }
4842+ lang = lang.replace( runescape, funescape ).toLowerCase();
4843+ return function( elem ) {
4844+ var elemLang;
4845+ do {
4846+ if ( (elemLang = documentIsXML ?
4847+ elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
4848+ elem.lang) ) {
4849+
4850+ elemLang = elemLang.toLowerCase();
4851+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
4852+ }
4853+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
4854+ return false;
4855+ };
4856+ }),
4857+
4858+ // Miscellaneous
4859+ "target": function( elem ) {
4860+ var hash = window.location && window.location.hash;
4861+ return hash && hash.slice( 1 ) === elem.id;
4862+ },
4863+
4864+ "root": function( elem ) {
4865+ return elem === docElem;
4866+ },
4867+
4868+ "focus": function( elem ) {
4869+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
4870+ },
4871+
4872+ // Boolean properties
4873+ "enabled": function( elem ) {
4874+ return elem.disabled === false;
4875+ },
4876+
4877+ "disabled": function( elem ) {
4878+ return elem.disabled === true;
4879+ },
4880+
4881+ "checked": function( elem ) {
4882+ // In CSS3, :checked should return both checked and selected elements
4883+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4884+ var nodeName = elem.nodeName.toLowerCase();
4885+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
4886+ },
4887+
4888+ "selected": function( elem ) {
4889+ // Accessing this property makes selected-by-default
4890+ // options in Safari work properly
4891+ if ( elem.parentNode ) {
4892+ elem.parentNode.selectedIndex;
4893+ }
4894+
4895+ return elem.selected === true;
4896+ },
4897+
4898+ // Contents
4899+ "empty": function( elem ) {
4900+ // http://www.w3.org/TR/selectors/#empty-pseudo
4901+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
4902+ // not comment, processing instructions, or others
4903+ // Thanks to Diego Perini for the nodeName shortcut
4904+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
4905+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4906+ if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
4907+ return false;
4908+ }
4909+ }
4910+ return true;
4911+ },
4912+
4913+ "parent": function( elem ) {
4914+ return !Expr.pseudos["empty"]( elem );
4915+ },
4916+
4917+ // Element/input types
4918+ "header": function( elem ) {
4919+ return rheader.test( elem.nodeName );
4920+ },
4921+
4922+ "input": function( elem ) {
4923+ return rinputs.test( elem.nodeName );
4924+ },
4925+
4926+ "button": function( elem ) {
4927+ var name = elem.nodeName.toLowerCase();
4928+ return name === "input" && elem.type === "button" || name === "button";
4929+ },
4930+
4931+ "text": function( elem ) {
4932+ var attr;
4933+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
4934+ // use getAttribute instead to test this case
4935+ return elem.nodeName.toLowerCase() === "input" &&
4936+ elem.type === "text" &&
4937+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
4938+ },
4939+
4940+ // Position-in-collection
4941+ "first": createPositionalPseudo(function() {
4942+ return [ 0 ];
4943+ }),
4944+
4945+ "last": createPositionalPseudo(function( matchIndexes, length ) {
4946+ return [ length - 1 ];
4947+ }),
4948+
4949+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
4950+ return [ argument < 0 ? argument + length : argument ];
4951+ }),
4952+
4953+ "even": createPositionalPseudo(function( matchIndexes, length ) {
4954+ var i = 0;
4955+ for ( ; i < length; i += 2 ) {
4956+ matchIndexes.push( i );
4957+ }
4958+ return matchIndexes;
4959+ }),
4960+
4961+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
4962+ var i = 1;
4963+ for ( ; i < length; i += 2 ) {
4964+ matchIndexes.push( i );
4965+ }
4966+ return matchIndexes;
4967+ }),
4968+
4969+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4970+ var i = argument < 0 ? argument + length : argument;
4971+ for ( ; --i >= 0; ) {
4972+ matchIndexes.push( i );
4973+ }
4974+ return matchIndexes;
4975+ }),
4976+
4977+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4978+ var i = argument < 0 ? argument + length : argument;
4979+ for ( ; ++i < length; ) {
4980+ matchIndexes.push( i );
4981+ }
4982+ return matchIndexes;
4983+ })
4984+ }
4985+};
4986+
4987+// Add button/input type pseudos
4988+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
4989+ Expr.pseudos[ i ] = createInputPseudo( i );
4990+}
4991+for ( i in { submit: true, reset: true } ) {
4992+ Expr.pseudos[ i ] = createButtonPseudo( i );
4993+}
4994+
4995+function tokenize( selector, parseOnly ) {
4996+ var matched, match, tokens, type,
4997+ soFar, groups, preFilters,
4998+ cached = tokenCache[ selector + " " ];
4999+
5000+ if ( cached ) {
5001+ return parseOnly ? 0 : cached.slice( 0 );
5002+ }
5003+
5004+ soFar = selector;
5005+ groups = [];
5006+ preFilters = Expr.preFilter;
5007+
5008+ while ( soFar ) {
5009+
5010+ // Comma and first run
5011+ if ( !matched || (match = rcomma.exec( soFar )) ) {
5012+ if ( match ) {
5013+ // Don't consume trailing commas as valid
5014+ soFar = soFar.slice( match[0].length ) || soFar;
5015+ }
5016+ groups.push( tokens = [] );
5017+ }
5018+
5019+ matched = false;
5020+
5021+ // Combinators
5022+ if ( (match = rcombinators.exec( soFar )) ) {
5023+ matched = match.shift();
5024+ tokens.push( {
5025+ value: matched,
5026+ // Cast descendant combinators to space
5027+ type: match[0].replace( rtrim, " " )
5028+ } );
5029+ soFar = soFar.slice( matched.length );
5030+ }
5031+
5032+ // Filters
5033+ for ( type in Expr.filter ) {
5034+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5035+ (match = preFilters[ type ]( match ))) ) {
5036+ matched = match.shift();
5037+ tokens.push( {
5038+ value: matched,
5039+ type: type,
5040+ matches: match
5041+ } );
5042+ soFar = soFar.slice( matched.length );
5043+ }
5044+ }
5045+
5046+ if ( !matched ) {
5047+ break;
5048+ }
5049+ }
5050+
5051+ // Return the length of the invalid excess
5052+ // if we're just parsing
5053+ // Otherwise, throw an error or return tokens
5054+ return parseOnly ?
5055+ soFar.length :
5056+ soFar ?
5057+ Sizzle.error( selector ) :
5058+ // Cache the tokens
5059+ tokenCache( selector, groups ).slice( 0 );
5060+}
5061+
5062+function toSelector( tokens ) {
5063+ var i = 0,
5064+ len = tokens.length,
5065+ selector = "";
5066+ for ( ; i < len; i++ ) {
5067+ selector += tokens[i].value;
5068+ }
5069+ return selector;
5070+}
5071+
5072+function addCombinator( matcher, combinator, base ) {
5073+ var dir = combinator.dir,
5074+ checkNonElements = base && combinator.dir === "parentNode",
5075+ doneName = done++;
5076+
5077+ return combinator.first ?
5078+ // Check against closest ancestor/preceding element
5079+ function( elem, context, xml ) {
5080+ while ( (elem = elem[ dir ]) ) {
5081+ if ( elem.nodeType === 1 || checkNonElements ) {
5082+ return matcher( elem, context, xml );
5083+ }
5084+ }
5085+ } :
5086+
5087+ // Check against all ancestor/preceding elements
5088+ function( elem, context, xml ) {
5089+ var data, cache, outerCache,
5090+ dirkey = dirruns + " " + doneName;
5091+
5092+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
5093+ if ( xml ) {
5094+ while ( (elem = elem[ dir ]) ) {
5095+ if ( elem.nodeType === 1 || checkNonElements ) {
5096+ if ( matcher( elem, context, xml ) ) {
5097+ return true;
5098+ }
5099+ }
5100+ }
5101+ } else {
5102+ while ( (elem = elem[ dir ]) ) {
5103+ if ( elem.nodeType === 1 || checkNonElements ) {
5104+ outerCache = elem[ expando ] || (elem[ expando ] = {});
5105+ if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
5106+ if ( (data = cache[1]) === true || data === cachedruns ) {
5107+ return data === true;
5108+ }
5109+ } else {
5110+ cache = outerCache[ dir ] = [ dirkey ];
5111+ cache[1] = matcher( elem, context, xml ) || cachedruns;
5112+ if ( cache[1] === true ) {
5113+ return true;
5114+ }
5115+ }
5116+ }
5117+ }
5118+ }
5119+ };
5120+}
5121+
5122+function elementMatcher( matchers ) {
5123+ return matchers.length > 1 ?
5124+ function( elem, context, xml ) {
5125+ var i = matchers.length;
5126+ while ( i-- ) {
5127+ if ( !matchers[i]( elem, context, xml ) ) {
5128+ return false;
5129+ }
5130+ }
5131+ return true;
5132+ } :
5133+ matchers[0];
5134+}
5135+
5136+function condense( unmatched, map, filter, context, xml ) {
5137+ var elem,
5138+ newUnmatched = [],
5139+ i = 0,
5140+ len = unmatched.length,
5141+ mapped = map != null;
5142+
5143+ for ( ; i < len; i++ ) {
5144+ if ( (elem = unmatched[i]) ) {
5145+ if ( !filter || filter( elem, context, xml ) ) {
5146+ newUnmatched.push( elem );
5147+ if ( mapped ) {
5148+ map.push( i );
5149+ }
5150+ }
5151+ }
5152+ }
5153+
5154+ return newUnmatched;
5155+}
5156+
5157+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5158+ if ( postFilter && !postFilter[ expando ] ) {
5159+ postFilter = setMatcher( postFilter );
5160+ }
5161+ if ( postFinder && !postFinder[ expando ] ) {
5162+ postFinder = setMatcher( postFinder, postSelector );
5163+ }
5164+ return markFunction(function( seed, results, context, xml ) {
5165+ var temp, i, elem,
5166+ preMap = [],
5167+ postMap = [],
5168+ preexisting = results.length,
5169+
5170+ // Get initial elements from seed or context
5171+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5172+
5173+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
5174+ matcherIn = preFilter && ( seed || !selector ) ?
5175+ condense( elems, preMap, preFilter, context, xml ) :
5176+ elems,
5177+
5178+ matcherOut = matcher ?
5179+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
5180+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5181+
5182+ // ...intermediate processing is necessary
5183+ [] :
5184+
5185+ // ...otherwise use results directly
5186+ results :
5187+ matcherIn;
5188+
5189+ // Find primary matches
5190+ if ( matcher ) {
5191+ matcher( matcherIn, matcherOut, context, xml );
5192+ }
5193+
5194+ // Apply postFilter
5195+ if ( postFilter ) {
5196+ temp = condense( matcherOut, postMap );
5197+ postFilter( temp, [], context, xml );
5198+
5199+ // Un-match failing elements by moving them back to matcherIn
5200+ i = temp.length;
5201+ while ( i-- ) {
5202+ if ( (elem = temp[i]) ) {
5203+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5204+ }
5205+ }
5206+ }
5207+
5208+ if ( seed ) {
5209+ if ( postFinder || preFilter ) {
5210+ if ( postFinder ) {
5211+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
5212+ temp = [];
5213+ i = matcherOut.length;
5214+ while ( i-- ) {
5215+ if ( (elem = matcherOut[i]) ) {
5216+ // Restore matcherIn since elem is not yet a final match
5217+ temp.push( (matcherIn[i] = elem) );
5218+ }
5219+ }
5220+ postFinder( null, (matcherOut = []), temp, xml );
5221+ }
5222+
5223+ // Move matched elements from seed to results to keep them synchronized
5224+ i = matcherOut.length;
5225+ while ( i-- ) {
5226+ if ( (elem = matcherOut[i]) &&
5227+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
5228+
5229+ seed[temp] = !(results[temp] = elem);
5230+ }
5231+ }
5232+ }
5233+
5234+ // Add elements to results, through postFinder if defined
5235+ } else {
5236+ matcherOut = condense(
5237+ matcherOut === results ?
5238+ matcherOut.splice( preexisting, matcherOut.length ) :
5239+ matcherOut
5240+ );
5241+ if ( postFinder ) {
5242+ postFinder( null, results, matcherOut, xml );
5243+ } else {
5244+ push.apply( results, matcherOut );
5245+ }
5246+ }
5247+ });
5248+}
5249+
5250+function matcherFromTokens( tokens ) {
5251+ var checkContext, matcher, j,
5252+ len = tokens.length,
5253+ leadingRelative = Expr.relative[ tokens[0].type ],
5254+ implicitRelative = leadingRelative || Expr.relative[" "],
5255+ i = leadingRelative ? 1 : 0,
5256+
5257+ // The foundational matcher ensures that elements are reachable from top-level context(s)
5258+ matchContext = addCombinator( function( elem ) {
5259+ return elem === checkContext;
5260+ }, implicitRelative, true ),
5261+ matchAnyContext = addCombinator( function( elem ) {
5262+ return indexOf.call( checkContext, elem ) > -1;
5263+ }, implicitRelative, true ),
5264+ matchers = [ function( elem, context, xml ) {
5265+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
5266+ (checkContext = context).nodeType ?
5267+ matchContext( elem, context, xml ) :
5268+ matchAnyContext( elem, context, xml ) );
5269+ } ];
5270+
5271+ for ( ; i < len; i++ ) {
5272+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
5273+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
5274+ } else {
5275+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
5276+
5277+ // Return special upon seeing a positional matcher
5278+ if ( matcher[ expando ] ) {
5279+ // Find the next relative operator (if any) for proper handling
5280+ j = ++i;
5281+ for ( ; j < len; j++ ) {
5282+ if ( Expr.relative[ tokens[j].type ] ) {
5283+ break;
5284+ }
5285+ }
5286+ return setMatcher(
5287+ i > 1 && elementMatcher( matchers ),
5288+ i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
5289+ matcher,
5290+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
5291+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
5292+ j < len && toSelector( tokens )
5293+ );
5294+ }
5295+ matchers.push( matcher );
5296+ }
5297+ }
5298+
5299+ return elementMatcher( matchers );
5300+}
5301+
5302+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
5303+ // A counter to specify which element is currently being matched
5304+ var matcherCachedRuns = 0,
5305+ bySet = setMatchers.length > 0,
5306+ byElement = elementMatchers.length > 0,
5307+ superMatcher = function( seed, context, xml, results, expandContext ) {
5308+ var elem, j, matcher,
5309+ setMatched = [],
5310+ matchedCount = 0,
5311+ i = "0",
5312+ unmatched = seed && [],
5313+ outermost = expandContext != null,
5314+ contextBackup = outermostContext,
5315+ // We must always have either seed elements or context
5316+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
5317+ // Nested matchers should use non-integer dirruns
5318+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);
5319+
5320+ if ( outermost ) {
5321+ outermostContext = context !== document && context;
5322+ cachedruns = matcherCachedRuns;
5323+ }
5324+
5325+ // Add elements passing elementMatchers directly to results
5326+ for ( ; (elem = elems[i]) != null; i++ ) {
5327+ if ( byElement && elem ) {
5328+ for ( j = 0; (matcher = elementMatchers[j]); j++ ) {
5329+ if ( matcher( elem, context, xml ) ) {
5330+ results.push( elem );
5331+ break;
5332+ }
5333+ }
5334+ if ( outermost ) {
5335+ dirruns = dirrunsUnique;
5336+ cachedruns = ++matcherCachedRuns;
5337+ }
5338+ }
5339+
5340+ // Track unmatched elements for set filters
5341+ if ( bySet ) {
5342+ // They will have gone through all possible matchers
5343+ if ( (elem = !matcher && elem) ) {
5344+ matchedCount--;
5345+ }
5346+
5347+ // Lengthen the array for every element, matched or not
5348+ if ( seed ) {
5349+ unmatched.push( elem );
5350+ }
5351+ }
5352+ }
5353+
5354+ // Apply set filters to unmatched elements
5355+ // `i` starts as a string, so matchedCount would equal "00" if there are no elements
5356+ matchedCount += i;
5357+ if ( bySet && i !== matchedCount ) {
5358+ for ( j = 0; (matcher = setMatchers[j]); j++ ) {
5359+ matcher( unmatched, setMatched, context, xml );
5360+ }
5361+
5362+ if ( seed ) {
5363+ // Reintegrate element matches to eliminate the need for sorting
5364+ if ( matchedCount > 0 ) {
5365+ while ( i-- ) {
5366+ if ( !(unmatched[i] || setMatched[i]) ) {
5367+ setMatched[i] = pop.call( results );
5368+ }
5369+ }
5370+ }
5371+
5372+ // Discard index placeholder values to get only actual matches
5373+ setMatched = condense( setMatched );
5374+ }
5375+
5376+ // Add matches to results
5377+ push.apply( results, setMatched );
5378+
5379+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
5380+ if ( outermost && !seed && setMatched.length > 0 &&
5381+ ( matchedCount + setMatchers.length ) > 1 ) {
5382+
5383+ Sizzle.uniqueSort( results );
5384+ }
5385+ }
5386+
5387+ // Override manipulation of globals by nested matchers
5388+ if ( outermost ) {
5389+ dirruns = dirrunsUnique;
5390+ outermostContext = contextBackup;
5391+ }
5392+
5393+ return unmatched;
5394+ };
5395+
5396+ return bySet ?
5397+ markFunction( superMatcher ) :
5398+ superMatcher;
5399+}
5400+
5401+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
5402+ var i,
5403+ setMatchers = [],
5404+ elementMatchers = [],
5405+ cached = compilerCache[ selector + " " ];
5406+
5407+ if ( !cached ) {
5408+ // Generate a function of recursive functions that can be used to check each element
5409+ if ( !group ) {
5410+ group = tokenize( selector );
5411+ }
5412+ i = group.length;
5413+ while ( i-- ) {
5414+ cached = matcherFromTokens( group[i] );
5415+ if ( cached[ expando ] ) {
5416+ setMatchers.push( cached );
5417+ } else {
5418+ elementMatchers.push( cached );
5419+ }
5420+ }
5421+
5422+ // Cache the compiled function
5423+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
5424+ }
5425+ return cached;
5426+};
5427+
5428+function multipleContexts( selector, contexts, results ) {
5429+ var i = 0,
5430+ len = contexts.length;
5431+ for ( ; i < len; i++ ) {
5432+ Sizzle( selector, contexts[i], results );
5433+ }
5434+ return results;
5435+}
5436+
5437+function select( selector, context, results, seed ) {
5438+ var i, tokens, token, type, find,
5439+ match = tokenize( selector );
5440+
5441+ if ( !seed ) {
5442+ // Try to minimize operations if there is only one group
5443+ if ( match.length === 1 ) {
5444+
5445+ // Take a shortcut and set the context if the root selector is an ID
5446+ tokens = match[0] = match[0].slice( 0 );
5447+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
5448+ context.nodeType === 9 && !documentIsXML &&
5449+ Expr.relative[ tokens[1].type ] ) {
5450+
5451+ context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
5452+ if ( !context ) {
5453+ return results;
5454+ }
5455+
5456+ selector = selector.slice( tokens.shift().value.length );
5457+ }
5458+
5459+ // Fetch a seed set for right-to-left matching
5460+ for ( i = matchExpr["needsContext"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {
5461+ token = tokens[i];
5462+
5463+ // Abort if we hit a combinator
5464+ if ( Expr.relative[ (type = token.type) ] ) {
5465+ break;
5466+ }
5467+ if ( (find = Expr.find[ type ]) ) {
5468+ // Search, expanding context for leading sibling combinators
5469+ if ( (seed = find(
5470+ token.matches[0].replace( runescape, funescape ),
5471+ rsibling.test( tokens[0].type ) && context.parentNode || context
5472+ )) ) {
5473+
5474+ // If seed is empty or no tokens remain, we can return early
5475+ tokens.splice( i, 1 );
5476+ selector = seed.length && toSelector( tokens );
5477+ if ( !selector ) {
5478+ push.apply( results, slice.call( seed, 0 ) );
5479+ return results;
5480+ }
5481+
5482+ break;
5483+ }
5484+ }
5485+ }
5486+ }
5487+ }
5488+
5489+ // Compile and execute a filtering function
5490+ // Provide `match` to avoid retokenization if we modified the selector above
5491+ compile( selector, match )(
5492+ seed,
5493+ context,
5494+ documentIsXML,
5495+ results,
5496+ rsibling.test( selector )
5497+ );
5498+ return results;
5499+}
5500+
5501+// Deprecated
5502+Expr.pseudos["nth"] = Expr.pseudos["eq"];
5503+
5504+// Easy API for creating new setFilters
5505+function setFilters() {}
5506+Expr.filters = setFilters.prototype = Expr.pseudos;
5507+Expr.setFilters = new setFilters();
5508+
5509+// Initialize with the default document
5510+setDocument();
5511+
5512+// Override sizzle attribute retrieval
5513+Sizzle.attr = jQuery.attr;
5514+jQuery.find = Sizzle;
5515+jQuery.expr = Sizzle.selectors;
5516+jQuery.expr[":"] = jQuery.expr.pseudos;
5517+jQuery.unique = Sizzle.uniqueSort;
5518+jQuery.text = Sizzle.getText;
5519+jQuery.isXMLDoc = Sizzle.isXML;
5520+jQuery.contains = Sizzle.contains;
5521+
5522+
5523+})( window );
5524+var runtil = /Until$/,
5525+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
5526+ isSimple = /^.[^:#\[\.,]*$/,
5527+ rneedsContext = jQuery.expr.match.needsContext,
5528+ // methods guaranteed to produce a unique set when starting from a unique set
5529+ guaranteedUnique = {
5530+ children: true,
5531+ contents: true,
5532+ next: true,
5533+ prev: true
5534+ };
5535+
5536+jQuery.fn.extend({
5537+ find: function( selector ) {
5538+ var i, ret, self;
5539+
5540+ if ( typeof selector !== "string" ) {
5541+ self = this;
5542+ return this.pushStack( jQuery( selector ).filter(function() {
5543+ for ( i = 0; i < self.length; i++ ) {
5544+ if ( jQuery.contains( self[ i ], this ) ) {
5545+ return true;
5546+ }
5547+ }
5548+ }) );
5549+ }
5550+
5551+ ret = [];
5552+ for ( i = 0; i < this.length; i++ ) {
5553+ jQuery.find( selector, this[ i ], ret );
5554+ }
5555+
5556+ // Needed because $( selector, context ) becomes $( context ).find( selector )
5557+ ret = this.pushStack( jQuery.unique( ret ) );
5558+ ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
5559+ return ret;
5560+ },
5561+
5562+ has: function( target ) {
5563+ var i,
5564+ targets = jQuery( target, this ),
5565+ len = targets.length;
5566+
5567+ return this.filter(function() {
5568+ for ( i = 0; i < len; i++ ) {
5569+ if ( jQuery.contains( this, targets[i] ) ) {
5570+ return true;
5571+ }
5572+ }
5573+ });
5574+ },
5575+
5576+ not: function( selector ) {
5577+ return this.pushStack( winnow(this, selector, false) );
5578+ },
5579+
5580+ filter: function( selector ) {
5581+ return this.pushStack( winnow(this, selector, true) );
5582+ },
5583+
5584+ is: function( selector ) {
5585+ return !!selector && (
5586+ typeof selector === "string" ?
5587+ // If this is a positional/relative selector, check membership in the returned set
5588+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
5589+ rneedsContext.test( selector ) ?
5590+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
5591+ jQuery.filter( selector, this ).length > 0 :
5592+ this.filter( selector ).length > 0 );
5593+ },
5594+
5595+ closest: function( selectors, context ) {
5596+ var cur,
5597+ i = 0,
5598+ l = this.length,
5599+ ret = [],
5600+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
5601+ jQuery( selectors, context || this.context ) :
5602+ 0;
5603+
5604+ for ( ; i < l; i++ ) {
5605+ cur = this[i];
5606+
5607+ while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
5608+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5609+ ret.push( cur );
5610+ break;
5611+ }
5612+ cur = cur.parentNode;
5613+ }
5614+ }
5615+
5616+ return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
5617+ },
5618+
5619+ // Determine the position of an element within
5620+ // the matched set of elements
5621+ index: function( elem ) {
5622+
5623+ // No argument, return index in parent
5624+ if ( !elem ) {
5625+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
5626+ }
5627+
5628+ // index in selector
5629+ if ( typeof elem === "string" ) {
5630+ return jQuery.inArray( this[0], jQuery( elem ) );
5631+ }
5632+
5633+ // Locate the position of the desired element
5634+ return jQuery.inArray(
5635+ // If it receives a jQuery object, the first element is used
5636+ elem.jquery ? elem[0] : elem, this );
5637+ },
5638+
5639+ add: function( selector, context ) {
5640+ var set = typeof selector === "string" ?
5641+ jQuery( selector, context ) :
5642+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5643+ all = jQuery.merge( this.get(), set );
5644+
5645+ return this.pushStack( jQuery.unique(all) );
5646+ },
5647+
5648+ addBack: function( selector ) {
5649+ return this.add( selector == null ?
5650+ this.prevObject : this.prevObject.filter(selector)
5651+ );
5652+ }
5653+});
5654+
5655+jQuery.fn.andSelf = jQuery.fn.addBack;
5656+
5657+function sibling( cur, dir ) {
5658+ do {
5659+ cur = cur[ dir ];
5660+ } while ( cur && cur.nodeType !== 1 );
5661+
5662+ return cur;
5663+}
5664+
5665+jQuery.each({
5666+ parent: function( elem ) {
5667+ var parent = elem.parentNode;
5668+ return parent && parent.nodeType !== 11 ? parent : null;
5669+ },
5670+ parents: function( elem ) {
5671+ return jQuery.dir( elem, "parentNode" );
5672+ },
5673+ parentsUntil: function( elem, i, until ) {
5674+ return jQuery.dir( elem, "parentNode", until );
5675+ },
5676+ next: function( elem ) {
5677+ return sibling( elem, "nextSibling" );
5678+ },
5679+ prev: function( elem ) {
5680+ return sibling( elem, "previousSibling" );
5681+ },
5682+ nextAll: function( elem ) {
5683+ return jQuery.dir( elem, "nextSibling" );
5684+ },
5685+ prevAll: function( elem ) {
5686+ return jQuery.dir( elem, "previousSibling" );
5687+ },
5688+ nextUntil: function( elem, i, until ) {
5689+ return jQuery.dir( elem, "nextSibling", until );
5690+ },
5691+ prevUntil: function( elem, i, until ) {
5692+ return jQuery.dir( elem, "previousSibling", until );
5693+ },
5694+ siblings: function( elem ) {
5695+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
5696+ },
5697+ children: function( elem ) {
5698+ return jQuery.sibling( elem.firstChild );
5699+ },
5700+ contents: function( elem ) {
5701+ return jQuery.nodeName( elem, "iframe" ) ?
5702+ elem.contentDocument || elem.contentWindow.document :
5703+ jQuery.merge( [], elem.childNodes );
5704+ }
5705+}, function( name, fn ) {
5706+ jQuery.fn[ name ] = function( until, selector ) {
5707+ var ret = jQuery.map( this, fn, until );
5708+
5709+ if ( !runtil.test( name ) ) {
5710+ selector = until;
5711+ }
5712+
5713+ if ( selector && typeof selector === "string" ) {
5714+ ret = jQuery.filter( selector, ret );
5715+ }
5716+
5717+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
5718+
5719+ if ( this.length > 1 && rparentsprev.test( name ) ) {
5720+ ret = ret.reverse();
5721+ }
5722+
5723+ return this.pushStack( ret );
5724+ };
5725+});
5726+
5727+jQuery.extend({
5728+ filter: function( expr, elems, not ) {
5729+ if ( not ) {
5730+ expr = ":not(" + expr + ")";
5731+ }
5732+
5733+ return elems.length === 1 ?
5734+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
5735+ jQuery.find.matches(expr, elems);
5736+ },
5737+
5738+ dir: function( elem, dir, until ) {
5739+ var matched = [],
5740+ cur = elem[ dir ];
5741+
5742+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5743+ if ( cur.nodeType === 1 ) {
5744+ matched.push( cur );
5745+ }
5746+ cur = cur[dir];
5747+ }
5748+ return matched;
5749+ },
5750+
5751+ sibling: function( n, elem ) {
5752+ var r = [];
5753+
5754+ for ( ; n; n = n.nextSibling ) {
5755+ if ( n.nodeType === 1 && n !== elem ) {
5756+ r.push( n );
5757+ }
5758+ }
5759+
5760+ return r;
5761+ }
5762+});
5763+
5764+// Implement the identical functionality for filter and not
5765+function winnow( elements, qualifier, keep ) {
5766+
5767+ // Can't pass null or undefined to indexOf in Firefox 4
5768+ // Set to 0 to skip string check
5769+ qualifier = qualifier || 0;
5770+
5771+ if ( jQuery.isFunction( qualifier ) ) {
5772+ return jQuery.grep(elements, function( elem, i ) {
5773+ var retVal = !!qualifier.call( elem, i, elem );
5774+ return retVal === keep;
5775+ });
5776+
5777+ } else if ( qualifier.nodeType ) {
5778+ return jQuery.grep(elements, function( elem ) {
5779+ return ( elem === qualifier ) === keep;
5780+ });
5781+
5782+ } else if ( typeof qualifier === "string" ) {
5783+ var filtered = jQuery.grep(elements, function( elem ) {
5784+ return elem.nodeType === 1;
5785+ });
5786+
5787+ if ( isSimple.test( qualifier ) ) {
5788+ return jQuery.filter(qualifier, filtered, !keep);
5789+ } else {
5790+ qualifier = jQuery.filter( qualifier, filtered );
5791+ }
5792+ }
5793+
5794+ return jQuery.grep(elements, function( elem ) {
5795+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
5796+ });
5797+}
5798+function createSafeFragment( document ) {
5799+ var list = nodeNames.split( "|" ),
5800+ safeFrag = document.createDocumentFragment();
5801+
5802+ if ( safeFrag.createElement ) {
5803+ while ( list.length ) {
5804+ safeFrag.createElement(
5805+ list.pop()
5806+ );
5807+ }
5808+ }
5809+ return safeFrag;
5810+}
5811+
5812+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5813+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5814+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5815+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5816+ rleadingWhitespace = /^\s+/,
5817+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5818+ rtagName = /<([\w:]+)/,
5819+ rtbody = /<tbody/i,
5820+ rhtml = /<|&#?\w+;/,
5821+ rnoInnerhtml = /<(?:script|style|link)/i,
5822+ manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
5823+ // checked="checked" or checked
5824+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5825+ rscriptType = /^$|\/(?:java|ecma)script/i,
5826+ rscriptTypeMasked = /^true\/(.*)/,
5827+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5828+
5829+ // We have to close these tags to support XHTML (#13200)
5830+ wrapMap = {
5831+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
5832+ legend: [ 1, "<fieldset>", "</fieldset>" ],
5833+ area: [ 1, "<map>", "</map>" ],
5834+ param: [ 1, "<object>", "</object>" ],
5835+ thead: [ 1, "<table>", "</table>" ],
5836+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5837+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5838+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5839+
5840+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5841+ // unless wrapped in a div with non-breaking characters in front of it.
5842+ _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
5843+ },
5844+ safeFragment = createSafeFragment( document ),
5845+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5846+
5847+wrapMap.optgroup = wrapMap.option;
5848+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5849+wrapMap.th = wrapMap.td;
5850+
5851+jQuery.fn.extend({
5852+ text: function( value ) {
5853+ return jQuery.access( this, function( value ) {
5854+ return value === undefined ?
5855+ jQuery.text( this ) :
5856+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5857+ }, null, value, arguments.length );
5858+ },
5859+
5860+ wrapAll: function( html ) {
5861+ if ( jQuery.isFunction( html ) ) {
5862+ return this.each(function(i) {
5863+ jQuery(this).wrapAll( html.call(this, i) );
5864+ });
5865+ }
5866+
5867+ if ( this[0] ) {
5868+ // The elements to wrap the target around
5869+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
5870+
5871+ if ( this[0].parentNode ) {
5872+ wrap.insertBefore( this[0] );
5873+ }
5874+
5875+ wrap.map(function() {
5876+ var elem = this;
5877+
5878+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
5879+ elem = elem.firstChild;
5880+ }
5881+
5882+ return elem;
5883+ }).append( this );
5884+ }
5885+
5886+ return this;
5887+ },
5888+
5889+ wrapInner: function( html ) {
5890+ if ( jQuery.isFunction( html ) ) {
5891+ return this.each(function(i) {
5892+ jQuery(this).wrapInner( html.call(this, i) );
5893+ });
5894+ }
5895+
5896+ return this.each(function() {
5897+ var self = jQuery( this ),
5898+ contents = self.contents();
5899+
5900+ if ( contents.length ) {
5901+ contents.wrapAll( html );
5902+
5903+ } else {
5904+ self.append( html );
5905+ }
5906+ });
5907+ },
5908+
5909+ wrap: function( html ) {
5910+ var isFunction = jQuery.isFunction( html );
5911+
5912+ return this.each(function(i) {
5913+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
5914+ });
5915+ },
5916+
5917+ unwrap: function() {
5918+ return this.parent().each(function() {
5919+ if ( !jQuery.nodeName( this, "body" ) ) {
5920+ jQuery( this ).replaceWith( this.childNodes );
5921+ }
5922+ }).end();
5923+ },
5924+
5925+ append: function() {
5926+ return this.domManip(arguments, true, function( elem ) {
5927+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5928+ this.appendChild( elem );
5929+ }
5930+ });
5931+ },
5932+
5933+ prepend: function() {
5934+ return this.domManip(arguments, true, function( elem ) {
5935+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5936+ this.insertBefore( elem, this.firstChild );
5937+ }
5938+ });
5939+ },
5940+
5941+ before: function() {
5942+ return this.domManip( arguments, false, function( elem ) {
5943+ if ( this.parentNode ) {
5944+ this.parentNode.insertBefore( elem, this );
5945+ }
5946+ });
5947+ },
5948+
5949+ after: function() {
5950+ return this.domManip( arguments, false, function( elem ) {
5951+ if ( this.parentNode ) {
5952+ this.parentNode.insertBefore( elem, this.nextSibling );
5953+ }
5954+ });
5955+ },
5956+
5957+ // keepData is for internal use only--do not document
5958+ remove: function( selector, keepData ) {
5959+ var elem,
5960+ i = 0;
5961+
5962+ for ( ; (elem = this[i]) != null; i++ ) {
5963+ if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
5964+ if ( !keepData && elem.nodeType === 1 ) {
5965+ jQuery.cleanData( getAll( elem ) );
5966+ }
5967+
5968+ if ( elem.parentNode ) {
5969+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
5970+ setGlobalEval( getAll( elem, "script" ) );
5971+ }
5972+ elem.parentNode.removeChild( elem );
5973+ }
5974+ }
5975+ }
5976+
5977+ return this;
5978+ },
5979+
5980+ empty: function() {
5981+ var elem,
5982+ i = 0;
5983+
5984+ for ( ; (elem = this[i]) != null; i++ ) {
5985+ // Remove element nodes and prevent memory leaks
5986+ if ( elem.nodeType === 1 ) {
5987+ jQuery.cleanData( getAll( elem, false ) );
5988+ }
5989+
5990+ // Remove any remaining nodes
5991+ while ( elem.firstChild ) {
5992+ elem.removeChild( elem.firstChild );
5993+ }
5994+
5995+ // If this is a select, ensure that it displays empty (#12336)
5996+ // Support: IE<9
5997+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
5998+ elem.options.length = 0;
5999+ }
6000+ }
6001+
6002+ return this;
6003+ },
6004+
6005+ clone: function( dataAndEvents, deepDataAndEvents ) {
6006+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6007+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6008+
6009+ return this.map( function () {
6010+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6011+ });
6012+ },
6013+
6014+ html: function( value ) {
6015+ return jQuery.access( this, function( value ) {
6016+ var elem = this[0] || {},
6017+ i = 0,
6018+ l = this.length;
6019+
6020+ if ( value === undefined ) {
6021+ return elem.nodeType === 1 ?
6022+ elem.innerHTML.replace( rinlinejQuery, "" ) :
6023+ undefined;
6024+ }
6025+
6026+ // See if we can take a shortcut and just use innerHTML
6027+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6028+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
6029+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
6030+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
6031+
6032+ value = value.replace( rxhtmlTag, "<$1></$2>" );
6033+
6034+ try {
6035+ for (; i < l; i++ ) {
6036+ // Remove element nodes and prevent memory leaks
6037+ elem = this[i] || {};
6038+ if ( elem.nodeType === 1 ) {
6039+ jQuery.cleanData( getAll( elem, false ) );
6040+ elem.innerHTML = value;
6041+ }
6042+ }
6043+
6044+ elem = 0;
6045+
6046+ // If using innerHTML throws an exception, use the fallback method
6047+ } catch(e) {}
6048+ }
6049+
6050+ if ( elem ) {
6051+ this.empty().append( value );
6052+ }
6053+ }, null, value, arguments.length );
6054+ },
6055+
6056+ replaceWith: function( value ) {
6057+ var isFunc = jQuery.isFunction( value );
6058+
6059+ // Make sure that the elements are removed from the DOM before they are inserted
6060+ // this can help fix replacing a parent with child elements
6061+ if ( !isFunc && typeof value !== "string" ) {
6062+ value = jQuery( value ).not( this ).detach();
6063+ }
6064+
6065+ return this.domManip( [ value ], true, function( elem ) {
6066+ var next = this.nextSibling,
6067+ parent = this.parentNode;
6068+
6069+ if ( parent && this.nodeType === 1 || this.nodeType === 11 ) {
6070+
6071+ jQuery( this ).remove();
6072+
6073+ if ( next ) {
6074+ next.parentNode.insertBefore( elem, next );
6075+ } else {
6076+ parent.appendChild( elem );
6077+ }
6078+ }
6079+ });
6080+ },
6081+
6082+ detach: function( selector ) {
6083+ return this.remove( selector, true );
6084+ },
6085+
6086+ domManip: function( args, table, callback ) {
6087+
6088+ // Flatten any nested arrays
6089+ args = core_concat.apply( [], args );
6090+
6091+ var fragment, first, scripts, hasScripts, node, doc,
6092+ i = 0,
6093+ l = this.length,
6094+ set = this,
6095+ iNoClone = l - 1,
6096+ value = args[0],
6097+ isFunction = jQuery.isFunction( value );
6098+
6099+ // We can't cloneNode fragments that contain checked, in WebKit
6100+ if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
6101+ return this.each(function( index ) {
6102+ var self = set.eq( index );
6103+ if ( isFunction ) {
6104+ args[0] = value.call( this, index, table ? self.html() : undefined );
6105+ }
6106+ self.domManip( args, table, callback );
6107+ });
6108+ }
6109+
6110+ if ( l ) {
6111+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
6112+ first = fragment.firstChild;
6113+
6114+ if ( fragment.childNodes.length === 1 ) {
6115+ fragment = first;
6116+ }
6117+
6118+ if ( first ) {
6119+ table = table && jQuery.nodeName( first, "tr" );
6120+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6121+ hasScripts = scripts.length;
6122+
6123+ // Use the original fragment for the last item instead of the first because it can end up
6124+ // being emptied incorrectly in certain situations (#8070).
6125+ for ( ; i < l; i++ ) {
6126+ node = fragment;
6127+
6128+ if ( i !== iNoClone ) {
6129+ node = jQuery.clone( node, true, true );
6130+
6131+ // Keep references to cloned scripts for later restoration
6132+ if ( hasScripts ) {
6133+ jQuery.merge( scripts, getAll( node, "script" ) );
6134+ }
6135+ }
6136+
6137+ callback.call(
6138+ table && jQuery.nodeName( this[i], "table" ) ?
6139+ findOrAppend( this[i], "tbody" ) :
6140+ this[i],
6141+ node,
6142+ i
6143+ );
6144+ }
6145+
6146+ if ( hasScripts ) {
6147+ doc = scripts[ scripts.length - 1 ].ownerDocument;
6148+
6149+ // Reenable scripts
6150+ jQuery.map( scripts, restoreScript );
6151+
6152+ // Evaluate executable scripts on first document insertion
6153+ for ( i = 0; i < hasScripts; i++ ) {
6154+ node = scripts[ i ];
6155+ if ( rscriptType.test( node.type || "" ) &&
6156+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
6157+
6158+ if ( node.src ) {
6159+ // Hope ajax is available...
6160+ jQuery.ajax({
6161+ url: node.src,
6162+ type: "GET",
6163+ dataType: "script",
6164+ async: false,
6165+ global: false,
6166+ "throws": true
6167+ });
6168+ } else {
6169+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
6170+ }
6171+ }
6172+ }
6173+ }
6174+
6175+ // Fix #11809: Avoid leaking memory
6176+ fragment = first = null;
6177+ }
6178+ }
6179+
6180+ return this;
6181+ }
6182+});
6183+
6184+function findOrAppend( elem, tag ) {
6185+ return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
6186+}
6187+
6188+// Replace/restore the type attribute of script elements for safe DOM manipulation
6189+function disableScript( elem ) {
6190+ var attr = elem.getAttributeNode("type");
6191+ elem.type = ( attr && attr.specified ) + "/" + elem.type;
6192+ return elem;
6193+}
6194+function restoreScript( elem ) {
6195+ var match = rscriptTypeMasked.exec( elem.type );
6196+ if ( match ) {
6197+ elem.type = match[1];
6198+ } else {
6199+ elem.removeAttribute("type");
6200+ }
6201+ return elem;
6202+}
6203+
6204+// Mark scripts as having already been evaluated
6205+function setGlobalEval( elems, refElements ) {
6206+ var elem,
6207+ i = 0;
6208+ for ( ; (elem = elems[i]) != null; i++ ) {
6209+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
6210+ }
6211+}
6212+
6213+function cloneCopyEvent( src, dest ) {
6214+
6215+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6216+ return;
6217+ }
6218+
6219+ var type, i, l,
6220+ oldData = jQuery._data( src ),
6221+ curData = jQuery._data( dest, oldData ),
6222+ events = oldData.events;
6223+
6224+ if ( events ) {
6225+ delete curData.handle;
6226+ curData.events = {};
6227+
6228+ for ( type in events ) {
6229+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6230+ jQuery.event.add( dest, type, events[ type ][ i ] );
6231+ }
6232+ }
6233+ }
6234+
6235+ // make the cloned public data object a copy from the original
6236+ if ( curData.data ) {
6237+ curData.data = jQuery.extend( {}, curData.data );
6238+ }
6239+}
6240+
6241+function fixCloneNodeIssues( src, dest ) {
6242+ var nodeName, data, e;
6243+
6244+ // We do not need to do anything for non-Elements
6245+ if ( dest.nodeType !== 1 ) {
6246+ return;
6247+ }
6248+
6249+ nodeName = dest.nodeName.toLowerCase();
6250+
6251+ // IE6-8 copies events bound via attachEvent when using cloneNode.
6252+ if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
6253+ data = jQuery._data( dest );
6254+
6255+ for ( e in data.events ) {
6256+ jQuery.removeEvent( dest, e, data.handle );
6257+ }
6258+
6259+ // Event data gets referenced instead of copied if the expando gets copied too
6260+ dest.removeAttribute( jQuery.expando );
6261+ }
6262+
6263+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
6264+ if ( nodeName === "script" && dest.text !== src.text ) {
6265+ disableScript( dest ).text = src.text;
6266+ restoreScript( dest );
6267+
6268+ // IE6-10 improperly clones children of object elements using classid.
6269+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
6270+ } else if ( nodeName === "object" ) {
6271+ if ( dest.parentNode ) {
6272+ dest.outerHTML = src.outerHTML;
6273+ }
6274+
6275+ // This path appears unavoidable for IE9. When cloning an object
6276+ // element in IE9, the outerHTML strategy above is not sufficient.
6277+ // If the src has innerHTML and the destination does not,
6278+ // copy the src.innerHTML into the dest.innerHTML. #10324
6279+ if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
6280+ dest.innerHTML = src.innerHTML;
6281+ }
6282+
6283+ } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
6284+ // IE6-8 fails to persist the checked state of a cloned checkbox
6285+ // or radio button. Worse, IE6-7 fail to give the cloned element
6286+ // a checked appearance if the defaultChecked value isn't also set
6287+
6288+ dest.defaultChecked = dest.checked = src.checked;
6289+
6290+ // IE6-7 get confused and end up setting the value of a cloned
6291+ // checkbox/radio button to an empty string instead of "on"
6292+ if ( dest.value !== src.value ) {
6293+ dest.value = src.value;
6294+ }
6295+
6296+ // IE6-8 fails to return the selected option to the default selected
6297+ // state when cloning options
6298+ } else if ( nodeName === "option" ) {
6299+ dest.defaultSelected = dest.selected = src.defaultSelected;
6300+
6301+ // IE6-8 fails to set the defaultValue to the correct value when
6302+ // cloning other types of input fields
6303+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
6304+ dest.defaultValue = src.defaultValue;
6305+ }
6306+}
6307+
6308+jQuery.each({
6309+ appendTo: "append",
6310+ prependTo: "prepend",
6311+ insertBefore: "before",
6312+ insertAfter: "after",
6313+ replaceAll: "replaceWith"
6314+}, function( name, original ) {
6315+ jQuery.fn[ name ] = function( selector ) {
6316+ var elems,
6317+ i = 0,
6318+ ret = [],
6319+ insert = jQuery( selector ),
6320+ last = insert.length - 1;
6321+
6322+ for ( ; i <= last; i++ ) {
6323+ elems = i === last ? this : this.clone(true);
6324+ jQuery( insert[i] )[ original ]( elems );
6325+
6326+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6327+ core_push.apply( ret, elems.get() );
6328+ }
6329+
6330+ return this.pushStack( ret );
6331+ };
6332+});
6333+
6334+function getAll( context, tag ) {
6335+ var elems, elem,
6336+ i = 0,
6337+ found = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( tag || "*" ) :
6338+ typeof context.querySelectorAll !== "undefined" ? context.querySelectorAll( tag || "*" ) :
6339+ undefined;
6340+
6341+ if ( !found ) {
6342+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
6343+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
6344+ found.push( elem );
6345+ } else {
6346+ jQuery.merge( found, getAll( elem, tag ) );
6347+ }
6348+ }
6349+ }
6350+
6351+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
6352+ jQuery.merge( [ context ], found ) :
6353+ found;
6354+}
6355+
6356+// Used in buildFragment, fixes the defaultChecked property
6357+function fixDefaultChecked( elem ) {
6358+ if ( manipulation_rcheckableType.test( elem.type ) ) {
6359+ elem.defaultChecked = elem.checked;
6360+ }
6361+}
6362+
6363+jQuery.extend({
6364+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6365+ var destElements, srcElements, node, i, clone,
6366+ inPage = jQuery.contains( elem.ownerDocument, elem );
6367+
6368+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6369+ clone = elem.cloneNode( true );
6370+
6371+ // IE<=8 does not properly clone detached, unknown element nodes
6372+ } else {
6373+ fragmentDiv.innerHTML = elem.outerHTML;
6374+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6375+ }
6376+
6377+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6378+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6379+
6380+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
6381+ destElements = getAll( clone );
6382+ srcElements = getAll( elem );
6383+
6384+ // Fix all IE cloning issues
6385+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
6386+ // Ensure that the destination node is not null; Fixes #9587
6387+ if ( destElements[i] ) {
6388+ fixCloneNodeIssues( node, destElements[i] );
6389+ }
6390+ }
6391+ }
6392+
6393+ // Copy the events from the original to the clone
6394+ if ( dataAndEvents ) {
6395+ if ( deepDataAndEvents ) {
6396+ srcElements = srcElements || getAll( elem );
6397+ destElements = destElements || getAll( clone );
6398+
6399+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
6400+ cloneCopyEvent( node, destElements[i] );
6401+ }
6402+ } else {
6403+ cloneCopyEvent( elem, clone );
6404+ }
6405+ }
6406+
6407+ // Preserve script evaluation history
6408+ destElements = getAll( clone, "script" );
6409+ if ( destElements.length > 0 ) {
6410+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6411+ }
6412+
6413+ destElements = srcElements = node = null;
6414+
6415+ // Return the cloned set
6416+ return clone;
6417+ },
6418+
6419+ buildFragment: function( elems, context, scripts, selection ) {
6420+ var contains, elem, tag, tmp, wrap, tbody, j,
6421+ l = elems.length,
6422+
6423+ // Ensure a safe fragment
6424+ safe = createSafeFragment( context ),
6425+
6426+ nodes = [],
6427+ i = 0;
6428+
6429+ for ( ; i < l; i++ ) {
6430+ elem = elems[ i ];
6431+
6432+ if ( elem || elem === 0 ) {
6433+
6434+ // Add nodes directly
6435+ if ( jQuery.type( elem ) === "object" ) {
6436+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
6437+
6438+ // Convert non-html into a text node
6439+ } else if ( !rhtml.test( elem ) ) {
6440+ nodes.push( context.createTextNode( elem ) );
6441+
6442+ // Convert html into DOM nodes
6443+ } else {
6444+ tmp = tmp || safe.appendChild( context.createElement("div") );
6445+
6446+ // Deserialize a standard representation
6447+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
6448+ wrap = wrapMap[ tag ] || wrapMap._default;
6449+
6450+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
6451+
6452+ // Descend through wrappers to the right content
6453+ j = wrap[0];
6454+ while ( j-- ) {
6455+ tmp = tmp.lastChild;
6456+ }
6457+
6458+ // Manually add leading whitespace removed by IE
6459+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6460+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
6461+ }
6462+
6463+ // Remove IE's autoinserted <tbody> from table fragments
6464+ if ( !jQuery.support.tbody ) {
6465+
6466+ // String was a <table>, *may* have spurious <tbody>
6467+ elem = tag === "table" && !rtbody.test( elem ) ?
6468+ tmp.firstChild :
6469+
6470+ // String was a bare <thead> or <tfoot>
6471+ wrap[1] === "<table>" && !rtbody.test( elem ) ?
6472+ tmp :
6473+ 0;
6474+
6475+ j = elem && elem.childNodes.length;
6476+ while ( j-- ) {
6477+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
6478+ elem.removeChild( tbody );
6479+ }
6480+ }
6481+ }
6482+
6483+ jQuery.merge( nodes, tmp.childNodes );
6484+
6485+ // Fix #12392 for WebKit and IE > 9
6486+ tmp.textContent = "";
6487+
6488+ // Fix #12392 for oldIE
6489+ while ( tmp.firstChild ) {
6490+ tmp.removeChild( tmp.firstChild );
6491+ }
6492+
6493+ // Remember the top-level container for proper cleanup
6494+ tmp = safe.lastChild;
6495+ }
6496+ }
6497+ }
6498+
6499+ // Fix #11356: Clear elements from fragment
6500+ if ( tmp ) {
6501+ safe.removeChild( tmp );
6502+ }
6503+
6504+ // Reset defaultChecked for any radios and checkboxes
6505+ // about to be appended to the DOM in IE 6/7 (#8060)
6506+ if ( !jQuery.support.appendChecked ) {
6507+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
6508+ }
6509+
6510+ i = 0;
6511+ while ( (elem = nodes[ i++ ]) ) {
6512+
6513+ // #4087 - If origin and destination elements are the same, and this is
6514+ // that element, do not do anything
6515+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
6516+ continue;
6517+ }
6518+
6519+ contains = jQuery.contains( elem.ownerDocument, elem );
6520+
6521+ // Append to fragment
6522+ tmp = getAll( safe.appendChild( elem ), "script" );
6523+
6524+ // Preserve script evaluation history
6525+ if ( contains ) {
6526+ setGlobalEval( tmp );
6527+ }
6528+
6529+ // Capture executables
6530+ if ( scripts ) {
6531+ j = 0;
6532+ while ( (elem = tmp[ j++ ]) ) {
6533+ if ( rscriptType.test( elem.type || "" ) ) {
6534+ scripts.push( elem );
6535+ }
6536+ }
6537+ }
6538+ }
6539+
6540+ tmp = null;
6541+
6542+ return safe;
6543+ },
6544+
6545+ cleanData: function( elems, /* internal */ acceptData ) {
6546+ var data, id, elem, type,
6547+ i = 0,
6548+ internalKey = jQuery.expando,
6549+ cache = jQuery.cache,
6550+ deleteExpando = jQuery.support.deleteExpando,
6551+ special = jQuery.event.special;
6552+
6553+ for ( ; (elem = elems[i]) != null; i++ ) {
6554+
6555+ if ( acceptData || jQuery.acceptData( elem ) ) {
6556+
6557+ id = elem[ internalKey ];
6558+ data = id && cache[ id ];
6559+
6560+ if ( data ) {
6561+ if ( data.events ) {
6562+ for ( type in data.events ) {
6563+ if ( special[ type ] ) {
6564+ jQuery.event.remove( elem, type );
6565+
6566+ // This is a shortcut to avoid jQuery.event.remove's overhead
6567+ } else {
6568+ jQuery.removeEvent( elem, type, data.handle );
6569+ }
6570+ }
6571+ }
6572+
6573+ // Remove cache only if it was not already removed by jQuery.event.remove
6574+ if ( cache[ id ] ) {
6575+
6576+ delete cache[ id ];
6577+
6578+ // IE does not allow us to delete expando properties from nodes,
6579+ // nor does it have a removeAttribute function on Document nodes;
6580+ // we must handle all of these cases
6581+ if ( deleteExpando ) {
6582+ delete elem[ internalKey ];
6583+
6584+ } else if ( typeof elem.removeAttribute !== "undefined" ) {
6585+ elem.removeAttribute( internalKey );
6586+
6587+ } else {
6588+ elem[ internalKey ] = null;
6589+ }
6590+
6591+ core_deletedIds.push( id );
6592+ }
6593+ }
6594+ }
6595+ }
6596+ }
6597+});
6598+var curCSS, getStyles, iframe,
6599+ ralpha = /alpha\([^)]*\)/i,
6600+ ropacity = /opacity\s*=\s*([^)]*)/,
6601+ rposition = /^(top|right|bottom|left)$/,
6602+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6603+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6604+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6605+ rmargin = /^margin/,
6606+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
6607+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
6608+ rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
6609+ elemdisplay = { BODY: "block" },
6610+
6611+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6612+ cssNormalTransform = {
6613+ letterSpacing: 0,
6614+ fontWeight: 400
6615+ },
6616+
6617+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
6618+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6619+
6620+// return a css property mapped to a potentially vendor prefixed property
6621+function vendorPropName( style, name ) {
6622+
6623+ // shortcut for names that are not vendor prefixed
6624+ if ( name in style ) {
6625+ return name;
6626+ }
6627+
6628+ // check for vendor prefixed names
6629+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
6630+ origName = name,
6631+ i = cssPrefixes.length;
6632+
6633+ while ( i-- ) {
6634+ name = cssPrefixes[ i ] + capName;
6635+ if ( name in style ) {
6636+ return name;
6637+ }
6638+ }
6639+
6640+ return origName;
6641+}
6642+
6643+function isHidden( elem, el ) {
6644+ // isHidden might be called from jQuery#filter function;
6645+ // in that case, element will be second argument
6646+ elem = el || elem;
6647+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
6648+}
6649+
6650+function showHide( elements, show ) {
6651+ var elem,
6652+ values = [],
6653+ index = 0,
6654+ length = elements.length;
6655+
6656+ for ( ; index < length; index++ ) {
6657+ elem = elements[ index ];
6658+ if ( !elem.style ) {
6659+ continue;
6660+ }
6661+ values[ index ] = jQuery._data( elem, "olddisplay" );
6662+ if ( show ) {
6663+ // Reset the inline display of this element to learn if it is
6664+ // being hidden by cascaded rules or not
6665+ if ( !values[ index ] && elem.style.display === "none" ) {
6666+ elem.style.display = "";
6667+ }
6668+
6669+ // Set elements which have been overridden with display: none
6670+ // in a stylesheet to whatever the default browser style is
6671+ // for such an element
6672+ if ( elem.style.display === "" && isHidden( elem ) ) {
6673+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
6674+ }
6675+ } else if ( !values[ index ] && !isHidden( elem ) ) {
6676+ jQuery._data( elem, "olddisplay", jQuery.css( elem, "display" ) );
6677+ }
6678+ }
6679+
6680+ // Set the display of most of the elements in a second loop
6681+ // to avoid the constant reflow
6682+ for ( index = 0; index < length; index++ ) {
6683+ elem = elements[ index ];
6684+ if ( !elem.style ) {
6685+ continue;
6686+ }
6687+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6688+ elem.style.display = show ? values[ index ] || "" : "none";
6689+ }
6690+ }
6691+
6692+ return elements;
6693+}
6694+
6695+jQuery.fn.extend({
6696+ css: function( name, value ) {
6697+ return jQuery.access( this, function( elem, name, value ) {
6698+ var styles, len,
6699+ map = {},
6700+ i = 0;
6701+
6702+ if ( jQuery.isArray( name ) ) {
6703+ styles = getStyles( elem );
6704+ len = name.length;
6705+
6706+ for ( ; i < len; i++ ) {
6707+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6708+ }
6709+
6710+ return map;
6711+ }
6712+
6713+ return value !== undefined ?
6714+ jQuery.style( elem, name, value ) :
6715+ jQuery.css( elem, name );
6716+ }, name, value, arguments.length > 1 );
6717+ },
6718+ show: function() {
6719+ return showHide( this, true );
6720+ },
6721+ hide: function() {
6722+ return showHide( this );
6723+ },
6724+ toggle: function( state ) {
6725+ var bool = typeof state === "boolean";
6726+
6727+ return this.each(function() {
6728+ if ( bool ? state : isHidden( this ) ) {
6729+ jQuery( this ).show();
6730+ } else {
6731+ jQuery( this ).hide();
6732+ }
6733+ });
6734+ }
6735+});
6736+
6737+jQuery.extend({
6738+ // Add in style property hooks for overriding the default
6739+ // behavior of getting and setting a style property
6740+ cssHooks: {
6741+ opacity: {
6742+ get: function( elem, computed ) {
6743+ if ( computed ) {
6744+ // We should always get a number back from opacity
6745+ var ret = curCSS( elem, "opacity" );
6746+ return ret === "" ? "1" : ret;
6747+ }
6748+ }
6749+ }
6750+ },
6751+
6752+ // Exclude the following css properties to add px
6753+ cssNumber: {
6754+ "columnCount": true,
6755+ "fillOpacity": true,
6756+ "fontWeight": true,
6757+ "lineHeight": true,
6758+ "opacity": true,
6759+ "orphans": true,
6760+ "widows": true,
6761+ "zIndex": true,
6762+ "zoom": true
6763+ },
6764+
6765+ // Add in properties whose names you wish to fix before
6766+ // setting or getting the value
6767+ cssProps: {
6768+ // normalize float css property
6769+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6770+ },
6771+
6772+ // Get and set the style property on a DOM Node
6773+ style: function( elem, name, value, extra ) {
6774+ // Don't set styles on text and comment nodes
6775+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6776+ return;
6777+ }
6778+
6779+ // Make sure that we're working with the right name
6780+ var ret, type, hooks,
6781+ origName = jQuery.camelCase( name ),
6782+ style = elem.style;
6783+
6784+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6785+
6786+ // gets hook for the prefixed version
6787+ // followed by the unprefixed version
6788+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6789+
6790+ // Check if we're setting a value
6791+ if ( value !== undefined ) {
6792+ type = typeof value;
6793+
6794+ // convert relative number strings (+= or -=) to relative numbers. #7345
6795+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6796+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6797+ // Fixes bug #9237
6798+ type = "number";
6799+ }
6800+
6801+ // Make sure that NaN and null values aren't set. See: #7116
6802+ if ( value == null || type === "number" && isNaN( value ) ) {
6803+ return;
6804+ }
6805+
6806+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
6807+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6808+ value += "px";
6809+ }
6810+
6811+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
6812+ // but it would mean to define eight (for every problematic property) identical functions
6813+ if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
6814+ style[ name ] = "inherit";
6815+ }
6816+
6817+ // If a hook was provided, use that value, otherwise just set the specified value
6818+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6819+
6820+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6821+ // Fixes bug #5509
6822+ try {
6823+ style[ name ] = value;
6824+ } catch(e) {}
6825+ }
6826+
6827+ } else {
6828+ // If a hook was provided get the non-computed value from there
6829+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6830+ return ret;
6831+ }
6832+
6833+ // Otherwise just get the value from the style object
6834+ return style[ name ];
6835+ }
6836+ },
6837+
6838+ css: function( elem, name, extra, styles ) {
6839+ var val, num, hooks,
6840+ origName = jQuery.camelCase( name );
6841+
6842+ // Make sure that we're working with the right name
6843+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6844+
6845+ // gets hook for the prefixed version
6846+ // followed by the unprefixed version
6847+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6848+
6849+ // If a hook was provided get the computed value from there
6850+ if ( hooks && "get" in hooks ) {
6851+ val = hooks.get( elem, true, extra );
6852+ }
6853+
6854+ // Otherwise, if a way to get the computed value exists, use that
6855+ if ( val === undefined ) {
6856+ val = curCSS( elem, name, styles );
6857+ }
6858+
6859+ //convert "normal" to computed value
6860+ if ( val === "normal" && name in cssNormalTransform ) {
6861+ val = cssNormalTransform[ name ];
6862+ }
6863+
6864+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
6865+ if ( extra ) {
6866+ num = parseFloat( val );
6867+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6868+ }
6869+ return val;
6870+ },
6871+
6872+ // A method for quickly swapping in/out CSS properties to get correct calculations
6873+ swap: function( elem, options, callback, args ) {
6874+ var ret, name,
6875+ old = {};
6876+
6877+ // Remember the old values, and insert the new ones
6878+ for ( name in options ) {
6879+ old[ name ] = elem.style[ name ];
6880+ elem.style[ name ] = options[ name ];
6881+ }
6882+
6883+ ret = callback.apply( elem, args || [] );
6884+
6885+ // Revert the old values
6886+ for ( name in options ) {
6887+ elem.style[ name ] = old[ name ];
6888+ }
6889+
6890+ return ret;
6891+ }
6892+});
6893+
6894+// NOTE: we've included the "window" in window.getComputedStyle
6895+// because jsdom on node.js will break without it.
6896+if ( window.getComputedStyle ) {
6897+ getStyles = function( elem ) {
6898+ return window.getComputedStyle( elem, null );
6899+ };
6900+
6901+ curCSS = function( elem, name, _computed ) {
6902+ var width, minWidth, maxWidth,
6903+ computed = _computed || getStyles( elem ),
6904+
6905+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6906+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
6907+ style = elem.style;
6908+
6909+ if ( computed ) {
6910+
6911+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6912+ ret = jQuery.style( elem, name );
6913+ }
6914+
6915+ // A tribute to the "awesome hack by Dean Edwards"
6916+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6917+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6918+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6919+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6920+
6921+ // Remember the original values
6922+ width = style.width;
6923+ minWidth = style.minWidth;
6924+ maxWidth = style.maxWidth;
6925+
6926+ // Put in the new values to get a computed value out
6927+ style.minWidth = style.maxWidth = style.width = ret;
6928+ ret = computed.width;
6929+
6930+ // Revert the changed values
6931+ style.width = width;
6932+ style.minWidth = minWidth;
6933+ style.maxWidth = maxWidth;
6934+ }
6935+ }
6936+
6937+ return ret;
6938+ };
6939+} else if ( document.documentElement.currentStyle ) {
6940+ getStyles = function( elem ) {
6941+ return elem.currentStyle;
6942+ };
6943+
6944+ curCSS = function( elem, name, _computed ) {
6945+ var left, rs, rsLeft,
6946+ computed = _computed || getStyles( elem ),
6947+ ret = computed ? computed[ name ] : undefined,
6948+ style = elem.style;
6949+
6950+ // Avoid setting ret to empty string here
6951+ // so we don't default to auto
6952+ if ( ret == null && style && style[ name ] ) {
6953+ ret = style[ name ];
6954+ }
6955+
6956+ // From the awesome hack by Dean Edwards
6957+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6958+
6959+ // If we're not dealing with a regular pixel number
6960+ // but a number that has a weird ending, we need to convert it to pixels
6961+ // but not position css attributes, as those are proportional to the parent element instead
6962+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
6963+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
6964+
6965+ // Remember the original values
6966+ left = style.left;
6967+ rs = elem.runtimeStyle;
6968+ rsLeft = rs && rs.left;
6969+
6970+ // Put in the new values to get a computed value out
6971+ if ( rsLeft ) {
6972+ rs.left = elem.currentStyle.left;
6973+ }
6974+ style.left = name === "fontSize" ? "1em" : ret;
6975+ ret = style.pixelLeft + "px";
6976+
6977+ // Revert the changed values
6978+ style.left = left;
6979+ if ( rsLeft ) {
6980+ rs.left = rsLeft;
6981+ }
6982+ }
6983+
6984+ return ret === "" ? "auto" : ret;
6985+ };
6986+}
6987+
6988+function setPositiveNumber( elem, value, subtract ) {
6989+ var matches = rnumsplit.exec( value );
6990+ return matches ?
6991+ // Guard against undefined "subtract", e.g., when used as in cssHooks
6992+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
6993+ value;
6994+}
6995+
6996+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
6997+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
6998+ // If we already have the right measurement, avoid augmentation
6999+ 4 :
7000+ // Otherwise initialize for horizontal or vertical properties
7001+ name === "width" ? 1 : 0,
7002+
7003+ val = 0;
7004+
7005+ for ( ; i < 4; i += 2 ) {
7006+ // both box models exclude margin, so add it if we want it
7007+ if ( extra === "margin" ) {
7008+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
7009+ }
7010+
7011+ if ( isBorderBox ) {
7012+ // border-box includes padding, so remove it if we want content
7013+ if ( extra === "content" ) {
7014+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7015+ }
7016+
7017+ // at this point, extra isn't border nor margin, so remove border
7018+ if ( extra !== "margin" ) {
7019+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7020+ }
7021+ } else {
7022+ // at this point, extra isn't content, so add padding
7023+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7024+
7025+ // at this point, extra isn't content nor padding, so add border
7026+ if ( extra !== "padding" ) {
7027+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7028+ }
7029+ }
7030+ }
7031+
7032+ return val;
7033+}
7034+
7035+function getWidthOrHeight( elem, name, extra ) {
7036+
7037+ // Start with offset property, which is equivalent to the border-box value
7038+ var valueIsBorderBox = true,
7039+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7040+ styles = getStyles( elem ),
7041+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
7042+
7043+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
7044+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
7045+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
7046+ if ( val <= 0 || val == null ) {
7047+ // Fall back to computed then uncomputed css if necessary
7048+ val = curCSS( elem, name, styles );
7049+ if ( val < 0 || val == null ) {
7050+ val = elem.style[ name ];
7051+ }
7052+
7053+ // Computed unit is not pixels. Stop here and return.
7054+ if ( rnumnonpx.test(val) ) {
7055+ return val;
7056+ }
7057+
7058+ // we need the check for style in case a browser which returns unreliable values
7059+ // for getComputedStyle silently falls back to the reliable elem.style
7060+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
7061+
7062+ // Normalize "", auto, and prepare for extra
7063+ val = parseFloat( val ) || 0;
7064+ }
7065+
7066+ // use the active box-sizing model to add/subtract irrelevant styles
7067+ return ( val +
7068+ augmentWidthOrHeight(
7069+ elem,
7070+ name,
7071+ extra || ( isBorderBox ? "border" : "content" ),
7072+ valueIsBorderBox,
7073+ styles
7074+ )
7075+ ) + "px";
7076+}
7077+
7078+// Try to determine the default display value of an element
7079+function css_defaultDisplay( nodeName ) {
7080+ var doc = document,
7081+ display = elemdisplay[ nodeName ];
7082+
7083+ if ( !display ) {
7084+ display = actualDisplay( nodeName, doc );
7085+
7086+ // If the simple way fails, read from inside an iframe
7087+ if ( display === "none" || !display ) {
7088+ // Use the already-created iframe if possible
7089+ iframe = ( iframe ||
7090+ jQuery("<iframe frameborder='0' width='0' height='0'/>")
7091+ .css( "cssText", "display:block !important" )
7092+ ).appendTo( doc.documentElement );
7093+
7094+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
7095+ doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
7096+ doc.write("<!doctype html><html><body>");
7097+ doc.close();
7098+
7099+ display = actualDisplay( nodeName, doc );
7100+ iframe.detach();
7101+ }
7102+
7103+ // Store the correct default display
7104+ elemdisplay[ nodeName ] = display;
7105+ }
7106+
7107+ return display;
7108+}
7109+
7110+// Called ONLY from within css_defaultDisplay
7111+function actualDisplay( name, doc ) {
7112+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
7113+ display = jQuery.css( elem[0], "display" );
7114+ elem.remove();
7115+ return display;
7116+}
7117+
7118+jQuery.each([ "height", "width" ], function( i, name ) {
7119+ jQuery.cssHooks[ name ] = {
7120+ get: function( elem, computed, extra ) {
7121+ if ( computed ) {
7122+ // certain elements can have dimension info if we invisibly show them
7123+ // however, it must have a current display style that would benefit from this
7124+ return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
7125+ jQuery.swap( elem, cssShow, function() {
7126+ return getWidthOrHeight( elem, name, extra );
7127+ }) :
7128+ getWidthOrHeight( elem, name, extra );
7129+ }
7130+ },
7131+
7132+ set: function( elem, value, extra ) {
7133+ var styles = extra && getStyles( elem );
7134+ return setPositiveNumber( elem, value, extra ?
7135+ augmentWidthOrHeight(
7136+ elem,
7137+ name,
7138+ extra,
7139+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7140+ styles
7141+ ) : 0
7142+ );
7143+ }
7144+ };
7145+});
7146+
7147+if ( !jQuery.support.opacity ) {
7148+ jQuery.cssHooks.opacity = {
7149+ get: function( elem, computed ) {
7150+ // IE uses filters for opacity
7151+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7152+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7153+ computed ? "1" : "";
7154+ },
7155+
7156+ set: function( elem, value ) {
7157+ var style = elem.style,
7158+ currentStyle = elem.currentStyle,
7159+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7160+ filter = currentStyle && currentStyle.filter || style.filter || "";
7161+
7162+ // IE has trouble with opacity if it does not have layout
7163+ // Force it by setting the zoom level
7164+ style.zoom = 1;
7165+
7166+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7167+ // if value === "", then remove inline opacity #12685
7168+ if ( ( value >= 1 || value === "" ) &&
7169+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7170+ style.removeAttribute ) {
7171+
7172+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7173+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
7174+ // style.removeAttribute is IE Only, but so apparently is this code path...
7175+ style.removeAttribute( "filter" );
7176+
7177+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
7178+ if ( value === "" || currentStyle && !currentStyle.filter ) {
7179+ return;
7180+ }
7181+ }
7182+
7183+ // otherwise, set new filter values
7184+ style.filter = ralpha.test( filter ) ?
7185+ filter.replace( ralpha, opacity ) :
7186+ filter + " " + opacity;
7187+ }
7188+ };
7189+}
7190+
7191+// These hooks cannot be added until DOM ready because the support test
7192+// for it is not run until after DOM ready
7193+jQuery(function() {
7194+ if ( !jQuery.support.reliableMarginRight ) {
7195+ jQuery.cssHooks.marginRight = {
7196+ get: function( elem, computed ) {
7197+ if ( computed ) {
7198+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7199+ // Work around by temporarily setting element display to inline-block
7200+ return jQuery.swap( elem, { "display": "inline-block" },
7201+ curCSS, [ elem, "marginRight" ] );
7202+ }
7203+ }
7204+ };
7205+ }
7206+
7207+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
7208+ // getComputedStyle returns percent when specified for top/left/bottom/right
7209+ // rather than make the css module depend on the offset module, we just check for it here
7210+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
7211+ jQuery.each( [ "top", "left" ], function( i, prop ) {
7212+ jQuery.cssHooks[ prop ] = {
7213+ get: function( elem, computed ) {
7214+ if ( computed ) {
7215+ computed = curCSS( elem, prop );
7216+ // if curCSS returns percentage, fallback to offset
7217+ return rnumnonpx.test( computed ) ?
7218+ jQuery( elem ).position()[ prop ] + "px" :
7219+ computed;
7220+ }
7221+ }
7222+ };
7223+ });
7224+ }
7225+
7226+});
7227+
7228+if ( jQuery.expr && jQuery.expr.filters ) {
7229+ jQuery.expr.filters.hidden = function( elem ) {
7230+ return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7231+ };
7232+
7233+ jQuery.expr.filters.visible = function( elem ) {
7234+ return !jQuery.expr.filters.hidden( elem );
7235+ };
7236+}
7237+
7238+// These hooks are used by animate to expand properties
7239+jQuery.each({
7240+ margin: "",
7241+ padding: "",
7242+ border: "Width"
7243+}, function( prefix, suffix ) {
7244+ jQuery.cssHooks[ prefix + suffix ] = {
7245+ expand: function( value ) {
7246+ var i = 0,
7247+ expanded = {},
7248+
7249+ // assumes a single number if not a string
7250+ parts = typeof value === "string" ? value.split(" ") : [ value ];
7251+
7252+ for ( ; i < 4; i++ ) {
7253+ expanded[ prefix + cssExpand[ i ] + suffix ] =
7254+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7255+ }
7256+
7257+ return expanded;
7258+ }
7259+ };
7260+
7261+ if ( !rmargin.test( prefix ) ) {
7262+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7263+ }
7264+});
7265+var r20 = /%20/g,
7266+ rbracket = /\[\]$/,
7267+ rCRLF = /\r?\n/g,
7268+ rsubmitterTypes = /^(?:submit|button|image|reset)$/i,
7269+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
7270+
7271+jQuery.fn.extend({
7272+ serialize: function() {
7273+ return jQuery.param( this.serializeArray() );
7274+ },
7275+ serializeArray: function() {
7276+ return this.map(function(){
7277+ // Can add propHook for "elements" to filter or add form elements
7278+ var elements = jQuery.prop( this, "elements" );
7279+ return elements ? jQuery.makeArray( elements ) : this;
7280+ })
7281+ .filter(function(){
7282+ var type = this.type;
7283+ // Use .is(":disabled") so that fieldset[disabled] works
7284+ return this.name && !jQuery( this ).is( ":disabled" ) &&
7285+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
7286+ ( this.checked || !manipulation_rcheckableType.test( type ) );
7287+ })
7288+ .map(function( i, elem ){
7289+ var val = jQuery( this ).val();
7290+
7291+ return val == null ?
7292+ null :
7293+ jQuery.isArray( val ) ?
7294+ jQuery.map( val, function( val ){
7295+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7296+ }) :
7297+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7298+ }).get();
7299+ }
7300+});
7301+
7302+//Serialize an array of form elements or a set of
7303+//key/values into a query string
7304+jQuery.param = function( a, traditional ) {
7305+ var prefix,
7306+ s = [],
7307+ add = function( key, value ) {
7308+ // If value is a function, invoke it and return its value
7309+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
7310+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7311+ };
7312+
7313+ // Set traditional to true for jQuery <= 1.3.2 behavior.
7314+ if ( traditional === undefined ) {
7315+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
7316+ }
7317+
7318+ // If an array was passed in, assume that it is an array of form elements.
7319+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7320+ // Serialize the form elements
7321+ jQuery.each( a, function() {
7322+ add( this.name, this.value );
7323+ });
7324+
7325+ } else {
7326+ // If traditional, encode the "old" way (the way 1.3.2 or older
7327+ // did it), otherwise encode params recursively.
7328+ for ( prefix in a ) {
7329+ buildParams( prefix, a[ prefix ], traditional, add );
7330+ }
7331+ }
7332+
7333+ // Return the resulting serialization
7334+ return s.join( "&" ).replace( r20, "+" );
7335+};
7336+
7337+function buildParams( prefix, obj, traditional, add ) {
7338+ var name;
7339+
7340+ if ( jQuery.isArray( obj ) ) {
7341+ // Serialize array item.
7342+ jQuery.each( obj, function( i, v ) {
7343+ if ( traditional || rbracket.test( prefix ) ) {
7344+ // Treat each array item as a scalar.
7345+ add( prefix, v );
7346+
7347+ } else {
7348+ // Item is non-scalar (array or object), encode its numeric index.
7349+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
7350+ }
7351+ });
7352+
7353+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
7354+ // Serialize object item.
7355+ for ( name in obj ) {
7356+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7357+ }
7358+
7359+ } else {
7360+ // Serialize scalar item.
7361+ add( prefix, obj );
7362+ }
7363+}
7364+var
7365+ // Document location
7366+ ajaxLocParts,
7367+ ajaxLocation,
7368+
7369+ ajax_nonce = jQuery.now(),
7370+
7371+ ajax_rquery = /\?/,
7372+ rhash = /#.*$/,
7373+ rts = /([?&])_=[^&]*/,
7374+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7375+ // #7653, #8125, #8152: local protocol detection
7376+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7377+ rnoContent = /^(?:GET|HEAD)$/,
7378+ rprotocol = /^\/\//,
7379+ rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
7380+
7381+ // Keep a copy of the old load method
7382+ _load = jQuery.fn.load,
7383+
7384+ /* Prefilters
7385+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7386+ * 2) These are called:
7387+ * - BEFORE asking for a transport
7388+ * - AFTER param serialization (s.data is a string if s.processData is true)
7389+ * 3) key is the dataType
7390+ * 4) the catchall symbol "*" can be used
7391+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7392+ */
7393+ prefilters = {},
7394+
7395+ /* Transports bindings
7396+ * 1) key is the dataType
7397+ * 2) the catchall symbol "*" can be used
7398+ * 3) selection will start with transport dataType and THEN go to "*" if needed
7399+ */
7400+ transports = {},
7401+
7402+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7403+ allTypes = "*/".concat("*");
7404+
7405+// #8138, IE may throw an exception when accessing
7406+// a field from window.location if document.domain has been set
7407+try {
7408+ ajaxLocation = location.href;
7409+} catch( e ) {
7410+ // Use the href attribute of an A element
7411+ // since IE will modify it given document.location
7412+ ajaxLocation = document.createElement( "a" );
7413+ ajaxLocation.href = "";
7414+ ajaxLocation = ajaxLocation.href;
7415+}
7416+
7417+// Segment location into parts
7418+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7419+
7420+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7421+function addToPrefiltersOrTransports( structure ) {
7422+
7423+ // dataTypeExpression is optional and defaults to "*"
7424+ return function( dataTypeExpression, func ) {
7425+
7426+ if ( typeof dataTypeExpression !== "string" ) {
7427+ func = dataTypeExpression;
7428+ dataTypeExpression = "*";
7429+ }
7430+
7431+ var dataType,
7432+ i = 0,
7433+ dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
7434+
7435+ if ( jQuery.isFunction( func ) ) {
7436+ // For each dataType in the dataTypeExpression
7437+ while ( (dataType = dataTypes[i++]) ) {
7438+ // Prepend if requested
7439+ if ( dataType[0] === "+" ) {
7440+ dataType = dataType.slice( 1 ) || "*";
7441+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7442+
7443+ // Otherwise append
7444+ } else {
7445+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
7446+ }
7447+ }
7448+ }
7449+ };
7450+}
7451+
7452+// Base inspection function for prefilters and transports
7453+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7454+
7455+ var inspected = {},
7456+ seekingTransport = ( structure === transports );
7457+
7458+ function inspect( dataType ) {
7459+ var selected;
7460+ inspected[ dataType ] = true;
7461+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7462+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7463+ if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7464+ options.dataTypes.unshift( dataTypeOrTransport );
7465+ inspect( dataTypeOrTransport );
7466+ return false;
7467+ } else if ( seekingTransport ) {
7468+ return !( selected = dataTypeOrTransport );
7469+ }
7470+ });
7471+ return selected;
7472+ }
7473+
7474+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7475+}
7476+
7477+// A special extend for ajax options
7478+// that takes "flat" options (not to be deep extended)
7479+// Fixes #9887
7480+function ajaxExtend( target, src ) {
7481+ var key, deep,
7482+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
7483+
7484+ for ( key in src ) {
7485+ if ( src[ key ] !== undefined ) {
7486+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7487+ }
7488+ }
7489+ if ( deep ) {
7490+ jQuery.extend( true, target, deep );
7491+ }
7492+
7493+ return target;
7494+}
7495+
7496+jQuery.fn.load = function( url, params, callback ) {
7497+ if ( typeof url !== "string" && _load ) {
7498+ return _load.apply( this, arguments );
7499+ }
7500+
7501+ var selector, type, response,
7502+ self = this,
7503+ off = url.indexOf(" ");
7504+
7505+ if ( off >= 0 ) {
7506+ selector = url.slice( off, url.length );
7507+ url = url.slice( 0, off );
7508+ }
7509+
7510+ // If it's a function
7511+ if ( jQuery.isFunction( params ) ) {
7512+
7513+ // We assume that it's the callback
7514+ callback = params;
7515+ params = undefined;
7516+
7517+ // Otherwise, build a param string
7518+ } else if ( params && typeof params === "object" ) {
7519+ type = "POST";
7520+ }
7521+
7522+ // If we have elements to modify, make the request
7523+ if ( self.length > 0 ) {
7524+ jQuery.ajax({
7525+ url: url,
7526+
7527+ // if "type" variable is undefined, then "GET" method will be used
7528+ type: type,
7529+ dataType: "html",
7530+ data: params
7531+ }).done(function( responseText ) {
7532+
7533+ // Save response for use in complete callback
7534+ response = arguments;
7535+
7536+ self.html( selector ?
7537+
7538+ // If a selector was specified, locate the right elements in a dummy div
7539+ // Exclude scripts to avoid IE 'Permission Denied' errors
7540+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
7541+
7542+ // Otherwise use the full result
7543+ responseText );
7544+
7545+ }).complete( callback && function( jqXHR, status ) {
7546+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
7547+ });
7548+ }
7549+
7550+ return this;
7551+};
7552+
7553+// Attach a bunch of functions for handling common AJAX events
7554+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
7555+ jQuery.fn[ type ] = function( fn ){
7556+ return this.on( type, fn );
7557+ };
7558+});
7559+
7560+jQuery.each( [ "get", "post" ], function( i, method ) {
7561+ jQuery[ method ] = function( url, data, callback, type ) {
7562+ // shift arguments if data argument was omitted
7563+ if ( jQuery.isFunction( data ) ) {
7564+ type = type || callback;
7565+ callback = data;
7566+ data = undefined;
7567+ }
7568+
7569+ return jQuery.ajax({
7570+ url: url,
7571+ type: method,
7572+ dataType: type,
7573+ data: data,
7574+ success: callback
7575+ });
7576+ };
7577+});
7578+
7579+jQuery.extend({
7580+
7581+ // Counter for holding the number of active queries
7582+ active: 0,
7583+
7584+ // Last-Modified header cache for next request
7585+ lastModified: {},
7586+ etag: {},
7587+
7588+ ajaxSettings: {
7589+ url: ajaxLocation,
7590+ type: "GET",
7591+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7592+ global: true,
7593+ processData: true,
7594+ async: true,
7595+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7596+ /*
7597+ timeout: 0,
7598+ data: null,
7599+ dataType: null,
7600+ username: null,
7601+ password: null,
7602+ cache: null,
7603+ throws: false,
7604+ traditional: false,
7605+ headers: {},
7606+ */
7607+
7608+ accepts: {
7609+ "*": allTypes,
7610+ text: "text/plain",
7611+ html: "text/html",
7612+ xml: "application/xml, text/xml",
7613+ json: "application/json, text/javascript"
7614+ },
7615+
7616+ contents: {
7617+ xml: /xml/,
7618+ html: /html/,
7619+ json: /json/
7620+ },
7621+
7622+ responseFields: {
7623+ xml: "responseXML",
7624+ text: "responseText"
7625+ },
7626+
7627+ // Data converters
7628+ // Keys separate source (or catchall "*") and destination types with a single space
7629+ converters: {
7630+
7631+ // Convert anything to text
7632+ "* text": window.String,
7633+
7634+ // Text to html (true = no transformation)
7635+ "text html": true,
7636+
7637+ // Evaluate text as a json expression
7638+ "text json": jQuery.parseJSON,
7639+
7640+ // Parse text as xml
7641+ "text xml": jQuery.parseXML
7642+ },
7643+
7644+ // For options that shouldn't be deep extended:
7645+ // you can add your own custom options here if
7646+ // and when you create one that shouldn't be
7647+ // deep extended (see ajaxExtend)
7648+ flatOptions: {
7649+ url: true,
7650+ context: true
7651+ }
7652+ },
7653+
7654+ // Creates a full fledged settings object into target
7655+ // with both ajaxSettings and settings fields.
7656+ // If target is omitted, writes into ajaxSettings.
7657+ ajaxSetup: function( target, settings ) {
7658+ return settings ?
7659+
7660+ // Building a settings object
7661+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7662+
7663+ // Extending ajaxSettings
7664+ ajaxExtend( jQuery.ajaxSettings, target );
7665+ },
7666+
7667+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7668+ ajaxTransport: addToPrefiltersOrTransports( transports ),
7669+
7670+ // Main method
7671+ ajax: function( url, options ) {
7672+
7673+ // If url is an object, simulate pre-1.5 signature
7674+ if ( typeof url === "object" ) {
7675+ options = url;
7676+ url = undefined;
7677+ }
7678+
7679+ // Force options to be an object
7680+ options = options || {};
7681+
7682+ var transport,
7683+ // URL without anti-cache param
7684+ cacheURL,
7685+ // Response headers
7686+ responseHeadersString,
7687+ responseHeaders,
7688+ // timeout handle
7689+ timeoutTimer,
7690+ // Cross-domain detection vars
7691+ parts,
7692+ // To know if global events are to be dispatched
7693+ fireGlobals,
7694+ // Loop variable
7695+ i,
7696+ // Create the final options object
7697+ s = jQuery.ajaxSetup( {}, options ),
7698+ // Callbacks context
7699+ callbackContext = s.context || s,
7700+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
7701+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7702+ jQuery( callbackContext ) :
7703+ jQuery.event,
7704+ // Deferreds
7705+ deferred = jQuery.Deferred(),
7706+ completeDeferred = jQuery.Callbacks("once memory"),
7707+ // Status-dependent callbacks
7708+ statusCode = s.statusCode || {},
7709+ // Headers (they are sent all at once)
7710+ requestHeaders = {},
7711+ requestHeadersNames = {},
7712+ // The jqXHR state
7713+ state = 0,
7714+ // Default abort message
7715+ strAbort = "canceled",
7716+ // Fake xhr
7717+ jqXHR = {
7718+ readyState: 0,
7719+
7720+ // Builds headers hashtable if needed
7721+ getResponseHeader: function( key ) {
7722+ var match;
7723+ if ( state === 2 ) {
7724+ if ( !responseHeaders ) {
7725+ responseHeaders = {};
7726+ while ( (match = rheaders.exec( responseHeadersString )) ) {
7727+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7728+ }
7729+ }
7730+ match = responseHeaders[ key.toLowerCase() ];
7731+ }
7732+ return match == null ? null : match;
7733+ },
7734+
7735+ // Raw string
7736+ getAllResponseHeaders: function() {
7737+ return state === 2 ? responseHeadersString : null;
7738+ },
7739+
7740+ // Caches the header
7741+ setRequestHeader: function( name, value ) {
7742+ var lname = name.toLowerCase();
7743+ if ( !state ) {
7744+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7745+ requestHeaders[ name ] = value;
7746+ }
7747+ return this;
7748+ },
7749+
7750+ // Overrides response content-type header
7751+ overrideMimeType: function( type ) {
7752+ if ( !state ) {
7753+ s.mimeType = type;
7754+ }
7755+ return this;
7756+ },
7757+
7758+ // Status-dependent callbacks
7759+ statusCode: function( map ) {
7760+ var code;
7761+ if ( map ) {
7762+ if ( state < 2 ) {
7763+ for ( code in map ) {
7764+ // Lazy-add the new callback in a way that preserves old ones
7765+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
7766+ }
7767+ } else {
7768+ // Execute the appropriate callbacks
7769+ jqXHR.always( map[ jqXHR.status ] );
7770+ }
7771+ }
7772+ return this;
7773+ },
7774+
7775+ // Cancel the request
7776+ abort: function( statusText ) {
7777+ var finalText = statusText || strAbort;
7778+ if ( transport ) {
7779+ transport.abort( finalText );
7780+ }
7781+ done( 0, finalText );
7782+ return this;
7783+ }
7784+ };
7785+
7786+ // Attach deferreds
7787+ deferred.promise( jqXHR ).complete = completeDeferred.add;
7788+ jqXHR.success = jqXHR.done;
7789+ jqXHR.error = jqXHR.fail;
7790+
7791+ // Remove hash character (#7531: and string promotion)
7792+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7793+ // Handle falsy url in the settings object (#10093: consistency with old signature)
7794+ // We also use the url parameter if available
7795+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7796+
7797+ // Alias method option to type as per ticket #12004
7798+ s.type = options.method || options.type || s.method || s.type;
7799+
7800+ // Extract dataTypes list
7801+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
7802+
7803+ // A cross-domain request is in order when we have a protocol:host:port mismatch
7804+ if ( s.crossDomain == null ) {
7805+ parts = rurl.exec( s.url.toLowerCase() );
7806+ s.crossDomain = !!( parts &&
7807+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
7808+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7809+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7810+ );
7811+ }
7812+
7813+ // Convert data if not already a string
7814+ if ( s.data && s.processData && typeof s.data !== "string" ) {
7815+ s.data = jQuery.param( s.data, s.traditional );
7816+ }
7817+
7818+ // Apply prefilters
7819+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7820+
7821+ // If request was aborted inside a prefilter, stop there
7822+ if ( state === 2 ) {
7823+ return jqXHR;
7824+ }
7825+
7826+ // We can fire global events as of now if asked to
7827+ fireGlobals = s.global;
7828+
7829+ // Watch for a new set of requests
7830+ if ( fireGlobals && jQuery.active++ === 0 ) {
7831+ jQuery.event.trigger("ajaxStart");
7832+ }
7833+
7834+ // Uppercase the type
7835+ s.type = s.type.toUpperCase();
7836+
7837+ // Determine if request has content
7838+ s.hasContent = !rnoContent.test( s.type );
7839+
7840+ // Save the URL in case we're toying with the If-Modified-Since
7841+ // and/or If-None-Match header later on
7842+ cacheURL = s.url;
7843+
7844+ // More options handling for requests with no content
7845+ if ( !s.hasContent ) {
7846+
7847+ // If data is available, append data to url
7848+ if ( s.data ) {
7849+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
7850+ // #9682: remove data so that it's not used in an eventual retry
7851+ delete s.data;
7852+ }
7853+
7854+ // Add anti-cache in url if needed
7855+ if ( s.cache === false ) {
7856+ s.url = rts.test( cacheURL ) ?
7857+
7858+ // If there is already a '_' parameter, set its value
7859+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
7860+
7861+ // Otherwise add one to the end
7862+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
7863+ }
7864+ }
7865+
7866+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7867+ if ( s.ifModified ) {
7868+ if ( jQuery.lastModified[ cacheURL ] ) {
7869+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
7870+ }
7871+ if ( jQuery.etag[ cacheURL ] ) {
7872+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
7873+ }
7874+ }
7875+
7876+ // Set the correct header, if data is being sent
7877+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7878+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
7879+ }
7880+
7881+ // Set the Accepts header for the server, depending on the dataType
7882+ jqXHR.setRequestHeader(
7883+ "Accept",
7884+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7885+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
7886+ s.accepts[ "*" ]
7887+ );
7888+
7889+ // Check for headers option
7890+ for ( i in s.headers ) {
7891+ jqXHR.setRequestHeader( i, s.headers[ i ] );
7892+ }
7893+
7894+ // Allow custom headers/mimetypes and early abort
7895+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7896+ // Abort if not done already and return
7897+ return jqXHR.abort();
7898+ }
7899+
7900+ // aborting is no longer a cancellation
7901+ strAbort = "abort";
7902+
7903+ // Install callbacks on deferreds
7904+ for ( i in { success: 1, error: 1, complete: 1 } ) {
7905+ jqXHR[ i ]( s[ i ] );
7906+ }
7907+
7908+ // Get transport
7909+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
7910+
7911+ // If no transport, we auto-abort
7912+ if ( !transport ) {
7913+ done( -1, "No Transport" );
7914+ } else {
7915+ jqXHR.readyState = 1;
7916+
7917+ // Send global event
7918+ if ( fireGlobals ) {
7919+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
7920+ }
7921+ // Timeout
7922+ if ( s.async && s.timeout > 0 ) {
7923+ timeoutTimer = setTimeout(function() {
7924+ jqXHR.abort("timeout");
7925+ }, s.timeout );
7926+ }
7927+
7928+ try {
7929+ state = 1;
7930+ transport.send( requestHeaders, done );
7931+ } catch ( e ) {
7932+ // Propagate exception as error if not done
7933+ if ( state < 2 ) {
7934+ done( -1, e );
7935+ // Simply rethrow otherwise
7936+ } else {
7937+ throw e;
7938+ }
7939+ }
7940+ }
7941+
7942+ // Callback for when everything is done
7943+ function done( status, nativeStatusText, responses, headers ) {
7944+ var isSuccess, success, error, response, modified,
7945+ statusText = nativeStatusText;
7946+
7947+ // Called once
7948+ if ( state === 2 ) {
7949+ return;
7950+ }
7951+
7952+ // State is "done" now
7953+ state = 2;
7954+
7955+ // Clear timeout if it exists
7956+ if ( timeoutTimer ) {
7957+ clearTimeout( timeoutTimer );
7958+ }
7959+
7960+ // Dereference transport for early garbage collection
7961+ // (no matter how long the jqXHR object will be used)
7962+ transport = undefined;
7963+
7964+ // Cache response headers
7965+ responseHeadersString = headers || "";
7966+
7967+ // Set readyState
7968+ jqXHR.readyState = status > 0 ? 4 : 0;
7969+
7970+ // Get response data
7971+ if ( responses ) {
7972+ response = ajaxHandleResponses( s, jqXHR, responses );
7973+ }
7974+
7975+ // If successful, handle type chaining
7976+ if ( status >= 200 && status < 300 || status === 304 ) {
7977+
7978+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7979+ if ( s.ifModified ) {
7980+ modified = jqXHR.getResponseHeader("Last-Modified");
7981+ if ( modified ) {
7982+ jQuery.lastModified[ cacheURL ] = modified;
7983+ }
7984+ modified = jqXHR.getResponseHeader("etag");
7985+ if ( modified ) {
7986+ jQuery.etag[ cacheURL ] = modified;
7987+ }
7988+ }
7989+
7990+ // If not modified
7991+ if ( status === 304 ) {
7992+ isSuccess = true;
7993+ statusText = "notmodified";
7994+
7995+ // If we have data
7996+ } else {
7997+ isSuccess = ajaxConvert( s, response );
7998+ statusText = isSuccess.state;
7999+ success = isSuccess.data;
8000+ error = isSuccess.error;
8001+ isSuccess = !error;
8002+ }
8003+ } else {
8004+ // We extract error from statusText
8005+ // then normalize statusText and status for non-aborts
8006+ error = statusText;
8007+ if ( status || !statusText ) {
8008+ statusText = "error";
8009+ if ( status < 0 ) {
8010+ status = 0;
8011+ }
8012+ }
8013+ }
8014+
8015+ // Set data for the fake xhr object
8016+ jqXHR.status = status;
8017+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8018+
8019+ // Success/Error
8020+ if ( isSuccess ) {
8021+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8022+ } else {
8023+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8024+ }
8025+
8026+ // Status-dependent callbacks
8027+ jqXHR.statusCode( statusCode );
8028+ statusCode = undefined;
8029+
8030+ if ( fireGlobals ) {
8031+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8032+ [ jqXHR, s, isSuccess ? success : error ] );
8033+ }
8034+
8035+ // Complete
8036+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8037+
8038+ if ( fireGlobals ) {
8039+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8040+ // Handle the global AJAX counter
8041+ if ( !( --jQuery.active ) ) {
8042+ jQuery.event.trigger("ajaxStop");
8043+ }
8044+ }
8045+ }
8046+
8047+ return jqXHR;
8048+ },
8049+
8050+ getScript: function( url, callback ) {
8051+ return jQuery.get( url, undefined, callback, "script" );
8052+ },
8053+
8054+ getJSON: function( url, data, callback ) {
8055+ return jQuery.get( url, data, callback, "json" );
8056+ }
8057+});
8058+
8059+/* Handles responses to an ajax request:
8060+ * - sets all responseXXX fields accordingly
8061+ * - finds the right dataType (mediates between content-type and expected dataType)
8062+ * - returns the corresponding response
8063+ */
8064+function ajaxHandleResponses( s, jqXHR, responses ) {
8065+
8066+ var ct, type, finalDataType, firstDataType,
8067+ contents = s.contents,
8068+ dataTypes = s.dataTypes,
8069+ responseFields = s.responseFields;
8070+
8071+ // Fill responseXXX fields
8072+ for ( type in responseFields ) {
8073+ if ( type in responses ) {
8074+ jqXHR[ responseFields[type] ] = responses[ type ];
8075+ }
8076+ }
8077+
8078+ // Remove auto dataType and get content-type in the process
8079+ while( dataTypes[ 0 ] === "*" ) {
8080+ dataTypes.shift();
8081+ if ( ct === undefined ) {
8082+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8083+ }
8084+ }
8085+
8086+ // Check if we're dealing with a known content-type
8087+ if ( ct ) {
8088+ for ( type in contents ) {
8089+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
8090+ dataTypes.unshift( type );
8091+ break;
8092+ }
8093+ }
8094+ }
8095+
8096+ // Check to see if we have a response for the expected dataType
8097+ if ( dataTypes[ 0 ] in responses ) {
8098+ finalDataType = dataTypes[ 0 ];
8099+ } else {
8100+ // Try convertible dataTypes
8101+ for ( type in responses ) {
8102+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8103+ finalDataType = type;
8104+ break;
8105+ }
8106+ if ( !firstDataType ) {
8107+ firstDataType = type;
8108+ }
8109+ }
8110+ // Or just use first one
8111+ finalDataType = finalDataType || firstDataType;
8112+ }
8113+
8114+ // If we found a dataType
8115+ // We add the dataType to the list if needed
8116+ // and return the corresponding response
8117+ if ( finalDataType ) {
8118+ if ( finalDataType !== dataTypes[ 0 ] ) {
8119+ dataTypes.unshift( finalDataType );
8120+ }
8121+ return responses[ finalDataType ];
8122+ }
8123+}
8124+
8125+// Chain conversions given the request and the original response
8126+function ajaxConvert( s, response ) {
8127+
8128+ var conv, conv2, current, tmp,
8129+ converters = {},
8130+ i = 0,
8131+ // Work with a copy of dataTypes in case we need to modify it for conversion
8132+ dataTypes = s.dataTypes.slice(),
8133+ prev = dataTypes[ 0 ];
8134+
8135+ // Apply the dataFilter if provided
8136+ if ( s.dataFilter ) {
8137+ response = s.dataFilter( response, s.dataType );
8138+ }
8139+
8140+ // Create converters map with lowercased keys
8141+ if ( dataTypes[ 1 ] ) {
8142+ for ( conv in s.converters ) {
8143+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
8144+ }
8145+ }
8146+
8147+ // Convert to each sequential dataType, tolerating list modification
8148+ for ( ; (current = dataTypes[++i]); ) {
8149+
8150+ // There's only work to do if current dataType is non-auto
8151+ if ( current !== "*" ) {
8152+
8153+ // Convert response if prev dataType is non-auto and differs from current
8154+ if ( prev !== "*" && prev !== current ) {
8155+
8156+ // Seek a direct converter
8157+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8158+
8159+ // If none found, seek a pair
8160+ if ( !conv ) {
8161+ for ( conv2 in converters ) {
8162+
8163+ // If conv2 outputs current
8164+ tmp = conv2.split(" ");
8165+ if ( tmp[ 1 ] === current ) {
8166+
8167+ // If prev can be converted to accepted input
8168+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
8169+ converters[ "* " + tmp[ 0 ] ];
8170+ if ( conv ) {
8171+ // Condense equivalence converters
8172+ if ( conv === true ) {
8173+ conv = converters[ conv2 ];
8174+
8175+ // Otherwise, insert the intermediate dataType
8176+ } else if ( converters[ conv2 ] !== true ) {
8177+ current = tmp[ 0 ];
8178+ dataTypes.splice( i--, 0, current );
8179+ }
8180+
8181+ break;
8182+ }
8183+ }
8184+ }
8185+ }
8186+
8187+ // Apply converter (if not an equivalence)
8188+ if ( conv !== true ) {
8189+
8190+ // Unless errors are allowed to bubble, catch and return them
8191+ if ( conv && s["throws"] ) {
8192+ response = conv( response );
8193+ } else {
8194+ try {
8195+ response = conv( response );
8196+ } catch ( e ) {
8197+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8198+ }
8199+ }
8200+ }
8201+ }
8202+
8203+ // Update prev for next iteration
8204+ prev = current;
8205+ }
8206+ }
8207+
8208+ return { state: "success", data: response };
8209+}
8210+// Install script dataType
8211+jQuery.ajaxSetup({
8212+ accepts: {
8213+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8214+ },
8215+ contents: {
8216+ script: /(?:java|ecma)script/
8217+ },
8218+ converters: {
8219+ "text script": function( text ) {
8220+ jQuery.globalEval( text );
8221+ return text;
8222+ }
8223+ }
8224+});
8225+
8226+// Handle cache's special case and global
8227+jQuery.ajaxPrefilter( "script", function( s ) {
8228+ if ( s.cache === undefined ) {
8229+ s.cache = false;
8230+ }
8231+ if ( s.crossDomain ) {
8232+ s.type = "GET";
8233+ s.global = false;
8234+ }
8235+});
8236+
8237+// Bind script tag hack transport
8238+jQuery.ajaxTransport( "script", function(s) {
8239+
8240+ // This transport only deals with cross domain requests
8241+ if ( s.crossDomain ) {
8242+
8243+ var script,
8244+ head = document.head || jQuery("head")[0] || document.documentElement;
8245+
8246+ return {
8247+
8248+ send: function( _, callback ) {
8249+
8250+ script = document.createElement("script");
8251+
8252+ script.async = true;
8253+
8254+ if ( s.scriptCharset ) {
8255+ script.charset = s.scriptCharset;
8256+ }
8257+
8258+ script.src = s.url;
8259+
8260+ // Attach handlers for all browsers
8261+ script.onload = script.onreadystatechange = function( _, isAbort ) {
8262+
8263+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8264+
8265+ // Handle memory leak in IE
8266+ script.onload = script.onreadystatechange = null;
8267+
8268+ // Remove the script
8269+ if ( script.parentNode ) {
8270+ script.parentNode.removeChild( script );
8271+ }
8272+
8273+ // Dereference the script
8274+ script = null;
8275+
8276+ // Callback if not abort
8277+ if ( !isAbort ) {
8278+ callback( 200, "success" );
8279+ }
8280+ }
8281+ };
8282+
8283+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
8284+ // Use native DOM manipulation to avoid our domManip AJAX trickery
8285+ head.insertBefore( script, head.firstChild );
8286+ },
8287+
8288+ abort: function() {
8289+ if ( script ) {
8290+ script.onload( undefined, true );
8291+ }
8292+ }
8293+ };
8294+ }
8295+});
8296+var oldCallbacks = [],
8297+ rjsonp = /(=)\?(?=&|$)|\?\?/;
8298+
8299+// Default jsonp settings
8300+jQuery.ajaxSetup({
8301+ jsonp: "callback",
8302+ jsonpCallback: function() {
8303+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
8304+ this[ callback ] = true;
8305+ return callback;
8306+ }
8307+});
8308+
8309+// Detect, normalize options and install callbacks for jsonp requests
8310+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8311+
8312+ var callbackName, overwritten, responseContainer,
8313+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8314+ "url" :
8315+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8316+ );
8317+
8318+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
8319+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8320+
8321+ // Get callback name, remembering preexisting value associated with it
8322+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8323+ s.jsonpCallback() :
8324+ s.jsonpCallback;
8325+
8326+ // Insert callback into url or form data
8327+ if ( jsonProp ) {
8328+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8329+ } else if ( s.jsonp !== false ) {
8330+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8331+ }
8332+
8333+ // Use data converter to retrieve json after script execution
8334+ s.converters["script json"] = function() {
8335+ if ( !responseContainer ) {
8336+ jQuery.error( callbackName + " was not called" );
8337+ }
8338+ return responseContainer[ 0 ];
8339+ };
8340+
8341+ // force json dataType
8342+ s.dataTypes[ 0 ] = "json";
8343+
8344+ // Install callback
8345+ overwritten = window[ callbackName ];
8346+ window[ callbackName ] = function() {
8347+ responseContainer = arguments;
8348+ };
8349+
8350+ // Clean-up function (fires after converters)
8351+ jqXHR.always(function() {
8352+ // Restore preexisting value
8353+ window[ callbackName ] = overwritten;
8354+
8355+ // Save back as free
8356+ if ( s[ callbackName ] ) {
8357+ // make sure that re-using the options doesn't screw things around
8358+ s.jsonpCallback = originalSettings.jsonpCallback;
8359+
8360+ // save the callback name for future use
8361+ oldCallbacks.push( callbackName );
8362+ }
8363+
8364+ // Call if it was a function and we have a response
8365+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8366+ overwritten( responseContainer[ 0 ] );
8367+ }
8368+
8369+ responseContainer = overwritten = undefined;
8370+ });
8371+
8372+ // Delegate to script
8373+ return "script";
8374+ }
8375+});
8376+var xhrCallbacks, xhrSupported,
8377+ xhrId = 0,
8378+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8379+ xhrOnUnloadAbort = window.ActiveXObject && function() {
8380+ // Abort all pending requests
8381+ var key;
8382+ for ( key in xhrCallbacks ) {
8383+ xhrCallbacks[ key ]( undefined, true );
8384+ }
8385+ };
8386+
8387+// Functions to create xhrs
8388+function createStandardXHR() {
8389+ try {
8390+ return new window.XMLHttpRequest();
8391+ } catch( e ) {}
8392+}
8393+
8394+function createActiveXHR() {
8395+ try {
8396+ return new window.ActiveXObject("Microsoft.XMLHTTP");
8397+ } catch( e ) {}
8398+}
8399+
8400+// Create the request object
8401+// (This is still attached to ajaxSettings for backward compatibility)
8402+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8403+ /* Microsoft failed to properly
8404+ * implement the XMLHttpRequest in IE7 (can't request local files),
8405+ * so we use the ActiveXObject when it is available
8406+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8407+ * we need a fallback.
8408+ */
8409+ function() {
8410+ return !this.isLocal && createStandardXHR() || createActiveXHR();
8411+ } :
8412+ // For all other browsers, use the standard XMLHttpRequest object
8413+ createStandardXHR;
8414+
8415+// Determine support properties
8416+xhrSupported = jQuery.ajaxSettings.xhr();
8417+jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8418+xhrSupported = jQuery.support.ajax = !!xhrSupported;
8419+
8420+// Create transport if the browser can provide an xhr
8421+if ( xhrSupported ) {
8422+
8423+ jQuery.ajaxTransport(function( s ) {
8424+ // Cross domain only allowed if supported through XMLHttpRequest
8425+ if ( !s.crossDomain || jQuery.support.cors ) {
8426+
8427+ var callback;
8428+
8429+ return {
8430+ send: function( headers, complete ) {
8431+
8432+ // Get a new xhr
8433+ var handle, i,
8434+ xhr = s.xhr();
8435+
8436+ // Open the socket
8437+ // Passing null username, generates a login popup on Opera (#2865)
8438+ if ( s.username ) {
8439+ xhr.open( s.type, s.url, s.async, s.username, s.password );
8440+ } else {
8441+ xhr.open( s.type, s.url, s.async );
8442+ }
8443+
8444+ // Apply custom fields if provided
8445+ if ( s.xhrFields ) {
8446+ for ( i in s.xhrFields ) {
8447+ xhr[ i ] = s.xhrFields[ i ];
8448+ }
8449+ }
8450+
8451+ // Override mime type if needed
8452+ if ( s.mimeType && xhr.overrideMimeType ) {
8453+ xhr.overrideMimeType( s.mimeType );
8454+ }
8455+
8456+ // X-Requested-With header
8457+ // For cross-domain requests, seeing as conditions for a preflight are
8458+ // akin to a jigsaw puzzle, we simply never set it to be sure.
8459+ // (it can always be set on a per-request basis or even using ajaxSetup)
8460+ // For same-domain requests, won't change header if already provided.
8461+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8462+ headers["X-Requested-With"] = "XMLHttpRequest";
8463+ }
8464+
8465+ // Need an extra try/catch for cross domain requests in Firefox 3
8466+ try {
8467+ for ( i in headers ) {
8468+ xhr.setRequestHeader( i, headers[ i ] );
8469+ }
8470+ } catch( err ) {}
8471+
8472+ // Do send the request
8473+ // This may raise an exception which is actually
8474+ // handled in jQuery.ajax (so no try/catch here)
8475+ xhr.send( ( s.hasContent && s.data ) || null );
8476+
8477+ // Listener
8478+ callback = function( _, isAbort ) {
8479+
8480+ var status,
8481+ statusText,
8482+ responseHeaders,
8483+ responses,
8484+ xml;
8485+
8486+ // Firefox throws exceptions when accessing properties
8487+ // of an xhr when a network error occurred
8488+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8489+ try {
8490+
8491+ // Was never called and is aborted or complete
8492+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8493+
8494+ // Only called once
8495+ callback = undefined;
8496+
8497+ // Do not keep as active anymore
8498+ if ( handle ) {
8499+ xhr.onreadystatechange = jQuery.noop;
8500+ if ( xhrOnUnloadAbort ) {
8501+ delete xhrCallbacks[ handle ];
8502+ }
8503+ }
8504+
8505+ // If it's an abort
8506+ if ( isAbort ) {
8507+ // Abort it manually if needed
8508+ if ( xhr.readyState !== 4 ) {
8509+ xhr.abort();
8510+ }
8511+ } else {
8512+ responses = {};
8513+ status = xhr.status;
8514+ xml = xhr.responseXML;
8515+ responseHeaders = xhr.getAllResponseHeaders();
8516+
8517+ // Construct response list
8518+ if ( xml && xml.documentElement /* #4958 */ ) {
8519+ responses.xml = xml;
8520+ }
8521+
8522+ // When requesting binary data, IE6-9 will throw an exception
8523+ // on any attempt to access responseText (#11426)
8524+ if ( typeof xhr.responseText === "string" ) {
8525+ responses.text = xhr.responseText;
8526+ }
8527+
8528+ // Firefox throws an exception when accessing
8529+ // statusText for faulty cross-domain requests
8530+ try {
8531+ statusText = xhr.statusText;
8532+ } catch( e ) {
8533+ // We normalize with Webkit giving an empty statusText
8534+ statusText = "";
8535+ }
8536+
8537+ // Filter status for non standard behaviors
8538+
8539+ // If the request is local and we have data: assume a success
8540+ // (success with no data won't get notified, that's the best we
8541+ // can do given current implementations)
8542+ if ( !status && s.isLocal && !s.crossDomain ) {
8543+ status = responses.text ? 200 : 404;
8544+ // IE - #1450: sometimes returns 1223 when it should be 204
8545+ } else if ( status === 1223 ) {
8546+ status = 204;
8547+ }
8548+ }
8549+ }
8550+ } catch( firefoxAccessException ) {
8551+ if ( !isAbort ) {
8552+ complete( -1, firefoxAccessException );
8553+ }
8554+ }
8555+
8556+ // Call complete if needed
8557+ if ( responses ) {
8558+ complete( status, statusText, responses, responseHeaders );
8559+ }
8560+ };
8561+
8562+ if ( !s.async ) {
8563+ // if we're in sync mode we fire the callback
8564+ callback();
8565+ } else if ( xhr.readyState === 4 ) {
8566+ // (IE6 & IE7) if it's in cache and has been
8567+ // retrieved directly we need to fire the callback
8568+ setTimeout( callback );
8569+ } else {
8570+ handle = ++xhrId;
8571+ if ( xhrOnUnloadAbort ) {
8572+ // Create the active xhrs callbacks list if needed
8573+ // and attach the unload handler
8574+ if ( !xhrCallbacks ) {
8575+ xhrCallbacks = {};
8576+ jQuery( window ).unload( xhrOnUnloadAbort );
8577+ }
8578+ // Add to list of active xhrs callbacks
8579+ xhrCallbacks[ handle ] = callback;
8580+ }
8581+ xhr.onreadystatechange = callback;
8582+ }
8583+ },
8584+
8585+ abort: function() {
8586+ if ( callback ) {
8587+ callback( undefined, true );
8588+ }
8589+ }
8590+ };
8591+ }
8592+ });
8593+}
8594+var fxNow, timerId,
8595+ rfxtypes = /^(?:toggle|show|hide)$/,
8596+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
8597+ rrun = /queueHooks$/,
8598+ animationPrefilters = [ defaultPrefilter ],
8599+ tweeners = {
8600+ "*": [function( prop, value ) {
8601+ var end, unit,
8602+ tween = this.createTween( prop, value ),
8603+ parts = rfxnum.exec( value ),
8604+ target = tween.cur(),
8605+ start = +target || 0,
8606+ scale = 1,
8607+ maxIterations = 20;
8608+
8609+ if ( parts ) {
8610+ end = +parts[2];
8611+ unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8612+
8613+ // We need to compute starting value
8614+ if ( unit !== "px" && start ) {
8615+ // Iteratively approximate from a nonzero starting point
8616+ // Prefer the current property, because this process will be trivial if it uses the same units
8617+ // Fallback to end or a simple constant
8618+ start = jQuery.css( tween.elem, prop, true ) || end || 1;
8619+
8620+ do {
8621+ // If previous iteration zeroed out, double until we get *something*
8622+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
8623+ scale = scale || ".5";
8624+
8625+ // Adjust and apply
8626+ start = start / scale;
8627+ jQuery.style( tween.elem, prop, start + unit );
8628+
8629+ // Update scale, tolerating zero or NaN from tween.cur()
8630+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8631+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8632+ }
8633+
8634+ tween.unit = unit;
8635+ tween.start = start;
8636+ // If a +=/-= token was provided, we're doing a relative animation
8637+ tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
8638+ }
8639+ return tween;
8640+ }]
8641+ };
8642+
8643+// Animations created synchronously will run synchronously
8644+function createFxNow() {
8645+ setTimeout(function() {
8646+ fxNow = undefined;
8647+ });
8648+ return ( fxNow = jQuery.now() );
8649+}
8650+
8651+function createTweens( animation, props ) {
8652+ jQuery.each( props, function( prop, value ) {
8653+ var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8654+ index = 0,
8655+ length = collection.length;
8656+ for ( ; index < length; index++ ) {
8657+ if ( collection[ index ].call( animation, prop, value ) ) {
8658+
8659+ // we're done with this property
8660+ return;
8661+ }
8662+ }
8663+ });
8664+}
8665+
8666+function Animation( elem, properties, options ) {
8667+ var result,
8668+ stopped,
8669+ index = 0,
8670+ length = animationPrefilters.length,
8671+ deferred = jQuery.Deferred().always( function() {
8672+ // don't match elem in the :animated selector
8673+ delete tick.elem;
8674+ }),
8675+ tick = function() {
8676+ if ( stopped ) {
8677+ return false;
8678+ }
8679+ var currentTime = fxNow || createFxNow(),
8680+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8681+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8682+ temp = remaining / animation.duration || 0,
8683+ percent = 1 - temp,
8684+ index = 0,
8685+ length = animation.tweens.length;
8686+
8687+ for ( ; index < length ; index++ ) {
8688+ animation.tweens[ index ].run( percent );
8689+ }
8690+
8691+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
8692+
8693+ if ( percent < 1 && length ) {
8694+ return remaining;
8695+ } else {
8696+ deferred.resolveWith( elem, [ animation ] );
8697+ return false;
8698+ }
8699+ },
8700+ animation = deferred.promise({
8701+ elem: elem,
8702+ props: jQuery.extend( {}, properties ),
8703+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
8704+ originalProperties: properties,
8705+ originalOptions: options,
8706+ startTime: fxNow || createFxNow(),
8707+ duration: options.duration,
8708+ tweens: [],
8709+ createTween: function( prop, end ) {
8710+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
8711+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
8712+ animation.tweens.push( tween );
8713+ return tween;
8714+ },
8715+ stop: function( gotoEnd ) {
8716+ var index = 0,
8717+ // if we are going to the end, we want to run all the tweens
8718+ // otherwise we skip this part
8719+ length = gotoEnd ? animation.tweens.length : 0;
8720+ if ( stopped ) {
8721+ return this;
8722+ }
8723+ stopped = true;
8724+ for ( ; index < length ; index++ ) {
8725+ animation.tweens[ index ].run( 1 );
8726+ }
8727+
8728+ // resolve when we played the last frame
8729+ // otherwise, reject
8730+ if ( gotoEnd ) {
8731+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
8732+ } else {
8733+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
8734+ }
8735+ return this;
8736+ }
8737+ }),
8738+ props = animation.props;
8739+
8740+ propFilter( props, animation.opts.specialEasing );
8741+
8742+ for ( ; index < length ; index++ ) {
8743+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
8744+ if ( result ) {
8745+ return result;
8746+ }
8747+ }
8748+
8749+ createTweens( animation, props );
8750+
8751+ if ( jQuery.isFunction( animation.opts.start ) ) {
8752+ animation.opts.start.call( elem, animation );
8753+ }
8754+
8755+ jQuery.fx.timer(
8756+ jQuery.extend( tick, {
8757+ elem: elem,
8758+ anim: animation,
8759+ queue: animation.opts.queue
8760+ })
8761+ );
8762+
8763+ // attach callbacks from options
8764+ return animation.progress( animation.opts.progress )
8765+ .done( animation.opts.done, animation.opts.complete )
8766+ .fail( animation.opts.fail )
8767+ .always( animation.opts.always );
8768+}
8769+
8770+function propFilter( props, specialEasing ) {
8771+ var index, name, easing, value, hooks;
8772+
8773+ // camelCase, specialEasing and expand cssHook pass
8774+ for ( index in props ) {
8775+ name = jQuery.camelCase( index );
8776+ easing = specialEasing[ name ];
8777+ value = props[ index ];
8778+ if ( jQuery.isArray( value ) ) {
8779+ easing = value[ 1 ];
8780+ value = props[ index ] = value[ 0 ];
8781+ }
8782+
8783+ if ( index !== name ) {
8784+ props[ name ] = value;
8785+ delete props[ index ];
8786+ }
8787+
8788+ hooks = jQuery.cssHooks[ name ];
8789+ if ( hooks && "expand" in hooks ) {
8790+ value = hooks.expand( value );
8791+ delete props[ name ];
8792+
8793+ // not quite $.extend, this wont overwrite keys already present.
8794+ // also - reusing 'index' from above because we have the correct "name"
8795+ for ( index in value ) {
8796+ if ( !( index in props ) ) {
8797+ props[ index ] = value[ index ];
8798+ specialEasing[ index ] = easing;
8799+ }
8800+ }
8801+ } else {
8802+ specialEasing[ name ] = easing;
8803+ }
8804+ }
8805+}
8806+
8807+jQuery.Animation = jQuery.extend( Animation, {
8808+
8809+ tweener: function( props, callback ) {
8810+ if ( jQuery.isFunction( props ) ) {
8811+ callback = props;
8812+ props = [ "*" ];
8813+ } else {
8814+ props = props.split(" ");
8815+ }
8816+
8817+ var prop,
8818+ index = 0,
8819+ length = props.length;
8820+
8821+ for ( ; index < length ; index++ ) {
8822+ prop = props[ index ];
8823+ tweeners[ prop ] = tweeners[ prop ] || [];
8824+ tweeners[ prop ].unshift( callback );
8825+ }
8826+ },
8827+
8828+ prefilter: function( callback, prepend ) {
8829+ if ( prepend ) {
8830+ animationPrefilters.unshift( callback );
8831+ } else {
8832+ animationPrefilters.push( callback );
8833+ }
8834+ }
8835+});
8836+
8837+function defaultPrefilter( elem, props, opts ) {
8838+ /*jshint validthis:true */
8839+ var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire,
8840+ anim = this,
8841+ style = elem.style,
8842+ orig = {},
8843+ handled = [],
8844+ hidden = elem.nodeType && isHidden( elem );
8845+
8846+ // handle queue: false promises
8847+ if ( !opts.queue ) {
8848+ hooks = jQuery._queueHooks( elem, "fx" );
8849+ if ( hooks.unqueued == null ) {
8850+ hooks.unqueued = 0;
8851+ oldfire = hooks.empty.fire;
8852+ hooks.empty.fire = function() {
8853+ if ( !hooks.unqueued ) {
8854+ oldfire();
8855+ }
8856+ };
8857+ }
8858+ hooks.unqueued++;
8859+
8860+ anim.always(function() {
8861+ // doing this makes sure that the complete handler will be called
8862+ // before this completes
8863+ anim.always(function() {
8864+ hooks.unqueued--;
8865+ if ( !jQuery.queue( elem, "fx" ).length ) {
8866+ hooks.empty.fire();
8867+ }
8868+ });
8869+ });
8870+ }
8871+
8872+ // height/width overflow pass
8873+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
8874+ // Make sure that nothing sneaks out
8875+ // Record all 3 overflow attributes because IE does not
8876+ // change the overflow attribute when overflowX and
8877+ // overflowY are set to the same value
8878+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
8879+
8880+ // Set display property to inline-block for height/width
8881+ // animations on inline elements that are having width/height animated
8882+ if ( jQuery.css( elem, "display" ) === "inline" &&
8883+ jQuery.css( elem, "float" ) === "none" ) {
8884+
8885+ // inline-level elements accept inline-block;
8886+ // block-level elements need to be inline with layout
8887+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
8888+ style.display = "inline-block";
8889+
8890+ } else {
8891+ style.zoom = 1;
8892+ }
8893+ }
8894+ }
8895+
8896+ if ( opts.overflow ) {
8897+ style.overflow = "hidden";
8898+ if ( !jQuery.support.shrinkWrapBlocks ) {
8899+ anim.done(function() {
8900+ style.overflow = opts.overflow[ 0 ];
8901+ style.overflowX = opts.overflow[ 1 ];
8902+ style.overflowY = opts.overflow[ 2 ];
8903+ });
8904+ }
8905+ }
8906+
8907+
8908+ // show/hide pass
8909+ for ( index in props ) {
8910+ value = props[ index ];
8911+ if ( rfxtypes.exec( value ) ) {
8912+ delete props[ index ];
8913+ toggle = toggle || value === "toggle";
8914+ if ( value === ( hidden ? "hide" : "show" ) ) {
8915+ continue;
8916+ }
8917+ handled.push( index );
8918+ }
8919+ }
8920+
8921+ length = handled.length;
8922+ if ( length ) {
8923+ dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
8924+ if ( "hidden" in dataShow ) {
8925+ hidden = dataShow.hidden;
8926+ }
8927+
8928+ // store state if its toggle - enables .stop().toggle() to "reverse"
8929+ if ( toggle ) {
8930+ dataShow.hidden = !hidden;
8931+ }
8932+ if ( hidden ) {
8933+ jQuery( elem ).show();
8934+ } else {
8935+ anim.done(function() {
8936+ jQuery( elem ).hide();
8937+ });
8938+ }
8939+ anim.done(function() {
8940+ var prop;
8941+ jQuery._removeData( elem, "fxshow" );
8942+ for ( prop in orig ) {
8943+ jQuery.style( elem, prop, orig[ prop ] );
8944+ }
8945+ });
8946+ for ( index = 0 ; index < length ; index++ ) {
8947+ prop = handled[ index ];
8948+ tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
8949+ orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
8950+
8951+ if ( !( prop in dataShow ) ) {
8952+ dataShow[ prop ] = tween.start;
8953+ if ( hidden ) {
8954+ tween.end = tween.start;
8955+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
8956+ }
8957+ }
8958+ }
8959+ }
8960+}
8961+
8962+function Tween( elem, options, prop, end, easing ) {
8963+ return new Tween.prototype.init( elem, options, prop, end, easing );
8964+}
8965+jQuery.Tween = Tween;
8966+
8967+Tween.prototype = {
8968+ constructor: Tween,
8969+ init: function( elem, options, prop, end, easing, unit ) {
8970+ this.elem = elem;
8971+ this.prop = prop;
8972+ this.easing = easing || "swing";
8973+ this.options = options;
8974+ this.start = this.now = this.cur();
8975+ this.end = end;
8976+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8977+ },
8978+ cur: function() {
8979+ var hooks = Tween.propHooks[ this.prop ];
8980+
8981+ return hooks && hooks.get ?
8982+ hooks.get( this ) :
8983+ Tween.propHooks._default.get( this );
8984+ },
8985+ run: function( percent ) {
8986+ var eased,
8987+ hooks = Tween.propHooks[ this.prop ];
8988+
8989+ if ( this.options.duration ) {
8990+ this.pos = eased = jQuery.easing[ this.easing ](
8991+ percent, this.options.duration * percent, 0, 1, this.options.duration
8992+ );
8993+ } else {
8994+ this.pos = eased = percent;
8995+ }
8996+ this.now = ( this.end - this.start ) * eased + this.start;
8997+
8998+ if ( this.options.step ) {
8999+ this.options.step.call( this.elem, this.now, this );
9000+ }
9001+
9002+ if ( hooks && hooks.set ) {
9003+ hooks.set( this );
9004+ } else {
9005+ Tween.propHooks._default.set( this );
9006+ }
9007+ return this;
9008+ }
9009+};
9010+
9011+Tween.prototype.init.prototype = Tween.prototype;
9012+
9013+Tween.propHooks = {
9014+ _default: {
9015+ get: function( tween ) {
9016+ var result;
9017+
9018+ if ( tween.elem[ tween.prop ] != null &&
9019+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
9020+ return tween.elem[ tween.prop ];
9021+ }
9022+
9023+ // passing a non empty string as a 3rd parameter to .css will automatically
9024+ // attempt a parseFloat and fallback to a string if the parse fails
9025+ // so, simple values such as "10px" are parsed to Float.
9026+ // complex values such as "rotate(1rad)" are returned as is.
9027+ result = jQuery.css( tween.elem, tween.prop, "auto" );
9028+ // Empty strings, null, undefined and "auto" are converted to 0.
9029+ return !result || result === "auto" ? 0 : result;
9030+ },
9031+ set: function( tween ) {
9032+ // use step hook for back compat - use cssHook if its there - use .style if its
9033+ // available and use plain properties where available
9034+ if ( jQuery.fx.step[ tween.prop ] ) {
9035+ jQuery.fx.step[ tween.prop ]( tween );
9036+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
9037+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
9038+ } else {
9039+ tween.elem[ tween.prop ] = tween.now;
9040+ }
9041+ }
9042+ }
9043+};
9044+
9045+// Remove in 2.0 - this supports IE8's panic based approach
9046+// to setting things on disconnected nodes
9047+
9048+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
9049+ set: function( tween ) {
9050+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
9051+ tween.elem[ tween.prop ] = tween.now;
9052+ }
9053+ }
9054+};
9055+
9056+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9057+ var cssFn = jQuery.fn[ name ];
9058+ jQuery.fn[ name ] = function( speed, easing, callback ) {
9059+ return speed == null || typeof speed === "boolean" ?
9060+ cssFn.apply( this, arguments ) :
9061+ this.animate( genFx( name, true ), speed, easing, callback );
9062+ };
9063+});
9064+
9065+jQuery.fn.extend({
9066+ fadeTo: function( speed, to, easing, callback ) {
9067+
9068+ // show any hidden elements after setting opacity to 0
9069+ return this.filter( isHidden ).css( "opacity", 0 ).show()
9070+
9071+ // animate to the value specified
9072+ .end().animate({ opacity: to }, speed, easing, callback );
9073+ },
9074+ animate: function( prop, speed, easing, callback ) {
9075+ var empty = jQuery.isEmptyObject( prop ),
9076+ optall = jQuery.speed( speed, easing, callback ),
9077+ doAnimation = function() {
9078+ // Operate on a copy of prop so per-property easing won't be lost
9079+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9080+ doAnimation.finish = function() {
9081+ anim.stop( true );
9082+ };
9083+ // Empty animations, or finishing resolves immediately
9084+ if ( empty || jQuery._data( this, "finish" ) ) {
9085+ anim.stop( true );
9086+ }
9087+ };
9088+ doAnimation.finish = doAnimation;
9089+
9090+ return empty || optall.queue === false ?
9091+ this.each( doAnimation ) :
9092+ this.queue( optall.queue, doAnimation );
9093+ },
9094+ stop: function( type, clearQueue, gotoEnd ) {
9095+ var stopQueue = function( hooks ) {
9096+ var stop = hooks.stop;
9097+ delete hooks.stop;
9098+ stop( gotoEnd );
9099+ };
9100+
9101+ if ( typeof type !== "string" ) {
9102+ gotoEnd = clearQueue;
9103+ clearQueue = type;
9104+ type = undefined;
9105+ }
9106+ if ( clearQueue && type !== false ) {
9107+ this.queue( type || "fx", [] );
9108+ }
9109+
9110+ return this.each(function() {
9111+ var dequeue = true,
9112+ index = type != null && type + "queueHooks",
9113+ timers = jQuery.timers,
9114+ data = jQuery._data( this );
9115+
9116+ if ( index ) {
9117+ if ( data[ index ] && data[ index ].stop ) {
9118+ stopQueue( data[ index ] );
9119+ }
9120+ } else {
9121+ for ( index in data ) {
9122+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9123+ stopQueue( data[ index ] );
9124+ }
9125+ }
9126+ }
9127+
9128+ for ( index = timers.length; index--; ) {
9129+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9130+ timers[ index ].anim.stop( gotoEnd );
9131+ dequeue = false;
9132+ timers.splice( index, 1 );
9133+ }
9134+ }
9135+
9136+ // start the next in the queue if the last step wasn't forced
9137+ // timers currently will call their complete callbacks, which will dequeue
9138+ // but only if they were gotoEnd
9139+ if ( dequeue || !gotoEnd ) {
9140+ jQuery.dequeue( this, type );
9141+ }
9142+ });
9143+ },
9144+ finish: function( type ) {
9145+ if ( type !== false ) {
9146+ type = type || "fx";
9147+ }
9148+ return this.each(function() {
9149+ var index,
9150+ data = jQuery._data( this ),
9151+ queue = data[ type + "queue" ],
9152+ hooks = data[ type + "queueHooks" ],
9153+ timers = jQuery.timers,
9154+ length = queue ? queue.length : 0;
9155+
9156+ // enable finishing flag on private data
9157+ data.finish = true;
9158+
9159+ // empty the queue first
9160+ jQuery.queue( this, type, [] );
9161+
9162+ if ( hooks && hooks.cur && hooks.cur.finish ) {
9163+ hooks.cur.finish.call( this );
9164+ }
9165+
9166+ // look for any active animations, and finish them
9167+ for ( index = timers.length; index--; ) {
9168+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
9169+ timers[ index ].anim.stop( true );
9170+ timers.splice( index, 1 );
9171+ }
9172+ }
9173+
9174+ // look for any animations in the old queue and finish them
9175+ for ( index = 0; index < length; index++ ) {
9176+ if ( queue[ index ] && queue[ index ].finish ) {
9177+ queue[ index ].finish.call( this );
9178+ }
9179+ }
9180+
9181+ // turn off finishing flag
9182+ delete data.finish;
9183+ });
9184+ }
9185+});
9186+
9187+// Generate parameters to create a standard animation
9188+function genFx( type, includeWidth ) {
9189+ var which,
9190+ attrs = { height: type },
9191+ i = 0;
9192+
9193+ // if we include width, step value is 1 to do all cssExpand values,
9194+ // if we don't include width, step value is 2 to skip over Left and Right
9195+ includeWidth = includeWidth? 1 : 0;
9196+ for( ; i < 4 ; i += 2 - includeWidth ) {
9197+ which = cssExpand[ i ];
9198+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
9199+ }
9200+
9201+ if ( includeWidth ) {
9202+ attrs.opacity = attrs.width = type;
9203+ }
9204+
9205+ return attrs;
9206+}
9207+
9208+// Generate shortcuts for custom animations
9209+jQuery.each({
9210+ slideDown: genFx("show"),
9211+ slideUp: genFx("hide"),
9212+ slideToggle: genFx("toggle"),
9213+ fadeIn: { opacity: "show" },
9214+ fadeOut: { opacity: "hide" },
9215+ fadeToggle: { opacity: "toggle" }
9216+}, function( name, props ) {
9217+ jQuery.fn[ name ] = function( speed, easing, callback ) {
9218+ return this.animate( props, speed, easing, callback );
9219+ };
9220+});
9221+
9222+jQuery.speed = function( speed, easing, fn ) {
9223+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9224+ complete: fn || !fn && easing ||
9225+ jQuery.isFunction( speed ) && speed,
9226+ duration: speed,
9227+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9228+ };
9229+
9230+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9231+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9232+
9233+ // normalize opt.queue - true/undefined/null -> "fx"
9234+ if ( opt.queue == null || opt.queue === true ) {
9235+ opt.queue = "fx";
9236+ }
9237+
9238+ // Queueing
9239+ opt.old = opt.complete;
9240+
9241+ opt.complete = function() {
9242+ if ( jQuery.isFunction( opt.old ) ) {
9243+ opt.old.call( this );
9244+ }
9245+
9246+ if ( opt.queue ) {
9247+ jQuery.dequeue( this, opt.queue );
9248+ }
9249+ };
9250+
9251+ return opt;
9252+};
9253+
9254+jQuery.easing = {
9255+ linear: function( p ) {
9256+ return p;
9257+ },
9258+ swing: function( p ) {
9259+ return 0.5 - Math.cos( p*Math.PI ) / 2;
9260+ }
9261+};
9262+
9263+jQuery.timers = [];
9264+jQuery.fx = Tween.prototype.init;
9265+jQuery.fx.tick = function() {
9266+ var timer,
9267+ timers = jQuery.timers,
9268+ i = 0;
9269+
9270+ fxNow = jQuery.now();
9271+
9272+ for ( ; i < timers.length; i++ ) {
9273+ timer = timers[ i ];
9274+ // Checks the timer has not already been removed
9275+ if ( !timer() && timers[ i ] === timer ) {
9276+ timers.splice( i--, 1 );
9277+ }
9278+ }
9279+
9280+ if ( !timers.length ) {
9281+ jQuery.fx.stop();
9282+ }
9283+ fxNow = undefined;
9284+};
9285+
9286+jQuery.fx.timer = function( timer ) {
9287+ if ( timer() && jQuery.timers.push( timer ) ) {
9288+ jQuery.fx.start();
9289+ }
9290+};
9291+
9292+jQuery.fx.interval = 13;
9293+
9294+jQuery.fx.start = function() {
9295+ if ( !timerId ) {
9296+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9297+ }
9298+};
9299+
9300+jQuery.fx.stop = function() {
9301+ clearInterval( timerId );
9302+ timerId = null;
9303+};
9304+
9305+jQuery.fx.speeds = {
9306+ slow: 600,
9307+ fast: 200,
9308+ // Default speed
9309+ _default: 400
9310+};
9311+
9312+// Back Compat <1.8 extension point
9313+jQuery.fx.step = {};
9314+
9315+if ( jQuery.expr && jQuery.expr.filters ) {
9316+ jQuery.expr.filters.animated = function( elem ) {
9317+ return jQuery.grep(jQuery.timers, function( fn ) {
9318+ return elem === fn.elem;
9319+ }).length;
9320+ };
9321+}
9322+jQuery.fn.offset = function( options ) {
9323+ if ( arguments.length ) {
9324+ return options === undefined ?
9325+ this :
9326+ this.each(function( i ) {
9327+ jQuery.offset.setOffset( this, options, i );
9328+ });
9329+ }
9330+
9331+ var docElem, win,
9332+ box = { top: 0, left: 0 },
9333+ elem = this[ 0 ],
9334+ doc = elem && elem.ownerDocument;
9335+
9336+ if ( !doc ) {
9337+ return;
9338+ }
9339+
9340+ docElem = doc.documentElement;
9341+
9342+ // Make sure it's not a disconnected DOM node
9343+ if ( !jQuery.contains( docElem, elem ) ) {
9344+ return box;
9345+ }
9346+
9347+ // If we don't have gBCR, just use 0,0 rather than error
9348+ // BlackBerry 5, iOS 3 (original iPhone)
9349+ if ( typeof elem.getBoundingClientRect !== "undefined" ) {
9350+ box = elem.getBoundingClientRect();
9351+ }
9352+ win = getWindow( doc );
9353+ return {
9354+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
9355+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
9356+ };
9357+};
9358+
9359+jQuery.offset = {
9360+
9361+ setOffset: function( elem, options, i ) {
9362+ var position = jQuery.css( elem, "position" );
9363+
9364+ // set position first, in-case top/left are set even on static elem
9365+ if ( position === "static" ) {
9366+ elem.style.position = "relative";
9367+ }
9368+
9369+ var curElem = jQuery( elem ),
9370+ curOffset = curElem.offset(),
9371+ curCSSTop = jQuery.css( elem, "top" ),
9372+ curCSSLeft = jQuery.css( elem, "left" ),
9373+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9374+ props = {}, curPosition = {}, curTop, curLeft;
9375+
9376+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9377+ if ( calculatePosition ) {
9378+ curPosition = curElem.position();
9379+ curTop = curPosition.top;
9380+ curLeft = curPosition.left;
9381+ } else {
9382+ curTop = parseFloat( curCSSTop ) || 0;
9383+ curLeft = parseFloat( curCSSLeft ) || 0;
9384+ }
9385+
9386+ if ( jQuery.isFunction( options ) ) {
9387+ options = options.call( elem, i, curOffset );
9388+ }
9389+
9390+ if ( options.top != null ) {
9391+ props.top = ( options.top - curOffset.top ) + curTop;
9392+ }
9393+ if ( options.left != null ) {
9394+ props.left = ( options.left - curOffset.left ) + curLeft;
9395+ }
9396+
9397+ if ( "using" in options ) {
9398+ options.using.call( elem, props );
9399+ } else {
9400+ curElem.css( props );
9401+ }
9402+ }
9403+};
9404+
9405+
9406+jQuery.fn.extend({
9407+
9408+ position: function() {
9409+ if ( !this[ 0 ] ) {
9410+ return;
9411+ }
9412+
9413+ var offsetParent, offset,
9414+ parentOffset = { top: 0, left: 0 },
9415+ elem = this[ 0 ];
9416+
9417+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
9418+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
9419+ // we assume that getBoundingClientRect is available when computed position is fixed
9420+ offset = elem.getBoundingClientRect();
9421+ } else {
9422+ // Get *real* offsetParent
9423+ offsetParent = this.offsetParent();
9424+
9425+ // Get correct offsets
9426+ offset = this.offset();
9427+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9428+ parentOffset = offsetParent.offset();
9429+ }
9430+
9431+ // Add offsetParent borders
9432+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9433+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9434+ }
9435+
9436+ // Subtract parent offsets and element margins
9437+ // note: when an element has margin: auto the offsetLeft and marginLeft
9438+ // are the same in Safari causing offset.left to incorrectly be 0
9439+ return {
9440+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9441+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
9442+ };
9443+ },
9444+
9445+ offsetParent: function() {
9446+ return this.map(function() {
9447+ var offsetParent = this.offsetParent || document.documentElement;
9448+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
9449+ offsetParent = offsetParent.offsetParent;
9450+ }
9451+ return offsetParent || document.documentElement;
9452+ });
9453+ }
9454+});
9455+
9456+
9457+// Create scrollLeft and scrollTop methods
9458+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
9459+ var top = /Y/.test( prop );
9460+
9461+ jQuery.fn[ method ] = function( val ) {
9462+ return jQuery.access( this, function( elem, method, val ) {
9463+ var win = getWindow( elem );
9464+
9465+ if ( val === undefined ) {
9466+ return win ? (prop in win) ? win[ prop ] :
9467+ win.document.documentElement[ method ] :
9468+ elem[ method ];
9469+ }
9470+
9471+ if ( win ) {
9472+ win.scrollTo(
9473+ !top ? val : jQuery( win ).scrollLeft(),
9474+ top ? val : jQuery( win ).scrollTop()
9475+ );
9476+
9477+ } else {
9478+ elem[ method ] = val;
9479+ }
9480+ }, method, val, arguments.length, null );
9481+ };
9482+});
9483+
9484+function getWindow( elem ) {
9485+ return jQuery.isWindow( elem ) ?
9486+ elem :
9487+ elem.nodeType === 9 ?
9488+ elem.defaultView || elem.parentWindow :
9489+ false;
9490+}
9491+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9492+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9493+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9494+ // margin is only for outerHeight, outerWidth
9495+ jQuery.fn[ funcName ] = function( margin, value ) {
9496+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9497+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9498+
9499+ return jQuery.access( this, function( elem, type, value ) {
9500+ var doc;
9501+
9502+ if ( jQuery.isWindow( elem ) ) {
9503+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9504+ // isn't a whole lot we can do. See pull request at this URL for discussion:
9505+ // https://github.com/jquery/jquery/pull/764
9506+ return elem.document.documentElement[ "client" + name ];
9507+ }
9508+
9509+ // Get document width or height
9510+ if ( elem.nodeType === 9 ) {
9511+ doc = elem.documentElement;
9512+
9513+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
9514+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
9515+ return Math.max(
9516+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9517+ elem.body[ "offset" + name ], doc[ "offset" + name ],
9518+ doc[ "client" + name ]
9519+ );
9520+ }
9521+
9522+ return value === undefined ?
9523+ // Get width or height on the element, requesting but not forcing parseFloat
9524+ jQuery.css( elem, type, extra ) :
9525+
9526+ // Set width or height on the element
9527+ jQuery.style( elem, type, value, extra );
9528+ }, type, chainable ? margin : undefined, chainable, null );
9529+ };
9530+ });
9531+});
9532+// Limit scope pollution from any deprecated API
9533+// (function() {
9534+
9535+// })();
9536+// Expose jQuery to the global object
9537+window.jQuery = window.$ = jQuery;
9538+
9539+// Expose jQuery as an AMD module, but only for AMD loaders that
9540+// understand the issues with loading multiple versions of jQuery
9541+// in a page that all might call define(). The loader will indicate
9542+// they have special allowances for multiple jQuery versions by
9543+// specifying define.amd.jQuery = true. Register as a named module,
9544+// since jQuery can be concatenated with other files that may use define,
9545+// but not use a proper concatenation script that understands anonymous
9546+// AMD modules. A named AMD is safest and most robust way to register.
9547+// Lowercase jquery is used because AMD module names are derived from
9548+// file names, and jQuery is normally delivered in a lowercase file name.
9549+// Do this after creating the global so that if an AMD module wants to call
9550+// noConflict to hide this version of jQuery, it will work.
9551+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9552+ define( "jquery", [], function () { return jQuery; } );
9553+}
9554+
9555+})( window );
--- a/secured/chat.xhtml
+++ b/secured/chat.xhtml
@@ -6,7 +6,6 @@
66
77 <ui:composition
88 template="/WEB-INF/templates/moto-template.xhtml"
9- xmlns:p="http://primefaces.org/ui"
109 >
1110 <ui:define name="pageTitle">jsf chat app</ui:define>
1211
@@ -59,7 +58,7 @@
5958 //]]>
6059 </script>
6160
62-<p:socket onMessage="handleMessage" channel="/#{chatBean.chatRoom}" />
61+<!--p:socket onMessage="handleMessage" channel="/#{chatBean.chatRoom}" / -->
6362
6463 </ui:define>
6564