ProvideSupport_Live_Chat - Version 1.0.0

Version Notes

First public release

Download this release

Release Info

Developer Provide Support, LLC
Extension ProvideSupport_Live_Chat
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

app/code/community/ProvideSupport/Livechat/Block/Help.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class ProvideSupport_Livechat_Block_Help extends Mage_Core_Block_Template
3
+ {
4
+ protected function _toHtml()
5
+ {
6
+
7
+ return '
8
+ <style type="text/css">
9
+ .help {
10
+ line-height: 18px;
11
+ }
12
+ .help h3{
13
+ padding: 5px 0 5px 0;
14
+ background: none repeat scroll 0 0 #6F8992;
15
+ color: #FFFFFF;
16
+ font-size: 16px;
17
+ font-weight: bold;
18
+ text-align: center;
19
+ margin: 20px 0 20px 0;
20
+
21
+ }
22
+ </style>
23
+
24
+ <div class="help">
25
+
26
+ <span style="font-weight:normal">Magento Live Chat module from </span><a href="http://www.providesupport.com/?utm_source=magento-plugin&amp;utm_medium=help&amp;utm_campaign=Plugins" target="_blank"><span><span style="font-weight:normal;text-decoration:underline">Provide Support, LLC</span></span></a><span style="font-weight:normal"> lets you integrate live chat tool with your Magneto based website
27
+ fast and without taking much effort. The integration is quite simple
28
+ but at the same time offers flexible settings which will give you an
29
+ opportunity to customize the appearance of the live chat tool on your
30
+ website according to your requirements. Should you have any questions
31
+ or need assistance with integration, please refer to below FAQ, Provide
32
+ Support </span><a href="http://www.providesupport.com/manual/index.html" target="_blank"><span><span style="font-weight:normal;text-decoration:underline">User Manual</span></span></a><span style="font-weight:normal"> or request assistance in Provide Support&#39;s 24/7 tech support chat,
33
+ which you can access by clicking </span><a href="http://messenger.providesupport.com/messenger/providesupport.html?source=magento-module-help" target="_blank"><span><span style="font-weight:normal;text-decoration:underline">this link</span></span></a><span style="font-weight:normal">. </span></h3>
34
+ <h3>Is Provide Support Live Chat Module for Magento
35
+ free?</h3>
36
+ <p>Our live chat module for Magento is free. But
37
+ it can only be used as a part of Provide Support Live Chat system which
38
+ is offered on a subscription basis. We offer free fully functional 10-day
39
+ trial to check if the system fits your requirements. If you like the
40
+ system, you are welcome to purchase a subscription. Please have a look
41
+ at our <a href="http://www.providesupport.com/prices/index.html?utm_source=magento-plugin&amp;utm_medium=help&amp;utm_campaign=Plugins" target="_blank"><span><span style="text-decoration:underline">pricing</span></span></a>.</p>
42
+ <h3>My chat is Offline. Why?</h3>
43
+ <p>Your live chat will switch to Online automatically
44
+ once you login into your Operator Console. The Operator Console is available
45
+ for downloading at <a href="http://www.providesupport.com/downloads/index.html?utm_source=magento-plugin&amp;utm_medium=help&amp;utm_campaign=Plugins" target="_blank"><span><span style="text-decoration:underline">http://www.providesupport.com/<WBR>downloads/index.html</span></span></a>,
46
+ its web-based version is available at <a href="http://operator.providesupport.com/" target="_blank"><span><span style="text-decoration:underline">http://operator.<WBR>providesupport.com</span></span></a>.</p>
47
+ <h3>I selected the position but my chat button does not appear.</h3>
48
+
49
+ <p>In Magento you get the list of all available positions,
50
+ you need to choose the position available for your theme for the chat
51
+ button to appear.</p>
52
+ <h3>Where can I get my login details for Operator
53
+ Console?</h3>
54
+ <p>Your operator login credentials are available
55
+ in your account Control Panel, Operators and Departments page.</p>
56
+ <h3>Where can I get more information about your
57
+ live chat system?</h3>
58
+ <p>Please check <a href="http://www.providesupport.com/features/index.html?utm_source=magento-plugin&amp;utm_medium=help&amp;utm_campaign=Plugins" target="_blank"><span><span style="text-decoration:underline">Features</span></span></a> and <a href="http://www.providesupport.com/screenshots/index.html?utm_source=magento-plugin&amp;utm_medium=help&amp;utm_campaign=Plugins" target="_blank"><span><span style="text-decoration:underline">Screenshots</span></span></a> pages on our website. In addition we
59
+ run <a href="http://www.providesupport.com/blog/" target="_blank"><span><span style="text-decoration:underline">Blog</span></span></a> where you will find lots of useful information
60
+ for delivering high quality customer service.</p>
61
+ <p> </p>
62
+ <h3>I see that your live chat system has a rich set of features, are they
63
+ available for Magento module?</h3>
64
+ <p>Sure, you can access and customize your account
65
+ in your account Control Panel, just log into it on <a href="http://www.providesupport.com/?utm_source=magento-plugin&amp;utm_medium=help&amp;utm_campaign=Plugins" target="_blank"><span><span style="text-decoration:underline">http://www.providesupport.com/</span></span></a> website with your
66
+ credentials (account name and account password you used to register).</p>
67
+ <h3>Is there a user manual I can check?</h3>
68
+ <p>Sure. Our user manual is available at <a href="http://www.providesupport.com/manual/index.html" target="_blank"><span><span style="text-decoration:underline">http://www.providesupport.com/<WBR>manual/</span></span></a>. Please also
69
+ check our <a href="http://www.providesupport.com/home/faq.html?utm_source=magento-plugin&amp;utm_medium=help&amp;utm_campaign=Plugins" target="_blank"><span><span style="text-decoration:underline">FAQ</span></span></a>.</p>
70
+ <h3>I haven&#39;t found information I need on your
71
+ website. Do you provide any live support along with your system?</h3>
72
+ <p>Sure, our customer support chat is online 24/7.
73
+ Please click <a href="http://messenger.providesupport.com/messenger/providesupport.html?source=magento-module-help" target="_blank"><span><span style="text-decoration:underline">this</span></span><span><span style="text-decoration:underline"> link</span></span></a> to ask your questions right now. </p>
74
+ </div>
75
+ ';
76
+
77
+ }
78
+ }
app/code/community/ProvideSupport/Livechat/Block/Settings.php ADDED
@@ -0,0 +1,449 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class ProvideSupport_Livechat_Block_Settings extends Mage_Core_Block_Template
3
+ {
4
+ private function addProvideCss()
5
+ {
6
+ $css = '
7
+ <style type="text/css">
8
+ /*
9
+ * Developed by Ortus IT.
10
+ * Web: http://ortus-it.com
11
+ * Code part:#02-01-rev.004, October 2013.
12
+ * -All Rights of this product are belong to Provide Support, LLC.-
13
+ *
14
+ */
15
+ *{
16
+ padding: 0;
17
+ margin: 0;
18
+ }
19
+ .novalid {
20
+ border-color: tomato !important;
21
+ border-width: 1px;
22
+ }
23
+ .novalidButton{background-color:tomato !important;}
24
+ #f7main {
25
+ background: none repeat scroll 0 0 #FAFAFA;
26
+ border: 1px solid #D6D6D6;
27
+
28
+ }
29
+ #f7main #f7title,
30
+ #f7main #f7message,
31
+ #f7main #f7settings,
32
+ #f7main #f7account,
33
+ #f7main #f7accountInfo {
34
+ width: 60%;
35
+ margin-top: 5px;
36
+ /*margin-left: 20px;*/
37
+ margin: 5px auto;
38
+ text-align: center;
39
+ padding-top: 5px;
40
+ padding-bottom: 5px;
41
+ border-radius:3px;
42
+ }
43
+ #f7main #f7title {
44
+ border: 1px solid lightgrey;
45
+ }
46
+ #f7main #f7message {
47
+ display: none;
48
+ color: darkgreen;
49
+ border: 1px solid darkgreen;
50
+ background-color: #caffca;
51
+ }
52
+ #f7main .f7warning {
53
+ color: darkred !important;
54
+ border: 1px solid darkred !important;
55
+ background-color: #fff1f1 !important;
56
+ }
57
+ #f7main #f7account {
58
+ text-align:left;
59
+ position:relative;
60
+ }
61
+ #f7main #f7account #f7buttonE,
62
+ #f7main #f7account #f7buttonN{
63
+ display:inline-block;
64
+ width:110px;height:25px;
65
+ line-height:25px;
66
+ background-color:#6F8992;
67
+ text-align:center;
68
+ border-top:1px solid #6F8992;
69
+ border-left:1px solid #6F8992;
70
+ border-right:1px solid #6F8992;
71
+ border-bottom:1px solid #6F8992;
72
+ position:relative;
73
+ top:1px;
74
+ left:30px;
75
+ z-index:100;
76
+ cursor:pointer;
77
+ color:white;
78
+ }
79
+ .f7buttonNoBorder{color:black !important;border-bottom:1px solid white !important;background-color:white !important;}
80
+ #f7main #f7account #f7buttonN{border-left:none;}
81
+ #f7main #f7account #f7accountE{
82
+ width:600px;
83
+ border-top: 1px solid black;
84
+ z-index:1;
85
+ position:relative;
86
+ }
87
+ #f7main #f7account #f7accountE .f7fields{
88
+ margin-top:10px;
89
+ position:relative;
90
+ width:100%;
91
+ height:20px;
92
+ }
93
+ #f7main #f7account #f7accountE .f7fields .f7label,
94
+ #f7main #f7account #f7accountE .f7fields .f7field{
95
+ position:absolute;
96
+ }
97
+ #f7main #f7account #f7accountE .f7fields .f7label{
98
+ top:4px;
99
+ left:11%;
100
+ }
101
+ #f7main #f7account #f7accountE .f7fields .f7field{
102
+ left:51%;
103
+ width:220px;
104
+ }
105
+ #f7main #f7account #f7accountE .f7fields .f7field input{
106
+ width:100%;
107
+ }
108
+ #f7main #f7account #f7accountE .f7fields .f7field #f7accountSubmit,#f7anotherAccount{
109
+ width:219px;
110
+ height:25px;
111
+ line-height:25px;
112
+ text-align:center;
113
+ font-weight:bold;
114
+ border:1px solid #6F8992;
115
+ border-radius:3px;
116
+ background-color: #6F8992;
117
+ cursor:pointer;
118
+ opacity:.8;
119
+ color:white;
120
+ }
121
+ #f7main #f7account #f7accountE .f7fields .f7field #f7accountSubmit:hover{opacity:1;}
122
+ #f7anotherAccount:hover{opacity:1;}
123
+ #f7main #f7settings {
124
+ position: relative;
125
+ text-align: left;
126
+ }
127
+ #f7main #f7settings input {
128
+ margin-right: 3px;
129
+ }
130
+ #f7main #f7settings .setting {
131
+ padding-top: 5px;
132
+ margin-left: 30px;
133
+ }
134
+ #f7main #f7settings .setting .settingInt {
135
+ padding-top: 5px;
136
+ margin-left: 25px;
137
+ }
138
+ #f7main #f7settings .setting .settingInt .f7part1,
139
+ #f7main #f7settings .setting .settingInt .f7part2,
140
+ #f7main #f7settings .setting .settingInt .f7part3,
141
+ #f7main #f7settings .setting .settingInt .f7part4 {
142
+ display: inline-block;
143
+ margin-left: 8px;
144
+ }
145
+ #f7main #f7settings .setting .settingInt .f7part1 {
146
+ width: 65px;
147
+ }
148
+ #f7main #f7settings .setting .settingInt .f7part3,
149
+ #f7main #f7settings .setting .settingInt .f7part4 {
150
+ position: relative;
151
+ top: 8px;
152
+ }
153
+ #f7main #f7settings .setting .settingInt #selectPagesMenus #selectPostMenus {
154
+ margin-left: 20px;
155
+ position: relative;
156
+ width: 250px;
157
+ height: auto;
158
+ padding: 0 0 0 20px;
159
+ }
160
+
161
+ #f7main #f7settings .setting .settingInt #f7pagesSubmit {
162
+ width: 50%;
163
+ margin: 2px auto;
164
+ height: 18px;
165
+ background-color: darkgreen;
166
+ border-radius: 10px;
167
+ text-align: center;
168
+ color: white;
169
+ font-weight: bold;
170
+ cursor: pointer;
171
+ }
172
+ #f7main #f7settings .setting .settingInt .settingIntInt {
173
+ padding-top: 5px;
174
+ margin-left: 25px;
175
+ }
176
+ #f7main #f7settings #f7livePreview {
177
+ position: absolute;
178
+ padding-bottom:0px;
179
+ width: auto;
180
+ height: auto;
181
+ top: 10px;
182
+ right: 30px;
183
+ border-radius:3px;
184
+ color:darkgrey;
185
+ }
186
+ #f7main #f7settings .f7separator{
187
+ position:relative;
188
+ width:450px;
189
+ border-bottom:1px solid darkgrey;
190
+ margin-top:15px;
191
+ margin-bottom:7px;
192
+ }
193
+ #f7main #f7settings .f7separator .f7inner{
194
+ position:absolute;
195
+ top:-9px;right:25px;
196
+ padding: 1px 4px;
197
+ background-color:white;
198
+ font-weight:bold;
199
+ }
200
+ #f7main #f7submit{
201
+ width:100px;
202
+ background-color: #6F8992 ;
203
+ margin: 15px auto;
204
+ padding:3px;
205
+ border-radius:10px;
206
+ text-align:center;
207
+ font-weight:bold;
208
+ color:white;
209
+ opacity:.9;
210
+ }
211
+ #f7main #f7submit:hover{opacity:1;}
212
+ .f7r{margin-right:2px !important;margin-left:1px !important;}
213
+
214
+ #selectPagesMenus label {
215
+ font-size: 1em;
216
+ margin-top: 5px;
217
+ margin-bottom: 0px;
218
+ }
219
+ #selectPagesMenus input {
220
+ margin: 2px 0 0 8px;
221
+ }
222
+ .menus-header{
223
+ color: #999999;
224
+ display: block;
225
+ font-size: 11px;
226
+ font-weight: bold;
227
+ padding: 3px 6px;
228
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
229
+ text-transform: uppercase;
230
+ }
231
+ #selectedBlock{
232
+ margin: 10px 0;
233
+ border-color: #6F8992;
234
+ }
235
+ </style>';
236
+ return $css;
237
+ }
238
+ protected function _toHtml()
239
+ {
240
+ $html = '<script>var urlAjax = "' . Mage::getUrl('') . 'livechat/admin/ajax/?isAjax=true";</script>';
241
+ $html .= $this->addProvideCss() . ' <div id="f7main">';
242
+ $html .= '<div id="f7title">';
243
+ $html .= 'Welcome to Provide Support Live Chat module settings page.<br/>Visit our website <a href="http://www.providesupport.com" target="_blank">www.providesupport.com</a> to find more information about our Live Chat system.';
244
+ $html .= '</div>';
245
+ $html .= '<div id="f7message">';
246
+ $html .= '';
247
+ $html .= '</div>';
248
+ $html .= '<div id="f7accountInfo"></div>';
249
+ $html .= '<div id="f7account">';
250
+ $html .= '<div id="f7buttonE" class="f7buttonNoBorder">Existing Account</div>';
251
+ $html .= '<div id="f7buttonN">New account</div>';
252
+ $html .= '<div id="f7accountE">';
253
+ $html .= '<div class="f7fields">';
254
+ $html .= '<div class="f7label">';
255
+ $html .= 'Your Provide Support account name:';
256
+ $html .= '</div>';
257
+ $html .= '<div class="f7field">';
258
+ $html .= '<input type="text">';
259
+ $html .= '</div>';
260
+ $html .= '</div>';
261
+ $html .= '<div class="f7fields">';
262
+ $html .= '<div class="f7label">';
263
+ $html .= 'Your Provide Support account password:';
264
+ $html .= '</div>';
265
+ $html .= '<div class="f7field">';
266
+ $html .= '<input type="password">';
267
+ $html .= '</div>';
268
+ $html .= '</div>';
269
+ $html .= '<div class="f7fields" style="display:none">';
270
+ $html .= '<div class="f7label">';
271
+ $html .= 'Your email:';
272
+ $html .= '</div>';
273
+ $html .= '<div class="f7field">';
274
+ $html .= '<input type="email">';
275
+ $html .= '</div>';
276
+ $html .= '</div>';
277
+ $html .= '<div class="f7fields">';
278
+ $html .= '<div class="f7field">';
279
+ $html .= '<div id="f7accountSubmit">Connect to Account</div>';
280
+ $html .= '</div>';
281
+ $html .= '</div>';
282
+ $html .= '</div>';
283
+ $html .= '</div>';
284
+ $html .= '<div id="f7settings" style="display:none">';
285
+ $html .= '<div id="f7livePreview"></div>';
286
+ $html .= '<div class="setting f7control">';
287
+ $html .= '<input type="checkbox" id="f7pluginEnabled">Enable live chat module';
288
+ $html .= '</div>';
289
+ $html .= '<div class="f7separator"><div class="f7inner">Select chat button type</div></div>';
290
+ $html .= '<div class="setting">';
291
+ $html .= '<input type="radio" name="buttonAppearance" id="buttonImageType" class="f7button1">Graphics chat button';
292
+ $html .= '<div class="settingInt">';
293
+ $html .= '<input type="radio" name="customImages" id="buttonImageSource" class="f7button3">Use images selected in your account setings';
294
+ $html .= '<div class="settingIntInt" style="width:240px;">';
295
+ $html .= 'Images uploaded to Account Settings / Images page of your Provide Support account Control Panel will be used';
296
+ $html .= '</div>';
297
+ $html .= '</div>';
298
+ $html .= '<div class="settingInt">';
299
+ $html .= '<input type="radio" name="customImages" class="f7button4">Use custom images';
300
+ $html .= '<div class="settingIntInt">';
301
+ $html .= 'Online image URL <input type="text" id="buttonImageUrlOnline">';
302
+ $html .= '</div>';
303
+ $html .= '<div class="settingIntInt">';
304
+ $html .= 'Offline image URL <input type="text" id="buttonImageUrlOffline">';
305
+ $html .= '</div>';
306
+ $html .= '<div class="settingIntInt" style="width:236px;margin:5px 0 5px 27px;font-size:10px;line-height:10px;">';
307
+ $html .= 'You can specify here actual links to images stored on your server. If you use your Live Chat account on several websites, this feature lets you display your custom chat icons, different from the ones uploaded to your Provide Support account ';
308
+ $html .= '</div>';
309
+ $html .= '</div>';
310
+ $html .= '</div>';
311
+ $html .= '<div class="setting">';
312
+ $html .= '<input type="radio" class="f7button2" name="buttonAppearance">Text chat link';
313
+ $html .= '<div class="settingInt">';
314
+ $html .= 'Online Chat Link text <input type="text" id="buttonImageTextOnline">';
315
+ $html .= '</div>';
316
+ $html .= '<div class="settingInt">';
317
+ $html .= 'Offline Chat Link text <input type="text" id="buttonImageTextOffline">';
318
+ $html .= '</div>';
319
+ $html .= '<div class="settingInt" style="width:236px;margin-left:39px;font-size:11px;line-height:10px;">';
320
+ $html .= 'HTML formatting is supported for Chat Link texts';
321
+ $html .= '</div>';
322
+ $html .= '</div>';
323
+ $html .= '<div class="f7separator"><div class="f7inner">Chat button position</div></div>';
324
+ $html .= '<div class="setting">';
325
+ $html .= '<input type="radio" location="define" name="buttonLocation">Show Chat Button in selected for a module position';
326
+ $html .= '<div class="settingInt" style="width:300px;font-size:12px;line-height:13px;">';
327
+ $html .= '<div style="text-align: justify;">Your Live Chat button will be displayed according to the module position selected from the below drop down list. <b style="color:red;">Please note!</b> The position should be available with your Magento theme, otherwise the chat button will not be displayed</div>';
328
+ $html .= $this->getMenu();
329
+ $html .= '</div>';
330
+ $html .= '</div>';
331
+ $html .= '<div class="setting">';
332
+ $html .= '<input type="radio" location="fixed" name="buttonLocation">Show Сhat Button at a fixed position on the browser window';
333
+ $html .= '<div class="settingInt" style=" padding-top: 0px; ">';
334
+ $html .= '<div class="f7part1">';
335
+ $html .= 'Vertical';
336
+ $html .= '</div>';
337
+ $html .= '<div class="f7part2">';
338
+ $html .= '<input type="text" id="buttonLocationVerticalValue" value=50>';
339
+ $html .= '</div>';
340
+ $html .= '<div class="f7part3">';
341
+ $html .= '<input type="radio" class="f7button5" name="specVerticalPx" id="buttonLocationVerticalBy">px';
342
+ $html .= '<br />';
343
+ $html .= '<input type="radio" class="f7button6" name="specVerticalPx" checked>%';
344
+ $html .= '</div>';
345
+ $html .= '<div class="f7part4">';
346
+ $html .= '<input type="radio" class="f7button9" name="specVerticalFrom" id="buttonLocationVerticalFrom">from top';
347
+ $html .= '<br />';
348
+ $html .= '<input type="radio" class="f7button10" name="specVerticalFrom" checked>from bottom';
349
+ $html .= '</div>';
350
+ $html .= '</div>';
351
+ $html .= '<div class="settingInt" style=" padding-top: 0px; ">';
352
+ $html .= '<div class="f7part1">';
353
+ $html .= 'Horizontal';
354
+ $html .= '</div>';
355
+ $html .= '<div class="f7part2">';
356
+ $html .= '<input type="text" id="buttonLocationHorizontalValue" value=0>';
357
+ $html .= '</div>';
358
+ $html .= '<div class="f7part3">';
359
+ $html .= '<input type="radio" class="f7button7" name="specHorizontalPx" id="buttonLocationHorizontalBy">px';
360
+ $html .= '<br />';
361
+ $html .= '<input type="radio" class="f7button8" name="specHorizontalPx" checked>%';
362
+ $html .= '</div>';
363
+ $html .= '<div class="f7part4">';
364
+ $html .= '<input type="radio" class="f7button11" name="specHorizontalFrom" id="buttonLocationHorizontalFrom">from left';
365
+ $html .= '<br />';
366
+ $html .= '<input type="radio" class="f7button12" name="specHorizontalFrom" checked>from right';
367
+ $html .= '</div>';
368
+ $html .= '</div>';
369
+ $html .= '<div class="settingInt" style="width:253px;margin-left:64px;">';
370
+ $html .= 'Specify vertical and horizontal position in pixels or percent for your Chat Button';
371
+ $html .= '</div>';
372
+ $html .= '</div>';
373
+ $html .= '<div class="f7separator"><div class="f7inner shortcodeSeparator">Display chat button at</div></div>';
374
+ $html .= '<div class="setting">';
375
+ $html .= '<input type="checkbox" id="buttonAvailableAll">All predefined Magento store pages';
376
+ $html .= '</div>';
377
+ $html .= '<div class="setting selectPostToggle">';
378
+ $html .= '<input type="checkbox" id="buttonAvailablePost">Single Posts created in CMS/Pages:';
379
+ $html .= '<div class="settingInt">';
380
+ $html .= '<input type="radio" class="f7button15" name="optionPost" id="buttonAvailablePostWhich">All';
381
+ $html .= '</div>';
382
+ $html .= '<div class="settingInt">';
383
+ $html .= '<input type="radio" class="f7button16" name="optionPost">Selected';
384
+ $html .= $this->getPage();
385
+ $html .= '</div>';
386
+ $html .= '</div>';
387
+ $html .= '<div class="setting">';
388
+ $html .= '<input type="checkbox" id="buttonAvailableWhole">Monitor the whole website';
389
+ $html .= '</div>';
390
+ $html .= '</div>';
391
+ $html .= '<div id="f7wait" style="margin:4px auto;width:33px;"></div>';
392
+ $html .= '<div id="f7submit" style="cursor:pointer;display:none;">UPDATE</div>';
393
+ $html .= '</div>';
394
+ return $html;
395
+ }
396
+ private function getPage()
397
+ {
398
+ $store = Mage::app()->getStore('default');
399
+ $cms_pages = Mage::getModel('cms/page')->getCollection();
400
+ $cms_pages->addStoreFilter($store);
401
+ $cms_pages->load();
402
+ $count = count($cms_pages);
403
+ if ($count > 0) {
404
+ $div_post = '<div id="selectPostMenus" style="padding: 0 0 0 15px;">';
405
+ foreach ($cms_pages as $_page) {
406
+ $data = $_page->getData();
407
+ if ($data['is_active'] == 0) {
408
+ $published = '<span style="color:grey;">' . $data['title'] . ' (Disabled) </span>';
409
+ $disabled = 'disabled';
410
+ $strike = $published;
411
+ } else {
412
+ $published = $data['title'];
413
+ $disabled = '';
414
+ $strike = $published;
415
+ }
416
+ $div_post .= '<input type="checkbox" ' . $disabled . ' postid="' . $data['page_id'] . '">' . $strike . '<br />';
417
+ }
418
+ $div_post .= '</div>';
419
+ return $div_post;
420
+ }
421
+ }
422
+ protected function getMenu()
423
+ {
424
+ $layout = '';//'default,catalog_category_layered,catalog_product_view';
425
+ //$layout = 'default,catalog_category_layered,catalog_product_view,PRODUCT_TYPE_simple,PRODUCT_TYPE_grouped,PRODUCT_TYPE_configurable,PRODUCT_TYPE_virtual,PRODUCT_TYPE_bundle,PRODUCT_TYPE_downloadable';
426
+ $blocksChooser = $this->getLayout()->createBlock('widget/adminhtml_widget_instance_edit_chooser_block')->setLayoutHandle($layout);
427
+ $option = $blocksChooser->toHtml();
428
+ $div_menu = '<div id="selectPagesMenus">';
429
+ $div_menu .= '<select id="selectedBlock">';
430
+ $div_menu .= $this->getParseOptions($option);
431
+ //$additional_blocks = $this->getLayout()->createBlock('widget/adminhtml_widget_instance_edit_chooser_layout');
432
+ //$option = $additional_blocks->toHtml();
433
+ //$div_menu .= $this->getParseOptions($option);
434
+ $div_menu .= '</select>';
435
+ $div_menu .= '</div>';
436
+ return $div_menu;
437
+ }
438
+ function getParseOptions($option)
439
+ {
440
+ preg_match_all('/<option value="([^"]*)" >([^>]*)<\/option>/', $option, $option_value);
441
+ $count = count($option_value[1]);
442
+ if ($count > 0) {
443
+ for ($i = 1; $i < $count; $i++) {
444
+ $div_menu .= '<option value="' . $option_value[1][$i] . '">' . $option_value[2][$i] . '</option>';
445
+ }
446
+ }
447
+ return $div_menu;
448
+ }
449
+ }
app/code/community/ProvideSupport/Livechat/Helper/Data.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class ProvideSupport_Livechat_Helper_Data extends Mage_Core_Helper_Abstract
3
+ {
4
+ public function initJs()
5
+ {
6
+ $this->page = Mage::getSingleton('cms/page');
7
+ $this->list_page = Zend_Json::decode($this->settings, Zend_Json::TYPE_OBJECT);
8
+ }
9
+ public function initCode($view)
10
+ {
11
+ $this->settings = $view->settings;
12
+ $this->code = $view->code;
13
+ $this->hiddencode = $view->hiddencode;
14
+ $this->setJsCode();
15
+ }
16
+ public function showModuleCode()
17
+ {
18
+ echo '<div class="f7x">' . $this->code . '</div><script type="text/javascript">console.log("ProvideSupport : chat button code loaded");</script>';
19
+ }
20
+ public function showModuleHiddenCode()
21
+ {
22
+ echo '<div class="f7x">' . $this->hiddencode . '</div><script type="text/javascript">console.log("ProvideSupport : hidden monitoring code loaded");</script>';
23
+ }
24
+ public function showModuleJsCode()
25
+ {
26
+ echo $this->setJavaScript($this->jsCode . ' showChat(f7php.code); console.log(BUTTONTEXT); ');
27
+ }
28
+ public function showModuleJsHiddenCode()
29
+ {
30
+ echo $this->setJavaScript($this->jsCode . ' showChat(f7php.hiddencode); console.log(HIDDENTEXT); ');
31
+ }
32
+ public function showInAllCode($pos = '')
33
+ {
34
+ if (!$this->page->getId()) {
35
+ switch ($pos) {
36
+ case 'fixed':
37
+ $this->showModuleJsCode();
38
+ break;
39
+ case 'define':
40
+ $this->showModuleCode();
41
+ break;
42
+ default:
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ public function showInAllHiddenCode($pos = '')
48
+ {
49
+ if (!$this->page->getId()) {
50
+ if ($this->list_page->buttonAvailableWhole) {
51
+ switch ($pos) {
52
+ case 'fixed':
53
+ $this->showModuleJsHiddenCode();
54
+ break;
55
+ case 'define':
56
+ $this->showModuleHiddenCode();
57
+ break;
58
+ default:
59
+ break;
60
+ }
61
+ }
62
+ }
63
+ }
64
+ public function showAllPageCode($pos = '')
65
+ {
66
+ if ($this->page->getId()) {
67
+ switch ($pos) {
68
+ case 'fixed':
69
+ $this->showModuleJsCode();
70
+ break;
71
+ case 'define':
72
+ $this->showModuleCode();
73
+ break;
74
+ default:
75
+ break;
76
+ }
77
+ }
78
+ }
79
+ public function showAllPageHiddenCode($pos = '')
80
+ {
81
+ if ($this->page->getId()) {
82
+ if ($this->list_page->buttonAvailableWhole) {
83
+ switch ($pos) {
84
+ case 'fixed':
85
+ $this->showModuleJsHiddenCode();
86
+ break;
87
+ case 'define':
88
+ $this->showModuleHiddenCode();
89
+ break;
90
+ default:
91
+ break;
92
+ }
93
+ }
94
+ }
95
+ }
96
+ public function showSelectedPageCode($pos = '')
97
+ {
98
+ if (is_array($this->list_page->buttonAvailablePostList) && count($this->list_page->buttonAvailablePostList) > 0 && in_array($this->page->getId(), $this->list_page->buttonAvailablePostList)) {
99
+ switch ($pos) {
100
+ case 'fixed':
101
+ $this->showModuleJsCode();
102
+ break;
103
+ case 'define':
104
+ $this->showModuleCode();
105
+ break;
106
+ default:
107
+ break;
108
+ }
109
+ } else {
110
+ if ($this->list_page->buttonAvailableWhole && $this->page->getId()) {
111
+ switch ($pos) {
112
+ case 'fixed':
113
+ $this->showModuleJsHiddenCode();
114
+ break;
115
+ case 'define':
116
+ $this->showModuleHiddenCode();
117
+ break;
118
+ default:
119
+ break;
120
+ }
121
+ }
122
+ }
123
+ }
124
+ public function setJavaScript($message)
125
+ {
126
+ $javascript = '
127
+ <script type="text/javascript">
128
+ (function ()
129
+ {
130
+ // Localize jQuery variable
131
+ var jQuery;
132
+ /******** Load jQuery if not present *********/
133
+ if(window.jQuery === undefined || window.jQuery.fn.jquery !== "1.4.2")
134
+ {
135
+ var script_tag = document.createElement("script");
136
+ script_tag.setAttribute("type", "text/javascript");
137
+ script_tag.setAttribute("src",
138
+ "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js");
139
+ if(script_tag.readyState)
140
+ {
141
+ script_tag.onreadystatechange = function ()
142
+ { // For old versions of IE
143
+ if(this.readyState == "complete" || this.readyState == "loaded")
144
+ {
145
+ scriptLoadHandler();
146
+ }
147
+ };
148
+ }
149
+ else
150
+ { // Other browsers
151
+ script_tag.onload = scriptLoadHandler;
152
+ }
153
+ // Try to find the head, otherwise default to the documentElement
154
+ (document.getElementsByTagName("head")[0] || document.documentElement)
155
+ .appendChild(script_tag);
156
+ }
157
+ else
158
+ {
159
+ // The jQuery version on the window is the one we want to use
160
+ jQuery = window.jQuery;
161
+ main();
162
+ }
163
+ /******** Called once jQuery has loaded ******/
164
+ function scriptLoadHandler()
165
+ {
166
+ // Restore $ and window.jQuery to their previous values and store the
167
+ // new jQuery in our local jQuery variable
168
+ jQuery = window.jQuery.noConflict(true);
169
+ // Call our main function
170
+ main();
171
+ }
172
+ /******** Our main function ********/
173
+ function main()
174
+ {
175
+ jQuery(document)
176
+ .ready(function ($)
177
+ {
178
+ ' . $message . '
179
+ });
180
+ }
181
+ })(); // We call our anonymous function immediately
182
+ </script>';
183
+ return $javascript;
184
+ }
185
+ public function setJsCode()
186
+ {
187
+ $this->jsCode = "
188
+
189
+ var BUTTONTEXT = 'ProvideSupport : chat button code loaded';
190
+ var HIDDENTEXT = 'ProvideSupport : hidden monitoring code loaded';
191
+ var f7php = new Object();
192
+ var f7s = new Object();
193
+ f7s = JSON.parse(" . Zend_Json::encode($this->settings) . "); //f7php.settings
194
+
195
+
196
+
197
+ f7php.code = " . Zend_Json::encode($this->code) . ";
198
+ f7php.hiddencode = " . Zend_Json::encode($this->hiddencode) . ";
199
+ showChat = function (code)
200
+ {
201
+ var codeBlock = document.createElement('div');
202
+
203
+
204
+
205
+ codeBlock.className = 'f7x';
206
+ document.body.appendChild(codeBlock);
207
+
208
+ jQuery('.f7x').html(code);
209
+
210
+ /*
211
+ conf = {'position': 'fixed','width': 'auto','height': 'auto','z-index': 10000}
212
+ jQuery('.f7x').css(conf);
213
+ */
214
+
215
+ jQuery('.f7x').css(f7s.buttonLocationHorizontalFrom, f7s.buttonLocationHorizontalValue + f7s.buttonLocationHorizontalBy);
216
+ jQuery('.f7x').css(f7s.buttonLocationVerticalFrom, f7s.buttonLocationVerticalValue + f7s.buttonLocationVerticalBy);
217
+
218
+ }; ";
219
+ }
220
+ }
app/code/community/ProvideSupport/Livechat/Model/Livechat.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class ProvideSupport_Livechat_Model_Livechat extends Mage_Core_Model_Abstract
3
+ {
4
+ protected function _construct()
5
+ {
6
+ $this->_init('livechat/livechat');
7
+ }
8
+ }
app/code/community/ProvideSupport/Livechat/Model/Mysql4/Livechat.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class ProvideSupport_Livechat_Model_Mysql4_Livechat extends Mage_Core_Model_Mysql4_Abstract
3
+ {
4
+ protected function _construct()
5
+ {
6
+ $this->_init('livechat/livechat', 'id');
7
+ }
8
+ }
app/code/community/ProvideSupport/Livechat/Model/Mysql4/Livechat/Collection.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ class ProvideSupport_Livechat_Model_Mysql4_Livechat_Collection extends Varien_Data_Collection_Db
3
+ {
4
+ }
app/code/community/ProvideSupport/Livechat/Model/Observer.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class ProvideSupport_Livechat_Model_Observer
3
+ {
4
+ public $countPastCode;
5
+ public function __construct()
6
+ {
7
+ $this->provide = Mage::getModel('livechat/livechat')->load(1)->getData('content');
8
+ $this->view = Zend_Json::decode($this->provide, Zend_Json::TYPE_OBJECT);
9
+ $this->settings = Zend_Json::decode($this->view->settings, Zend_Json::TYPE_OBJECT);
10
+ $this->pos = $this->settings->buttonLocation;
11
+ $this->list = $this->settings->buttonAvailableMenusList[0];
12
+ $this->helper = Mage::helper('livechat/data');
13
+ $this->helper->initCode($this->view);
14
+ }
15
+ public function insertBlock($observer)
16
+ {
17
+ if (Mage::app()->getLayout()->getArea() == 'frontend') {
18
+ $_name = $observer->getBlock()->getNameInLayout();
19
+ $_type = $observer->getBlock()->getType();
20
+ if ($this->settings->pluginEnabled) {
21
+ if ($this->pos == 'fixed') {
22
+ if ($_name == 'root') {
23
+ $this->handler();
24
+ }
25
+ } elseif ($this->pos == 'define') {
26
+ if ($_name == $this->list) {
27
+ $this->countPastCode = true; //1
28
+ $this->handler();
29
+ } else {
30
+ if ($_name == 'before_body_end' && !$this->countPastCode && $this->settings->buttonAvailableWhole) {
31
+ $this->helper->showModuleHiddenCode();
32
+ $this->countPastCode = true;
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ }
39
+ protected function handler()
40
+ {
41
+ $this->helper->initJs();
42
+ if ($this->settings->buttonAvailableAll == false && $this->settings->buttonAvailablePost == false && $this->settings->buttonAvailableWhole == false) {
43
+ //Nothing to display in fixed position
44
+ } elseif ($this->settings->buttonAvailableAll == false && $this->settings->buttonAvailablePost == false && $this->settings->buttonAvailableWhole) {
45
+ //Only display the hidden code
46
+ if ($this->pos === 'fixed') {
47
+ $this->helper->showModuleJsHiddenCode();
48
+ } else {
49
+ $this->helper->showModuleHiddenCode();
50
+ $this->countPastCode = true;
51
+ }
52
+ } else {
53
+ if ($this->settings->buttonAvailableAll) {
54
+ $this->helper->showInAllCode($this->pos);
55
+ } else {
56
+ $this->helper->showInAllHiddenCode($this->pos);
57
+ }
58
+ if ($this->settings->buttonAvailablePost) {
59
+ if ($this->settings->buttonAvailablePostWhich == 'all') {
60
+ $this->helper->showAllPageCode($this->pos);
61
+ } elseif ($this->settings->buttonAvailablePostWhich == 'selected') {
62
+ $this->helper->showSelectedPageCode($this->pos);
63
+ }
64
+ } else {
65
+ $this->helper->showAllPageHiddenCode($this->pos);
66
+ }
67
+ }
68
+ }
69
+ }
app/code/community/ProvideSupport/Livechat/controllers/AdminController.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class ProvideSupport_Livechat_AdminController extends Mage_Adminhtml_Controller_Action
3
+ {
4
+ public function settingsAction()
5
+ {
6
+ $this->loadLayout();
7
+ $this->getLayout()->getBlock('head')->addJs('provide/jquery.js');
8
+ $this->getLayout()->getBlock('head')->addJs('provide/jquery-noconflict.js');
9
+ $this->getLayout()->getBlock('head')->addJs('provide/md5.js');
10
+ $this->getLayout()->getBlock('head')->addJs('provide/provide.js');
11
+ $this->_addContent($this->getLayout()->createBlock('livechat/settings'))->_setActiveMenu('livechat');
12
+ $this->renderLayout();
13
+ }
14
+ public function helpAction()
15
+ {
16
+ $this->loadLayout();
17
+ $this->_addContent($this->getLayout()->createBlock('livechat/help'))->_setActiveMenu('livechat');
18
+ $this->renderLayout();
19
+ }
20
+ public function ajaxAction()
21
+ {
22
+ $dbction = $this->getRequest()->getParam('action');
23
+ $db = Mage::getModel('livechat/livechat')->load(1);
24
+ if (!empty($dbction)) {
25
+ switch ($dbction) {
26
+ case 'getaccount':
27
+ echo $db->content;
28
+ break;
29
+ case 'setaccount':
30
+ $data = array(
31
+ 'accountName' => $this->getRequest()->getParam('accountName'),
32
+ 'accountHash' => $this->getRequest()->getParam('accountHash')
33
+ );
34
+ $param = Zend_Json::decode($db->content);
35
+ $param['account'] = $data;
36
+ $param = Zend_Json::encode((array) $param);
37
+ $db->setContent($param);
38
+ $db->save();
39
+ echo $db->content;
40
+ break;
41
+ case 'setsettings':
42
+ $settings = $this->getRequest()->getParam('settings');
43
+ $param = Zend_Json::decode($db->content);
44
+ $param['settings'] = $settings;
45
+ $param = Zend_Json::encode((array) $param);
46
+ $db->setContent($param);
47
+ $db->save();
48
+ echo $db->content;
49
+ break;
50
+ case 'setcode':
51
+ $param = Zend_Json::decode($db->content);
52
+ $value = $this->getRequest()->getParam('value');
53
+ $type = $this->getRequest()->getParam('type');
54
+ if ($type == 'true') {
55
+ $param['hiddencode'] = '';
56
+ $param['hiddencode'] = $value;
57
+ } else {
58
+ $param['code'] = '';
59
+ $param['code'] = $value;
60
+ }
61
+ $param = Zend_Json::encode((array) $param);
62
+ $db->setContent($param);
63
+ $db->save();
64
+ echo $db->content;
65
+ break;
66
+ case 'clearall':
67
+ $param = Zend_Json::decode($db->content);
68
+ $data = array(
69
+ 'accountName' => '',
70
+ 'accountHash' => ''
71
+ );
72
+ $param['account'] = $data;
73
+ $param['hiddencode'] = '';
74
+ $param['code'] = '';
75
+ $param['settings'] = 'null';
76
+ $param = Zend_Json::encode((array) $param);
77
+ $db->setContent($param);
78
+ $db->save();
79
+ echo $db->content;
80
+ break;
81
+ default:
82
+ break;
83
+ }
84
+ }
85
+ }
86
+ public function indexAction()
87
+ {
88
+ settingsAction();
89
+ }
90
+ }
app/code/community/ProvideSupport/Livechat/etc/config.xml ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <ProvideSupport_Livechat>
5
+ <version>1.0.0</version>
6
+ </ProvideSupport_Livechat>
7
+ </modules>
8
+ <global>
9
+ <events>
10
+ <core_block_abstract_to_html_before>
11
+ <observers>
12
+ <ProvideSupport_Livechat_core_block_abstract_to_html_before>
13
+ <type>singleton</type>
14
+ <class>ProvideSupport_Livechat_Model_Observer</class>
15
+ <method>insertBlock</method>
16
+ </ProvideSupport_Livechat_core_block_abstract_to_html_before>
17
+ </observers>
18
+ </core_block_abstract_to_html_before>
19
+ </events>
20
+ <models>
21
+ <livechat>
22
+ <class>ProvideSupport_Livechat_Model</class>
23
+ <resourceModel>livechat_mysql4</resourceModel>
24
+ </livechat>
25
+ <livechat_mysql4>
26
+ <class>ProvideSupport_Livechat_Model_Mysql4</class>
27
+ <entities>
28
+ <livechat>
29
+ <table>providelivechat</table>
30
+ </livechat>
31
+ </entities>
32
+ </livechat_mysql4>
33
+ </models>
34
+ <blocks>
35
+ <livechat>
36
+ <class>ProvideSupport_Livechat_Block</class>
37
+ </livechat>
38
+ </blocks>
39
+ <helpers>
40
+ <livechat>
41
+ <class>ProvideSupport_Livechat_Helper</class>
42
+ </livechat>
43
+ </helpers>
44
+ <resources>
45
+ <providelivechat_setup>
46
+ <setup>
47
+ <module>ProvideSupport_Livechat</module>
48
+ </setup>
49
+ <connection>
50
+ <use>core_setup</use>
51
+ </connection>
52
+ </providelivechat_setup>
53
+ <livechat_write>
54
+ <connection>
55
+ <use>core_write</use>
56
+ </connection>
57
+ </livechat_write>
58
+ <livechat_read>
59
+ <connection>
60
+ <use>core_read</use>
61
+ </connection>
62
+ </livechat_read>
63
+ </resources>
64
+ </global>
65
+ <admin>
66
+ <routers>
67
+ <ProvideSupport_Livechat>
68
+ <use>admin</use>
69
+ <args>
70
+ <module>ProvideSupport_Livechat</module>
71
+ <frontName>livechat</frontName>
72
+ </args>
73
+ </ProvideSupport_Livechat>
74
+ </routers>
75
+ </admin>
76
+ <adminhtml>
77
+ <menu>
78
+ <livechat translate="title" module="livechat">
79
+ <title>Provide Support Live Chat</title>
80
+ <sort_order>1000</sort_order>
81
+ <children>
82
+ <settings translate="title" module="livechat">
83
+ <title>Settings</title>
84
+ <action>livechat/admin/settings</action>
85
+ <sort_order>0</sort_order>
86
+ </settings>
87
+ <help translate="title" module="livechat">
88
+ <title>Help</title>
89
+ <action>livechat/admin/help</action>
90
+ <sort_order>20</sort_order>
91
+ </help>
92
+ </children>
93
+ </livechat>
94
+ </menu>
95
+ <acl>
96
+ <resources>
97
+ <admin>
98
+ <children>
99
+ <livechat translate="title" module="livechat">
100
+ <title>Provide Support Live Chat</title>
101
+ <sort_order>1000</sort_order>
102
+ <children>
103
+ <settings translate="title" module="livechat">
104
+ <title>Settings</title>
105
+ <action>livechat/admin/settings</action>
106
+ <sort_order>0</sort_order>
107
+ </settings>
108
+ <help translate="title" module="livechat">
109
+ <title>Help</title>
110
+ <action>livechat/admin/help</action>
111
+ <sort_order>30</sort_order>
112
+ </help>
113
+ </children>
114
+ </livechat>
115
+ </children>
116
+ </admin>
117
+ </resources>
118
+ </acl>
119
+ </adminhtml>
120
+ </config>
app/code/community/ProvideSupport/Livechat/sql/providelivechat_setup/mysql4-install-1.0.0.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+ $installer->startSetup();
4
+
5
+ $installer->run("
6
+ CREATE TABLE IF NOT EXISTS {$this->getTable('providelivechat')} (
7
+ `id` int(11) NOT NULL auto_increment,
8
+ `title` varchar(100) NOT NULL,
9
+ `content` text NOT NULL,
10
+ PRIMARY KEY (`id`)
11
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
12
+
13
+ INSERT INTO {$this->getTable('providelivechat')}
14
+ (`id`, `title`, `content`) VALUES
15
+ (1, 'Provide Support LiveChat', '{\"account\":{\"accountName\":\"\",\"accountHash\":\"\"},\"settings\":\"null\",\"code\":\"\",\"hiddencode\":\"\"}');
16
+ ");
17
+
18
+ $installer->endSetup();
app/etc/modules/ProvideSupport_All.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <ProvideSupport_Livechat>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </ProvideSupport_Livechat>
8
+ </modules>
9
+ </config>
js/provide/jquery-noconflict.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery.noConflict();
js/provide/jquery.js ADDED
@@ -0,0 +1,10830 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery JavaScript Library v1.8.1
3
+ * http://jquery.com/
4
+ *
5
+ * Includes Sizzle.js
6
+ * http://sizzlejs.com/
7
+ *
8
+ * Copyright 2012 jQuery Foundation and other contributors
9
+ * Released under the MIT license
10
+ * http://jquery.org/license
11
+ *
12
+ * Date: Thu Aug 30 2012 17:17:22 GMT-0400 (Eastern Daylight Time)
13
+ */
14
+ (function( window, undefined ) {
15
+ var
16
+ // A central reference to the root jQuery(document)
17
+ rootjQuery,
18
+
19
+ // The deferred used on DOM ready
20
+ readyList,
21
+
22
+ // Use the correct document accordingly with window argument (sandbox)
23
+ document = window.document,
24
+ location = window.location,
25
+ navigator = window.navigator,
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
+ // Save a reference to some core methods
34
+ core_push = Array.prototype.push,
35
+ core_slice = Array.prototype.slice,
36
+ core_indexOf = Array.prototype.indexOf,
37
+ core_toString = Object.prototype.toString,
38
+ core_hasOwn = Object.prototype.hasOwnProperty,
39
+ core_trim = String.prototype.trim,
40
+
41
+ // Define a local copy of jQuery
42
+ jQuery = function( selector, context ) {
43
+ // The jQuery object is actually just the init constructor 'enhanced'
44
+ return new jQuery.fn.init( selector, context, rootjQuery );
45
+ },
46
+
47
+ // Used for matching numbers
48
+ core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
49
+
50
+ // Used for detecting and trimming whitespace
51
+ core_rnotwhite = /\S/,
52
+ core_rspace = /\s+/,
53
+
54
+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
55
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
56
+
57
+ // A simple way to check for HTML strings
58
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
59
+ rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
60
+
61
+ // Match a standalone tag
62
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
63
+
64
+ // JSON RegExp
65
+ rvalidchars = /^[\],:{}\s]*$/,
66
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
67
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
68
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
69
+
70
+ // Matches dashed string for camelizing
71
+ rmsPrefix = /^-ms-/,
72
+ rdashAlpha = /-([\da-z])/gi,
73
+
74
+ // Used by jQuery.camelCase as callback to replace()
75
+ fcamelCase = function( all, letter ) {
76
+ return ( letter + "" ).toUpperCase();
77
+ },
78
+
79
+ // The ready event handler and self cleanup method
80
+ DOMContentLoaded = function() {
81
+ if ( document.addEventListener ) {
82
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
83
+ jQuery.ready();
84
+ } else if ( document.readyState === "complete" ) {
85
+ // we're here because readyState === "complete" in oldIE
86
+ // which is good enough for us to call the dom ready!
87
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
88
+ jQuery.ready();
89
+ }
90
+ },
91
+
92
+ // [[Class]] -> type pairs
93
+ class2type = {};
94
+
95
+ jQuery.fn = jQuery.prototype = {
96
+ constructor: jQuery,
97
+ init: function( selector, context, rootjQuery ) {
98
+ var match, elem, ret, doc;
99
+
100
+ // Handle $(""), $(null), $(undefined), $(false)
101
+ if ( !selector ) {
102
+ return this;
103
+ }
104
+
105
+ // Handle $(DOMElement)
106
+ if ( selector.nodeType ) {
107
+ this.context = this[0] = selector;
108
+ this.length = 1;
109
+ return this;
110
+ }
111
+
112
+ // Handle HTML strings
113
+ if ( typeof selector === "string" ) {
114
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
115
+ // Assume that strings that start and end with <> are HTML and skip the regex check
116
+ match = [ null, selector, null ];
117
+
118
+ } else {
119
+ match = rquickExpr.exec( selector );
120
+ }
121
+
122
+ // Match html or make sure no context is specified for #id
123
+ if ( match && (match[1] || !context) ) {
124
+
125
+ // HANDLE: $(html) -> $(array)
126
+ if ( match[1] ) {
127
+ context = context instanceof jQuery ? context[0] : context;
128
+ doc = ( context && context.nodeType ? context.ownerDocument || context : document );
129
+
130
+ // scripts is true for back-compat
131
+ selector = jQuery.parseHTML( match[1], doc, true );
132
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
133
+ this.attr.call( selector, context, true );
134
+ }
135
+
136
+ return jQuery.merge( this, selector );
137
+
138
+ // HANDLE: $(#id)
139
+ } else {
140
+ elem = document.getElementById( match[2] );
141
+
142
+ // Check parentNode to catch when Blackberry 4.6 returns
143
+ // nodes that are no longer in the document #6963
144
+ if ( elem && elem.parentNode ) {
145
+ // Handle the case where IE and Opera return items
146
+ // by name instead of ID
147
+ if ( elem.id !== match[2] ) {
148
+ return rootjQuery.find( selector );
149
+ }
150
+
151
+ // Otherwise, we inject the element directly into the jQuery object
152
+ this.length = 1;
153
+ this[0] = elem;
154
+ }
155
+
156
+ this.context = document;
157
+ this.selector = selector;
158
+ return this;
159
+ }
160
+
161
+ // HANDLE: $(expr, $(...))
162
+ } else if ( !context || context.jquery ) {
163
+ return ( context || rootjQuery ).find( selector );
164
+
165
+ // HANDLE: $(expr, context)
166
+ // (which is just equivalent to: $(context).find(expr)
167
+ } else {
168
+ return this.constructor( context ).find( selector );
169
+ }
170
+
171
+ // HANDLE: $(function)
172
+ // Shortcut for document ready
173
+ } else if ( jQuery.isFunction( selector ) ) {
174
+ return rootjQuery.ready( selector );
175
+ }
176
+
177
+ if ( selector.selector !== undefined ) {
178
+ this.selector = selector.selector;
179
+ this.context = selector.context;
180
+ }
181
+
182
+ return jQuery.makeArray( selector, this );
183
+ },
184
+
185
+ // Start with an empty selector
186
+ selector: "",
187
+
188
+ // The current version of jQuery being used
189
+ jquery: "1.8.1",
190
+
191
+ // The default length of a jQuery object is 0
192
+ length: 0,
193
+
194
+ // The number of elements contained in the matched element set
195
+ size: function() {
196
+ return this.length;
197
+ },
198
+
199
+ toArray: function() {
200
+ return core_slice.call( this );
201
+ },
202
+
203
+ // Get the Nth element in the matched element set OR
204
+ // Get the whole matched element set as a clean array
205
+ get: function( num ) {
206
+ return num == null ?
207
+
208
+ // Return a 'clean' array
209
+ this.toArray() :
210
+
211
+ // Return just the object
212
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
213
+ },
214
+
215
+ // Take an array of elements and push it onto the stack
216
+ // (returning the new matched element set)
217
+ pushStack: function( elems, name, selector ) {
218
+
219
+ // Build a new jQuery matched element set
220
+ var ret = jQuery.merge( this.constructor(), elems );
221
+
222
+ // Add the old object onto the stack (as a reference)
223
+ ret.prevObject = this;
224
+
225
+ ret.context = this.context;
226
+
227
+ if ( name === "find" ) {
228
+ ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
229
+ } else if ( name ) {
230
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
231
+ }
232
+
233
+ // Return the newly-formed element set
234
+ return ret;
235
+ },
236
+
237
+ // Execute a callback for every element in the matched set.
238
+ // (You can seed the arguments with an array of args, but this is
239
+ // only used internally.)
240
+ each: function( callback, args ) {
241
+ return jQuery.each( this, callback, args );
242
+ },
243
+
244
+ ready: function( fn ) {
245
+ // Add the callback
246
+ jQuery.ready.promise().done( fn );
247
+
248
+ return this;
249
+ },
250
+
251
+ eq: function( i ) {
252
+ i = +i;
253
+ return i === -1 ?
254
+ this.slice( i ) :
255
+ this.slice( i, i + 1 );
256
+ },
257
+
258
+ first: function() {
259
+ return this.eq( 0 );
260
+ },
261
+
262
+ last: function() {
263
+ return this.eq( -1 );
264
+ },
265
+
266
+ slice: function() {
267
+ return this.pushStack( core_slice.apply( this, arguments ),
268
+ "slice", core_slice.call(arguments).join(",") );
269
+ },
270
+
271
+ map: function( callback ) {
272
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
273
+ return callback.call( elem, i, elem );
274
+ }));
275
+ },
276
+
277
+ end: function() {
278
+ return this.prevObject || this.constructor(null);
279
+ },
280
+
281
+ // For internal use only.
282
+ // Behaves like an Array's method, not like a jQuery method.
283
+ push: core_push,
284
+ sort: [].sort,
285
+ splice: [].splice
286
+ };
287
+
288
+ // Give the init function the jQuery prototype for later instantiation
289
+ jQuery.fn.init.prototype = jQuery.fn;
290
+
291
+ jQuery.extend = jQuery.fn.extend = function() {
292
+ var options, name, src, copy, copyIsArray, clone,
293
+ target = arguments[0] || {},
294
+ i = 1,
295
+ length = arguments.length,
296
+ deep = false;
297
+
298
+ // Handle a deep copy situation
299
+ if ( typeof target === "boolean" ) {
300
+ deep = target;
301
+ target = arguments[1] || {};
302
+ // skip the boolean and the target
303
+ i = 2;
304
+ }
305
+
306
+ // Handle case when target is a string or something (possible in deep copy)
307
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
308
+ target = {};
309
+ }
310
+
311
+ // extend jQuery itself if only one argument is passed
312
+ if ( length === i ) {
313
+ target = this;
314
+ --i;
315
+ }
316
+
317
+ for ( ; i < length; i++ ) {
318
+ // Only deal with non-null/undefined values
319
+ if ( (options = arguments[ i ]) != null ) {
320
+ // Extend the base object
321
+ for ( name in options ) {
322
+ src = target[ name ];
323
+ copy = options[ name ];
324
+
325
+ // Prevent never-ending loop
326
+ if ( target === copy ) {
327
+ continue;
328
+ }
329
+
330
+ // Recurse if we're merging plain objects or arrays
331
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
332
+ if ( copyIsArray ) {
333
+ copyIsArray = false;
334
+ clone = src && jQuery.isArray(src) ? src : [];
335
+
336
+ } else {
337
+ clone = src && jQuery.isPlainObject(src) ? src : {};
338
+ }
339
+
340
+ // Never move original objects, clone them
341
+ target[ name ] = jQuery.extend( deep, clone, copy );
342
+
343
+ // Don't bring in undefined values
344
+ } else if ( copy !== undefined ) {
345
+ target[ name ] = copy;
346
+ }
347
+ }
348
+ }
349
+ }
350
+
351
+ // Return the modified object
352
+ return target;
353
+ };
354
+
355
+ jQuery.extend({
356
+ noConflict: function( deep ) {
357
+ if ( window.$ === jQuery ) {
358
+ window.$ = _$;
359
+ }
360
+
361
+ if ( deep && window.jQuery === jQuery ) {
362
+ window.jQuery = _jQuery;
363
+ }
364
+
365
+ return jQuery;
366
+ },
367
+
368
+ // Is the DOM ready to be used? Set to true once it occurs.
369
+ isReady: false,
370
+
371
+ // A counter to track how many items to wait for before
372
+ // the ready event fires. See #6781
373
+ readyWait: 1,
374
+
375
+ // Hold (or release) the ready event
376
+ holdReady: function( hold ) {
377
+ if ( hold ) {
378
+ jQuery.readyWait++;
379
+ } else {
380
+ jQuery.ready( true );
381
+ }
382
+ },
383
+
384
+ // Handle when the DOM is ready
385
+ ready: function( wait ) {
386
+
387
+ // Abort if there are pending holds or we're already ready
388
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
389
+ return;
390
+ }
391
+
392
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
393
+ if ( !document.body ) {
394
+ return setTimeout( jQuery.ready, 1 );
395
+ }
396
+
397
+ // Remember that the DOM is ready
398
+ jQuery.isReady = true;
399
+
400
+ // If a normal DOM Ready event fired, decrement, and wait if need be
401
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
402
+ return;
403
+ }
404
+
405
+ // If there are functions bound, to execute
406
+ readyList.resolveWith( document, [ jQuery ] );
407
+
408
+ // Trigger any bound ready events
409
+ if ( jQuery.fn.trigger ) {
410
+ jQuery( document ).trigger("ready").off("ready");
411
+ }
412
+ },
413
+
414
+ // See test/unit/core.js for details concerning isFunction.
415
+ // Since version 1.3, DOM methods and functions like alert
416
+ // aren't supported. They return false on IE (#2968).
417
+ isFunction: function( obj ) {
418
+ return jQuery.type(obj) === "function";
419
+ },
420
+
421
+ isArray: Array.isArray || function( obj ) {
422
+ return jQuery.type(obj) === "array";
423
+ },
424
+
425
+ isWindow: function( obj ) {
426
+ return obj != null && obj == obj.window;
427
+ },
428
+
429
+ isNumeric: function( obj ) {
430
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
431
+ },
432
+
433
+ type: function( obj ) {
434
+ return obj == null ?
435
+ String( obj ) :
436
+ class2type[ core_toString.call(obj) ] || "object";
437
+ },
438
+
439
+ isPlainObject: function( obj ) {
440
+ // Must be an Object.
441
+ // Because of IE, we also have to check the presence of the constructor property.
442
+ // Make sure that DOM nodes and window objects don't pass through, as well
443
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
444
+ return false;
445
+ }
446
+
447
+ try {
448
+ // Not own constructor property must be Object
449
+ if ( obj.constructor &&
450
+ !core_hasOwn.call(obj, "constructor") &&
451
+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
452
+ return false;
453
+ }
454
+ } catch ( e ) {
455
+ // IE8,9 Will throw exceptions on certain host objects #9897
456
+ return false;
457
+ }
458
+
459
+ // Own properties are enumerated firstly, so to speed up,
460
+ // if last one is own, then all properties are own.
461
+
462
+ var key;
463
+ for ( key in obj ) {}
464
+
465
+ return key === undefined || core_hasOwn.call( obj, key );
466
+ },
467
+
468
+ isEmptyObject: function( obj ) {
469
+ var name;
470
+ for ( name in obj ) {
471
+ return false;
472
+ }
473
+ return true;
474
+ },
475
+
476
+ error: function( msg ) {
477
+ throw new Error( msg );
478
+ },
479
+
480
+ // data: string of html
481
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
482
+ // scripts (optional): If true, will include scripts passed in the html string
483
+ parseHTML: function( data, context, scripts ) {
484
+ var parsed;
485
+ if ( !data || typeof data !== "string" ) {
486
+ return null;
487
+ }
488
+ if ( typeof context === "boolean" ) {
489
+ scripts = context;
490
+ context = 0;
491
+ }
492
+ context = context || document;
493
+
494
+ // Single tag
495
+ if ( (parsed = rsingleTag.exec( data )) ) {
496
+ return [ context.createElement( parsed[1] ) ];
497
+ }
498
+
499
+ parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
500
+ return jQuery.merge( [],
501
+ (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
502
+ },
503
+
504
+ parseJSON: function( data ) {
505
+ if ( !data || typeof data !== "string") {
506
+ return null;
507
+ }
508
+
509
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
510
+ data = jQuery.trim( data );
511
+
512
+ // Attempt to parse using the native JSON parser first
513
+ if ( window.JSON && window.JSON.parse ) {
514
+ return window.JSON.parse( data );
515
+ }
516
+
517
+ // Make sure the incoming data is actual JSON
518
+ // Logic borrowed from http://json.org/json2.js
519
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
520
+ .replace( rvalidtokens, "]" )
521
+ .replace( rvalidbraces, "")) ) {
522
+
523
+ return ( new Function( "return " + data ) )();
524
+
525
+ }
526
+ jQuery.error( "Invalid JSON: " + data );
527
+ },
528
+
529
+ // Cross-browser xml parsing
530
+ parseXML: function( data ) {
531
+ var xml, tmp;
532
+ if ( !data || typeof data !== "string" ) {
533
+ return null;
534
+ }
535
+ try {
536
+ if ( window.DOMParser ) { // Standard
537
+ tmp = new DOMParser();
538
+ xml = tmp.parseFromString( data , "text/xml" );
539
+ } else { // IE
540
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
541
+ xml.async = "false";
542
+ xml.loadXML( data );
543
+ }
544
+ } catch( e ) {
545
+ xml = undefined;
546
+ }
547
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
548
+ jQuery.error( "Invalid XML: " + data );
549
+ }
550
+ return xml;
551
+ },
552
+
553
+ noop: function() {},
554
+
555
+ // Evaluates a script in a global context
556
+ // Workarounds based on findings by Jim Driscoll
557
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
558
+ globalEval: function( data ) {
559
+ if ( data && core_rnotwhite.test( data ) ) {
560
+ // We use execScript on Internet Explorer
561
+ // We use an anonymous function so that context is window
562
+ // rather than jQuery in Firefox
563
+ ( window.execScript || function( data ) {
564
+ window[ "eval" ].call( window, data );
565
+ } )( data );
566
+ }
567
+ },
568
+
569
+ // Convert dashed to camelCase; used by the css and data modules
570
+ // Microsoft forgot to hump their vendor prefix (#9572)
571
+ camelCase: function( string ) {
572
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
573
+ },
574
+
575
+ nodeName: function( elem, name ) {
576
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
577
+ },
578
+
579
+ // args is for internal usage only
580
+ each: function( obj, callback, args ) {
581
+ var name,
582
+ i = 0,
583
+ length = obj.length,
584
+ isObj = length === undefined || jQuery.isFunction( obj );
585
+
586
+ if ( args ) {
587
+ if ( isObj ) {
588
+ for ( name in obj ) {
589
+ if ( callback.apply( obj[ name ], args ) === false ) {
590
+ break;
591
+ }
592
+ }
593
+ } else {
594
+ for ( ; i < length; ) {
595
+ if ( callback.apply( obj[ i++ ], args ) === false ) {
596
+ break;
597
+ }
598
+ }
599
+ }
600
+
601
+ // A special, fast, case for the most common use of each
602
+ } else {
603
+ if ( isObj ) {
604
+ for ( name in obj ) {
605
+ if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
606
+ break;
607
+ }
608
+ }
609
+ } else {
610
+ for ( ; i < length; ) {
611
+ if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
612
+ break;
613
+ }
614
+ }
615
+ }
616
+ }
617
+
618
+ return obj;
619
+ },
620
+
621
+ // Use native String.trim function wherever possible
622
+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
623
+ function( text ) {
624
+ return text == null ?
625
+ "" :
626
+ core_trim.call( text );
627
+ } :
628
+
629
+ // Otherwise use our own trimming functionality
630
+ function( text ) {
631
+ return text == null ?
632
+ "" :
633
+ text.toString().replace( rtrim, "" );
634
+ },
635
+
636
+ // results is for internal usage only
637
+ makeArray: function( arr, results ) {
638
+ var type,
639
+ ret = results || [];
640
+
641
+ if ( arr != null ) {
642
+ // The window, strings (and functions) also have 'length'
643
+ // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
644
+ type = jQuery.type( arr );
645
+
646
+ if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) {
647
+ core_push.call( ret, arr );
648
+ } else {
649
+ jQuery.merge( ret, arr );
650
+ }
651
+ }
652
+
653
+ return ret;
654
+ },
655
+
656
+ inArray: function( elem, arr, i ) {
657
+ var len;
658
+
659
+ if ( arr ) {
660
+ if ( core_indexOf ) {
661
+ return core_indexOf.call( arr, elem, i );
662
+ }
663
+
664
+ len = arr.length;
665
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
666
+
667
+ for ( ; i < len; i++ ) {
668
+ // Skip accessing in sparse arrays
669
+ if ( i in arr && arr[ i ] === elem ) {
670
+ return i;
671
+ }
672
+ }
673
+ }
674
+
675
+ return -1;
676
+ },
677
+
678
+ merge: function( first, second ) {
679
+ var l = second.length,
680
+ i = first.length,
681
+ j = 0;
682
+
683
+ if ( typeof l === "number" ) {
684
+ for ( ; j < l; j++ ) {
685
+ first[ i++ ] = second[ j ];
686
+ }
687
+
688
+ } else {
689
+ while ( second[j] !== undefined ) {
690
+ first[ i++ ] = second[ j++ ];
691
+ }
692
+ }
693
+
694
+ first.length = i;
695
+
696
+ return first;
697
+ },
698
+
699
+ grep: function( elems, callback, inv ) {
700
+ var retVal,
701
+ ret = [],
702
+ i = 0,
703
+ length = elems.length;
704
+ inv = !!inv;
705
+
706
+ // Go through the array, only saving the items
707
+ // that pass the validator function
708
+ for ( ; i < length; i++ ) {
709
+ retVal = !!callback( elems[ i ], i );
710
+ if ( inv !== retVal ) {
711
+ ret.push( elems[ i ] );
712
+ }
713
+ }
714
+
715
+ return ret;
716
+ },
717
+
718
+ // arg is for internal usage only
719
+ map: function( elems, callback, arg ) {
720
+ var value, key,
721
+ ret = [],
722
+ i = 0,
723
+ length = elems.length,
724
+ // jquery objects are treated as arrays
725
+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
726
+
727
+ // Go through the array, translating each of the items to their
728
+ if ( isArray ) {
729
+ for ( ; i < length; i++ ) {
730
+ value = callback( elems[ i ], i, arg );
731
+
732
+ if ( value != null ) {
733
+ ret[ ret.length ] = value;
734
+ }
735
+ }
736
+
737
+ // Go through every key on the object,
738
+ } else {
739
+ for ( key in elems ) {
740
+ value = callback( elems[ key ], key, arg );
741
+
742
+ if ( value != null ) {
743
+ ret[ ret.length ] = value;
744
+ }
745
+ }
746
+ }
747
+
748
+ // Flatten any nested arrays
749
+ return ret.concat.apply( [], ret );
750
+ },
751
+
752
+ // A global GUID counter for objects
753
+ guid: 1,
754
+
755
+ // Bind a function to a context, optionally partially applying any
756
+ // arguments.
757
+ proxy: function( fn, context ) {
758
+ var tmp, args, proxy;
759
+
760
+ if ( typeof context === "string" ) {
761
+ tmp = fn[ context ];
762
+ context = fn;
763
+ fn = tmp;
764
+ }
765
+
766
+ // Quick check to determine if target is callable, in the spec
767
+ // this throws a TypeError, but we will just return undefined.
768
+ if ( !jQuery.isFunction( fn ) ) {
769
+ return undefined;
770
+ }
771
+
772
+ // Simulated bind
773
+ args = core_slice.call( arguments, 2 );
774
+ proxy = function() {
775
+ return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
776
+ };
777
+
778
+ // Set the guid of unique handler to the same of original handler, so it can be removed
779
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
780
+
781
+ return proxy;
782
+ },
783
+
784
+ // Multifunctional method to get and set values of a collection
785
+ // The value/s can optionally be executed if it's a function
786
+ access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
787
+ var exec,
788
+ bulk = key == null,
789
+ i = 0,
790
+ length = elems.length;
791
+
792
+ // Sets many values
793
+ if ( key && typeof key === "object" ) {
794
+ for ( i in key ) {
795
+ jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
796
+ }
797
+ chainable = 1;
798
+
799
+ // Sets one value
800
+ } else if ( value !== undefined ) {
801
+ // Optionally, function values get executed if exec is true
802
+ exec = pass === undefined && jQuery.isFunction( value );
803
+
804
+ if ( bulk ) {
805
+ // Bulk operations only iterate when executing function values
806
+ if ( exec ) {
807
+ exec = fn;
808
+ fn = function( elem, key, value ) {
809
+ return exec.call( jQuery( elem ), value );
810
+ };
811
+
812
+ // Otherwise they run against the entire set
813
+ } else {
814
+ fn.call( elems, value );
815
+ fn = null;
816
+ }
817
+ }
818
+
819
+ if ( fn ) {
820
+ for (; i < length; i++ ) {
821
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
822
+ }
823
+ }
824
+
825
+ chainable = 1;
826
+ }
827
+
828
+ return chainable ?
829
+ elems :
830
+
831
+ // Gets
832
+ bulk ?
833
+ fn.call( elems ) :
834
+ length ? fn( elems[0], key ) : emptyGet;
835
+ },
836
+
837
+ now: function() {
838
+ return ( new Date() ).getTime();
839
+ }
840
+ });
841
+
842
+ jQuery.ready.promise = function( obj ) {
843
+ if ( !readyList ) {
844
+
845
+ readyList = jQuery.Deferred();
846
+
847
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
848
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
849
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
850
+ if ( document.readyState === "complete" ) {
851
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
852
+ setTimeout( jQuery.ready, 1 );
853
+
854
+ // Standards-based browsers support DOMContentLoaded
855
+ } else if ( document.addEventListener ) {
856
+ // Use the handy event callback
857
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
858
+
859
+ // A fallback to window.onload, that will always work
860
+ window.addEventListener( "load", jQuery.ready, false );
861
+
862
+ // If IE event model is used
863
+ } else {
864
+ // Ensure firing before onload, maybe late but safe also for iframes
865
+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
866
+
867
+ // A fallback to window.onload, that will always work
868
+ window.attachEvent( "onload", jQuery.ready );
869
+
870
+ // If IE and not a frame
871
+ // continually check to see if the document is ready
872
+ var top = false;
873
+
874
+ try {
875
+ top = window.frameElement == null && document.documentElement;
876
+ } catch(e) {}
877
+
878
+ if ( top && top.doScroll ) {
879
+ (function doScrollCheck() {
880
+ if ( !jQuery.isReady ) {
881
+
882
+ try {
883
+ // Use the trick by Diego Perini
884
+ // http://javascript.nwbox.com/IEContentLoaded/
885
+ top.doScroll("left");
886
+ } catch(e) {
887
+ return setTimeout( doScrollCheck, 50 );
888
+ }
889
+
890
+ // and execute any waiting functions
891
+ jQuery.ready();
892
+ }
893
+ })();
894
+ }
895
+ }
896
+ }
897
+ return readyList.promise( obj );
898
+ };
899
+
900
+ // Populate the class2type map
901
+ jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
902
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
903
+ });
904
+
905
+ // All jQuery objects should point back to these
906
+ rootjQuery = jQuery(document);
907
+ // String to Object options format cache
908
+ var optionsCache = {};
909
+
910
+ // Convert String-formatted options into Object-formatted ones and store in cache
911
+ function createOptions( options ) {
912
+ var object = optionsCache[ options ] = {};
913
+ jQuery.each( options.split( core_rspace ), function( _, flag ) {
914
+ object[ flag ] = true;
915
+ });
916
+ return object;
917
+ }
918
+
919
+ /*
920
+ * Create a callback list using the following parameters:
921
+ *
922
+ * options: an optional list of space-separated options that will change how
923
+ * the callback list behaves or a more traditional option object
924
+ *
925
+ * By default a callback list will act like an event callback list and can be
926
+ * "fired" multiple times.
927
+ *
928
+ * Possible options:
929
+ *
930
+ * once: will ensure the callback list can only be fired once (like a Deferred)
931
+ *
932
+ * memory: will keep track of previous values and will call any callback added
933
+ * after the list has been fired right away with the latest "memorized"
934
+ * values (like a Deferred)
935
+ *
936
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
937
+ *
938
+ * stopOnFalse: interrupt callings when a callback returns false
939
+ *
940
+ */
941
+ jQuery.Callbacks = function( options ) {
942
+
943
+ // Convert options from String-formatted to Object-formatted if needed
944
+ // (we check in cache first)
945
+ options = typeof options === "string" ?
946
+ ( optionsCache[ options ] || createOptions( options ) ) :
947
+ jQuery.extend( {}, options );
948
+
949
+ var // Last fire value (for non-forgettable lists)
950
+ memory,
951
+ // Flag to know if list was already fired
952
+ fired,
953
+ // Flag to know if list is currently firing
954
+ firing,
955
+ // First callback to fire (used internally by add and fireWith)
956
+ firingStart,
957
+ // End of the loop when firing
958
+ firingLength,
959
+ // Index of currently firing callback (modified by remove if needed)
960
+ firingIndex,
961
+ // Actual callback list
962
+ list = [],
963
+ // Stack of fire calls for repeatable lists
964
+ stack = !options.once && [],
965
+ // Fire callbacks
966
+ fire = function( data ) {
967
+ memory = options.memory && data;
968
+ fired = true;
969
+ firingIndex = firingStart || 0;
970
+ firingStart = 0;
971
+ firingLength = list.length;
972
+ firing = true;
973
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
974
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
975
+ memory = false; // To prevent further calls using add
976
+ break;
977
+ }
978
+ }
979
+ firing = false;
980
+ if ( list ) {
981
+ if ( stack ) {
982
+ if ( stack.length ) {
983
+ fire( stack.shift() );
984
+ }
985
+ } else if ( memory ) {
986
+ list = [];
987
+ } else {
988
+ self.disable();
989
+ }
990
+ }
991
+ },
992
+ // Actual Callbacks object
993
+ self = {
994
+ // Add a callback or a collection of callbacks to the list
995
+ add: function() {
996
+ if ( list ) {
997
+ // First, we save the current length
998
+ var start = list.length;
999
+ (function add( args ) {
1000
+ jQuery.each( args, function( _, arg ) {
1001
+ var type = jQuery.type( arg );
1002
+ if ( type === "function" && ( !options.unique || !self.has( arg ) ) ) {
1003
+ list.push( arg );
1004
+ } else if ( arg && arg.length && type !== "string" ) {
1005
+ // Inspect recursively
1006
+ add( arg );
1007
+ }
1008
+ });
1009
+ })( arguments );
1010
+ // Do we need to add the callbacks to the
1011
+ // current firing batch?
1012
+ if ( firing ) {
1013
+ firingLength = list.length;
1014
+ // With memory, if we're not firing then
1015
+ // we should call right away
1016
+ } else if ( memory ) {
1017
+ firingStart = start;
1018
+ fire( memory );
1019
+ }
1020
+ }
1021
+ return this;
1022
+ },
1023
+ // Remove a callback from the list
1024
+ remove: function() {
1025
+ if ( list ) {
1026
+ jQuery.each( arguments, function( _, arg ) {
1027
+ var index;
1028
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1029
+ list.splice( index, 1 );
1030
+ // Handle firing indexes
1031
+ if ( firing ) {
1032
+ if ( index <= firingLength ) {
1033
+ firingLength--;
1034
+ }
1035
+ if ( index <= firingIndex ) {
1036
+ firingIndex--;
1037
+ }
1038
+ }
1039
+ }
1040
+ });
1041
+ }
1042
+ return this;
1043
+ },
1044
+ // Control if a given callback is in the list
1045
+ has: function( fn ) {
1046
+ return jQuery.inArray( fn, list ) > -1;
1047
+ },
1048
+ // Remove all callbacks from the list
1049
+ empty: function() {
1050
+ list = [];
1051
+ return this;
1052
+ },
1053
+ // Have the list do nothing anymore
1054
+ disable: function() {
1055
+ list = stack = memory = undefined;
1056
+ return this;
1057
+ },
1058
+ // Is it disabled?
1059
+ disabled: function() {
1060
+ return !list;
1061
+ },
1062
+ // Lock the list in its current state
1063
+ lock: function() {
1064
+ stack = undefined;
1065
+ if ( !memory ) {
1066
+ self.disable();
1067
+ }
1068
+ return this;
1069
+ },
1070
+ // Is it locked?
1071
+ locked: function() {
1072
+ return !stack;
1073
+ },
1074
+ // Call all callbacks with the given context and arguments
1075
+ fireWith: function( context, args ) {
1076
+ args = args || [];
1077
+ args = [ context, args.slice ? args.slice() : args ];
1078
+ if ( list && ( !fired || stack ) ) {
1079
+ if ( firing ) {
1080
+ stack.push( args );
1081
+ } else {
1082
+ fire( args );
1083
+ }
1084
+ }
1085
+ return this;
1086
+ },
1087
+ // Call all the callbacks with the given arguments
1088
+ fire: function() {
1089
+ self.fireWith( this, arguments );
1090
+ return this;
1091
+ },
1092
+ // To know if the callbacks have already been called at least once
1093
+ fired: function() {
1094
+ return !!fired;
1095
+ }
1096
+ };
1097
+
1098
+ return self;
1099
+ };
1100
+ jQuery.extend({
1101
+
1102
+ Deferred: function( func ) {
1103
+ var tuples = [
1104
+ // action, add listener, listener list, final state
1105
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1106
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1107
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
1108
+ ],
1109
+ state = "pending",
1110
+ promise = {
1111
+ state: function() {
1112
+ return state;
1113
+ },
1114
+ always: function() {
1115
+ deferred.done( arguments ).fail( arguments );
1116
+ return this;
1117
+ },
1118
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
1119
+ var fns = arguments;
1120
+ return jQuery.Deferred(function( newDefer ) {
1121
+ jQuery.each( tuples, function( i, tuple ) {
1122
+ var action = tuple[ 0 ],
1123
+ fn = fns[ i ];
1124
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
1125
+ deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
1126
+ function() {
1127
+ var returned = fn.apply( this, arguments );
1128
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
1129
+ returned.promise()
1130
+ .done( newDefer.resolve )
1131
+ .fail( newDefer.reject )
1132
+ .progress( newDefer.notify );
1133
+ } else {
1134
+ newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
1135
+ }
1136
+ } :
1137
+ newDefer[ action ]
1138
+ );
1139
+ });
1140
+ fns = null;
1141
+ }).promise();
1142
+ },
1143
+ // Get a promise for this deferred
1144
+ // If obj is provided, the promise aspect is added to the object
1145
+ promise: function( obj ) {
1146
+ return typeof obj === "object" ? jQuery.extend( obj, promise ) : promise;
1147
+ }
1148
+ },
1149
+ deferred = {};
1150
+
1151
+ // Keep pipe for back-compat
1152
+ promise.pipe = promise.then;
1153
+
1154
+ // Add list-specific methods
1155
+ jQuery.each( tuples, function( i, tuple ) {
1156
+ var list = tuple[ 2 ],
1157
+ stateString = tuple[ 3 ];
1158
+
1159
+ // promise[ done | fail | progress ] = list.add
1160
+ promise[ tuple[1] ] = list.add;
1161
+
1162
+ // Handle state
1163
+ if ( stateString ) {
1164
+ list.add(function() {
1165
+ // state = [ resolved | rejected ]
1166
+ state = stateString;
1167
+
1168
+ // [ reject_list | resolve_list ].disable; progress_list.lock
1169
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1170
+ }
1171
+
1172
+ // deferred[ resolve | reject | notify ] = list.fire
1173
+ deferred[ tuple[0] ] = list.fire;
1174
+ deferred[ tuple[0] + "With" ] = list.fireWith;
1175
+ });
1176
+
1177
+ // Make the deferred a promise
1178
+ promise.promise( deferred );
1179
+
1180
+ // Call given func if any
1181
+ if ( func ) {
1182
+ func.call( deferred, deferred );
1183
+ }
1184
+
1185
+ // All done!
1186
+ return deferred;
1187
+ },
1188
+
1189
+ // Deferred helper
1190
+ when: function( subordinate /* , ..., subordinateN */ ) {
1191
+ var i = 0,
1192
+ resolveValues = core_slice.call( arguments ),
1193
+ length = resolveValues.length,
1194
+
1195
+ // the count of uncompleted subordinates
1196
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1197
+
1198
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1199
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1200
+
1201
+ // Update function for both resolve and progress values
1202
+ updateFunc = function( i, contexts, values ) {
1203
+ return function( value ) {
1204
+ contexts[ i ] = this;
1205
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1206
+ if( values === progressValues ) {
1207
+ deferred.notifyWith( contexts, values );
1208
+ } else if ( !( --remaining ) ) {
1209
+ deferred.resolveWith( contexts, values );
1210
+ }
1211
+ };
1212
+ },
1213
+
1214
+ progressValues, progressContexts, resolveContexts;
1215
+
1216
+ // add listeners to Deferred subordinates; treat others as resolved
1217
+ if ( length > 1 ) {
1218
+ progressValues = new Array( length );
1219
+ progressContexts = new Array( length );
1220
+ resolveContexts = new Array( length );
1221
+ for ( ; i < length; i++ ) {
1222
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1223
+ resolveValues[ i ].promise()
1224
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
1225
+ .fail( deferred.reject )
1226
+ .progress( updateFunc( i, progressContexts, progressValues ) );
1227
+ } else {
1228
+ --remaining;
1229
+ }
1230
+ }
1231
+ }
1232
+
1233
+ // if we're not waiting on anything, resolve the master
1234
+ if ( !remaining ) {
1235
+ deferred.resolveWith( resolveContexts, resolveValues );
1236
+ }
1237
+
1238
+ return deferred.promise();
1239
+ }
1240
+ });
1241
+ jQuery.support = (function() {
1242
+
1243
+ var support,
1244
+ all,
1245
+ a,
1246
+ select,
1247
+ opt,
1248
+ input,
1249
+ fragment,
1250
+ eventName,
1251
+ i,
1252
+ isSupported,
1253
+ clickFn,
1254
+ div = document.createElement("div");
1255
+
1256
+ // Preliminary tests
1257
+ div.setAttribute( "className", "t" );
1258
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1259
+
1260
+ all = div.getElementsByTagName("*");
1261
+ a = div.getElementsByTagName("a")[ 0 ];
1262
+ a.style.cssText = "top:1px;float:left;opacity:.5";
1263
+
1264
+ // Can't get basic test support
1265
+ if ( !all || !all.length || !a ) {
1266
+ return {};
1267
+ }
1268
+
1269
+ // First batch of supports tests
1270
+ select = document.createElement("select");
1271
+ opt = select.appendChild( document.createElement("option") );
1272
+ input = div.getElementsByTagName("input")[ 0 ];
1273
+
1274
+ support = {
1275
+ // IE strips leading whitespace when .innerHTML is used
1276
+ leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1277
+
1278
+ // Make sure that tbody elements aren't automatically inserted
1279
+ // IE will insert them into empty tables
1280
+ tbody: !div.getElementsByTagName("tbody").length,
1281
+
1282
+ // Make sure that link elements get serialized correctly by innerHTML
1283
+ // This requires a wrapper element in IE
1284
+ htmlSerialize: !!div.getElementsByTagName("link").length,
1285
+
1286
+ // Get the style information from getAttribute
1287
+ // (IE uses .cssText instead)
1288
+ style: /top/.test( a.getAttribute("style") ),
1289
+
1290
+ // Make sure that URLs aren't manipulated
1291
+ // (IE normalizes it by default)
1292
+ hrefNormalized: ( a.getAttribute("href") === "/a" ),
1293
+
1294
+ // Make sure that element opacity exists
1295
+ // (IE uses filter instead)
1296
+ // Use a regex to work around a WebKit issue. See #5145
1297
+ opacity: /^0.5/.test( a.style.opacity ),
1298
+
1299
+ // Verify style float existence
1300
+ // (IE uses styleFloat instead of cssFloat)
1301
+ cssFloat: !!a.style.cssFloat,
1302
+
1303
+ // Make sure that if no value is specified for a checkbox
1304
+ // that it defaults to "on".
1305
+ // (WebKit defaults to "" instead)
1306
+ checkOn: ( input.value === "on" ),
1307
+
1308
+ // Make sure that a selected-by-default option has a working selected property.
1309
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1310
+ optSelected: opt.selected,
1311
+
1312
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1313
+ getSetAttribute: div.className !== "t",
1314
+
1315
+ // Tests for enctype support on a form(#6743)
1316
+ enctype: !!document.createElement("form").enctype,
1317
+
1318
+ // Makes sure cloning an html5 element does not cause problems
1319
+ // Where outerHTML is undefined, this still works
1320
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1321
+
1322
+ // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1323
+ boxModel: ( document.compatMode === "CSS1Compat" ),
1324
+
1325
+ // Will be defined later
1326
+ submitBubbles: true,
1327
+ changeBubbles: true,
1328
+ focusinBubbles: false,
1329
+ deleteExpando: true,
1330
+ noCloneEvent: true,
1331
+ inlineBlockNeedsLayout: false,
1332
+ shrinkWrapBlocks: false,
1333
+ reliableMarginRight: true,
1334
+ boxSizingReliable: true,
1335
+ pixelPosition: false
1336
+ };
1337
+
1338
+ // Make sure checked status is properly cloned
1339
+ input.checked = true;
1340
+ support.noCloneChecked = input.cloneNode( true ).checked;
1341
+
1342
+ // Make sure that the options inside disabled selects aren't marked as disabled
1343
+ // (WebKit marks them as disabled)
1344
+ select.disabled = true;
1345
+ support.optDisabled = !opt.disabled;
1346
+
1347
+ // Test to see if it's possible to delete an expando from an element
1348
+ // Fails in Internet Explorer
1349
+ try {
1350
+ delete div.test;
1351
+ } catch( e ) {
1352
+ support.deleteExpando = false;
1353
+ }
1354
+
1355
+ if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
1356
+ div.attachEvent( "onclick", clickFn = function() {
1357
+ // Cloning a node shouldn't copy over any
1358
+ // bound event handlers (IE does this)
1359
+ support.noCloneEvent = false;
1360
+ });
1361
+ div.cloneNode( true ).fireEvent("onclick");
1362
+ div.detachEvent( "onclick", clickFn );
1363
+ }
1364
+
1365
+ // Check if a radio maintains its value
1366
+ // after being appended to the DOM
1367
+ input = document.createElement("input");
1368
+ input.value = "t";
1369
+ input.setAttribute( "type", "radio" );
1370
+ support.radioValue = input.value === "t";
1371
+
1372
+ input.setAttribute( "checked", "checked" );
1373
+
1374
+ // #11217 - WebKit loses check when the name is after the checked attribute
1375
+ input.setAttribute( "name", "t" );
1376
+
1377
+ div.appendChild( input );
1378
+ fragment = document.createDocumentFragment();
1379
+ fragment.appendChild( div.lastChild );
1380
+
1381
+ // WebKit doesn't clone checked state correctly in fragments
1382
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1383
+
1384
+ // Check if a disconnected checkbox will retain its checked
1385
+ // value of true after appended to the DOM (IE6/7)
1386
+ support.appendChecked = input.checked;
1387
+
1388
+ fragment.removeChild( input );
1389
+ fragment.appendChild( div );
1390
+
1391
+ // Technique from Juriy Zaytsev
1392
+ // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
1393
+ // We only care about the case where non-standard event systems
1394
+ // are used, namely in IE. Short-circuiting here helps us to
1395
+ // avoid an eval call (in setAttribute) which can cause CSP
1396
+ // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
1397
+ if ( div.attachEvent ) {
1398
+ for ( i in {
1399
+ submit: true,
1400
+ change: true,
1401
+ focusin: true
1402
+ }) {
1403
+ eventName = "on" + i;
1404
+ isSupported = ( eventName in div );
1405
+ if ( !isSupported ) {
1406
+ div.setAttribute( eventName, "return;" );
1407
+ isSupported = ( typeof div[ eventName ] === "function" );
1408
+ }
1409
+ support[ i + "Bubbles" ] = isSupported;
1410
+ }
1411
+ }
1412
+
1413
+ // Run tests that need a body at doc ready
1414
+ jQuery(function() {
1415
+ var container, div, tds, marginDiv,
1416
+ divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
1417
+ body = document.getElementsByTagName("body")[0];
1418
+
1419
+ if ( !body ) {
1420
+ // Return for frameset docs that don't have a body
1421
+ return;
1422
+ }
1423
+
1424
+ container = document.createElement("div");
1425
+ container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
1426
+ body.insertBefore( container, body.firstChild );
1427
+
1428
+ // Construct the test element
1429
+ div = document.createElement("div");
1430
+ container.appendChild( div );
1431
+
1432
+ // Check if table cells still have offsetWidth/Height when they are set
1433
+ // to display:none and there are still other visible table cells in a
1434
+ // table row; if so, offsetWidth/Height are not reliable for use when
1435
+ // determining if an element has been hidden directly using
1436
+ // display:none (it is still safe to use offsets if a parent element is
1437
+ // hidden; don safety goggles and see bug #4512 for more information).
1438
+ // (only IE 8 fails this test)
1439
+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1440
+ tds = div.getElementsByTagName("td");
1441
+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1442
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
1443
+
1444
+ tds[ 0 ].style.display = "";
1445
+ tds[ 1 ].style.display = "none";
1446
+
1447
+ // Check if empty table cells still have offsetWidth/Height
1448
+ // (IE <= 8 fail this test)
1449
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1450
+
1451
+ // Check box-sizing and margin behavior
1452
+ div.innerHTML = "";
1453
+ 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%;";
1454
+ support.boxSizing = ( div.offsetWidth === 4 );
1455
+ support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1456
+
1457
+ // NOTE: To any future maintainer, we've window.getComputedStyle
1458
+ // because jsdom on node.js will break without it.
1459
+ if ( window.getComputedStyle ) {
1460
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1461
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
1462
+
1463
+ // Check if div with explicit width and no margin-right incorrectly
1464
+ // gets computed margin-right based on width of container. For more
1465
+ // info see bug #3333
1466
+ // Fails in WebKit before Feb 2011 nightlies
1467
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1468
+ marginDiv = document.createElement("div");
1469
+ marginDiv.style.cssText = div.style.cssText = divReset;
1470
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
1471
+ div.style.width = "1px";
1472
+ div.appendChild( marginDiv );
1473
+ support.reliableMarginRight =
1474
+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
1475
+ }
1476
+
1477
+ if ( typeof div.style.zoom !== "undefined" ) {
1478
+ // Check if natively block-level elements act like inline-block
1479
+ // elements when setting their display to 'inline' and giving
1480
+ // them layout
1481
+ // (IE < 8 does this)
1482
+ div.innerHTML = "";
1483
+ div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
1484
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
1485
+
1486
+ // Check if elements with layout shrink-wrap their children
1487
+ // (IE 6 does this)
1488
+ div.style.display = "block";
1489
+ div.style.overflow = "visible";
1490
+ div.innerHTML = "<div></div>";
1491
+ div.firstChild.style.width = "5px";
1492
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
1493
+
1494
+ container.style.zoom = 1;
1495
+ }
1496
+
1497
+ // Null elements to avoid leaks in IE
1498
+ body.removeChild( container );
1499
+ container = div = tds = marginDiv = null;
1500
+ });
1501
+
1502
+ // Null elements to avoid leaks in IE
1503
+ fragment.removeChild( div );
1504
+ all = a = select = opt = input = fragment = div = null;
1505
+
1506
+ return support;
1507
+ })();
1508
+ var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
1509
+ rmultiDash = /([A-Z])/g;
1510
+
1511
+ jQuery.extend({
1512
+ cache: {},
1513
+
1514
+ deletedIds: [],
1515
+
1516
+ // Please use with caution
1517
+ uuid: 0,
1518
+
1519
+ // Unique for each copy of jQuery on the page
1520
+ // Non-digits removed to match rinlinejQuery
1521
+ expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
1522
+
1523
+ // The following elements throw uncatchable exceptions if you
1524
+ // attempt to add expando properties to them.
1525
+ noData: {
1526
+ "embed": true,
1527
+ // Ban all objects except for Flash (which handle expandos)
1528
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1529
+ "applet": true
1530
+ },
1531
+
1532
+ hasData: function( elem ) {
1533
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1534
+ return !!elem && !isEmptyDataObject( elem );
1535
+ },
1536
+
1537
+ data: function( elem, name, data, pvt /* Internal Use Only */ ) {
1538
+ if ( !jQuery.acceptData( elem ) ) {
1539
+ return;
1540
+ }
1541
+
1542
+ var thisCache, ret,
1543
+ internalKey = jQuery.expando,
1544
+ getByName = typeof name === "string",
1545
+
1546
+ // We have to handle DOM nodes and JS objects differently because IE6-7
1547
+ // can't GC object references properly across the DOM-JS boundary
1548
+ isNode = elem.nodeType,
1549
+
1550
+ // Only DOM nodes need the global jQuery cache; JS object data is
1551
+ // attached directly to the object so GC can occur automatically
1552
+ cache = isNode ? jQuery.cache : elem,
1553
+
1554
+ // Only defining an ID for JS objects if its cache already exists allows
1555
+ // the code to shortcut on the same path as a DOM node with no cache
1556
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
1557
+
1558
+ // Avoid doing any more work than we need to when trying to get data on an
1559
+ // object that has no data at all
1560
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
1561
+ return;
1562
+ }
1563
+
1564
+ if ( !id ) {
1565
+ // Only DOM nodes need a new unique ID for each element since their data
1566
+ // ends up in the global cache
1567
+ if ( isNode ) {
1568
+ elem[ internalKey ] = id = jQuery.deletedIds.pop() || ++jQuery.uuid;
1569
+ } else {
1570
+ id = internalKey;
1571
+ }
1572
+ }
1573
+
1574
+ if ( !cache[ id ] ) {
1575
+ cache[ id ] = {};
1576
+
1577
+ // Avoids exposing jQuery metadata on plain JS objects when the object
1578
+ // is serialized using JSON.stringify
1579
+ if ( !isNode ) {
1580
+ cache[ id ].toJSON = jQuery.noop;
1581
+ }
1582
+ }
1583
+
1584
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
1585
+ // shallow copied over onto the existing cache
1586
+ if ( typeof name === "object" || typeof name === "function" ) {
1587
+ if ( pvt ) {
1588
+ cache[ id ] = jQuery.extend( cache[ id ], name );
1589
+ } else {
1590
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1591
+ }
1592
+ }
1593
+
1594
+ thisCache = cache[ id ];
1595
+
1596
+ // jQuery data() is stored in a separate object inside the object's internal data
1597
+ // cache in order to avoid key collisions between internal data and user-defined
1598
+ // data.
1599
+ if ( !pvt ) {
1600
+ if ( !thisCache.data ) {
1601
+ thisCache.data = {};
1602
+ }
1603
+
1604
+ thisCache = thisCache.data;
1605
+ }
1606
+
1607
+ if ( data !== undefined ) {
1608
+ thisCache[ jQuery.camelCase( name ) ] = data;
1609
+ }
1610
+
1611
+ // Check for both converted-to-camel and non-converted data property names
1612
+ // If a data property was specified
1613
+ if ( getByName ) {
1614
+
1615
+ // First Try to find as-is property data
1616
+ ret = thisCache[ name ];
1617
+
1618
+ // Test for null|undefined property data
1619
+ if ( ret == null ) {
1620
+
1621
+ // Try to find the camelCased property
1622
+ ret = thisCache[ jQuery.camelCase( name ) ];
1623
+ }
1624
+ } else {
1625
+ ret = thisCache;
1626
+ }
1627
+
1628
+ return ret;
1629
+ },
1630
+
1631
+ removeData: function( elem, name, pvt /* Internal Use Only */ ) {
1632
+ if ( !jQuery.acceptData( elem ) ) {
1633
+ return;
1634
+ }
1635
+
1636
+ var thisCache, i, l,
1637
+
1638
+ isNode = elem.nodeType,
1639
+
1640
+ // See jQuery.data for more information
1641
+ cache = isNode ? jQuery.cache : elem,
1642
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1643
+
1644
+ // If there is already no cache entry for this object, there is no
1645
+ // purpose in continuing
1646
+ if ( !cache[ id ] ) {
1647
+ return;
1648
+ }
1649
+
1650
+ if ( name ) {
1651
+
1652
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
1653
+
1654
+ if ( thisCache ) {
1655
+
1656
+ // Support array or space separated string names for data keys
1657
+ if ( !jQuery.isArray( name ) ) {
1658
+
1659
+ // try the string as a key before any manipulation
1660
+ if ( name in thisCache ) {
1661
+ name = [ name ];
1662
+ } else {
1663
+
1664
+ // split the camel cased version by spaces unless a key with the spaces exists
1665
+ name = jQuery.camelCase( name );
1666
+ if ( name in thisCache ) {
1667
+ name = [ name ];
1668
+ } else {
1669
+ name = name.split(" ");
1670
+ }
1671
+ }
1672
+ }
1673
+
1674
+ for ( i = 0, l = name.length; i < l; i++ ) {
1675
+ delete thisCache[ name[i] ];
1676
+ }
1677
+
1678
+ // If there is no data left in the cache, we want to continue
1679
+ // and let the cache object itself get destroyed
1680
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1681
+ return;
1682
+ }
1683
+ }
1684
+ }
1685
+
1686
+ // See jQuery.data for more information
1687
+ if ( !pvt ) {
1688
+ delete cache[ id ].data;
1689
+
1690
+ // Don't destroy the parent cache unless the internal data object
1691
+ // had been the only thing left in it
1692
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
1693
+ return;
1694
+ }
1695
+ }
1696
+
1697
+ // Destroy the cache
1698
+ if ( isNode ) {
1699
+ jQuery.cleanData( [ elem ], true );
1700
+
1701
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
1702
+ } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
1703
+ delete cache[ id ];
1704
+
1705
+ // When all else fails, null
1706
+ } else {
1707
+ cache[ id ] = null;
1708
+ }
1709
+ },
1710
+
1711
+ // For internal use only.
1712
+ _data: function( elem, name, data ) {
1713
+ return jQuery.data( elem, name, data, true );
1714
+ },
1715
+
1716
+ // A method for determining if a DOM node can handle the data expando
1717
+ acceptData: function( elem ) {
1718
+ var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
1719
+
1720
+ // nodes accept data unless otherwise specified; rejection can be conditional
1721
+ return !noData || noData !== true && elem.getAttribute("classid") === noData;
1722
+ }
1723
+ });
1724
+
1725
+ jQuery.fn.extend({
1726
+ data: function( key, value ) {
1727
+ var parts, part, attr, name, l,
1728
+ elem = this[0],
1729
+ i = 0,
1730
+ data = null;
1731
+
1732
+ // Gets all values
1733
+ if ( key === undefined ) {
1734
+ if ( this.length ) {
1735
+ data = jQuery.data( elem );
1736
+
1737
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
1738
+ attr = elem.attributes;
1739
+ for ( l = attr.length; i < l; i++ ) {
1740
+ name = attr[i].name;
1741
+
1742
+ if ( name.indexOf( "data-" ) === 0 ) {
1743
+ name = jQuery.camelCase( name.substring(5) );
1744
+
1745
+ dataAttr( elem, name, data[ name ] );
1746
+ }
1747
+ }
1748
+ jQuery._data( elem, "parsedAttrs", true );
1749
+ }
1750
+ }
1751
+
1752
+ return data;
1753
+ }
1754
+
1755
+ // Sets multiple values
1756
+ if ( typeof key === "object" ) {
1757
+ return this.each(function() {
1758
+ jQuery.data( this, key );
1759
+ });
1760
+ }
1761
+
1762
+ parts = key.split( ".", 2 );
1763
+ parts[1] = parts[1] ? "." + parts[1] : "";
1764
+ part = parts[1] + "!";
1765
+
1766
+ return jQuery.access( this, function( value ) {
1767
+
1768
+ if ( value === undefined ) {
1769
+ data = this.triggerHandler( "getData" + part, [ parts[0] ] );
1770
+
1771
+ // Try to fetch any internally stored data first
1772
+ if ( data === undefined && elem ) {
1773
+ data = jQuery.data( elem, key );
1774
+ data = dataAttr( elem, key, data );
1775
+ }
1776
+
1777
+ return data === undefined && parts[1] ?
1778
+ this.data( parts[0] ) :
1779
+ data;
1780
+ }
1781
+
1782
+ parts[1] = value;
1783
+ this.each(function() {
1784
+ var self = jQuery( this );
1785
+
1786
+ self.triggerHandler( "setData" + part, parts );
1787
+ jQuery.data( this, key, value );
1788
+ self.triggerHandler( "changeData" + part, parts );
1789
+ });
1790
+ }, null, value, arguments.length > 1, null, false );
1791
+ },
1792
+
1793
+ removeData: function( key ) {
1794
+ return this.each(function() {
1795
+ jQuery.removeData( this, key );
1796
+ });
1797
+ }
1798
+ });
1799
+
1800
+ function dataAttr( elem, key, data ) {
1801
+ // If nothing was found internally, try to fetch any
1802
+ // data from the HTML5 data-* attribute
1803
+ if ( data === undefined && elem.nodeType === 1 ) {
1804
+
1805
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1806
+
1807
+ data = elem.getAttribute( name );
1808
+
1809
+ if ( typeof data === "string" ) {
1810
+ try {
1811
+ data = data === "true" ? true :
1812
+ data === "false" ? false :
1813
+ data === "null" ? null :
1814
+ // Only convert to a number if it doesn't change the string
1815
+ +data + "" === data ? +data :
1816
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
1817
+ data;
1818
+ } catch( e ) {}
1819
+
1820
+ // Make sure we set the data so it isn't changed later
1821
+ jQuery.data( elem, key, data );
1822
+
1823
+ } else {
1824
+ data = undefined;
1825
+ }
1826
+ }
1827
+
1828
+ return data;
1829
+ }
1830
+
1831
+ // checks a cache object for emptiness
1832
+ function isEmptyDataObject( obj ) {
1833
+ var name;
1834
+ for ( name in obj ) {
1835
+
1836
+ // if the public data object is empty, the private is still empty
1837
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1838
+ continue;
1839
+ }
1840
+ if ( name !== "toJSON" ) {
1841
+ return false;
1842
+ }
1843
+ }
1844
+
1845
+ return true;
1846
+ }
1847
+ jQuery.extend({
1848
+ queue: function( elem, type, data ) {
1849
+ var queue;
1850
+
1851
+ if ( elem ) {
1852
+ type = ( type || "fx" ) + "queue";
1853
+ queue = jQuery._data( elem, type );
1854
+
1855
+ // Speed up dequeue by getting out quickly if this is just a lookup
1856
+ if ( data ) {
1857
+ if ( !queue || jQuery.isArray(data) ) {
1858
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
1859
+ } else {
1860
+ queue.push( data );
1861
+ }
1862
+ }
1863
+ return queue || [];
1864
+ }
1865
+ },
1866
+
1867
+ dequeue: function( elem, type ) {
1868
+ type = type || "fx";
1869
+
1870
+ var queue = jQuery.queue( elem, type ),
1871
+ startLength = queue.length,
1872
+ fn = queue.shift(),
1873
+ hooks = jQuery._queueHooks( elem, type ),
1874
+ next = function() {
1875
+ jQuery.dequeue( elem, type );
1876
+ };
1877
+
1878
+ // If the fx queue is dequeued, always remove the progress sentinel
1879
+ if ( fn === "inprogress" ) {
1880
+ fn = queue.shift();
1881
+ startLength--;
1882
+ }
1883
+
1884
+ if ( fn ) {
1885
+
1886
+ // Add a progress sentinel to prevent the fx queue from being
1887
+ // automatically dequeued
1888
+ if ( type === "fx" ) {
1889
+ queue.unshift( "inprogress" );
1890
+ }
1891
+
1892
+ // clear up the last queue stop function
1893
+ delete hooks.stop;
1894
+ fn.call( elem, next, hooks );
1895
+ }
1896
+
1897
+ if ( !startLength && hooks ) {
1898
+ hooks.empty.fire();
1899
+ }
1900
+ },
1901
+
1902
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
1903
+ _queueHooks: function( elem, type ) {
1904
+ var key = type + "queueHooks";
1905
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
1906
+ empty: jQuery.Callbacks("once memory").add(function() {
1907
+ jQuery.removeData( elem, type + "queue", true );
1908
+ jQuery.removeData( elem, key, true );
1909
+ })
1910
+ });
1911
+ }
1912
+ });
1913
+
1914
+ jQuery.fn.extend({
1915
+ queue: function( type, data ) {
1916
+ var setter = 2;
1917
+
1918
+ if ( typeof type !== "string" ) {
1919
+ data = type;
1920
+ type = "fx";
1921
+ setter--;
1922
+ }
1923
+
1924
+ if ( arguments.length < setter ) {
1925
+ return jQuery.queue( this[0], type );
1926
+ }
1927
+
1928
+ return data === undefined ?
1929
+ this :
1930
+ this.each(function() {
1931
+ var queue = jQuery.queue( this, type, data );
1932
+
1933
+ // ensure a hooks for this queue
1934
+ jQuery._queueHooks( this, type );
1935
+
1936
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
1937
+ jQuery.dequeue( this, type );
1938
+ }
1939
+ });
1940
+ },
1941
+ dequeue: function( type ) {
1942
+ return this.each(function() {
1943
+ jQuery.dequeue( this, type );
1944
+ });
1945
+ },
1946
+ // Based off of the plugin by Clint Helfers, with permission.
1947
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
1948
+ delay: function( time, type ) {
1949
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
1950
+ type = type || "fx";
1951
+
1952
+ return this.queue( type, function( next, hooks ) {
1953
+ var timeout = setTimeout( next, time );
1954
+ hooks.stop = function() {
1955
+ clearTimeout( timeout );
1956
+ };
1957
+ });
1958
+ },
1959
+ clearQueue: function( type ) {
1960
+ return this.queue( type || "fx", [] );
1961
+ },
1962
+ // Get a promise resolved when queues of a certain type
1963
+ // are emptied (fx is the type by default)
1964
+ promise: function( type, obj ) {
1965
+ var tmp,
1966
+ count = 1,
1967
+ defer = jQuery.Deferred(),
1968
+ elements = this,
1969
+ i = this.length,
1970
+ resolve = function() {
1971
+ if ( !( --count ) ) {
1972
+ defer.resolveWith( elements, [ elements ] );
1973
+ }
1974
+ };
1975
+
1976
+ if ( typeof type !== "string" ) {
1977
+ obj = type;
1978
+ type = undefined;
1979
+ }
1980
+ type = type || "fx";
1981
+
1982
+ while( i-- ) {
1983
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
1984
+ if ( tmp && tmp.empty ) {
1985
+ count++;
1986
+ tmp.empty.add( resolve );
1987
+ }
1988
+ }
1989
+ resolve();
1990
+ return defer.promise( obj );
1991
+ }
1992
+ });
1993
+ var nodeHook, boolHook, fixSpecified,
1994
+ rclass = /[\t\r\n]/g,
1995
+ rreturn = /\r/g,
1996
+ rtype = /^(?:button|input)$/i,
1997
+ rfocusable = /^(?:button|input|object|select|textarea)$/i,
1998
+ rclickable = /^a(?:rea|)$/i,
1999
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
2000
+ getSetAttribute = jQuery.support.getSetAttribute;
2001
+
2002
+ jQuery.fn.extend({
2003
+ attr: function( name, value ) {
2004
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
2005
+ },
2006
+
2007
+ removeAttr: function( name ) {
2008
+ return this.each(function() {
2009
+ jQuery.removeAttr( this, name );
2010
+ });
2011
+ },
2012
+
2013
+ prop: function( name, value ) {
2014
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2015
+ },
2016
+
2017
+ removeProp: function( name ) {
2018
+ name = jQuery.propFix[ name ] || name;
2019
+ return this.each(function() {
2020
+ // try/catch handles cases where IE balks (such as removing a property on window)
2021
+ try {
2022
+ this[ name ] = undefined;
2023
+ delete this[ name ];
2024
+ } catch( e ) {}
2025
+ });
2026
+ },
2027
+
2028
+ addClass: function( value ) {
2029
+ var classNames, i, l, elem,
2030
+ setClass, c, cl;
2031
+
2032
+ if ( jQuery.isFunction( value ) ) {
2033
+ return this.each(function( j ) {
2034
+ jQuery( this ).addClass( value.call(this, j, this.className) );
2035
+ });
2036
+ }
2037
+
2038
+ if ( value && typeof value === "string" ) {
2039
+ classNames = value.split( core_rspace );
2040
+
2041
+ for ( i = 0, l = this.length; i < l; i++ ) {
2042
+ elem = this[ i ];
2043
+
2044
+ if ( elem.nodeType === 1 ) {
2045
+ if ( !elem.className && classNames.length === 1 ) {
2046
+ elem.className = value;
2047
+
2048
+ } else {
2049
+ setClass = " " + elem.className + " ";
2050
+
2051
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2052
+ if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
2053
+ setClass += classNames[ c ] + " ";
2054
+ }
2055
+ }
2056
+ elem.className = jQuery.trim( setClass );
2057
+ }
2058
+ }
2059
+ }
2060
+ }
2061
+
2062
+ return this;
2063
+ },
2064
+
2065
+ removeClass: function( value ) {
2066
+ var removes, className, elem, c, cl, i, l;
2067
+
2068
+ if ( jQuery.isFunction( value ) ) {
2069
+ return this.each(function( j ) {
2070
+ jQuery( this ).removeClass( value.call(this, j, this.className) );
2071
+ });
2072
+ }
2073
+ if ( (value && typeof value === "string") || value === undefined ) {
2074
+ removes = ( value || "" ).split( core_rspace );
2075
+
2076
+ for ( i = 0, l = this.length; i < l; i++ ) {
2077
+ elem = this[ i ];
2078
+ if ( elem.nodeType === 1 && elem.className ) {
2079
+
2080
+ className = (" " + elem.className + " ").replace( rclass, " " );
2081
+
2082
+ // loop over each item in the removal list
2083
+ for ( c = 0, cl = removes.length; c < cl; c++ ) {
2084
+ // Remove until there is nothing to remove,
2085
+ while ( className.indexOf(" " + removes[ c ] + " ") > -1 ) {
2086
+ className = className.replace( " " + removes[ c ] + " " , " " );
2087
+ }
2088
+ }
2089
+ elem.className = value ? jQuery.trim( className ) : "";
2090
+ }
2091
+ }
2092
+ }
2093
+
2094
+ return this;
2095
+ },
2096
+
2097
+ toggleClass: function( value, stateVal ) {
2098
+ var type = typeof value,
2099
+ isBool = typeof stateVal === "boolean";
2100
+
2101
+ if ( jQuery.isFunction( value ) ) {
2102
+ return this.each(function( i ) {
2103
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2104
+ });
2105
+ }
2106
+
2107
+ return this.each(function() {
2108
+ if ( type === "string" ) {
2109
+ // toggle individual class names
2110
+ var className,
2111
+ i = 0,
2112
+ self = jQuery( this ),
2113
+ state = stateVal,
2114
+ classNames = value.split( core_rspace );
2115
+
2116
+ while ( (className = classNames[ i++ ]) ) {
2117
+ // check each className given, space separated list
2118
+ state = isBool ? state : !self.hasClass( className );
2119
+ self[ state ? "addClass" : "removeClass" ]( className );
2120
+ }
2121
+
2122
+ } else if ( type === "undefined" || type === "boolean" ) {
2123
+ if ( this.className ) {
2124
+ // store className if set
2125
+ jQuery._data( this, "__className__", this.className );
2126
+ }
2127
+
2128
+ // toggle whole className
2129
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2130
+ }
2131
+ });
2132
+ },
2133
+
2134
+ hasClass: function( selector ) {
2135
+ var className = " " + selector + " ",
2136
+ i = 0,
2137
+ l = this.length;
2138
+ for ( ; i < l; i++ ) {
2139
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2140
+ return true;
2141
+ }
2142
+ }
2143
+
2144
+ return false;
2145
+ },
2146
+
2147
+ val: function( value ) {
2148
+ var hooks, ret, isFunction,
2149
+ elem = this[0];
2150
+
2151
+ if ( !arguments.length ) {
2152
+ if ( elem ) {
2153
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
2154
+
2155
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2156
+ return ret;
2157
+ }
2158
+
2159
+ ret = elem.value;
2160
+
2161
+ return typeof ret === "string" ?
2162
+ // handle most common string cases
2163
+ ret.replace(rreturn, "") :
2164
+ // handle cases where value is null/undef or number
2165
+ ret == null ? "" : ret;
2166
+ }
2167
+
2168
+ return;
2169
+ }
2170
+
2171
+ isFunction = jQuery.isFunction( value );
2172
+
2173
+ return this.each(function( i ) {
2174
+ var val,
2175
+ self = jQuery(this);
2176
+
2177
+ if ( this.nodeType !== 1 ) {
2178
+ return;
2179
+ }
2180
+
2181
+ if ( isFunction ) {
2182
+ val = value.call( this, i, self.val() );
2183
+ } else {
2184
+ val = value;
2185
+ }
2186
+
2187
+ // Treat null/undefined as ""; convert numbers to string
2188
+ if ( val == null ) {
2189
+ val = "";
2190
+ } else if ( typeof val === "number" ) {
2191
+ val += "";
2192
+ } else if ( jQuery.isArray( val ) ) {
2193
+ val = jQuery.map(val, function ( value ) {
2194
+ return value == null ? "" : value + "";
2195
+ });
2196
+ }
2197
+
2198
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
2199
+
2200
+ // If set returns undefined, fall back to normal setting
2201
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2202
+ this.value = val;
2203
+ }
2204
+ });
2205
+ }
2206
+ });
2207
+
2208
+ jQuery.extend({
2209
+ valHooks: {
2210
+ option: {
2211
+ get: function( elem ) {
2212
+ // attributes.value is undefined in Blackberry 4.7 but
2213
+ // uses .value. See #6932
2214
+ var val = elem.attributes.value;
2215
+ return !val || val.specified ? elem.value : elem.text;
2216
+ }
2217
+ },
2218
+ select: {
2219
+ get: function( elem ) {
2220
+ var value, i, max, option,
2221
+ index = elem.selectedIndex,
2222
+ values = [],
2223
+ options = elem.options,
2224
+ one = elem.type === "select-one";
2225
+
2226
+ // Nothing was selected
2227
+ if ( index < 0 ) {
2228
+ return null;
2229
+ }
2230
+
2231
+ // Loop through all the selected options
2232
+ i = one ? index : 0;
2233
+ max = one ? index + 1 : options.length;
2234
+ for ( ; i < max; i++ ) {
2235
+ option = options[ i ];
2236
+
2237
+ // Don't return options that are disabled or in a disabled optgroup
2238
+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
2239
+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
2240
+
2241
+ // Get the specific value for the option
2242
+ value = jQuery( option ).val();
2243
+
2244
+ // We don't need an array for one selects
2245
+ if ( one ) {
2246
+ return value;
2247
+ }
2248
+
2249
+ // Multi-Selects return an array
2250
+ values.push( value );
2251
+ }
2252
+ }
2253
+
2254
+ // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
2255
+ if ( one && !values.length && options.length ) {
2256
+ return jQuery( options[ index ] ).val();
2257
+ }
2258
+
2259
+ return values;
2260
+ },
2261
+
2262
+ set: function( elem, value ) {
2263
+ var values = jQuery.makeArray( value );
2264
+
2265
+ jQuery(elem).find("option").each(function() {
2266
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2267
+ });
2268
+
2269
+ if ( !values.length ) {
2270
+ elem.selectedIndex = -1;
2271
+ }
2272
+ return values;
2273
+ }
2274
+ }
2275
+ },
2276
+
2277
+ // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
2278
+ attrFn: {},
2279
+
2280
+ attr: function( elem, name, value, pass ) {
2281
+ var ret, hooks, notxml,
2282
+ nType = elem.nodeType;
2283
+
2284
+ // don't get/set attributes on text, comment and attribute nodes
2285
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2286
+ return;
2287
+ }
2288
+
2289
+ if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
2290
+ return jQuery( elem )[ name ]( value );
2291
+ }
2292
+
2293
+ // Fallback to prop when attributes are not supported
2294
+ if ( typeof elem.getAttribute === "undefined" ) {
2295
+ return jQuery.prop( elem, name, value );
2296
+ }
2297
+
2298
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2299
+
2300
+ // All attributes are lowercase
2301
+ // Grab necessary hook if one is defined
2302
+ if ( notxml ) {
2303
+ name = name.toLowerCase();
2304
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2305
+ }
2306
+
2307
+ if ( value !== undefined ) {
2308
+
2309
+ if ( value === null ) {
2310
+ jQuery.removeAttr( elem, name );
2311
+ return;
2312
+
2313
+ } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
2314
+ return ret;
2315
+
2316
+ } else {
2317
+ elem.setAttribute( name, "" + value );
2318
+ return value;
2319
+ }
2320
+
2321
+ } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
2322
+ return ret;
2323
+
2324
+ } else {
2325
+
2326
+ ret = elem.getAttribute( name );
2327
+
2328
+ // Non-existent attributes return null, we normalize to undefined
2329
+ return ret === null ?
2330
+ undefined :
2331
+ ret;
2332
+ }
2333
+ },
2334
+
2335
+ removeAttr: function( elem, value ) {
2336
+ var propName, attrNames, name, isBool,
2337
+ i = 0;
2338
+
2339
+ if ( value && elem.nodeType === 1 ) {
2340
+
2341
+ attrNames = value.split( core_rspace );
2342
+
2343
+ for ( ; i < attrNames.length; i++ ) {
2344
+ name = attrNames[ i ];
2345
+
2346
+ if ( name ) {
2347
+ propName = jQuery.propFix[ name ] || name;
2348
+ isBool = rboolean.test( name );
2349
+
2350
+ // See #9699 for explanation of this approach (setting first, then removal)
2351
+ // Do not do this for boolean attributes (see #10870)
2352
+ if ( !isBool ) {
2353
+ jQuery.attr( elem, name, "" );
2354
+ }
2355
+ elem.removeAttribute( getSetAttribute ? name : propName );
2356
+
2357
+ // Set corresponding property to false for boolean attributes
2358
+ if ( isBool && propName in elem ) {
2359
+ elem[ propName ] = false;
2360
+ }
2361
+ }
2362
+ }
2363
+ }
2364
+ },
2365
+
2366
+ attrHooks: {
2367
+ type: {
2368
+ set: function( elem, value ) {
2369
+ // We can't allow the type property to be changed (since it causes problems in IE)
2370
+ if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
2371
+ jQuery.error( "type property can't be changed" );
2372
+ } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2373
+ // Setting the type on a radio button after the value resets the value in IE6-9
2374
+ // Reset value to it's default in case type is set after value
2375
+ // This is for element creation
2376
+ var val = elem.value;
2377
+ elem.setAttribute( "type", value );
2378
+ if ( val ) {
2379
+ elem.value = val;
2380
+ }
2381
+ return value;
2382
+ }
2383
+ }
2384
+ },
2385
+ // Use the value property for back compat
2386
+ // Use the nodeHook for button elements in IE6/7 (#1954)
2387
+ value: {
2388
+ get: function( elem, name ) {
2389
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2390
+ return nodeHook.get( elem, name );
2391
+ }
2392
+ return name in elem ?
2393
+ elem.value :
2394
+ null;
2395
+ },
2396
+ set: function( elem, value, name ) {
2397
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2398
+ return nodeHook.set( elem, value, name );
2399
+ }
2400
+ // Does not return so that setAttribute is also used
2401
+ elem.value = value;
2402
+ }
2403
+ }
2404
+ },
2405
+
2406
+ propFix: {
2407
+ tabindex: "tabIndex",
2408
+ readonly: "readOnly",
2409
+ "for": "htmlFor",
2410
+ "class": "className",
2411
+ maxlength: "maxLength",
2412
+ cellspacing: "cellSpacing",
2413
+ cellpadding: "cellPadding",
2414
+ rowspan: "rowSpan",
2415
+ colspan: "colSpan",
2416
+ usemap: "useMap",
2417
+ frameborder: "frameBorder",
2418
+ contenteditable: "contentEditable"
2419
+ },
2420
+
2421
+ prop: function( elem, name, value ) {
2422
+ var ret, hooks, notxml,
2423
+ nType = elem.nodeType;
2424
+
2425
+ // don't get/set properties on text, comment and attribute nodes
2426
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2427
+ return;
2428
+ }
2429
+
2430
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2431
+
2432
+ if ( notxml ) {
2433
+ // Fix name and attach hooks
2434
+ name = jQuery.propFix[ name ] || name;
2435
+ hooks = jQuery.propHooks[ name ];
2436
+ }
2437
+
2438
+ if ( value !== undefined ) {
2439
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2440
+ return ret;
2441
+
2442
+ } else {
2443
+ return ( elem[ name ] = value );
2444
+ }
2445
+
2446
+ } else {
2447
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2448
+ return ret;
2449
+
2450
+ } else {
2451
+ return elem[ name ];
2452
+ }
2453
+ }
2454
+ },
2455
+
2456
+ propHooks: {
2457
+ tabIndex: {
2458
+ get: function( elem ) {
2459
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2460
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2461
+ var attributeNode = elem.getAttributeNode("tabindex");
2462
+
2463
+ return attributeNode && attributeNode.specified ?
2464
+ parseInt( attributeNode.value, 10 ) :
2465
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2466
+ 0 :
2467
+ undefined;
2468
+ }
2469
+ }
2470
+ }
2471
+ });
2472
+
2473
+ // Hook for boolean attributes
2474
+ boolHook = {
2475
+ get: function( elem, name ) {
2476
+ // Align boolean attributes with corresponding properties
2477
+ // Fall back to attribute presence where some booleans are not supported
2478
+ var attrNode,
2479
+ property = jQuery.prop( elem, name );
2480
+ return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
2481
+ name.toLowerCase() :
2482
+ undefined;
2483
+ },
2484
+ set: function( elem, value, name ) {
2485
+ var propName;
2486
+ if ( value === false ) {
2487
+ // Remove boolean attributes when set to false
2488
+ jQuery.removeAttr( elem, name );
2489
+ } else {
2490
+ // value is true since we know at this point it's type boolean and not false
2491
+ // Set boolean attributes to the same name and set the DOM property
2492
+ propName = jQuery.propFix[ name ] || name;
2493
+ if ( propName in elem ) {
2494
+ // Only set the IDL specifically if it already exists on the element
2495
+ elem[ propName ] = true;
2496
+ }
2497
+
2498
+ elem.setAttribute( name, name.toLowerCase() );
2499
+ }
2500
+ return name;
2501
+ }
2502
+ };
2503
+
2504
+ // IE6/7 do not support getting/setting some attributes with get/setAttribute
2505
+ if ( !getSetAttribute ) {
2506
+
2507
+ fixSpecified = {
2508
+ name: true,
2509
+ id: true,
2510
+ coords: true
2511
+ };
2512
+
2513
+ // Use this for any attribute in IE6/7
2514
+ // This fixes almost every IE6/7 issue
2515
+ nodeHook = jQuery.valHooks.button = {
2516
+ get: function( elem, name ) {
2517
+ var ret;
2518
+ ret = elem.getAttributeNode( name );
2519
+ return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
2520
+ ret.value :
2521
+ undefined;
2522
+ },
2523
+ set: function( elem, value, name ) {
2524
+ // Set the existing or create a new attribute node
2525
+ var ret = elem.getAttributeNode( name );
2526
+ if ( !ret ) {
2527
+ ret = document.createAttribute( name );
2528
+ elem.setAttributeNode( ret );
2529
+ }
2530
+ return ( ret.value = value + "" );
2531
+ }
2532
+ };
2533
+
2534
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2535
+ // This is for removals
2536
+ jQuery.each([ "width", "height" ], function( i, name ) {
2537
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2538
+ set: function( elem, value ) {
2539
+ if ( value === "" ) {
2540
+ elem.setAttribute( name, "auto" );
2541
+ return value;
2542
+ }
2543
+ }
2544
+ });
2545
+ });
2546
+
2547
+ // Set contenteditable to false on removals(#10429)
2548
+ // Setting to empty string throws an error as an invalid value
2549
+ jQuery.attrHooks.contenteditable = {
2550
+ get: nodeHook.get,
2551
+ set: function( elem, value, name ) {
2552
+ if ( value === "" ) {
2553
+ value = "false";
2554
+ }
2555
+ nodeHook.set( elem, value, name );
2556
+ }
2557
+ };
2558
+ }
2559
+
2560
+
2561
+ // Some attributes require a special call on IE
2562
+ if ( !jQuery.support.hrefNormalized ) {
2563
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2564
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2565
+ get: function( elem ) {
2566
+ var ret = elem.getAttribute( name, 2 );
2567
+ return ret === null ? undefined : ret;
2568
+ }
2569
+ });
2570
+ });
2571
+ }
2572
+
2573
+ if ( !jQuery.support.style ) {
2574
+ jQuery.attrHooks.style = {
2575
+ get: function( elem ) {
2576
+ // Return undefined in the case of empty string
2577
+ // Normalize to lowercase since IE uppercases css property names
2578
+ return elem.style.cssText.toLowerCase() || undefined;
2579
+ },
2580
+ set: function( elem, value ) {
2581
+ return ( elem.style.cssText = "" + value );
2582
+ }
2583
+ };
2584
+ }
2585
+
2586
+ // Safari mis-reports the default selected property of an option
2587
+ // Accessing the parent's selectedIndex property fixes it
2588
+ if ( !jQuery.support.optSelected ) {
2589
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2590
+ get: function( elem ) {
2591
+ var parent = elem.parentNode;
2592
+
2593
+ if ( parent ) {
2594
+ parent.selectedIndex;
2595
+
2596
+ // Make sure that it also works with optgroups, see #5701
2597
+ if ( parent.parentNode ) {
2598
+ parent.parentNode.selectedIndex;
2599
+ }
2600
+ }
2601
+ return null;
2602
+ }
2603
+ });
2604
+ }
2605
+
2606
+ // IE6/7 call enctype encoding
2607
+ if ( !jQuery.support.enctype ) {
2608
+ jQuery.propFix.enctype = "encoding";
2609
+ }
2610
+
2611
+ // Radios and checkboxes getter/setter
2612
+ if ( !jQuery.support.checkOn ) {
2613
+ jQuery.each([ "radio", "checkbox" ], function() {
2614
+ jQuery.valHooks[ this ] = {
2615
+ get: function( elem ) {
2616
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2617
+ return elem.getAttribute("value") === null ? "on" : elem.value;
2618
+ }
2619
+ };
2620
+ });
2621
+ }
2622
+ jQuery.each([ "radio", "checkbox" ], function() {
2623
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2624
+ set: function( elem, value ) {
2625
+ if ( jQuery.isArray( value ) ) {
2626
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2627
+ }
2628
+ }
2629
+ });
2630
+ });
2631
+ var rformElems = /^(?:textarea|input|select)$/i,
2632
+ rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
2633
+ rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
2634
+ rkeyEvent = /^key/,
2635
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
2636
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2637
+ hoverHack = function( events ) {
2638
+ return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
2639
+ };
2640
+
2641
+ /*
2642
+ * Helper functions for managing events -- not part of the public interface.
2643
+ * Props to Dean Edwards' addEvent library for many of the ideas.
2644
+ */
2645
+ jQuery.event = {
2646
+
2647
+ add: function( elem, types, handler, data, selector ) {
2648
+
2649
+ var elemData, eventHandle, events,
2650
+ t, tns, type, namespaces, handleObj,
2651
+ handleObjIn, handlers, special;
2652
+
2653
+ // Don't attach events to noData or text/comment nodes (allow plain objects tho)
2654
+ if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
2655
+ return;
2656
+ }
2657
+
2658
+ // Caller can pass in an object of custom data in lieu of the handler
2659
+ if ( handler.handler ) {
2660
+ handleObjIn = handler;
2661
+ handler = handleObjIn.handler;
2662
+ selector = handleObjIn.selector;
2663
+ }
2664
+
2665
+ // Make sure that the handler has a unique ID, used to find/remove it later
2666
+ if ( !handler.guid ) {
2667
+ handler.guid = jQuery.guid++;
2668
+ }
2669
+
2670
+ // Init the element's event structure and main handler, if this is the first
2671
+ events = elemData.events;
2672
+ if ( !events ) {
2673
+ elemData.events = events = {};
2674
+ }
2675
+ eventHandle = elemData.handle;
2676
+ if ( !eventHandle ) {
2677
+ elemData.handle = eventHandle = function( e ) {
2678
+ // Discard the second event of a jQuery.event.trigger() and
2679
+ // when an event is called after a page has unloaded
2680
+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
2681
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2682
+ undefined;
2683
+ };
2684
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2685
+ eventHandle.elem = elem;
2686
+ }
2687
+
2688
+ // Handle multiple events separated by a space
2689
+ // jQuery(...).bind("mouseover mouseout", fn);
2690
+ types = jQuery.trim( hoverHack(types) ).split( " " );
2691
+ for ( t = 0; t < types.length; t++ ) {
2692
+
2693
+ tns = rtypenamespace.exec( types[t] ) || [];
2694
+ type = tns[1];
2695
+ namespaces = ( tns[2] || "" ).split( "." ).sort();
2696
+
2697
+ // If event changes its type, use the special event handlers for the changed type
2698
+ special = jQuery.event.special[ type ] || {};
2699
+
2700
+ // If selector defined, determine special event api type, otherwise given type
2701
+ type = ( selector ? special.delegateType : special.bindType ) || type;
2702
+
2703
+ // Update special based on newly reset type
2704
+ special = jQuery.event.special[ type ] || {};
2705
+
2706
+ // handleObj is passed to all event handlers
2707
+ handleObj = jQuery.extend({
2708
+ type: type,
2709
+ origType: tns[1],
2710
+ data: data,
2711
+ handler: handler,
2712
+ guid: handler.guid,
2713
+ selector: selector,
2714
+ namespace: namespaces.join(".")
2715
+ }, handleObjIn );
2716
+
2717
+ // Init the event handler queue if we're the first
2718
+ handlers = events[ type ];
2719
+ if ( !handlers ) {
2720
+ handlers = events[ type ] = [];
2721
+ handlers.delegateCount = 0;
2722
+
2723
+ // Only use addEventListener/attachEvent if the special events handler returns false
2724
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2725
+ // Bind the global event handler to the element
2726
+ if ( elem.addEventListener ) {
2727
+ elem.addEventListener( type, eventHandle, false );
2728
+
2729
+ } else if ( elem.attachEvent ) {
2730
+ elem.attachEvent( "on" + type, eventHandle );
2731
+ }
2732
+ }
2733
+ }
2734
+
2735
+ if ( special.add ) {
2736
+ special.add.call( elem, handleObj );
2737
+
2738
+ if ( !handleObj.handler.guid ) {
2739
+ handleObj.handler.guid = handler.guid;
2740
+ }
2741
+ }
2742
+
2743
+ // Add to the element's handler list, delegates in front
2744
+ if ( selector ) {
2745
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
2746
+ } else {
2747
+ handlers.push( handleObj );
2748
+ }
2749
+
2750
+ // Keep track of which events have ever been used, for event optimization
2751
+ jQuery.event.global[ type ] = true;
2752
+ }
2753
+
2754
+ // Nullify elem to prevent memory leaks in IE
2755
+ elem = null;
2756
+ },
2757
+
2758
+ global: {},
2759
+
2760
+ // Detach an event or set of events from an element
2761
+ remove: function( elem, types, handler, selector, mappedTypes ) {
2762
+
2763
+ var t, tns, type, origType, namespaces, origCount,
2764
+ j, events, special, eventType, handleObj,
2765
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
2766
+
2767
+ if ( !elemData || !(events = elemData.events) ) {
2768
+ return;
2769
+ }
2770
+
2771
+ // Once for each type.namespace in types; type may be omitted
2772
+ types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
2773
+ for ( t = 0; t < types.length; t++ ) {
2774
+ tns = rtypenamespace.exec( types[t] ) || [];
2775
+ type = origType = tns[1];
2776
+ namespaces = tns[2];
2777
+
2778
+ // Unbind all events (on this namespace, if provided) for the element
2779
+ if ( !type ) {
2780
+ for ( type in events ) {
2781
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
2782
+ }
2783
+ continue;
2784
+ }
2785
+
2786
+ special = jQuery.event.special[ type ] || {};
2787
+ type = ( selector? special.delegateType : special.bindType ) || type;
2788
+ eventType = events[ type ] || [];
2789
+ origCount = eventType.length;
2790
+ namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
2791
+
2792
+ // Remove matching events
2793
+ for ( j = 0; j < eventType.length; j++ ) {
2794
+ handleObj = eventType[ j ];
2795
+
2796
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
2797
+ ( !handler || handler.guid === handleObj.guid ) &&
2798
+ ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
2799
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
2800
+ eventType.splice( j--, 1 );
2801
+
2802
+ if ( handleObj.selector ) {
2803
+ eventType.delegateCount--;
2804
+ }
2805
+ if ( special.remove ) {
2806
+ special.remove.call( elem, handleObj );
2807
+ }
2808
+ }
2809
+ }
2810
+
2811
+ // Remove generic event handler if we removed something and no more handlers exist
2812
+ // (avoids potential for endless recursion during removal of special event handlers)
2813
+ if ( eventType.length === 0 && origCount !== eventType.length ) {
2814
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
2815
+ jQuery.removeEvent( elem, type, elemData.handle );
2816
+ }
2817
+
2818
+ delete events[ type ];
2819
+ }
2820
+ }
2821
+
2822
+ // Remove the expando if it's no longer used
2823
+ if ( jQuery.isEmptyObject( events ) ) {
2824
+ delete elemData.handle;
2825
+
2826
+ // removeData also checks for emptiness and clears the expando if empty
2827
+ // so use it instead of delete
2828
+ jQuery.removeData( elem, "events", true );
2829
+ }
2830
+ },
2831
+
2832
+ // Events that are safe to short-circuit if no handlers are attached.
2833
+ // Native DOM events should not be added, they may have inline handlers.
2834
+ customEvent: {
2835
+ "getData": true,
2836
+ "setData": true,
2837
+ "changeData": true
2838
+ },
2839
+
2840
+ trigger: function( event, data, elem, onlyHandlers ) {
2841
+ // Don't do events on text and comment nodes
2842
+ if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
2843
+ return;
2844
+ }
2845
+
2846
+ // Event object or event type
2847
+ var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,
2848
+ type = event.type || event,
2849
+ namespaces = [];
2850
+
2851
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
2852
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
2853
+ return;
2854
+ }
2855
+
2856
+ if ( type.indexOf( "!" ) >= 0 ) {
2857
+ // Exclusive events trigger only for the exact event (no namespaces)
2858
+ type = type.slice(0, -1);
2859
+ exclusive = true;
2860
+ }
2861
+
2862
+ if ( type.indexOf( "." ) >= 0 ) {
2863
+ // Namespaced trigger; create a regexp to match event type in handle()
2864
+ namespaces = type.split(".");
2865
+ type = namespaces.shift();
2866
+ namespaces.sort();
2867
+ }
2868
+
2869
+ if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
2870
+ // No jQuery handlers for this event type, and it can't have inline handlers
2871
+ return;
2872
+ }
2873
+
2874
+ // Caller can pass in an Event, Object, or just an event type string
2875
+ event = typeof event === "object" ?
2876
+ // jQuery.Event object
2877
+ event[ jQuery.expando ] ? event :
2878
+ // Object literal
2879
+ new jQuery.Event( type, event ) :
2880
+ // Just the event type (string)
2881
+ new jQuery.Event( type );
2882
+
2883
+ event.type = type;
2884
+ event.isTrigger = true;
2885
+ event.exclusive = exclusive;
2886
+ event.namespace = namespaces.join( "." );
2887
+ event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
2888
+ ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
2889
+
2890
+ // Handle a global trigger
2891
+ if ( !elem ) {
2892
+
2893
+ // TODO: Stop taunting the data cache; remove global events and always attach to document
2894
+ cache = jQuery.cache;
2895
+ for ( i in cache ) {
2896
+ if ( cache[ i ].events && cache[ i ].events[ type ] ) {
2897
+ jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
2898
+ }
2899
+ }
2900
+ return;
2901
+ }
2902
+
2903
+ // Clean up the event in case it is being reused
2904
+ event.result = undefined;
2905
+ if ( !event.target ) {
2906
+ event.target = elem;
2907
+ }
2908
+
2909
+ // Clone any incoming data and prepend the event, creating the handler arg list
2910
+ data = data != null ? jQuery.makeArray( data ) : [];
2911
+ data.unshift( event );
2912
+
2913
+ // Allow special events to draw outside the lines
2914
+ special = jQuery.event.special[ type ] || {};
2915
+ if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
2916
+ return;
2917
+ }
2918
+
2919
+ // Determine event propagation path in advance, per W3C events spec (#9951)
2920
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
2921
+ eventPath = [[ elem, special.bindType || type ]];
2922
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
2923
+
2924
+ bubbleType = special.delegateType || type;
2925
+ cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
2926
+ for ( old = elem; cur; cur = cur.parentNode ) {
2927
+ eventPath.push([ cur, bubbleType ]);
2928
+ old = cur;
2929
+ }
2930
+
2931
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
2932
+ if ( old === (elem.ownerDocument || document) ) {
2933
+ eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
2934
+ }
2935
+ }
2936
+
2937
+ // Fire handlers on the event path
2938
+ for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
2939
+
2940
+ cur = eventPath[i][0];
2941
+ event.type = eventPath[i][1];
2942
+
2943
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
2944
+ if ( handle ) {
2945
+ handle.apply( cur, data );
2946
+ }
2947
+ // Note that this is a bare JS function and not a jQuery handler
2948
+ handle = ontype && cur[ ontype ];
2949
+ if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
2950
+ event.preventDefault();
2951
+ }
2952
+ }
2953
+ event.type = type;
2954
+
2955
+ // If nobody prevented the default action, do it now
2956
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
2957
+
2958
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
2959
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
2960
+
2961
+ // Call a native DOM method on the target with the same name name as the event.
2962
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
2963
+ // Don't do default actions on window, that's where global variables be (#6170)
2964
+ // IE<9 dies on focus/blur to hidden element (#1486)
2965
+ if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
2966
+
2967
+ // Don't re-trigger an onFOO event when we call its FOO() method
2968
+ old = elem[ ontype ];
2969
+
2970
+ if ( old ) {
2971
+ elem[ ontype ] = null;
2972
+ }
2973
+
2974
+ // Prevent re-triggering of the same event, since we already bubbled it above
2975
+ jQuery.event.triggered = type;
2976
+ elem[ type ]();
2977
+ jQuery.event.triggered = undefined;
2978
+
2979
+ if ( old ) {
2980
+ elem[ ontype ] = old;
2981
+ }
2982
+ }
2983
+ }
2984
+ }
2985
+
2986
+ return event.result;
2987
+ },
2988
+
2989
+ dispatch: function( event ) {
2990
+
2991
+ // Make a writable jQuery.Event from the native event object
2992
+ event = jQuery.event.fix( event || window.event );
2993
+
2994
+ var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,
2995
+ handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
2996
+ delegateCount = handlers.delegateCount,
2997
+ args = [].slice.call( arguments ),
2998
+ run_all = !event.exclusive && !event.namespace,
2999
+ special = jQuery.event.special[ event.type ] || {},
3000
+ handlerQueue = [];
3001
+
3002
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
3003
+ args[0] = event;
3004
+ event.delegateTarget = this;
3005
+
3006
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
3007
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
3008
+ return;
3009
+ }
3010
+
3011
+ // Determine handlers that should run if there are delegated events
3012
+ // Avoid non-left-click bubbling in Firefox (#3861)
3013
+ if ( delegateCount && !(event.button && event.type === "click") ) {
3014
+
3015
+ for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
3016
+
3017
+ // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)
3018
+ if ( cur.disabled !== true || event.type !== "click" ) {
3019
+ selMatch = {};
3020
+ matches = [];
3021
+ for ( i = 0; i < delegateCount; i++ ) {
3022
+ handleObj = handlers[ i ];
3023
+ sel = handleObj.selector;
3024
+
3025
+ if ( selMatch[ sel ] === undefined ) {
3026
+ selMatch[ sel ] = jQuery( sel, this ).index( cur ) >= 0;
3027
+ }
3028
+ if ( selMatch[ sel ] ) {
3029
+ matches.push( handleObj );
3030
+ }
3031
+ }
3032
+ if ( matches.length ) {
3033
+ handlerQueue.push({ elem: cur, matches: matches });
3034
+ }
3035
+ }
3036
+ }
3037
+ }
3038
+
3039
+ // Add the remaining (directly-bound) handlers
3040
+ if ( handlers.length > delegateCount ) {
3041
+ handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
3042
+ }
3043
+
3044
+ // Run delegates first; they may want to stop propagation beneath us
3045
+ for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
3046
+ matched = handlerQueue[ i ];
3047
+ event.currentTarget = matched.elem;
3048
+
3049
+ for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
3050
+ handleObj = matched.matches[ j ];
3051
+
3052
+ // Triggered event must either 1) be non-exclusive and have no namespace, or
3053
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3054
+ if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
3055
+
3056
+ event.data = handleObj.data;
3057
+ event.handleObj = handleObj;
3058
+
3059
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
3060
+ .apply( matched.elem, args );
3061
+
3062
+ if ( ret !== undefined ) {
3063
+ event.result = ret;
3064
+ if ( ret === false ) {
3065
+ event.preventDefault();
3066
+ event.stopPropagation();
3067
+ }
3068
+ }
3069
+ }
3070
+ }
3071
+ }
3072
+
3073
+ // Call the postDispatch hook for the mapped type
3074
+ if ( special.postDispatch ) {
3075
+ special.postDispatch.call( this, event );
3076
+ }
3077
+
3078
+ return event.result;
3079
+ },
3080
+
3081
+ // Includes some event props shared by KeyEvent and MouseEvent
3082
+ // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
3083
+ props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3084
+
3085
+ fixHooks: {},
3086
+
3087
+ keyHooks: {
3088
+ props: "char charCode key keyCode".split(" "),
3089
+ filter: function( event, original ) {
3090
+
3091
+ // Add which for key events
3092
+ if ( event.which == null ) {
3093
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
3094
+ }
3095
+
3096
+ return event;
3097
+ }
3098
+ },
3099
+
3100
+ mouseHooks: {
3101
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3102
+ filter: function( event, original ) {
3103
+ var eventDoc, doc, body,
3104
+ button = original.button,
3105
+ fromElement = original.fromElement;
3106
+
3107
+ // Calculate pageX/Y if missing and clientX/Y available
3108
+ if ( event.pageX == null && original.clientX != null ) {
3109
+ eventDoc = event.target.ownerDocument || document;
3110
+ doc = eventDoc.documentElement;
3111
+ body = eventDoc.body;
3112
+
3113
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3114
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3115
+ }
3116
+
3117
+ // Add relatedTarget, if necessary
3118
+ if ( !event.relatedTarget && fromElement ) {
3119
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3120
+ }
3121
+
3122
+ // Add which for click: 1 === left; 2 === middle; 3 === right
3123
+ // Note: button is not normalized, so don't use it
3124
+ if ( !event.which && button !== undefined ) {
3125
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3126
+ }
3127
+
3128
+ return event;
3129
+ }
3130
+ },
3131
+
3132
+ fix: function( event ) {
3133
+ if ( event[ jQuery.expando ] ) {
3134
+ return event;
3135
+ }
3136
+
3137
+ // Create a writable copy of the event object and normalize some properties
3138
+ var i, prop,
3139
+ originalEvent = event,
3140
+ fixHook = jQuery.event.fixHooks[ event.type ] || {},
3141
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3142
+
3143
+ event = jQuery.Event( originalEvent );
3144
+
3145
+ for ( i = copy.length; i; ) {
3146
+ prop = copy[ --i ];
3147
+ event[ prop ] = originalEvent[ prop ];
3148
+ }
3149
+
3150
+ // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
3151
+ if ( !event.target ) {
3152
+ event.target = originalEvent.srcElement || document;
3153
+ }
3154
+
3155
+ // Target should not be a text node (#504, Safari)
3156
+ if ( event.target.nodeType === 3 ) {
3157
+ event.target = event.target.parentNode;
3158
+ }
3159
+
3160
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)
3161
+ event.metaKey = !!event.metaKey;
3162
+
3163
+ return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
3164
+ },
3165
+
3166
+ special: {
3167
+ load: {
3168
+ // Prevent triggered image.load events from bubbling to window.load
3169
+ noBubble: true
3170
+ },
3171
+
3172
+ focus: {
3173
+ delegateType: "focusin"
3174
+ },
3175
+ blur: {
3176
+ delegateType: "focusout"
3177
+ },
3178
+
3179
+ beforeunload: {
3180
+ setup: function( data, namespaces, eventHandle ) {
3181
+ // We only want to do this special case on windows
3182
+ if ( jQuery.isWindow( this ) ) {
3183
+ this.onbeforeunload = eventHandle;
3184
+ }
3185
+ },
3186
+
3187
+ teardown: function( namespaces, eventHandle ) {
3188
+ if ( this.onbeforeunload === eventHandle ) {
3189
+ this.onbeforeunload = null;
3190
+ }
3191
+ }
3192
+ }
3193
+ },
3194
+
3195
+ simulate: function( type, elem, event, bubble ) {
3196
+ // Piggyback on a donor event to simulate a different one.
3197
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
3198
+ // simulated event prevents default then we do the same on the donor.
3199
+ var e = jQuery.extend(
3200
+ new jQuery.Event(),
3201
+ event,
3202
+ { type: type,
3203
+ isSimulated: true,
3204
+ originalEvent: {}
3205
+ }
3206
+ );
3207
+ if ( bubble ) {
3208
+ jQuery.event.trigger( e, null, elem );
3209
+ } else {
3210
+ jQuery.event.dispatch.call( elem, e );
3211
+ }
3212
+ if ( e.isDefaultPrevented() ) {
3213
+ event.preventDefault();
3214
+ }
3215
+ }
3216
+ };
3217
+
3218
+ // Some plugins are using, but it's undocumented/deprecated and will be removed.
3219
+ // The 1.7 special event interface should provide all the hooks needed now.
3220
+ jQuery.event.handle = jQuery.event.dispatch;
3221
+
3222
+ jQuery.removeEvent = document.removeEventListener ?
3223
+ function( elem, type, handle ) {
3224
+ if ( elem.removeEventListener ) {
3225
+ elem.removeEventListener( type, handle, false );
3226
+ }
3227
+ } :
3228
+ function( elem, type, handle ) {
3229
+ var name = "on" + type;
3230
+
3231
+ if ( elem.detachEvent ) {
3232
+
3233
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8 –
3234
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
3235
+ if ( typeof elem[ name ] === "undefined" ) {
3236
+ elem[ name ] = null;
3237
+ }
3238
+
3239
+ elem.detachEvent( name, handle );
3240
+ }
3241
+ };
3242
+
3243
+ jQuery.Event = function( src, props ) {
3244
+ // Allow instantiation without the 'new' keyword
3245
+ if ( !(this instanceof jQuery.Event) ) {
3246
+ return new jQuery.Event( src, props );
3247
+ }
3248
+
3249
+ // Event object
3250
+ if ( src && src.type ) {
3251
+ this.originalEvent = src;
3252
+ this.type = src.type;
3253
+
3254
+ // Events bubbling up the document may have been marked as prevented
3255
+ // by a handler lower down the tree; reflect the correct value.
3256
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3257
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3258
+
3259
+ // Event type
3260
+ } else {
3261
+ this.type = src;
3262
+ }
3263
+
3264
+ // Put explicitly provided properties onto the event object
3265
+ if ( props ) {
3266
+ jQuery.extend( this, props );
3267
+ }
3268
+
3269
+ // Create a timestamp if incoming event doesn't have one
3270
+ this.timeStamp = src && src.timeStamp || jQuery.now();
3271
+
3272
+ // Mark it as fixed
3273
+ this[ jQuery.expando ] = true;
3274
+ };
3275
+
3276
+ function returnFalse() {
3277
+ return false;
3278
+ }
3279
+ function returnTrue() {
3280
+ return true;
3281
+ }
3282
+
3283
+ // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3284
+ // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3285
+ jQuery.Event.prototype = {
3286
+ preventDefault: function() {
3287
+ this.isDefaultPrevented = returnTrue;
3288
+
3289
+ var e = this.originalEvent;
3290
+ if ( !e ) {
3291
+ return;
3292
+ }
3293
+
3294
+ // if preventDefault exists run it on the original event
3295
+ if ( e.preventDefault ) {
3296
+ e.preventDefault();
3297
+
3298
+ // otherwise set the returnValue property of the original event to false (IE)
3299
+ } else {
3300
+ e.returnValue = false;
3301
+ }
3302
+ },
3303
+ stopPropagation: function() {
3304
+ this.isPropagationStopped = returnTrue;
3305
+
3306
+ var e = this.originalEvent;
3307
+ if ( !e ) {
3308
+ return;
3309
+ }
3310
+ // if stopPropagation exists run it on the original event
3311
+ if ( e.stopPropagation ) {
3312
+ e.stopPropagation();
3313
+ }
3314
+ // otherwise set the cancelBubble property of the original event to true (IE)
3315
+ e.cancelBubble = true;
3316
+ },
3317
+ stopImmediatePropagation: function() {
3318
+ this.isImmediatePropagationStopped = returnTrue;
3319
+ this.stopPropagation();
3320
+ },
3321
+ isDefaultPrevented: returnFalse,
3322
+ isPropagationStopped: returnFalse,
3323
+ isImmediatePropagationStopped: returnFalse
3324
+ };
3325
+
3326
+ // Create mouseenter/leave events using mouseover/out and event-time checks
3327
+ jQuery.each({
3328
+ mouseenter: "mouseover",
3329
+ mouseleave: "mouseout"
3330
+ }, function( orig, fix ) {
3331
+ jQuery.event.special[ orig ] = {
3332
+ delegateType: fix,
3333
+ bindType: fix,
3334
+
3335
+ handle: function( event ) {
3336
+ var ret,
3337
+ target = this,
3338
+ related = event.relatedTarget,
3339
+ handleObj = event.handleObj,
3340
+ selector = handleObj.selector;
3341
+
3342
+ // For mousenter/leave call the handler if related is outside the target.
3343
+ // NB: No relatedTarget if the mouse left/entered the browser window
3344
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3345
+ event.type = handleObj.origType;
3346
+ ret = handleObj.handler.apply( this, arguments );
3347
+ event.type = fix;
3348
+ }
3349
+ return ret;
3350
+ }
3351
+ };
3352
+ });
3353
+
3354
+ // IE submit delegation
3355
+ if ( !jQuery.support.submitBubbles ) {
3356
+
3357
+ jQuery.event.special.submit = {
3358
+ setup: function() {
3359
+ // Only need this for delegated form submit events
3360
+ if ( jQuery.nodeName( this, "form" ) ) {
3361
+ return false;
3362
+ }
3363
+
3364
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
3365
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
3366
+ // Node name check avoids a VML-related crash in IE (#9807)
3367
+ var elem = e.target,
3368
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
3369
+ if ( form && !jQuery._data( form, "_submit_attached" ) ) {
3370
+ jQuery.event.add( form, "submit._submit", function( event ) {
3371
+ event._submit_bubble = true;
3372
+ });
3373
+ jQuery._data( form, "_submit_attached", true );
3374
+ }
3375
+ });
3376
+ // return undefined since we don't need an event listener
3377
+ },
3378
+
3379
+ postDispatch: function( event ) {
3380
+ // If form was submitted by the user, bubble the event up the tree
3381
+ if ( event._submit_bubble ) {
3382
+ delete event._submit_bubble;
3383
+ if ( this.parentNode && !event.isTrigger ) {
3384
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
3385
+ }
3386
+ }
3387
+ },
3388
+
3389
+ teardown: function() {
3390
+ // Only need this for delegated form submit events
3391
+ if ( jQuery.nodeName( this, "form" ) ) {
3392
+ return false;
3393
+ }
3394
+
3395
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
3396
+ jQuery.event.remove( this, "._submit" );
3397
+ }
3398
+ };
3399
+ }
3400
+
3401
+ // IE change delegation and checkbox/radio fix
3402
+ if ( !jQuery.support.changeBubbles ) {
3403
+
3404
+ jQuery.event.special.change = {
3405
+
3406
+ setup: function() {
3407
+
3408
+ if ( rformElems.test( this.nodeName ) ) {
3409
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
3410
+ // after a propertychange. Eat the blur-change in special.change.handle.
3411
+ // This still fires onchange a second time for check/radio after blur.
3412
+ if ( this.type === "checkbox" || this.type === "radio" ) {
3413
+ jQuery.event.add( this, "propertychange._change", function( event ) {
3414
+ if ( event.originalEvent.propertyName === "checked" ) {
3415
+ this._just_changed = true;
3416
+ }
3417
+ });
3418
+ jQuery.event.add( this, "click._change", function( event ) {
3419
+ if ( this._just_changed && !event.isTrigger ) {
3420
+ this._just_changed = false;
3421
+ }
3422
+ // Allow triggered, simulated change events (#11500)
3423
+ jQuery.event.simulate( "change", this, event, true );
3424
+ });
3425
+ }
3426
+ return false;
3427
+ }
3428
+ // Delegated event; lazy-add a change handler on descendant inputs
3429
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
3430
+ var elem = e.target;
3431
+
3432
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) {
3433
+ jQuery.event.add( elem, "change._change", function( event ) {
3434
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
3435
+ jQuery.event.simulate( "change", this.parentNode, event, true );
3436
+ }
3437
+ });
3438
+ jQuery._data( elem, "_change_attached", true );
3439
+ }
3440
+ });
3441
+ },
3442
+
3443
+ handle: function( event ) {
3444
+ var elem = event.target;
3445
+
3446
+ // Swallow native change events from checkbox/radio, we already triggered them above
3447
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
3448
+ return event.handleObj.handler.apply( this, arguments );
3449
+ }
3450
+ },
3451
+
3452
+ teardown: function() {
3453
+ jQuery.event.remove( this, "._change" );
3454
+
3455
+ return !rformElems.test( this.nodeName );
3456
+ }
3457
+ };
3458
+ }
3459
+
3460
+ // Create "bubbling" focus and blur events
3461
+ if ( !jQuery.support.focusinBubbles ) {
3462
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
3463
+
3464
+ // Attach a single capturing handler while someone wants focusin/focusout
3465
+ var attaches = 0,
3466
+ handler = function( event ) {
3467
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
3468
+ };
3469
+
3470
+ jQuery.event.special[ fix ] = {
3471
+ setup: function() {
3472
+ if ( attaches++ === 0 ) {
3473
+ document.addEventListener( orig, handler, true );
3474
+ }
3475
+ },
3476
+ teardown: function() {
3477
+ if ( --attaches === 0 ) {
3478
+ document.removeEventListener( orig, handler, true );
3479
+ }
3480
+ }
3481
+ };
3482
+ });
3483
+ }
3484
+
3485
+ jQuery.fn.extend({
3486
+
3487
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
3488
+ var origFn, type;
3489
+
3490
+ // Types can be a map of types/handlers
3491
+ if ( typeof types === "object" ) {
3492
+ // ( types-Object, selector, data )
3493
+ if ( typeof selector !== "string" ) { // && selector != null
3494
+ // ( types-Object, data )
3495
+ data = data || selector;
3496
+ selector = undefined;
3497
+ }
3498
+ for ( type in types ) {
3499
+ this.on( type, selector, data, types[ type ], one );
3500
+ }
3501
+ return this;
3502
+ }
3503
+
3504
+ if ( data == null && fn == null ) {
3505
+ // ( types, fn )
3506
+ fn = selector;
3507
+ data = selector = undefined;
3508
+ } else if ( fn == null ) {
3509
+ if ( typeof selector === "string" ) {
3510
+ // ( types, selector, fn )
3511
+ fn = data;
3512
+ data = undefined;
3513
+ } else {
3514
+ // ( types, data, fn )
3515
+ fn = data;
3516
+ data = selector;
3517
+ selector = undefined;
3518
+ }
3519
+ }
3520
+ if ( fn === false ) {
3521
+ fn = returnFalse;
3522
+ } else if ( !fn ) {
3523
+ return this;
3524
+ }
3525
+
3526
+ if ( one === 1 ) {
3527
+ origFn = fn;
3528
+ fn = function( event ) {
3529
+ // Can use an empty set, since event contains the info
3530
+ jQuery().off( event );
3531
+ return origFn.apply( this, arguments );
3532
+ };
3533
+ // Use same guid so caller can remove using origFn
3534
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
3535
+ }
3536
+ return this.each( function() {
3537
+ jQuery.event.add( this, types, fn, data, selector );
3538
+ });
3539
+ },
3540
+ one: function( types, selector, data, fn ) {
3541
+ return this.on( types, selector, data, fn, 1 );
3542
+ },
3543
+ off: function( types, selector, fn ) {
3544
+ var handleObj, type;
3545
+ if ( types && types.preventDefault && types.handleObj ) {
3546
+ // ( event ) dispatched jQuery.Event
3547
+ handleObj = types.handleObj;
3548
+ jQuery( types.delegateTarget ).off(
3549
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
3550
+ handleObj.selector,
3551
+ handleObj.handler
3552
+ );
3553
+ return this;
3554
+ }
3555
+ if ( typeof types === "object" ) {
3556
+ // ( types-object [, selector] )
3557
+ for ( type in types ) {
3558
+ this.off( type, selector, types[ type ] );
3559
+ }
3560
+ return this;
3561
+ }
3562
+ if ( selector === false || typeof selector === "function" ) {
3563
+ // ( types [, fn] )
3564
+ fn = selector;
3565
+ selector = undefined;
3566
+ }
3567
+ if ( fn === false ) {
3568
+ fn = returnFalse;
3569
+ }
3570
+ return this.each(function() {
3571
+ jQuery.event.remove( this, types, fn, selector );
3572
+ });
3573
+ },
3574
+
3575
+ bind: function( types, data, fn ) {
3576
+ return this.on( types, null, data, fn );
3577
+ },
3578
+ unbind: function( types, fn ) {
3579
+ return this.off( types, null, fn );
3580
+ },
3581
+
3582
+ live: function( types, data, fn ) {
3583
+ jQuery( this.context ).on( types, this.selector, data, fn );
3584
+ return this;
3585
+ },
3586
+ die: function( types, fn ) {
3587
+ jQuery( this.context ).off( types, this.selector || "**", fn );
3588
+ return this;
3589
+ },
3590
+
3591
+ delegate: function( selector, types, data, fn ) {
3592
+ return this.on( types, selector, data, fn );
3593
+ },
3594
+ undelegate: function( selector, types, fn ) {
3595
+ // ( namespace ) or ( selector, types [, fn] )
3596
+ return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3597
+ },
3598
+
3599
+ trigger: function( type, data ) {
3600
+ return this.each(function() {
3601
+ jQuery.event.trigger( type, data, this );
3602
+ });
3603
+ },
3604
+ triggerHandler: function( type, data ) {
3605
+ if ( this[0] ) {
3606
+ return jQuery.event.trigger( type, data, this[0], true );
3607
+ }
3608
+ },
3609
+
3610
+ toggle: function( fn ) {
3611
+ // Save reference to arguments for access in closure
3612
+ var args = arguments,
3613
+ guid = fn.guid || jQuery.guid++,
3614
+ i = 0,
3615
+ toggler = function( event ) {
3616
+ // Figure out which function to execute
3617
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
3618
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
3619
+
3620
+ // Make sure that clicks stop
3621
+ event.preventDefault();
3622
+
3623
+ // and execute the function
3624
+ return args[ lastToggle ].apply( this, arguments ) || false;
3625
+ };
3626
+
3627
+ // link all the functions, so any of them can unbind this click handler
3628
+ toggler.guid = guid;
3629
+ while ( i < args.length ) {
3630
+ args[ i++ ].guid = guid;
3631
+ }
3632
+
3633
+ return this.click( toggler );
3634
+ },
3635
+
3636
+ hover: function( fnOver, fnOut ) {
3637
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
3638
+ }
3639
+ });
3640
+
3641
+ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
3642
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
3643
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
3644
+
3645
+ // Handle event binding
3646
+ jQuery.fn[ name ] = function( data, fn ) {
3647
+ if ( fn == null ) {
3648
+ fn = data;
3649
+ data = null;
3650
+ }
3651
+
3652
+ return arguments.length > 0 ?
3653
+ this.on( name, null, data, fn ) :
3654
+ this.trigger( name );
3655
+ };
3656
+
3657
+ if ( rkeyEvent.test( name ) ) {
3658
+ jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
3659
+ }
3660
+
3661
+ if ( rmouseEvent.test( name ) ) {
3662
+ jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
3663
+ }
3664
+ });
3665
+ /*!
3666
+
3667
+ * Sizzle CSS Selector Engine
3668
+
3669
+ * Copyright 2012 jQuery Foundation and other contributors
3670
+
3671
+ * Released under the MIT license
3672
+
3673
+ * http://sizzlejs.com/
3674
+
3675
+ */
3676
+
3677
+ (function( window, undefined ) {
3678
+
3679
+
3680
+
3681
+ var dirruns,
3682
+
3683
+ cachedruns,
3684
+
3685
+ assertGetIdNotName,
3686
+
3687
+ Expr,
3688
+
3689
+ getText,
3690
+
3691
+ isXML,
3692
+
3693
+ contains,
3694
+
3695
+ compile,
3696
+
3697
+ sortOrder,
3698
+
3699
+ hasDuplicate,
3700
+
3701
+
3702
+
3703
+ baseHasDuplicate = true,
3704
+
3705
+ strundefined = "undefined",
3706
+
3707
+
3708
+
3709
+ expando = ( "sizcache" + Math.random() ).replace( ".", "" ),
3710
+
3711
+
3712
+
3713
+ document = window.document,
3714
+
3715
+ docElem = document.documentElement,
3716
+
3717
+ done = 0,
3718
+
3719
+ slice = [].slice,
3720
+
3721
+ push = [].push,
3722
+
3723
+
3724
+
3725
+ // Augment a function for special use by Sizzle
3726
+
3727
+ markFunction = function( fn, value ) {
3728
+
3729
+ fn[ expando ] = value || true;
3730
+
3731
+ return fn;
3732
+
3733
+ },
3734
+
3735
+
3736
+
3737
+ createCache = function() {
3738
+
3739
+ var cache = {},
3740
+
3741
+ keys = [];
3742
+
3743
+
3744
+
3745
+ return markFunction(function( key, value ) {
3746
+
3747
+ // Only keep the most recent entries
3748
+
3749
+ if ( keys.push( key ) > Expr.cacheLength ) {
3750
+
3751
+ delete cache[ keys.shift() ];
3752
+
3753
+ }
3754
+
3755
+
3756
+
3757
+ return (cache[ key ] = value);
3758
+
3759
+ }, cache );
3760
+
3761
+ },
3762
+
3763
+
3764
+
3765
+ classCache = createCache(),
3766
+
3767
+ tokenCache = createCache(),
3768
+
3769
+ compilerCache = createCache(),
3770
+
3771
+
3772
+
3773
+ // Regex
3774
+
3775
+
3776
+
3777
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
3778
+
3779
+ whitespace = "[\\x20\\t\\r\\n\\f]",
3780
+
3781
+ // http://www.w3.org/TR/css3-syntax/#characters
3782
+
3783
+ characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",
3784
+
3785
+
3786
+
3787
+ // Loosely modeled on CSS identifier characters
3788
+
3789
+ // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)
3790
+
3791
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
3792
+
3793
+ identifier = characterEncoding.replace( "w", "w#" ),
3794
+
3795
+
3796
+
3797
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
3798
+
3799
+ operators = "([*^$|!~]?=)",
3800
+
3801
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
3802
+
3803
+ "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
3804
+
3805
+
3806
+
3807
+ // Prefer arguments not in parens/brackets,
3808
+
3809
+ // then attribute selectors and non-pseudos (denoted by :),
3810
+
3811
+ // then anything else
3812
+
3813
+ // These preferences are here to reduce the number of selectors
3814
+
3815
+ // needing tokenize in the PSEUDO preFilter
3816
+
3817
+ pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",
3818
+
3819
+
3820
+
3821
+ // For matchExpr.POS and matchExpr.needsContext
3822
+
3823
+ pos = ":(nth|eq|gt|lt|first|last|even|odd)(?:\\(((?:-\\d)?\\d*)\\)|)(?=[^-]|$)",
3824
+
3825
+
3826
+
3827
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
3828
+
3829
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
3830
+
3831
+
3832
+
3833
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
3834
+
3835
+ rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
3836
+
3837
+ rpseudo = new RegExp( pseudos ),
3838
+
3839
+
3840
+
3841
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
3842
+
3843
+ rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,
3844
+
3845
+
3846
+
3847
+ rnot = /^:not/,
3848
+
3849
+ rsibling = /[\x20\t\r\n\f]*[+~]/,
3850
+
3851
+ rendsWithNot = /:not\($/,
3852
+
3853
+
3854
+
3855
+ rheader = /h\d/i,
3856
+
3857
+ rinputs = /input|select|textarea|button/i,
3858
+
3859
+
3860
+
3861
+ rbackslash = /\\(?!\\)/g,
3862
+
3863
+
3864
+
3865
+ matchExpr = {
3866
+
3867
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
3868
+
3869
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
3870
+
3871
+ "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
3872
+
3873
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
3874
+
3875
+ "ATTR": new RegExp( "^" + attributes ),
3876
+
3877
+ "PSEUDO": new RegExp( "^" + pseudos ),
3878
+
3879
+ "CHILD": new RegExp( "^:(only|nth|last|first)-child(?:\\(" + whitespace +
3880
+
3881
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
3882
+
3883
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
3884
+
3885
+ "POS": new RegExp( pos, "ig" ),
3886
+
3887
+ // For use in libraries implementing .is()
3888
+
3889
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )
3890
+
3891
+ },
3892
+
3893
+
3894
+
3895
+ // Support
3896
+
3897
+
3898
+
3899
+ // Used for testing something on an element
3900
+
3901
+ assert = function( fn ) {
3902
+
3903
+ var div = document.createElement("div");
3904
+
3905
+
3906
+
3907
+ try {
3908
+
3909
+ return fn( div );
3910
+
3911
+ } catch (e) {
3912
+
3913
+ return false;
3914
+
3915
+ } finally {
3916
+
3917
+ // release memory in IE
3918
+
3919
+ div = null;
3920
+
3921
+ }
3922
+
3923
+ },
3924
+
3925
+
3926
+
3927
+ // Check if getElementsByTagName("*") returns only elements
3928
+
3929
+ assertTagNameNoComments = assert(function( div ) {
3930
+
3931
+ div.appendChild( document.createComment("") );
3932
+
3933
+ return !div.getElementsByTagName("*").length;
3934
+
3935
+ }),
3936
+
3937
+
3938
+
3939
+ // Check if getAttribute returns normalized href attributes
3940
+
3941
+ assertHrefNotNormalized = assert(function( div ) {
3942
+
3943
+ div.innerHTML = "<a href='#'></a>";
3944
+
3945
+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
3946
+
3947
+ div.firstChild.getAttribute("href") === "#";
3948
+
3949
+ }),
3950
+
3951
+
3952
+
3953
+ // Check if attributes should be retrieved by attribute nodes
3954
+
3955
+ assertAttributes = assert(function( div ) {
3956
+
3957
+ div.innerHTML = "<select></select>";
3958
+
3959
+ var type = typeof div.lastChild.getAttribute("multiple");
3960
+
3961
+ // IE8 returns a string for some attributes even when not present
3962
+
3963
+ return type !== "boolean" && type !== "string";
3964
+
3965
+ }),
3966
+
3967
+
3968
+
3969
+ // Check if getElementsByClassName can be trusted
3970
+
3971
+ assertUsableClassName = assert(function( div ) {
3972
+
3973
+ // Opera can't find a second classname (in 9.6)
3974
+
3975
+ div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
3976
+
3977
+ if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
3978
+
3979
+ return false;
3980
+
3981
+ }
3982
+
3983
+
3984
+
3985
+ // Safari 3.2 caches class attributes and doesn't catch changes
3986
+
3987
+ div.lastChild.className = "e";
3988
+
3989
+ return div.getElementsByClassName("e").length === 2;
3990
+
3991
+ }),
3992
+
3993
+
3994
+
3995
+ // Check if getElementById returns elements by name
3996
+
3997
+ // Check if getElementsByName privileges form controls or returns elements by ID
3998
+
3999
+ assertUsableName = assert(function( div ) {
4000
+
4001
+ // Inject content
4002
+
4003
+ div.id = expando + 0;
4004
+
4005
+ div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
4006
+
4007
+ docElem.insertBefore( div, docElem.firstChild );
4008
+
4009
+
4010
+
4011
+ // Test
4012
+
4013
+ var pass = document.getElementsByName &&
4014
+
4015
+ // buggy browsers will return fewer than the correct 2
4016
+
4017
+ document.getElementsByName( expando ).length === 2 +
4018
+
4019
+ // buggy browsers will return more than the correct 0
4020
+
4021
+ document.getElementsByName( expando + 0 ).length;
4022
+
4023
+ assertGetIdNotName = !document.getElementById( expando );
4024
+
4025
+
4026
+
4027
+ // Cleanup
4028
+
4029
+ docElem.removeChild( div );
4030
+
4031
+
4032
+
4033
+ return pass;
4034
+
4035
+ });
4036
+
4037
+
4038
+
4039
+ // If slice is not available, provide a backup
4040
+
4041
+ try {
4042
+
4043
+ slice.call( docElem.childNodes, 0 )[0].nodeType;
4044
+
4045
+ } catch ( e ) {
4046
+
4047
+ slice = function( i ) {
4048
+
4049
+ var elem, results = [];
4050
+
4051
+ for ( ; (elem = this[i]); i++ ) {
4052
+
4053
+ results.push( elem );
4054
+
4055
+ }
4056
+
4057
+ return results;
4058
+
4059
+ };
4060
+
4061
+ }
4062
+
4063
+
4064
+
4065
+ function Sizzle( selector, context, results, seed ) {
4066
+
4067
+ results = results || [];
4068
+
4069
+ context = context || document;
4070
+
4071
+ var match, elem, xml, m,
4072
+
4073
+ nodeType = context.nodeType;
4074
+
4075
+
4076
+
4077
+ if ( nodeType !== 1 && nodeType !== 9 ) {
4078
+
4079
+ return [];
4080
+
4081
+ }
4082
+
4083
+
4084
+
4085
+ if ( !selector || typeof selector !== "string" ) {
4086
+
4087
+ return results;
4088
+
4089
+ }
4090
+
4091
+
4092
+
4093
+ xml = isXML( context );
4094
+
4095
+
4096
+
4097
+ if ( !xml && !seed ) {
4098
+
4099
+ if ( (match = rquickExpr.exec( selector )) ) {
4100
+
4101
+ // Speed-up: Sizzle("#ID")
4102
+
4103
+ if ( (m = match[1]) ) {
4104
+
4105
+ if ( nodeType === 9 ) {
4106
+
4107
+ elem = context.getElementById( m );
4108
+
4109
+ // Check parentNode to catch when Blackberry 4.6 returns
4110
+
4111
+ // nodes that are no longer in the document #6963
4112
+
4113
+ if ( elem && elem.parentNode ) {
4114
+
4115
+ // Handle the case where IE, Opera, and Webkit return items
4116
+
4117
+ // by name instead of ID
4118
+
4119
+ if ( elem.id === m ) {
4120
+
4121
+ results.push( elem );
4122
+
4123
+ return results;
4124
+
4125
+ }
4126
+
4127
+ } else {
4128
+
4129
+ return results;
4130
+
4131
+ }
4132
+
4133
+ } else {
4134
+
4135
+ // Context is not a document
4136
+
4137
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
4138
+
4139
+ contains( context, elem ) && elem.id === m ) {
4140
+
4141
+ results.push( elem );
4142
+
4143
+ return results;
4144
+
4145
+ }
4146
+
4147
+ }
4148
+
4149
+
4150
+
4151
+ // Speed-up: Sizzle("TAG")
4152
+
4153
+ } else if ( match[2] ) {
4154
+
4155
+ push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
4156
+
4157
+ return results;
4158
+
4159
+
4160
+
4161
+ // Speed-up: Sizzle(".CLASS")
4162
+
4163
+ } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {
4164
+
4165
+ push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
4166
+
4167
+ return results;
4168
+
4169
+ }
4170
+
4171
+ }
4172
+
4173
+ }
4174
+
4175
+
4176
+
4177
+ // All others
4178
+
4179
+ return select( selector, context, results, seed, xml );
4180
+
4181
+ }
4182
+
4183
+
4184
+
4185
+ Sizzle.matches = function( expr, elements ) {
4186
+
4187
+ return Sizzle( expr, null, null, elements );
4188
+
4189
+ };
4190
+
4191
+
4192
+
4193
+ Sizzle.matchesSelector = function( elem, expr ) {
4194
+
4195
+ return Sizzle( expr, null, null, [ elem ] ).length > 0;
4196
+
4197
+ };
4198
+
4199
+
4200
+
4201
+ // Returns a function to use in pseudos for input types
4202
+
4203
+ function createInputPseudo( type ) {
4204
+
4205
+ return function( elem ) {
4206
+
4207
+ var name = elem.nodeName.toLowerCase();
4208
+
4209
+ return name === "input" && elem.type === type;
4210
+
4211
+ };
4212
+
4213
+ }
4214
+
4215
+
4216
+
4217
+ // Returns a function to use in pseudos for buttons
4218
+
4219
+ function createButtonPseudo( type ) {
4220
+
4221
+ return function( elem ) {
4222
+
4223
+ var name = elem.nodeName.toLowerCase();
4224
+
4225
+ return (name === "input" || name === "button") && elem.type === type;
4226
+
4227
+ };
4228
+
4229
+ }
4230
+
4231
+
4232
+
4233
+ /**
4234
+
4235
+ * Utility function for retrieving the text value of an array of DOM nodes
4236
+
4237
+ * @param {Array|Element} elem
4238
+
4239
+ */
4240
+
4241
+ getText = Sizzle.getText = function( elem ) {
4242
+
4243
+ var node,
4244
+
4245
+ ret = "",
4246
+
4247
+ i = 0,
4248
+
4249
+ nodeType = elem.nodeType;
4250
+
4251
+
4252
+
4253
+ if ( nodeType ) {
4254
+
4255
+ if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
4256
+
4257
+ // Use textContent for elements
4258
+
4259
+ // innerText usage removed for consistency of new lines (see #11153)
4260
+
4261
+ if ( typeof elem.textContent === "string" ) {
4262
+
4263
+ return elem.textContent;
4264
+
4265
+ } else {
4266
+
4267
+ // Traverse its children
4268
+
4269
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4270
+
4271
+ ret += getText( elem );
4272
+
4273
+ }
4274
+
4275
+ }
4276
+
4277
+ } else if ( nodeType === 3 || nodeType === 4 ) {
4278
+
4279
+ return elem.nodeValue;
4280
+
4281
+ }
4282
+
4283
+ // Do not include comment or processing instruction nodes
4284
+
4285
+ } else {
4286
+
4287
+
4288
+
4289
+ // If no nodeType, this is expected to be an array
4290
+
4291
+ for ( ; (node = elem[i]); i++ ) {
4292
+
4293
+ // Do not traverse comment nodes
4294
+
4295
+ ret += getText( node );
4296
+
4297
+ }
4298
+
4299
+ }
4300
+
4301
+ return ret;
4302
+
4303
+ };
4304
+
4305
+
4306
+
4307
+ isXML = Sizzle.isXML = function isXML( elem ) {
4308
+
4309
+ // documentElement is verified for cases where it doesn't yet exist
4310
+
4311
+ // (such as loading iframes in IE - #4833)
4312
+
4313
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4314
+
4315
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
4316
+
4317
+ };
4318
+
4319
+
4320
+
4321
+ // Element contains another
4322
+
4323
+ contains = Sizzle.contains = docElem.contains ?
4324
+
4325
+ function( a, b ) {
4326
+
4327
+ var adown = a.nodeType === 9 ? a.documentElement : a,
4328
+
4329
+ bup = b && b.parentNode;
4330
+
4331
+ return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );
4332
+
4333
+ } :
4334
+
4335
+ docElem.compareDocumentPosition ?
4336
+
4337
+ function( a, b ) {
4338
+
4339
+ return b && !!( a.compareDocumentPosition( b ) & 16 );
4340
+
4341
+ } :
4342
+
4343
+ function( a, b ) {
4344
+
4345
+ while ( (b = b.parentNode) ) {
4346
+
4347
+ if ( b === a ) {
4348
+
4349
+ return true;
4350
+
4351
+ }
4352
+
4353
+ }
4354
+
4355
+ return false;
4356
+
4357
+ };
4358
+
4359
+
4360
+
4361
+ Sizzle.attr = function( elem, name ) {
4362
+
4363
+ var attr,
4364
+
4365
+ xml = isXML( elem );
4366
+
4367
+
4368
+
4369
+ if ( !xml ) {
4370
+
4371
+ name = name.toLowerCase();
4372
+
4373
+ }
4374
+
4375
+ if ( Expr.attrHandle[ name ] ) {
4376
+
4377
+ return Expr.attrHandle[ name ]( elem );
4378
+
4379
+ }
4380
+
4381
+ if ( assertAttributes || xml ) {
4382
+
4383
+ return elem.getAttribute( name );
4384
+
4385
+ }
4386
+
4387
+ attr = elem.getAttributeNode( name );
4388
+
4389
+ return attr ?
4390
+
4391
+ typeof elem[ name ] === "boolean" ?
4392
+
4393
+ elem[ name ] ? name : null :
4394
+
4395
+ attr.specified ? attr.value : null :
4396
+
4397
+ null;
4398
+
4399
+ };
4400
+
4401
+
4402
+
4403
+ Expr = Sizzle.selectors = {
4404
+
4405
+
4406
+
4407
+ // Can be adjusted by the user
4408
+
4409
+ cacheLength: 50,
4410
+
4411
+
4412
+
4413
+ createPseudo: markFunction,
4414
+
4415
+
4416
+
4417
+ match: matchExpr,
4418
+
4419
+
4420
+
4421
+ order: new RegExp( "ID|TAG" +
4422
+
4423
+ (assertUsableName ? "|NAME" : "") +
4424
+
4425
+ (assertUsableClassName ? "|CLASS" : "")
4426
+
4427
+ ),
4428
+
4429
+
4430
+
4431
+ // IE6/7 return a modified href
4432
+
4433
+ attrHandle: assertHrefNotNormalized ?
4434
+
4435
+ {} :
4436
+
4437
+ {
4438
+
4439
+ "href": function( elem ) {
4440
+
4441
+ return elem.getAttribute( "href", 2 );
4442
+
4443
+ },
4444
+
4445
+ "type": function( elem ) {
4446
+
4447
+ return elem.getAttribute("type");
4448
+
4449
+ }
4450
+
4451
+ },
4452
+
4453
+
4454
+
4455
+ find: {
4456
+
4457
+ "ID": assertGetIdNotName ?
4458
+
4459
+ function( id, context, xml ) {
4460
+
4461
+ if ( typeof context.getElementById !== strundefined && !xml ) {
4462
+
4463
+ var m = context.getElementById( id );
4464
+
4465
+ // Check parentNode to catch when Blackberry 4.6 returns
4466
+
4467
+ // nodes that are no longer in the document #6963
4468
+
4469
+ return m && m.parentNode ? [m] : [];
4470
+
4471
+ }
4472
+
4473
+ } :
4474
+
4475
+ function( id, context, xml ) {
4476
+
4477
+ if ( typeof context.getElementById !== strundefined && !xml ) {
4478
+
4479
+ var m = context.getElementById( id );
4480
+
4481
+
4482
+
4483
+ return m ?
4484
+
4485
+ m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
4486
+
4487
+ [m] :
4488
+
4489
+ undefined :
4490
+
4491
+ [];
4492
+
4493
+ }
4494
+
4495
+ },
4496
+
4497
+
4498
+
4499
+ "TAG": assertTagNameNoComments ?
4500
+
4501
+ function( tag, context ) {
4502
+
4503
+ if ( typeof context.getElementsByTagName !== strundefined ) {
4504
+
4505
+ return context.getElementsByTagName( tag );
4506
+
4507
+ }
4508
+
4509
+ } :
4510
+
4511
+ function( tag, context ) {
4512
+
4513
+ var results = context.getElementsByTagName( tag );
4514
+
4515
+
4516
+
4517
+ // Filter out possible comments
4518
+
4519
+ if ( tag === "*" ) {
4520
+
4521
+ var elem,
4522
+
4523
+ tmp = [],
4524
+
4525
+ i = 0;
4526
+
4527
+
4528
+
4529
+ for ( ; (elem = results[i]); i++ ) {
4530
+
4531
+ if ( elem.nodeType === 1 ) {
4532
+
4533
+ tmp.push( elem );
4534
+
4535
+ }
4536
+
4537
+ }
4538
+
4539
+
4540
+
4541
+ return tmp;
4542
+
4543
+ }
4544
+
4545
+ return results;
4546
+
4547
+ },
4548
+
4549
+
4550
+
4551
+ "NAME": function( tag, context ) {
4552
+
4553
+ if ( typeof context.getElementsByName !== strundefined ) {
4554
+
4555
+ return context.getElementsByName( name );
4556
+
4557
+ }
4558
+
4559
+ },
4560
+
4561
+
4562
+
4563
+ "CLASS": function( className, context, xml ) {
4564
+
4565
+ if ( typeof context.getElementsByClassName !== strundefined && !xml ) {
4566
+
4567
+ return context.getElementsByClassName( className );
4568
+
4569
+ }
4570
+
4571
+ }
4572
+
4573
+ },
4574
+
4575
+
4576
+
4577
+ relative: {
4578
+
4579
+ ">": { dir: "parentNode", first: true },
4580
+
4581
+ " ": { dir: "parentNode" },
4582
+
4583
+ "+": { dir: "previousSibling", first: true },
4584
+
4585
+ "~": { dir: "previousSibling" }
4586
+
4587
+ },
4588
+
4589
+
4590
+
4591
+ preFilter: {
4592
+
4593
+ "ATTR": function( match ) {
4594
+
4595
+ match[1] = match[1].replace( rbackslash, "" );
4596
+
4597
+
4598
+
4599
+ // Move the given value to match[3] whether quoted or unquoted
4600
+
4601
+ match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" );
4602
+
4603
+
4604
+
4605
+ if ( match[2] === "~=" ) {
4606
+
4607
+ match[3] = " " + match[3] + " ";
4608
+
4609
+ }
4610
+
4611
+
4612
+
4613
+ return match.slice( 0, 4 );
4614
+
4615
+ },
4616
+
4617
+
4618
+
4619
+ "CHILD": function( match ) {
4620
+
4621
+ /* matches from matchExpr.CHILD
4622
+
4623
+ 1 type (only|nth|...)
4624
+
4625
+ 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4626
+
4627
+ 3 xn-component of xn+y argument ([+-]?\d*n|)
4628
+
4629
+ 4 sign of xn-component
4630
+
4631
+ 5 x of xn-component
4632
+
4633
+ 6 sign of y-component
4634
+
4635
+ 7 y of y-component
4636
+
4637
+ */
4638
+
4639
+ match[1] = match[1].toLowerCase();
4640
+
4641
+
4642
+
4643
+ if ( match[1] === "nth" ) {
4644
+
4645
+ // nth-child requires argument
4646
+
4647
+ if ( !match[2] ) {
4648
+
4649
+ Sizzle.error( match[0] );
4650
+
4651
+ }
4652
+
4653
+
4654
+
4655
+ // numeric x and y parameters for Expr.filter.CHILD
4656
+
4657
+ // remember that false/true cast respectively to 0/1
4658
+
4659
+ match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );
4660
+
4661
+ match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );
4662
+
4663
+
4664
+
4665
+ // other types prohibit arguments
4666
+
4667
+ } else if ( match[2] ) {
4668
+
4669
+ Sizzle.error( match[0] );
4670
+
4671
+ }
4672
+
4673
+
4674
+
4675
+ return match;
4676
+
4677
+ },
4678
+
4679
+
4680
+
4681
+ "PSEUDO": function( match, context, xml ) {
4682
+
4683
+ var unquoted, excess;
4684
+
4685
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
4686
+
4687
+ return null;
4688
+
4689
+ }
4690
+
4691
+
4692
+
4693
+ if ( match[3] ) {
4694
+
4695
+ match[2] = match[3];
4696
+
4697
+ } else if ( (unquoted = match[4]) ) {
4698
+
4699
+ // Only check arguments that contain a pseudo
4700
+
4701
+ if ( rpseudo.test(unquoted) &&
4702
+
4703
+ // Get excess from tokenize (recursively)
4704
+
4705
+ (excess = tokenize( unquoted, context, xml, true )) &&
4706
+
4707
+ // advance to the next closing parenthesis
4708
+
4709
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
4710
+
4711
+
4712
+
4713
+ // excess is a negative index
4714
+
4715
+ unquoted = unquoted.slice( 0, excess );
4716
+
4717
+ match[0] = match[0].slice( 0, excess );
4718
+
4719
+ }
4720
+
4721
+ match[2] = unquoted;
4722
+
4723
+ }
4724
+
4725
+
4726
+
4727
+ // Return only captures needed by the pseudo filter method (type and argument)
4728
+
4729
+ return match.slice( 0, 3 );
4730
+
4731
+ }
4732
+
4733
+ },
4734
+
4735
+
4736
+
4737
+ filter: {
4738
+
4739
+ "ID": assertGetIdNotName ?
4740
+
4741
+ function( id ) {
4742
+
4743
+ id = id.replace( rbackslash, "" );
4744
+
4745
+ return function( elem ) {
4746
+
4747
+ return elem.getAttribute("id") === id;
4748
+
4749
+ };
4750
+
4751
+ } :
4752
+
4753
+ function( id ) {
4754
+
4755
+ id = id.replace( rbackslash, "" );
4756
+
4757
+ return function( elem ) {
4758
+
4759
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
4760
+
4761
+ return node && node.value === id;
4762
+
4763
+ };
4764
+
4765
+ },
4766
+
4767
+
4768
+
4769
+ "TAG": function( nodeName ) {
4770
+
4771
+ if ( nodeName === "*" ) {
4772
+
4773
+ return function() { return true; };
4774
+
4775
+ }
4776
+
4777
+ nodeName = nodeName.replace( rbackslash, "" ).toLowerCase();
4778
+
4779
+
4780
+
4781
+ return function( elem ) {
4782
+
4783
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
4784
+
4785
+ };
4786
+
4787
+ },
4788
+
4789
+
4790
+
4791
+ "CLASS": function( className ) {
4792
+
4793
+ var pattern = classCache[ expando ][ className ];
4794
+
4795
+ if ( !pattern ) {
4796
+
4797
+ pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") );
4798
+
4799
+ }
4800
+
4801
+ return function( elem ) {
4802
+
4803
+ return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
4804
+
4805
+ };
4806
+
4807
+ },
4808
+
4809
+
4810
+
4811
+ "ATTR": function( name, operator, check ) {
4812
+
4813
+ if ( !operator ) {
4814
+
4815
+ return function( elem ) {
4816
+
4817
+ return Sizzle.attr( elem, name ) != null;
4818
+
4819
+ };
4820
+
4821
+ }
4822
+
4823
+
4824
+
4825
+ return function( elem ) {
4826
+
4827
+ var result = Sizzle.attr( elem, name ),
4828
+
4829
+ value = result + "";
4830
+
4831
+
4832
+
4833
+ if ( result == null ) {
4834
+
4835
+ return operator === "!=";
4836
+
4837
+ }
4838
+
4839
+
4840
+
4841
+ switch ( operator ) {
4842
+
4843
+ case "=":
4844
+
4845
+ return value === check;
4846
+
4847
+ case "!=":
4848
+
4849
+ return value !== check;
4850
+
4851
+ case "^=":
4852
+
4853
+ return check && value.indexOf( check ) === 0;
4854
+
4855
+ case "*=":
4856
+
4857
+ return check && value.indexOf( check ) > -1;
4858
+
4859
+ case "$=":
4860
+
4861
+ return check && value.substr( value.length - check.length ) === check;
4862
+
4863
+ case "~=":
4864
+
4865
+ return ( " " + value + " " ).indexOf( check ) > -1;
4866
+
4867
+ case "|=":
4868
+
4869
+ return value === check || value.substr( 0, check.length + 1 ) === check + "-";
4870
+
4871
+ }
4872
+
4873
+ };
4874
+
4875
+ },
4876
+
4877
+
4878
+
4879
+ "CHILD": function( type, argument, first, last ) {
4880
+
4881
+
4882
+
4883
+ if ( type === "nth" ) {
4884
+
4885
+ var doneName = done++;
4886
+
4887
+
4888
+
4889
+ return function( elem ) {
4890
+
4891
+ var parent, diff,
4892
+
4893
+ count = 0,
4894
+
4895
+ node = elem;
4896
+
4897
+
4898
+
4899
+ if ( first === 1 && last === 0 ) {
4900
+
4901
+ return true;
4902
+
4903
+ }
4904
+
4905
+
4906
+
4907
+ parent = elem.parentNode;
4908
+
4909
+
4910
+
4911
+ if ( parent && (parent[ expando ] !== doneName || !elem.sizset) ) {
4912
+
4913
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
4914
+
4915
+ if ( node.nodeType === 1 ) {
4916
+
4917
+ node.sizset = ++count;
4918
+
4919
+ if ( node === elem ) {
4920
+
4921
+ break;
4922
+
4923
+ }
4924
+
4925
+ }
4926
+
4927
+ }
4928
+
4929
+
4930
+
4931
+ parent[ expando ] = doneName;
4932
+
4933
+ }
4934
+
4935
+
4936
+
4937
+ diff = elem.sizset - last;
4938
+
4939
+
4940
+
4941
+ if ( first === 0 ) {
4942
+
4943
+ return diff === 0;
4944
+
4945
+
4946
+
4947
+ } else {
4948
+
4949
+ return ( diff % first === 0 && diff / first >= 0 );
4950
+
4951
+ }
4952
+
4953
+ };
4954
+
4955
+ }
4956
+
4957
+
4958
+
4959
+ return function( elem ) {
4960
+
4961
+ var node = elem;
4962
+
4963
+
4964
+
4965
+ switch ( type ) {
4966
+
4967
+ case "only":
4968
+
4969
+ case "first":
4970
+
4971
+ while ( (node = node.previousSibling) ) {
4972
+
4973
+ if ( node.nodeType === 1 ) {
4974
+
4975
+ return false;
4976
+
4977
+ }
4978
+
4979
+ }
4980
+
4981
+
4982
+
4983
+ if ( type === "first" ) {
4984
+
4985
+ return true;
4986
+
4987
+ }
4988
+
4989
+
4990
+
4991
+ node = elem;
4992
+
4993
+
4994
+
4995
+ /* falls through */
4996
+
4997
+ case "last":
4998
+
4999
+ while ( (node = node.nextSibling) ) {
5000
+
5001
+ if ( node.nodeType === 1 ) {
5002
+
5003
+ return false;
5004
+
5005
+ }
5006
+
5007
+ }
5008
+
5009
+
5010
+
5011
+ return true;
5012
+
5013
+ }
5014
+
5015
+ };
5016
+
5017
+ },
5018
+
5019
+
5020
+
5021
+ "PSEUDO": function( pseudo, argument, context, xml ) {
5022
+
5023
+ // pseudo-class names are case-insensitive
5024
+
5025
+ // http://www.w3.org/TR/selectors/#pseudo-classes
5026
+
5027
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
5028
+
5029
+ var args,
5030
+
5031
+ fn = Expr.pseudos[ pseudo ] || Expr.pseudos[ pseudo.toLowerCase() ];
5032
+
5033
+
5034
+
5035
+ if ( !fn ) {
5036
+
5037
+ Sizzle.error( "unsupported pseudo: " + pseudo );
5038
+
5039
+ }
5040
+
5041
+
5042
+
5043
+ // The user may use createPseudo to indicate that
5044
+
5045
+ // arguments are needed to create the filter function
5046
+
5047
+ // just as Sizzle does
5048
+
5049
+ if ( !fn[ expando ] ) {
5050
+
5051
+ if ( fn.length > 1 ) {
5052
+
5053
+ args = [ pseudo, pseudo, "", argument ];
5054
+
5055
+ return function( elem ) {
5056
+
5057
+ return fn( elem, 0, args );
5058
+
5059
+ };
5060
+
5061
+ }
5062
+
5063
+ return fn;
5064
+
5065
+ }
5066
+
5067
+
5068
+
5069
+ return fn( argument, context, xml );
5070
+
5071
+ }
5072
+
5073
+ },
5074
+
5075
+
5076
+
5077
+ pseudos: {
5078
+
5079
+ "not": markFunction(function( selector, context, xml ) {
5080
+
5081
+ // Trim the selector passed to compile
5082
+
5083
+ // to avoid treating leading and trailing
5084
+
5085
+ // spaces as combinators
5086
+
5087
+ var matcher = compile( selector.replace( rtrim, "$1" ), context, xml );
5088
+
5089
+ return function( elem ) {
5090
+
5091
+ return !matcher( elem );
5092
+
5093
+ };
5094
+
5095
+ }),
5096
+
5097
+
5098
+
5099
+ "enabled": function( elem ) {
5100
+
5101
+ return elem.disabled === false;
5102
+
5103
+ },
5104
+
5105
+
5106
+
5107
+ "disabled": function( elem ) {
5108
+
5109
+ return elem.disabled === true;
5110
+
5111
+ },
5112
+
5113
+
5114
+
5115
+ "checked": function( elem ) {
5116
+
5117
+ // In CSS3, :checked should return both checked and selected elements
5118
+
5119
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
5120
+
5121
+ var nodeName = elem.nodeName.toLowerCase();
5122
+
5123
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
5124
+
5125
+ },
5126
+
5127
+
5128
+
5129
+ "selected": function( elem ) {
5130
+
5131
+ // Accessing this property makes selected-by-default
5132
+
5133
+ // options in Safari work properly
5134
+
5135
+ if ( elem.parentNode ) {
5136
+
5137
+ elem.parentNode.selectedIndex;
5138
+
5139
+ }
5140
+
5141
+
5142
+
5143
+ return elem.selected === true;
5144
+
5145
+ },
5146
+
5147
+
5148
+
5149
+ "parent": function( elem ) {
5150
+
5151
+ return !Expr.pseudos["empty"]( elem );
5152
+
5153
+ },
5154
+
5155
+
5156
+
5157
+ "empty": function( elem ) {
5158
+
5159
+ // http://www.w3.org/TR/selectors/#empty-pseudo
5160
+
5161
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
5162
+
5163
+ // not comment, processing instructions, or others
5164
+
5165
+ // Thanks to Diego Perini for the nodeName shortcut
5166
+
5167
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
5168
+
5169
+ var nodeType;
5170
+
5171
+ elem = elem.firstChild;
5172
+
5173
+ while ( elem ) {
5174
+
5175
+ if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {
5176
+
5177
+ return false;
5178
+
5179
+ }
5180
+
5181
+ elem = elem.nextSibling;
5182
+
5183
+ }
5184
+
5185
+ return true;
5186
+
5187
+ },
5188
+
5189
+
5190
+
5191
+ "contains": markFunction(function( text ) {
5192
+
5193
+ return function( elem ) {
5194
+
5195
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
5196
+
5197
+ };
5198
+
5199
+ }),
5200
+
5201
+
5202
+
5203
+ "has": markFunction(function( selector ) {
5204
+
5205
+ return function( elem ) {
5206
+
5207
+ return Sizzle( selector, elem ).length > 0;
5208
+
5209
+ };
5210
+
5211
+ }),
5212
+
5213
+
5214
+
5215
+ "header": function( elem ) {
5216
+
5217
+ return rheader.test( elem.nodeName );
5218
+
5219
+ },
5220
+
5221
+
5222
+
5223
+ "text": function( elem ) {
5224
+
5225
+ var type, attr;
5226
+
5227
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
5228
+
5229
+ // use getAttribute instead to test this case
5230
+
5231
+ return elem.nodeName.toLowerCase() === "input" &&
5232
+
5233
+ (type = elem.type) === "text" &&
5234
+
5235
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );
5236
+
5237
+ },
5238
+
5239
+
5240
+
5241
+ // Input types
5242
+
5243
+ "radio": createInputPseudo("radio"),
5244
+
5245
+ "checkbox": createInputPseudo("checkbox"),
5246
+
5247
+ "file": createInputPseudo("file"),
5248
+
5249
+ "password": createInputPseudo("password"),
5250
+
5251
+ "image": createInputPseudo("image"),
5252
+
5253
+
5254
+
5255
+ "submit": createButtonPseudo("submit"),
5256
+
5257
+ "reset": createButtonPseudo("reset"),
5258
+
5259
+
5260
+
5261
+ "button": function( elem ) {
5262
+
5263
+ var name = elem.nodeName.toLowerCase();
5264
+
5265
+ return name === "input" && elem.type === "button" || name === "button";
5266
+
5267
+ },
5268
+
5269
+
5270
+
5271
+ "input": function( elem ) {
5272
+
5273
+ return rinputs.test( elem.nodeName );
5274
+
5275
+ },
5276
+
5277
+
5278
+
5279
+ "focus": function( elem ) {
5280
+
5281
+ var doc = elem.ownerDocument;
5282
+
5283
+ return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);
5284
+
5285
+ },
5286
+
5287
+
5288
+
5289
+ "active": function( elem ) {
5290
+
5291
+ return elem === elem.ownerDocument.activeElement;
5292
+
5293
+ }
5294
+
5295
+ },
5296
+
5297
+
5298
+
5299
+ setFilters: {
5300
+
5301
+ "first": function( elements, argument, not ) {
5302
+
5303
+ return not ? elements.slice( 1 ) : [ elements[0] ];
5304
+
5305
+ },
5306
+
5307
+
5308
+
5309
+ "last": function( elements, argument, not ) {
5310
+
5311
+ var elem = elements.pop();
5312
+
5313
+ return not ? elements : [ elem ];
5314
+
5315
+ },
5316
+
5317
+
5318
+
5319
+ "even": function( elements, argument, not ) {
5320
+
5321
+ var results = [],
5322
+
5323
+ i = not ? 1 : 0,
5324
+
5325
+ len = elements.length;
5326
+
5327
+ for ( ; i < len; i = i + 2 ) {
5328
+
5329
+ results.push( elements[i] );
5330
+
5331
+ }
5332
+
5333
+ return results;
5334
+
5335
+ },
5336
+
5337
+
5338
+
5339
+ "odd": function( elements, argument, not ) {
5340
+
5341
+ var results = [],
5342
+
5343
+ i = not ? 0 : 1,
5344
+
5345
+ len = elements.length;
5346
+
5347
+ for ( ; i < len; i = i + 2 ) {
5348
+
5349
+ results.push( elements[i] );
5350
+
5351
+ }
5352
+
5353
+ return results;
5354
+
5355
+ },
5356
+
5357
+
5358
+
5359
+ "lt": function( elements, argument, not ) {
5360
+
5361
+ return not ? elements.slice( +argument ) : elements.slice( 0, +argument );
5362
+
5363
+ },
5364
+
5365
+
5366
+
5367
+ "gt": function( elements, argument, not ) {
5368
+
5369
+ return not ? elements.slice( 0, +argument + 1 ) : elements.slice( +argument + 1 );
5370
+
5371
+ },
5372
+
5373
+
5374
+
5375
+ "eq": function( elements, argument, not ) {
5376
+
5377
+ var elem = elements.splice( +argument, 1 );
5378
+
5379
+ return not ? elements : elem;
5380
+
5381
+ }
5382
+
5383
+ }
5384
+
5385
+ };
5386
+
5387
+
5388
+
5389
+ function siblingCheck( a, b, ret ) {
5390
+
5391
+ if ( a === b ) {
5392
+
5393
+ return ret;
5394
+
5395
+ }
5396
+
5397
+
5398
+
5399
+ var cur = a.nextSibling;
5400
+
5401
+
5402
+
5403
+ while ( cur ) {
5404
+
5405
+ if ( cur === b ) {
5406
+
5407
+ return -1;
5408
+
5409
+ }
5410
+
5411
+
5412
+
5413
+ cur = cur.nextSibling;
5414
+
5415
+ }
5416
+
5417
+
5418
+
5419
+ return 1;
5420
+
5421
+ }
5422
+
5423
+
5424
+
5425
+ sortOrder = docElem.compareDocumentPosition ?
5426
+
5427
+ function( a, b ) {
5428
+
5429
+ if ( a === b ) {
5430
+
5431
+ hasDuplicate = true;
5432
+
5433
+ return 0;
5434
+
5435
+ }
5436
+
5437
+
5438
+
5439
+ return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?
5440
+
5441
+ a.compareDocumentPosition :
5442
+
5443
+ a.compareDocumentPosition(b) & 4
5444
+
5445
+ ) ? -1 : 1;
5446
+
5447
+ } :
5448
+
5449
+ function( a, b ) {
5450
+
5451
+ // The nodes are identical, we can exit early
5452
+
5453
+ if ( a === b ) {
5454
+
5455
+ hasDuplicate = true;
5456
+
5457
+ return 0;
5458
+
5459
+
5460
+
5461
+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
5462
+
5463
+ } else if ( a.sourceIndex && b.sourceIndex ) {
5464
+
5465
+ return a.sourceIndex - b.sourceIndex;
5466
+
5467
+ }
5468
+
5469
+
5470
+
5471
+ var al, bl,
5472
+
5473
+ ap = [],
5474
+
5475
+ bp = [],
5476
+
5477
+ aup = a.parentNode,
5478
+
5479
+ bup = b.parentNode,
5480
+
5481
+ cur = aup;
5482
+
5483
+
5484
+
5485
+ // If the nodes are siblings (or identical) we can do a quick check
5486
+
5487
+ if ( aup === bup ) {
5488
+
5489
+ return siblingCheck( a, b );
5490
+
5491
+
5492
+
5493
+ // If no parents were found then the nodes are disconnected
5494
+
5495
+ } else if ( !aup ) {
5496
+
5497
+ return -1;
5498
+
5499
+
5500
+
5501
+ } else if ( !bup ) {
5502
+
5503
+ return 1;
5504
+
5505
+ }
5506
+
5507
+
5508
+
5509
+ // Otherwise they're somewhere else in the tree so we need
5510
+
5511
+ // to build up a full list of the parentNodes for comparison
5512
+
5513
+ while ( cur ) {
5514
+
5515
+ ap.unshift( cur );
5516
+
5517
+ cur = cur.parentNode;
5518
+
5519
+ }
5520
+
5521
+
5522
+
5523
+ cur = bup;
5524
+
5525
+
5526
+
5527
+ while ( cur ) {
5528
+
5529
+ bp.unshift( cur );
5530
+
5531
+ cur = cur.parentNode;
5532
+
5533
+ }
5534
+
5535
+
5536
+
5537
+ al = ap.length;
5538
+
5539
+ bl = bp.length;
5540
+
5541
+
5542
+
5543
+ // Start walking down the tree looking for a discrepancy
5544
+
5545
+ for ( var i = 0; i < al && i < bl; i++ ) {
5546
+
5547
+ if ( ap[i] !== bp[i] ) {
5548
+
5549
+ return siblingCheck( ap[i], bp[i] );
5550
+
5551
+ }
5552
+
5553
+ }
5554
+
5555
+
5556
+
5557
+ // We ended someplace up the tree so do a sibling check
5558
+
5559
+ return i === al ?
5560
+
5561
+ siblingCheck( a, bp[i], -1 ) :
5562
+
5563
+ siblingCheck( ap[i], b, 1 );
5564
+
5565
+ };
5566
+
5567
+
5568
+
5569
+ // Always assume the presence of duplicates if sort doesn't
5570
+
5571
+ // pass them to our comparison function (as in Google Chrome).
5572
+
5573
+ [0, 0].sort( sortOrder );
5574
+
5575
+ baseHasDuplicate = !hasDuplicate;
5576
+
5577
+
5578
+
5579
+ // Document sorting and removing duplicates
5580
+
5581
+ Sizzle.uniqueSort = function( results ) {
5582
+
5583
+ var elem,
5584
+
5585
+ i = 1;
5586
+
5587
+
5588
+
5589
+ hasDuplicate = baseHasDuplicate;
5590
+
5591
+ results.sort( sortOrder );
5592
+
5593
+
5594
+
5595
+ if ( hasDuplicate ) {
5596
+
5597
+ for ( ; (elem = results[i]); i++ ) {
5598
+
5599
+ if ( elem === results[ i - 1 ] ) {
5600
+
5601
+ results.splice( i--, 1 );
5602
+
5603
+ }
5604
+
5605
+ }
5606
+
5607
+ }
5608
+
5609
+
5610
+
5611
+ return results;
5612
+
5613
+ };
5614
+
5615
+
5616
+
5617
+ Sizzle.error = function( msg ) {
5618
+
5619
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
5620
+
5621
+ };
5622
+
5623
+
5624
+
5625
+ function tokenize( selector, context, xml, parseOnly ) {
5626
+
5627
+ var matched, match, tokens, type,
5628
+
5629
+ soFar, groups, group, i,
5630
+
5631
+ preFilters, filters,
5632
+
5633
+ checkContext = !xml && context !== document,
5634
+
5635
+ // Token cache should maintain spaces
5636
+
5637
+ key = ( checkContext ? "<s>" : "" ) + selector.replace( rtrim, "$1<s>" ),
5638
+
5639
+ cached = tokenCache[ expando ][ key ];
5640
+
5641
+
5642
+
5643
+ if ( cached ) {
5644
+
5645
+ return parseOnly ? 0 : slice.call( cached, 0 );
5646
+
5647
+ }
5648
+
5649
+
5650
+
5651
+ soFar = selector;
5652
+
5653
+ groups = [];
5654
+
5655
+ i = 0;
5656
+
5657
+ preFilters = Expr.preFilter;
5658
+
5659
+ filters = Expr.filter;
5660
+
5661
+
5662
+
5663
+ while ( soFar ) {
5664
+
5665
+
5666
+
5667
+ // Comma and first run
5668
+
5669
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
5670
+
5671
+ if ( match ) {
5672
+
5673
+ soFar = soFar.slice( match[0].length );
5674
+
5675
+ tokens.selector = group;
5676
+
5677
+ }
5678
+
5679
+ groups.push( tokens = [] );
5680
+
5681
+ group = "";
5682
+
5683
+
5684
+
5685
+ // Need to make sure we're within a narrower context if necessary
5686
+
5687
+ // Adding a descendant combinator will generate what is needed
5688
+
5689
+ if ( checkContext ) {
5690
+
5691
+ soFar = " " + soFar;
5692
+
5693
+ }
5694
+
5695
+ }
5696
+
5697
+
5698
+
5699
+ matched = false;
5700
+
5701
+
5702
+
5703
+ // Combinators
5704
+
5705
+ if ( (match = rcombinators.exec( soFar )) ) {
5706
+
5707
+ group += match[0];
5708
+
5709
+ soFar = soFar.slice( match[0].length );
5710
+
5711
+
5712
+
5713
+ // Cast descendant combinators to space
5714
+
5715
+ matched = tokens.push({
5716
+
5717
+ part: match.pop().replace( rtrim, " " ),
5718
+
5719
+ string: match[0],
5720
+
5721
+ captures: match
5722
+
5723
+ });
5724
+
5725
+ }
5726
+
5727
+
5728
+
5729
+ // Filters
5730
+
5731
+ for ( type in filters ) {
5732
+
5733
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5734
+
5735
+ ( match = preFilters[ type ](match, context, xml) )) ) {
5736
+
5737
+
5738
+
5739
+ group += match[0];
5740
+
5741
+ soFar = soFar.slice( match[0].length );
5742
+
5743
+ matched = tokens.push({
5744
+
5745
+ part: type,
5746
+
5747
+ string: match.shift(),
5748
+
5749
+ captures: match
5750
+
5751
+ });
5752
+
5753
+ }
5754
+
5755
+ }
5756
+
5757
+
5758
+
5759
+ if ( !matched ) {
5760
+
5761
+ break;
5762
+
5763
+ }
5764
+
5765
+ }
5766
+
5767
+
5768
+
5769
+ // Attach the full group as a selector
5770
+
5771
+ if ( group ) {
5772
+
5773
+ tokens.selector = group;
5774
+
5775
+ }
5776
+
5777
+
5778
+
5779
+ // Return the length of the invalid excess
5780
+
5781
+ // if we're just parsing
5782
+
5783
+ // Otherwise, throw an error or return tokens
5784
+
5785
+ return parseOnly ?
5786
+
5787
+ soFar.length :
5788
+
5789
+ soFar ?
5790
+
5791
+ Sizzle.error( selector ) :
5792
+
5793
+ // Cache the tokens
5794
+
5795
+ slice.call( tokenCache(key, groups), 0 );
5796
+
5797
+ }
5798
+
5799
+
5800
+
5801
+ function addCombinator( matcher, combinator, context, xml ) {
5802
+
5803
+ var dir = combinator.dir,
5804
+
5805
+ doneName = done++;
5806
+
5807
+
5808
+
5809
+ if ( !matcher ) {
5810
+
5811
+ // If there is no matcher to check, check against the context
5812
+
5813
+ matcher = function( elem ) {
5814
+
5815
+ return elem === context;
5816
+
5817
+ };
5818
+
5819
+ }
5820
+
5821
+ return combinator.first ?
5822
+
5823
+ function( elem ) {
5824
+
5825
+ while ( (elem = elem[ dir ]) ) {
5826
+
5827
+ if ( elem.nodeType === 1 ) {
5828
+
5829
+ return matcher( elem ) && elem;
5830
+
5831
+ }
5832
+
5833
+ }
5834
+
5835
+ } :
5836
+
5837
+ xml ?
5838
+
5839
+ function( elem ) {
5840
+
5841
+ while ( (elem = elem[ dir ]) ) {
5842
+
5843
+ if ( elem.nodeType === 1 ) {
5844
+
5845
+ if ( matcher( elem ) ) {
5846
+
5847
+ return elem;
5848
+
5849
+ }
5850
+
5851
+ }
5852
+
5853
+ }
5854
+
5855
+ } :
5856
+
5857
+ function( elem ) {
5858
+
5859
+ var cache,
5860
+
5861
+ dirkey = doneName + "." + dirruns,
5862
+
5863
+ cachedkey = dirkey + "." + cachedruns;
5864
+
5865
+ while ( (elem = elem[ dir ]) ) {
5866
+
5867
+ if ( elem.nodeType === 1 ) {
5868
+
5869
+ if ( (cache = elem[ expando ]) === cachedkey ) {
5870
+
5871
+ return elem.sizset;
5872
+
5873
+ } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {
5874
+
5875
+ if ( elem.sizset ) {
5876
+
5877
+ return elem;
5878
+
5879
+ }
5880
+
5881
+ } else {
5882
+
5883
+ elem[ expando ] = cachedkey;
5884
+
5885
+ if ( matcher( elem ) ) {
5886
+
5887
+ elem.sizset = true;
5888
+
5889
+ return elem;
5890
+
5891
+ }
5892
+
5893
+ elem.sizset = false;
5894
+
5895
+ }
5896
+
5897
+ }
5898
+
5899
+ }
5900
+
5901
+ };
5902
+
5903
+ }
5904
+
5905
+
5906
+
5907
+ function addMatcher( higher, deeper ) {
5908
+
5909
+ return higher ?
5910
+
5911
+ function( elem ) {
5912
+
5913
+ var result = deeper( elem );
5914
+
5915
+ return result && higher( result === true ? elem : result );
5916
+
5917
+ } :
5918
+
5919
+ deeper;
5920
+
5921
+ }
5922
+
5923
+
5924
+
5925
+ // ["TAG", ">", "ID", " ", "CLASS"]
5926
+
5927
+ function matcherFromTokens( tokens, context, xml ) {
5928
+
5929
+ var token, matcher,
5930
+
5931
+ i = 0;
5932
+
5933
+
5934
+
5935
+ for ( ; (token = tokens[i]); i++ ) {
5936
+
5937
+ if ( Expr.relative[ token.part ] ) {
5938
+
5939
+ matcher = addCombinator( matcher, Expr.relative[ token.part ], context, xml );
5940
+
5941
+ } else {
5942
+
5943
+ matcher = addMatcher( matcher, Expr.filter[ token.part ].apply(null, token.captures.concat( context, xml )) );
5944
+
5945
+ }
5946
+
5947
+ }
5948
+
5949
+
5950
+
5951
+ return matcher;
5952
+
5953
+ }
5954
+
5955
+
5956
+
5957
+ function matcherFromGroupMatchers( matchers ) {
5958
+
5959
+ return function( elem ) {
5960
+
5961
+ var matcher,
5962
+
5963
+ j = 0;
5964
+
5965
+ for ( ; (matcher = matchers[j]); j++ ) {
5966
+
5967
+ if ( matcher(elem) ) {
5968
+
5969
+ return true;
5970
+
5971
+ }
5972
+
5973
+ }
5974
+
5975
+ return false;
5976
+
5977
+ };
5978
+
5979
+ }
5980
+
5981
+
5982
+
5983
+ compile = Sizzle.compile = function( selector, context, xml ) {
5984
+
5985
+ var group, i, len,
5986
+
5987
+ cached = compilerCache[ expando ][ selector ];
5988
+
5989
+
5990
+
5991
+ // Return a cached group function if already generated (context dependent)
5992
+
5993
+ if ( cached && cached.context === context ) {
5994
+
5995
+ return cached;
5996
+
5997
+ }
5998
+
5999
+
6000
+
6001
+ // Generate a function of recursive functions that can be used to check each element
6002
+
6003
+ group = tokenize( selector, context, xml );
6004
+
6005
+ for ( i = 0, len = group.length; i < len; i++ ) {
6006
+
6007
+ group[i] = matcherFromTokens(group[i], context, xml);
6008
+
6009
+ }
6010
+
6011
+
6012
+
6013
+ // Cache the compiled function
6014
+
6015
+ cached = compilerCache( selector, matcherFromGroupMatchers(group) );
6016
+
6017
+ cached.context = context;
6018
+
6019
+ cached.runs = cached.dirruns = 0;
6020
+
6021
+ return cached;
6022
+
6023
+ };
6024
+
6025
+
6026
+
6027
+ function multipleContexts( selector, contexts, results, seed ) {
6028
+
6029
+ var i = 0,
6030
+
6031
+ len = contexts.length;
6032
+
6033
+ for ( ; i < len; i++ ) {
6034
+
6035
+ Sizzle( selector, contexts[i], results, seed );
6036
+
6037
+ }
6038
+
6039
+ }
6040
+
6041
+
6042
+
6043
+ function handlePOSGroup( selector, posfilter, argument, contexts, seed, not ) {
6044
+
6045
+ var results,
6046
+
6047
+ fn = Expr.setFilters[ posfilter.toLowerCase() ];
6048
+
6049
+
6050
+
6051
+ if ( !fn ) {
6052
+
6053
+ Sizzle.error( posfilter );
6054
+
6055
+ }
6056
+
6057
+
6058
+
6059
+ if ( selector || !(results = seed) ) {
6060
+
6061
+ multipleContexts( selector || "*", contexts, (results = []), seed );
6062
+
6063
+ }
6064
+
6065
+
6066
+
6067
+ return results.length > 0 ? fn( results, argument, not ) : [];
6068
+
6069
+ }
6070
+
6071
+
6072
+
6073
+ function handlePOS( groups, context, results, seed ) {
6074
+
6075
+ var group, part, j, groupLen, token, selector,
6076
+
6077
+ anchor, elements, match, matched,
6078
+
6079
+ lastIndex, currentContexts, not,
6080
+
6081
+ i = 0,
6082
+
6083
+ len = groups.length,
6084
+
6085
+ rpos = matchExpr["POS"],
6086
+
6087
+ // This is generated here in case matchExpr["POS"] is extended
6088
+
6089
+ rposgroups = new RegExp( "^" + rpos.source + "(?!" + whitespace + ")", "i" ),
6090
+
6091
+ // This is for making sure non-participating
6092
+
6093
+ // matching groups are represented cross-browser (IE6-8)
6094
+
6095
+ setUndefined = function() {
6096
+
6097
+ var i = 1,
6098
+
6099
+ len = arguments.length - 2;
6100
+
6101
+ for ( ; i < len; i++ ) {
6102
+
6103
+ if ( arguments[i] === undefined ) {
6104
+
6105
+ match[i] = undefined;
6106
+
6107
+ }
6108
+
6109
+ }
6110
+
6111
+ };
6112
+
6113
+
6114
+
6115
+ for ( ; i < len; i++ ) {
6116
+
6117
+ group = groups[i];
6118
+
6119
+ part = "";
6120
+
6121
+ elements = seed;
6122
+
6123
+ for ( j = 0, groupLen = group.length; j < groupLen; j++ ) {
6124
+
6125
+ token = group[j];
6126
+
6127
+ selector = token.string;
6128
+
6129
+ if ( token.part === "PSEUDO" ) {
6130
+
6131
+ // Reset regex index to 0
6132
+
6133
+ rpos.exec("");
6134
+
6135
+ anchor = 0;
6136
+
6137
+ while ( (match = rpos.exec( selector )) ) {
6138
+
6139
+ matched = true;
6140
+
6141
+ lastIndex = rpos.lastIndex = match.index + match[0].length;
6142
+
6143
+ if ( lastIndex > anchor ) {
6144
+
6145
+ part += selector.slice( anchor, match.index );
6146
+
6147
+ anchor = lastIndex;
6148
+
6149
+ currentContexts = [ context ];
6150
+
6151
+
6152
+
6153
+ if ( rcombinators.test(part) ) {
6154
+
6155
+ if ( elements ) {
6156
+
6157
+ currentContexts = elements;
6158
+
6159
+ }
6160
+
6161
+ elements = seed;
6162
+
6163
+ }
6164
+
6165
+
6166
+
6167
+ if ( (not = rendsWithNot.test( part )) ) {
6168
+
6169
+ part = part.slice( 0, -5 ).replace( rcombinators, "$&*" );
6170
+
6171
+ anchor++;
6172
+
6173
+ }
6174
+
6175
+
6176
+
6177
+ if ( match.length > 1 ) {
6178
+
6179
+ match[0].replace( rposgroups, setUndefined );
6180
+
6181
+ }
6182
+
6183
+ elements = handlePOSGroup( part, match[1], match[2], currentContexts, elements, not );
6184
+
6185
+ }
6186
+
6187
+ part = "";
6188
+
6189
+ }
6190
+
6191
+
6192
+
6193
+ }
6194
+
6195
+
6196
+
6197
+ if ( !matched ) {
6198
+
6199
+ part += selector;
6200
+
6201
+ }
6202
+
6203
+ matched = false;
6204
+
6205
+ }
6206
+
6207
+
6208
+
6209
+ if ( part ) {
6210
+
6211
+ if ( rcombinators.test(part) ) {
6212
+
6213
+ multipleContexts( part, elements || [ context ], results, seed );
6214
+
6215
+ } else {
6216
+
6217
+ Sizzle( part, context, results, seed ? seed.concat(elements) : elements );
6218
+
6219
+ }
6220
+
6221
+ } else {
6222
+
6223
+ push.apply( results, elements );
6224
+
6225
+ }
6226
+
6227
+ }
6228
+
6229
+
6230
+
6231
+ // Do not sort if this is a single filter
6232
+
6233
+ return len === 1 ? results : Sizzle.uniqueSort( results );
6234
+
6235
+ }
6236
+
6237
+
6238
+
6239
+ function select( selector, context, results, seed, xml ) {
6240
+
6241
+ // Remove excessive whitespace
6242
+
6243
+ selector = selector.replace( rtrim, "$1" );
6244
+
6245
+ var elements, matcher, cached, elem,
6246
+
6247
+ i, tokens, token, lastToken, findContext, type,
6248
+
6249
+ match = tokenize( selector, context, xml ),
6250
+
6251
+ contextNodeType = context.nodeType;
6252
+
6253
+
6254
+
6255
+ // POS handling
6256
+
6257
+ if ( matchExpr["POS"].test(selector) ) {
6258
+
6259
+ return handlePOS( match, context, results, seed );
6260
+
6261
+ }
6262
+
6263
+
6264
+
6265
+ if ( seed ) {
6266
+
6267
+ elements = slice.call( seed, 0 );
6268
+
6269
+
6270
+
6271
+ // To maintain document order, only narrow the
6272
+
6273
+ // set if there is one group
6274
+
6275
+ } else if ( match.length === 1 ) {
6276
+
6277
+
6278
+
6279
+ // Take a shortcut and set the context if the root selector is an ID
6280
+
6281
+ if ( (tokens = slice.call( match[0], 0 )).length > 2 &&
6282
+
6283
+ (token = tokens[0]).part === "ID" &&
6284
+
6285
+ contextNodeType === 9 && !xml &&
6286
+
6287
+ Expr.relative[ tokens[1].part ] ) {
6288
+
6289
+
6290
+
6291
+ context = Expr.find["ID"]( token.captures[0].replace( rbackslash, "" ), context, xml )[0];
6292
+
6293
+ if ( !context ) {
6294
+
6295
+ return results;
6296
+
6297
+ }
6298
+
6299
+
6300
+
6301
+ selector = selector.slice( tokens.shift().string.length );
6302
+
6303
+ }
6304
+
6305
+
6306
+
6307
+ findContext = ( (match = rsibling.exec( tokens[0].string )) && !match.index && context.parentNode ) || context;
6308
+
6309
+
6310
+
6311
+ // Reduce the set if possible
6312
+
6313
+ lastToken = "";
6314
+
6315
+ for ( i = tokens.length - 1; i >= 0; i-- ) {
6316
+
6317
+ token = tokens[i];
6318
+
6319
+ type = token.part;
6320
+
6321
+ lastToken = token.string + lastToken;
6322
+
6323
+ if ( Expr.relative[ type ] ) {
6324
+
6325
+ break;
6326
+
6327
+ }
6328
+
6329
+ if ( Expr.order.test(type) ) {
6330
+
6331
+ elements = Expr.find[ type ]( token.captures[0].replace( rbackslash, "" ), findContext, xml );
6332
+
6333
+ if ( elements == null ) {
6334
+
6335
+ continue;
6336
+
6337
+ } else {
6338
+
6339
+ selector = selector.slice( 0, selector.length - lastToken.length ) +
6340
+
6341
+ lastToken.replace( matchExpr[ type ], "" );
6342
+
6343
+
6344
+
6345
+ if ( !selector ) {
6346
+
6347
+ push.apply( results, slice.call(elements, 0) );
6348
+
6349
+ }
6350
+
6351
+
6352
+
6353
+ break;
6354
+
6355
+ }
6356
+
6357
+ }
6358
+
6359
+ }
6360
+
6361
+ }
6362
+
6363
+
6364
+
6365
+ // Only loop over the given elements once
6366
+
6367
+ if ( selector ) {
6368
+
6369
+ matcher = compile( selector, context, xml );
6370
+
6371
+ dirruns = matcher.dirruns++;
6372
+
6373
+ if ( elements == null ) {
6374
+
6375
+ elements = Expr.find["TAG"]( "*", (rsibling.test( selector ) && context.parentNode) || context );
6376
+
6377
+ }
6378
+
6379
+
6380
+
6381
+ for ( i = 0; (elem = elements[i]); i++ ) {
6382
+
6383
+ cachedruns = matcher.runs++;
6384
+
6385
+ if ( matcher(elem) ) {
6386
+
6387
+ results.push( elem );
6388
+
6389
+ }
6390
+
6391
+ }
6392
+
6393
+ }
6394
+
6395
+
6396
+
6397
+ return results;
6398
+
6399
+ }
6400
+
6401
+
6402
+
6403
+ if ( document.querySelectorAll ) {
6404
+
6405
+ (function() {
6406
+
6407
+ var disconnectedMatch,
6408
+
6409
+ oldSelect = select,
6410
+
6411
+ rescape = /'|\\/g,
6412
+
6413
+ rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
6414
+
6415
+ rbuggyQSA = [],
6416
+
6417
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
6418
+
6419
+ // A support test would require too much code (would include document ready)
6420
+
6421
+ // just skip matchesSelector for :active
6422
+
6423
+ rbuggyMatches = [":active"],
6424
+
6425
+ matches = docElem.matchesSelector ||
6426
+
6427
+ docElem.mozMatchesSelector ||
6428
+
6429
+ docElem.webkitMatchesSelector ||
6430
+
6431
+ docElem.oMatchesSelector ||
6432
+
6433
+ docElem.msMatchesSelector;
6434
+
6435
+
6436
+
6437
+ // Build QSA regex
6438
+
6439
+ // Regex strategy adopted from Diego Perini
6440
+
6441
+ assert(function( div ) {
6442
+
6443
+ // Select is set to empty string on purpose
6444
+
6445
+ // This is to test IE's treatment of not explictly
6446
+
6447
+ // setting a boolean content attribute,
6448
+
6449
+ // since its presence should be enough
6450
+
6451
+ // http://bugs.jquery.com/ticket/12359
6452
+
6453
+ div.innerHTML = "<select><option selected=''></option></select>";
6454
+
6455
+
6456
+
6457
+ // IE8 - Some boolean attributes are not treated correctly
6458
+
6459
+ if ( !div.querySelectorAll("[selected]").length ) {
6460
+
6461
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
6462
+
6463
+ }
6464
+
6465
+
6466
+
6467
+ // Webkit/Opera - :checked should return selected option elements
6468
+
6469
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
6470
+
6471
+ // IE8 throws error here (do not put tests after this one)
6472
+
6473
+ if ( !div.querySelectorAll(":checked").length ) {
6474
+
6475
+ rbuggyQSA.push(":checked");
6476
+
6477
+ }
6478
+
6479
+ });
6480
+
6481
+
6482
+
6483
+ assert(function( div ) {
6484
+
6485
+
6486
+
6487
+ // Opera 10-12/IE9 - ^= $= *= and empty values
6488
+
6489
+ // Should not select anything
6490
+
6491
+ div.innerHTML = "<p test=''></p>";
6492
+
6493
+ if ( div.querySelectorAll("[test^='']").length ) {
6494
+
6495
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
6496
+
6497
+ }
6498
+
6499
+
6500
+
6501
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
6502
+
6503
+ // IE8 throws error here (do not put tests after this one)
6504
+
6505
+ div.innerHTML = "<input type='hidden'/>";
6506
+
6507
+ if ( !div.querySelectorAll(":enabled").length ) {
6508
+
6509
+ rbuggyQSA.push(":enabled", ":disabled");
6510
+
6511
+ }
6512
+
6513
+ });
6514
+
6515
+
6516
+
6517
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
6518
+
6519
+
6520
+
6521
+ select = function( selector, context, results, seed, xml ) {
6522
+
6523
+ // Only use querySelectorAll when not filtering,
6524
+
6525
+ // when this is not xml,
6526
+
6527
+ // and when no QSA bugs apply
6528
+
6529
+ if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
6530
+
6531
+ if ( context.nodeType === 9 ) {
6532
+
6533
+ try {
6534
+
6535
+ push.apply( results, slice.call(context.querySelectorAll( selector ), 0) );
6536
+
6537
+ return results;
6538
+
6539
+ } catch(qsaError) {}
6540
+
6541
+ // qSA works strangely on Element-rooted queries
6542
+
6543
+ // We can work around this by specifying an extra ID on the root
6544
+
6545
+ // and working up from there (Thanks to Andrew Dupont for the technique)
6546
+
6547
+ // IE 8 doesn't work on object elements
6548
+
6549
+ } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
6550
+
6551
+ var groups, i, len,
6552
+
6553
+ old = context.getAttribute("id"),
6554
+
6555
+ nid = old || expando,
6556
+
6557
+ newContext = rsibling.test( selector ) && context.parentNode || context;
6558
+
6559
+
6560
+
6561
+ if ( old ) {
6562
+
6563
+ nid = nid.replace( rescape, "\\$&" );
6564
+
6565
+ } else {
6566
+
6567
+ context.setAttribute( "id", nid );
6568
+
6569
+ }
6570
+
6571
+
6572
+
6573
+ groups = tokenize(selector, context, xml);
6574
+
6575
+ // Trailing space is unnecessary
6576
+
6577
+ // There is always a context check
6578
+
6579
+ nid = "[id='" + nid + "']";
6580
+
6581
+ for ( i = 0, len = groups.length; i < len; i++ ) {
6582
+
6583
+ groups[i] = nid + groups[i].selector;
6584
+
6585
+ }
6586
+
6587
+ try {
6588
+
6589
+ push.apply( results, slice.call( newContext.querySelectorAll(
6590
+
6591
+ groups.join(",")
6592
+
6593
+ ), 0 ) );
6594
+
6595
+ return results;
6596
+
6597
+ } catch(qsaError) {
6598
+
6599
+ } finally {
6600
+
6601
+ if ( !old ) {
6602
+
6603
+ context.removeAttribute("id");
6604
+
6605
+ }
6606
+
6607
+ }
6608
+
6609
+ }
6610
+
6611
+ }
6612
+
6613
+
6614
+
6615
+ return oldSelect( selector, context, results, seed, xml );
6616
+
6617
+ };
6618
+
6619
+
6620
+
6621
+ if ( matches ) {
6622
+
6623
+ assert(function( div ) {
6624
+
6625
+ // Check to see if it's possible to do matchesSelector
6626
+
6627
+ // on a disconnected node (IE 9)
6628
+
6629
+ disconnectedMatch = matches.call( div, "div" );
6630
+
6631
+
6632
+
6633
+ // This should fail with an exception
6634
+
6635
+ // Gecko does not error, returns false instead
6636
+
6637
+ try {
6638
+
6639
+ matches.call( div, "[test!='']:sizzle" );
6640
+
6641
+ rbuggyMatches.push( matchExpr["PSEUDO"].source, matchExpr["POS"].source, "!=" );
6642
+
6643
+ } catch ( e ) {}
6644
+
6645
+ });
6646
+
6647
+
6648
+
6649
+ // rbuggyMatches always contains :active, so no need for a length check
6650
+
6651
+ rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );
6652
+
6653
+
6654
+
6655
+ Sizzle.matchesSelector = function( elem, expr ) {
6656
+
6657
+ // Make sure that attribute selectors are quoted
6658
+
6659
+ expr = expr.replace( rattributeQuotes, "='$1']" );
6660
+
6661
+
6662
+
6663
+ // rbuggyMatches always contains :active, so no need for an existence check
6664
+
6665
+ if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) {
6666
+
6667
+ try {
6668
+
6669
+ var ret = matches.call( elem, expr );
6670
+
6671
+
6672
+
6673
+ // IE 9's matchesSelector returns false on disconnected nodes
6674
+
6675
+ if ( ret || disconnectedMatch ||
6676
+
6677
+ // As well, disconnected nodes are said to be in a document
6678
+
6679
+ // fragment in IE 9
6680
+
6681
+ elem.document && elem.document.nodeType !== 11 ) {
6682
+
6683
+ return ret;
6684
+
6685
+ }
6686
+
6687
+ } catch(e) {}
6688
+
6689
+ }
6690
+
6691
+
6692
+
6693
+ return Sizzle( expr, null, null, [ elem ] ).length > 0;
6694
+
6695
+ };
6696
+
6697
+ }
6698
+
6699
+ })();
6700
+
6701
+ }
6702
+
6703
+
6704
+
6705
+ // Deprecated
6706
+
6707
+ Expr.setFilters["nth"] = Expr.setFilters["eq"];
6708
+
6709
+
6710
+
6711
+ // Back-compat
6712
+
6713
+ Expr.filters = Expr.pseudos;
6714
+
6715
+
6716
+
6717
+ // Override sizzle attribute retrieval
6718
+ Sizzle.attr = jQuery.attr;
6719
+ jQuery.find = Sizzle;
6720
+ jQuery.expr = Sizzle.selectors;
6721
+ jQuery.expr[":"] = jQuery.expr.pseudos;
6722
+ jQuery.unique = Sizzle.uniqueSort;
6723
+ jQuery.text = Sizzle.getText;
6724
+ jQuery.isXMLDoc = Sizzle.isXML;
6725
+ jQuery.contains = Sizzle.contains;
6726
+
6727
+
6728
+
6729
+
6730
+ })( window );
6731
+
6732
+ var runtil = /Until$/,
6733
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
6734
+ isSimple = /^.[^:#\[\.,]*$/,
6735
+ rneedsContext = jQuery.expr.match.needsContext,
6736
+ // methods guaranteed to produce a unique set when starting from a unique set
6737
+ guaranteedUnique = {
6738
+ children: true,
6739
+ contents: true,
6740
+ next: true,
6741
+ prev: true
6742
+ };
6743
+
6744
+ jQuery.fn.extend({
6745
+ find: function( selector ) {
6746
+ var i, l, length, n, r, ret,
6747
+ self = this;
6748
+
6749
+ if ( typeof selector !== "string" ) {
6750
+ return jQuery( selector ).filter(function() {
6751
+ for ( i = 0, l = self.length; i < l; i++ ) {
6752
+ if ( jQuery.contains( self[ i ], this ) ) {
6753
+ return true;
6754
+ }
6755
+ }
6756
+ });
6757
+ }
6758
+
6759
+ ret = this.pushStack( "", "find", selector );
6760
+
6761
+ for ( i = 0, l = this.length; i < l; i++ ) {
6762
+ length = ret.length;
6763
+ jQuery.find( selector, this[i], ret );
6764
+
6765
+ if ( i > 0 ) {
6766
+ // Make sure that the results are unique
6767
+ for ( n = length; n < ret.length; n++ ) {
6768
+ for ( r = 0; r < length; r++ ) {
6769
+ if ( ret[r] === ret[n] ) {
6770
+ ret.splice(n--, 1);
6771
+ break;
6772
+ }
6773
+ }
6774
+ }
6775
+ }
6776
+ }
6777
+
6778
+ return ret;
6779
+ },
6780
+
6781
+ has: function( target ) {
6782
+ var i,
6783
+ targets = jQuery( target, this ),
6784
+ len = targets.length;
6785
+
6786
+ return this.filter(function() {
6787
+ for ( i = 0; i < len; i++ ) {
6788
+ if ( jQuery.contains( this, targets[i] ) ) {
6789
+ return true;
6790
+ }
6791
+ }
6792
+ });
6793
+ },
6794
+
6795
+ not: function( selector ) {
6796
+ return this.pushStack( winnow(this, selector, false), "not", selector);
6797
+ },
6798
+
6799
+ filter: function( selector ) {
6800
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
6801
+ },
6802
+
6803
+ is: function( selector ) {
6804
+ return !!selector && (
6805
+ typeof selector === "string" ?
6806
+ // If this is a positional/relative selector, check membership in the returned set
6807
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
6808
+ rneedsContext.test( selector ) ?
6809
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
6810
+ jQuery.filter( selector, this ).length > 0 :
6811
+ this.filter( selector ).length > 0 );
6812
+ },
6813
+
6814
+ closest: function( selectors, context ) {
6815
+ var cur,
6816
+ i = 0,
6817
+ l = this.length,
6818
+ ret = [],
6819
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
6820
+ jQuery( selectors, context || this.context ) :
6821
+ 0;
6822
+
6823
+ for ( ; i < l; i++ ) {
6824
+ cur = this[i];
6825
+
6826
+ while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
6827
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
6828
+ ret.push( cur );
6829
+ break;
6830
+ }
6831
+ cur = cur.parentNode;
6832
+ }
6833
+ }
6834
+
6835
+ ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
6836
+
6837
+ return this.pushStack( ret, "closest", selectors );
6838
+ },
6839
+
6840
+ // Determine the position of an element within
6841
+ // the matched set of elements
6842
+ index: function( elem ) {
6843
+
6844
+ // No argument, return index in parent
6845
+ if ( !elem ) {
6846
+ return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
6847
+ }
6848
+
6849
+ // index in selector
6850
+ if ( typeof elem === "string" ) {
6851
+ return jQuery.inArray( this[0], jQuery( elem ) );
6852
+ }
6853
+
6854
+ // Locate the position of the desired element
6855
+ return jQuery.inArray(
6856
+ // If it receives a jQuery object, the first element is used
6857
+ elem.jquery ? elem[0] : elem, this );
6858
+ },
6859
+
6860
+ add: function( selector, context ) {
6861
+ var set = typeof selector === "string" ?
6862
+ jQuery( selector, context ) :
6863
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
6864
+ all = jQuery.merge( this.get(), set );
6865
+
6866
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
6867
+ all :
6868
+ jQuery.unique( all ) );
6869
+ },
6870
+
6871
+ addBack: function( selector ) {
6872
+ return this.add( selector == null ?
6873
+ this.prevObject : this.prevObject.filter(selector)
6874
+ );
6875
+ }
6876
+ });
6877
+
6878
+ jQuery.fn.andSelf = jQuery.fn.addBack;
6879
+
6880
+ // A painfully simple check to see if an element is disconnected
6881
+ // from a document (should be improved, where feasible).
6882
+ function isDisconnected( node ) {
6883
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
6884
+ }
6885
+
6886
+ function sibling( cur, dir ) {
6887
+ do {
6888
+ cur = cur[ dir ];
6889
+ } while ( cur && cur.nodeType !== 1 );
6890
+
6891
+ return cur;
6892
+ }
6893
+
6894
+ jQuery.each({
6895
+ parent: function( elem ) {
6896
+ var parent = elem.parentNode;
6897
+ return parent && parent.nodeType !== 11 ? parent : null;
6898
+ },
6899
+ parents: function( elem ) {
6900
+ return jQuery.dir( elem, "parentNode" );
6901
+ },
6902
+ parentsUntil: function( elem, i, until ) {
6903
+ return jQuery.dir( elem, "parentNode", until );
6904
+ },
6905
+ next: function( elem ) {
6906
+ return sibling( elem, "nextSibling" );
6907
+ },
6908
+ prev: function( elem ) {
6909
+ return sibling( elem, "previousSibling" );
6910
+ },
6911
+ nextAll: function( elem ) {
6912
+ return jQuery.dir( elem, "nextSibling" );
6913
+ },
6914
+ prevAll: function( elem ) {
6915
+ return jQuery.dir( elem, "previousSibling" );
6916
+ },
6917
+ nextUntil: function( elem, i, until ) {
6918
+ return jQuery.dir( elem, "nextSibling", until );
6919
+ },
6920
+ prevUntil: function( elem, i, until ) {
6921
+ return jQuery.dir( elem, "previousSibling", until );
6922
+ },
6923
+ siblings: function( elem ) {
6924
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
6925
+ },
6926
+ children: function( elem ) {
6927
+ return jQuery.sibling( elem.firstChild );
6928
+ },
6929
+ contents: function( elem ) {
6930
+ return jQuery.nodeName( elem, "iframe" ) ?
6931
+ elem.contentDocument || elem.contentWindow.document :
6932
+ jQuery.merge( [], elem.childNodes );
6933
+ }
6934
+ }, function( name, fn ) {
6935
+ jQuery.fn[ name ] = function( until, selector ) {
6936
+ var ret = jQuery.map( this, fn, until );
6937
+
6938
+ if ( !runtil.test( name ) ) {
6939
+ selector = until;
6940
+ }
6941
+
6942
+ if ( selector && typeof selector === "string" ) {
6943
+ ret = jQuery.filter( selector, ret );
6944
+ }
6945
+
6946
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
6947
+
6948
+ if ( this.length > 1 && rparentsprev.test( name ) ) {
6949
+ ret = ret.reverse();
6950
+ }
6951
+
6952
+ return this.pushStack( ret, name, core_slice.call( arguments ).join(",") );
6953
+ };
6954
+ });
6955
+
6956
+ jQuery.extend({
6957
+ filter: function( expr, elems, not ) {
6958
+ if ( not ) {
6959
+ expr = ":not(" + expr + ")";
6960
+ }
6961
+
6962
+ return elems.length === 1 ?
6963
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
6964
+ jQuery.find.matches(expr, elems);
6965
+ },
6966
+
6967
+ dir: function( elem, dir, until ) {
6968
+ var matched = [],
6969
+ cur = elem[ dir ];
6970
+
6971
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
6972
+ if ( cur.nodeType === 1 ) {
6973
+ matched.push( cur );
6974
+ }
6975
+ cur = cur[dir];
6976
+ }
6977
+ return matched;
6978
+ },
6979
+
6980
+ sibling: function( n, elem ) {
6981
+ var r = [];
6982
+
6983
+ for ( ; n; n = n.nextSibling ) {
6984
+ if ( n.nodeType === 1 && n !== elem ) {
6985
+ r.push( n );
6986
+ }
6987
+ }
6988
+
6989
+ return r;
6990
+ }
6991
+ });
6992
+
6993
+ // Implement the identical functionality for filter and not
6994
+ function winnow( elements, qualifier, keep ) {
6995
+
6996
+ // Can't pass null or undefined to indexOf in Firefox 4
6997
+ // Set to 0 to skip string check
6998
+ qualifier = qualifier || 0;
6999
+
7000
+ if ( jQuery.isFunction( qualifier ) ) {
7001
+ return jQuery.grep(elements, function( elem, i ) {
7002
+ var retVal = !!qualifier.call( elem, i, elem );
7003
+ return retVal === keep;
7004
+ });
7005
+
7006
+ } else if ( qualifier.nodeType ) {
7007
+ return jQuery.grep(elements, function( elem, i ) {
7008
+ return ( elem === qualifier ) === keep;
7009
+ });
7010
+
7011
+ } else if ( typeof qualifier === "string" ) {
7012
+ var filtered = jQuery.grep(elements, function( elem ) {
7013
+ return elem.nodeType === 1;
7014
+ });
7015
+
7016
+ if ( isSimple.test( qualifier ) ) {
7017
+ return jQuery.filter(qualifier, filtered, !keep);
7018
+ } else {
7019
+ qualifier = jQuery.filter( qualifier, filtered );
7020
+ }
7021
+ }
7022
+
7023
+ return jQuery.grep(elements, function( elem, i ) {
7024
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
7025
+ });
7026
+ }
7027
+ function createSafeFragment( document ) {
7028
+ var list = nodeNames.split( "|" ),
7029
+ safeFrag = document.createDocumentFragment();
7030
+
7031
+ if ( safeFrag.createElement ) {
7032
+ while ( list.length ) {
7033
+ safeFrag.createElement(
7034
+ list.pop()
7035
+ );
7036
+ }
7037
+ }
7038
+ return safeFrag;
7039
+ }
7040
+
7041
+ var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
7042
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
7043
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
7044
+ rleadingWhitespace = /^\s+/,
7045
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
7046
+ rtagName = /<([\w:]+)/,
7047
+ rtbody = /<tbody/i,
7048
+ rhtml = /<|&#?\w+;/,
7049
+ rnoInnerhtml = /<(?:script|style|link)/i,
7050
+ rnocache = /<(?:script|object|embed|option|style)/i,
7051
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
7052
+ rcheckableType = /^(?:checkbox|radio)$/,
7053
+ // checked="checked" or checked
7054
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
7055
+ rscriptType = /\/(java|ecma)script/i,
7056
+ rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,
7057
+ wrapMap = {
7058
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
7059
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
7060
+ thead: [ 1, "<table>", "</table>" ],
7061
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
7062
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
7063
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
7064
+ area: [ 1, "<map>", "</map>" ],
7065
+ _default: [ 0, "", "" ]
7066
+ },
7067
+ safeFragment = createSafeFragment( document ),
7068
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
7069
+
7070
+ wrapMap.optgroup = wrapMap.option;
7071
+ wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
7072
+ wrapMap.th = wrapMap.td;
7073
+
7074
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
7075
+ // unless wrapped in a div with non-breaking characters in front of it.
7076
+ if ( !jQuery.support.htmlSerialize ) {
7077
+ wrapMap._default = [ 1, "X<div>", "</div>" ];
7078
+ }
7079
+
7080
+ jQuery.fn.extend({
7081
+ text: function( value ) {
7082
+ return jQuery.access( this, function( value ) {
7083
+ return value === undefined ?
7084
+ jQuery.text( this ) :
7085
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
7086
+ }, null, value, arguments.length );
7087
+ },
7088
+
7089
+ wrapAll: function( html ) {
7090
+ if ( jQuery.isFunction( html ) ) {
7091
+ return this.each(function(i) {
7092
+ jQuery(this).wrapAll( html.call(this, i) );
7093
+ });
7094
+ }
7095
+
7096
+ if ( this[0] ) {
7097
+ // The elements to wrap the target around
7098
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
7099
+
7100
+ if ( this[0].parentNode ) {
7101
+ wrap.insertBefore( this[0] );
7102
+ }
7103
+
7104
+ wrap.map(function() {
7105
+ var elem = this;
7106
+
7107
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
7108
+ elem = elem.firstChild;
7109
+ }
7110
+
7111
+ return elem;
7112
+ }).append( this );
7113
+ }
7114
+
7115
+ return this;
7116
+ },
7117
+
7118
+ wrapInner: function( html ) {
7119
+ if ( jQuery.isFunction( html ) ) {
7120
+ return this.each(function(i) {
7121
+ jQuery(this).wrapInner( html.call(this, i) );
7122
+ });
7123
+ }
7124
+
7125
+ return this.each(function() {
7126
+ var self = jQuery( this ),
7127
+ contents = self.contents();
7128
+
7129
+ if ( contents.length ) {
7130
+ contents.wrapAll( html );
7131
+
7132
+ } else {
7133
+ self.append( html );
7134
+ }
7135
+ });
7136
+ },
7137
+
7138
+ wrap: function( html ) {
7139
+ var isFunction = jQuery.isFunction( html );
7140
+
7141
+ return this.each(function(i) {
7142
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
7143
+ });
7144
+ },
7145
+
7146
+ unwrap: function() {
7147
+ return this.parent().each(function() {
7148
+ if ( !jQuery.nodeName( this, "body" ) ) {
7149
+ jQuery( this ).replaceWith( this.childNodes );
7150
+ }
7151
+ }).end();
7152
+ },
7153
+
7154
+ append: function() {
7155
+ return this.domManip(arguments, true, function( elem ) {
7156
+ if ( this.nodeType === 1 || this.nodeType === 11 ) {
7157
+ this.appendChild( elem );
7158
+ }
7159
+ });
7160
+ },
7161
+
7162
+ prepend: function() {
7163
+ return this.domManip(arguments, true, function( elem ) {
7164
+ if ( this.nodeType === 1 || this.nodeType === 11 ) {
7165
+ this.insertBefore( elem, this.firstChild );
7166
+ }
7167
+ });
7168
+ },
7169
+
7170
+ before: function() {
7171
+ if ( !isDisconnected( this[0] ) ) {
7172
+ return this.domManip(arguments, false, function( elem ) {
7173
+ this.parentNode.insertBefore( elem, this );
7174
+ });
7175
+ }
7176
+
7177
+ if ( arguments.length ) {
7178
+ var set = jQuery.clean( arguments );
7179
+ return this.pushStack( jQuery.merge( set, this ), "before", this.selector );
7180
+ }
7181
+ },
7182
+
7183
+ after: function() {
7184
+ if ( !isDisconnected( this[0] ) ) {
7185
+ return this.domManip(arguments, false, function( elem ) {
7186
+ this.parentNode.insertBefore( elem, this.nextSibling );
7187
+ });
7188
+ }
7189
+
7190
+ if ( arguments.length ) {
7191
+ var set = jQuery.clean( arguments );
7192
+ return this.pushStack( jQuery.merge( this, set ), "after", this.selector );
7193
+ }
7194
+ },
7195
+
7196
+ // keepData is for internal use only--do not document
7197
+ remove: function( selector, keepData ) {
7198
+ var elem,
7199
+ i = 0;
7200
+
7201
+ for ( ; (elem = this[i]) != null; i++ ) {
7202
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
7203
+ if ( !keepData && elem.nodeType === 1 ) {
7204
+ jQuery.cleanData( elem.getElementsByTagName("*") );
7205
+ jQuery.cleanData( [ elem ] );
7206
+ }
7207
+
7208
+ if ( elem.parentNode ) {
7209
+ elem.parentNode.removeChild( elem );
7210
+ }
7211
+ }
7212
+ }
7213
+
7214
+ return this;
7215
+ },
7216
+
7217
+ empty: function() {
7218
+ var elem,
7219
+ i = 0;
7220
+
7221
+ for ( ; (elem = this[i]) != null; i++ ) {
7222
+ // Remove element nodes and prevent memory leaks
7223
+ if ( elem.nodeType === 1 ) {
7224
+ jQuery.cleanData( elem.getElementsByTagName("*") );
7225
+ }
7226
+
7227
+ // Remove any remaining nodes
7228
+ while ( elem.firstChild ) {
7229
+ elem.removeChild( elem.firstChild );
7230
+ }
7231
+ }
7232
+
7233
+ return this;
7234
+ },
7235
+
7236
+ clone: function( dataAndEvents, deepDataAndEvents ) {
7237
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
7238
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
7239
+
7240
+ return this.map( function () {
7241
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
7242
+ });
7243
+ },
7244
+
7245
+ html: function( value ) {
7246
+ return jQuery.access( this, function( value ) {
7247
+ var elem = this[0] || {},
7248
+ i = 0,
7249
+ l = this.length;
7250
+
7251
+ if ( value === undefined ) {
7252
+ return elem.nodeType === 1 ?
7253
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
7254
+ undefined;
7255
+ }
7256
+
7257
+ // See if we can take a shortcut and just use innerHTML
7258
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
7259
+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
7260
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
7261
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
7262
+
7263
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
7264
+
7265
+ try {
7266
+ for (; i < l; i++ ) {
7267
+ // Remove element nodes and prevent memory leaks
7268
+ elem = this[i] || {};
7269
+ if ( elem.nodeType === 1 ) {
7270
+ jQuery.cleanData( elem.getElementsByTagName( "*" ) );
7271
+ elem.innerHTML = value;
7272
+ }
7273
+ }
7274
+
7275
+ elem = 0;
7276
+
7277
+ // If using innerHTML throws an exception, use the fallback method
7278
+ } catch(e) {}
7279
+ }
7280
+
7281
+ if ( elem ) {
7282
+ this.empty().append( value );
7283
+ }
7284
+ }, null, value, arguments.length );
7285
+ },
7286
+
7287
+ replaceWith: function( value ) {
7288
+ if ( !isDisconnected( this[0] ) ) {
7289
+ // Make sure that the elements are removed from the DOM before they are inserted
7290
+ // this can help fix replacing a parent with child elements
7291
+ if ( jQuery.isFunction( value ) ) {
7292
+ return this.each(function(i) {
7293
+ var self = jQuery(this), old = self.html();
7294
+ self.replaceWith( value.call( this, i, old ) );
7295
+ });
7296
+ }
7297
+
7298
+ if ( typeof value !== "string" ) {
7299
+ value = jQuery( value ).detach();
7300
+ }
7301
+
7302
+ return this.each(function() {
7303
+ var next = this.nextSibling,
7304
+ parent = this.parentNode;
7305
+
7306
+ jQuery( this ).remove();
7307
+
7308
+ if ( next ) {
7309
+ jQuery(next).before( value );
7310
+ } else {
7311
+ jQuery(parent).append( value );
7312
+ }
7313
+ });
7314
+ }
7315
+
7316
+ return this.length ?
7317
+ this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
7318
+ this;
7319
+ },
7320
+
7321
+ detach: function( selector ) {
7322
+ return this.remove( selector, true );
7323
+ },
7324
+
7325
+ domManip: function( args, table, callback ) {
7326
+
7327
+ // Flatten any nested arrays
7328
+ args = [].concat.apply( [], args );
7329
+
7330
+ var results, first, fragment, iNoClone,
7331
+ i = 0,
7332
+ value = args[0],
7333
+ scripts = [],
7334
+ l = this.length;
7335
+
7336
+ // We can't cloneNode fragments that contain checked, in WebKit
7337
+ if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) {
7338
+ return this.each(function() {
7339
+ jQuery(this).domManip( args, table, callback );
7340
+ });
7341
+ }
7342
+
7343
+ if ( jQuery.isFunction(value) ) {
7344
+ return this.each(function(i) {
7345
+ var self = jQuery(this);
7346
+ args[0] = value.call( this, i, table ? self.html() : undefined );
7347
+ self.domManip( args, table, callback );
7348
+ });
7349
+ }
7350
+
7351
+ if ( this[0] ) {
7352
+ results = jQuery.buildFragment( args, this, scripts );
7353
+ fragment = results.fragment;
7354
+ first = fragment.firstChild;
7355
+
7356
+ if ( fragment.childNodes.length === 1 ) {
7357
+ fragment = first;
7358
+ }
7359
+
7360
+ if ( first ) {
7361
+ table = table && jQuery.nodeName( first, "tr" );
7362
+
7363
+ // Use the original fragment for the last item instead of the first because it can end up
7364
+ // being emptied incorrectly in certain situations (#8070).
7365
+ // Fragments from the fragment cache must always be cloned and never used in place.
7366
+ for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {
7367
+ callback.call(
7368
+ table && jQuery.nodeName( this[i], "table" ) ?
7369
+ findOrAppend( this[i], "tbody" ) :
7370
+ this[i],
7371
+ i === iNoClone ?
7372
+ fragment :
7373
+ jQuery.clone( fragment, true, true )
7374
+ );
7375
+ }
7376
+ }
7377
+
7378
+ // Fix #11809: Avoid leaking memory
7379
+ fragment = first = null;
7380
+
7381
+ if ( scripts.length ) {
7382
+ jQuery.each( scripts, function( i, elem ) {
7383
+ if ( elem.src ) {
7384
+ if ( jQuery.ajax ) {
7385
+ jQuery.ajax({
7386
+ url: elem.src,
7387
+ type: "GET",
7388
+ dataType: "script",
7389
+ async: false,
7390
+ global: false,
7391
+ "throws": true
7392
+ });
7393
+ } else {
7394
+ jQuery.error("no ajax");
7395
+ }
7396
+ } else {
7397
+ jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) );
7398
+ }
7399
+
7400
+ if ( elem.parentNode ) {
7401
+ elem.parentNode.removeChild( elem );
7402
+ }
7403
+ });
7404
+ }
7405
+ }
7406
+
7407
+ return this;
7408
+ }
7409
+ });
7410
+
7411
+ function findOrAppend( elem, tag ) {
7412
+ return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
7413
+ }
7414
+
7415
+ function cloneCopyEvent( src, dest ) {
7416
+
7417
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
7418
+ return;
7419
+ }
7420
+
7421
+ var type, i, l,
7422
+ oldData = jQuery._data( src ),
7423
+ curData = jQuery._data( dest, oldData ),
7424
+ events = oldData.events;
7425
+
7426
+ if ( events ) {
7427
+ delete curData.handle;
7428
+ curData.events = {};
7429
+
7430
+ for ( type in events ) {
7431
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
7432
+ jQuery.event.add( dest, type, events[ type ][ i ] );
7433
+ }
7434
+ }
7435
+ }
7436
+
7437
+ // make the cloned public data object a copy from the original
7438
+ if ( curData.data ) {
7439
+ curData.data = jQuery.extend( {}, curData.data );
7440
+ }
7441
+ }
7442
+
7443
+ function cloneFixAttributes( src, dest ) {
7444
+ var nodeName;
7445
+
7446
+ // We do not need to do anything for non-Elements
7447
+ if ( dest.nodeType !== 1 ) {
7448
+ return;
7449
+ }
7450
+
7451
+ // clearAttributes removes the attributes, which we don't want,
7452
+ // but also removes the attachEvent events, which we *do* want
7453
+ if ( dest.clearAttributes ) {
7454
+ dest.clearAttributes();
7455
+ }
7456
+
7457
+ // mergeAttributes, in contrast, only merges back on the
7458
+ // original attributes, not the events
7459
+ if ( dest.mergeAttributes ) {
7460
+ dest.mergeAttributes( src );
7461
+ }
7462
+
7463
+ nodeName = dest.nodeName.toLowerCase();
7464
+
7465
+ if ( nodeName === "object" ) {
7466
+ // IE6-10 improperly clones children of object elements using classid.
7467
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
7468
+ if ( dest.parentNode ) {
7469
+ dest.outerHTML = src.outerHTML;
7470
+ }
7471
+
7472
+ // This path appears unavoidable for IE9. When cloning an object
7473
+ // element in IE9, the outerHTML strategy above is not sufficient.
7474
+ // If the src has innerHTML and the destination does not,
7475
+ // copy the src.innerHTML into the dest.innerHTML. #10324
7476
+ if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {
7477
+ dest.innerHTML = src.innerHTML;
7478
+ }
7479
+
7480
+ } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
7481
+ // IE6-8 fails to persist the checked state of a cloned checkbox
7482
+ // or radio button. Worse, IE6-7 fail to give the cloned element
7483
+ // a checked appearance if the defaultChecked value isn't also set
7484
+
7485
+ dest.defaultChecked = dest.checked = src.checked;
7486
+
7487
+ // IE6-7 get confused and end up setting the value of a cloned
7488
+ // checkbox/radio button to an empty string instead of "on"
7489
+ if ( dest.value !== src.value ) {
7490
+ dest.value = src.value;
7491
+ }
7492
+
7493
+ // IE6-8 fails to return the selected option to the default selected
7494
+ // state when cloning options
7495
+ } else if ( nodeName === "option" ) {
7496
+ dest.selected = src.defaultSelected;
7497
+
7498
+ // IE6-8 fails to set the defaultValue to the correct value when
7499
+ // cloning other types of input fields
7500
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
7501
+ dest.defaultValue = src.defaultValue;
7502
+
7503
+ // IE blanks contents when cloning scripts
7504
+ } else if ( nodeName === "script" && dest.text !== src.text ) {
7505
+ dest.text = src.text;
7506
+ }
7507
+
7508
+ // Event data gets referenced instead of copied if the expando
7509
+ // gets copied too
7510
+ dest.removeAttribute( jQuery.expando );
7511
+ }
7512
+
7513
+ jQuery.buildFragment = function( args, context, scripts ) {
7514
+ var fragment, cacheable, cachehit,
7515
+ first = args[ 0 ];
7516
+
7517
+ // Set context from what may come in as undefined or a jQuery collection or a node
7518
+ // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 &
7519
+ // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception
7520
+ context = context || document;
7521
+ context = !context.nodeType && context[0] || context;
7522
+ context = context.ownerDocument || context;
7523
+
7524
+ // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
7525
+ // Cloning options loses the selected state, so don't cache them
7526
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
7527
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
7528
+ // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
7529
+ if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document &&
7530
+ first.charAt(0) === "<" && !rnocache.test( first ) &&
7531
+ (jQuery.support.checkClone || !rchecked.test( first )) &&
7532
+ (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
7533
+
7534
+ // Mark cacheable and look for a hit
7535
+ cacheable = true;
7536
+ fragment = jQuery.fragments[ first ];
7537
+ cachehit = fragment !== undefined;
7538
+ }
7539
+
7540
+ if ( !fragment ) {
7541
+ fragment = context.createDocumentFragment();
7542
+ jQuery.clean( args, context, fragment, scripts );
7543
+
7544
+ // Update the cache, but only store false
7545
+ // unless this is a second parsing of the same content
7546
+ if ( cacheable ) {
7547
+ jQuery.fragments[ first ] = cachehit && fragment;
7548
+ }
7549
+ }
7550
+
7551
+ return { fragment: fragment, cacheable: cacheable };
7552
+ };
7553
+
7554
+ jQuery.fragments = {};
7555
+
7556
+ jQuery.each({
7557
+ appendTo: "append",
7558
+ prependTo: "prepend",
7559
+ insertBefore: "before",
7560
+ insertAfter: "after",
7561
+ replaceAll: "replaceWith"
7562
+ }, function( name, original ) {
7563
+ jQuery.fn[ name ] = function( selector ) {
7564
+ var elems,
7565
+ i = 0,
7566
+ ret = [],
7567
+ insert = jQuery( selector ),
7568
+ l = insert.length,
7569
+ parent = this.length === 1 && this[0].parentNode;
7570
+
7571
+ if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {
7572
+ insert[ original ]( this[0] );
7573
+ return this;
7574
+ } else {
7575
+ for ( ; i < l; i++ ) {
7576
+ elems = ( i > 0 ? this.clone(true) : this ).get();
7577
+ jQuery( insert[i] )[ original ]( elems );
7578
+ ret = ret.concat( elems );
7579
+ }
7580
+
7581
+ return this.pushStack( ret, name, insert.selector );
7582
+ }
7583
+ };
7584
+ });
7585
+
7586
+ function getAll( elem ) {
7587
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
7588
+ return elem.getElementsByTagName( "*" );
7589
+
7590
+ } else if ( typeof elem.querySelectorAll !== "undefined" ) {
7591
+ return elem.querySelectorAll( "*" );
7592
+
7593
+ } else {
7594
+ return [];
7595
+ }
7596
+ }
7597
+
7598
+ // Used in clean, fixes the defaultChecked property
7599
+ function fixDefaultChecked( elem ) {
7600
+ if ( rcheckableType.test( elem.type ) ) {
7601
+ elem.defaultChecked = elem.checked;
7602
+ }
7603
+ }
7604
+
7605
+ jQuery.extend({
7606
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
7607
+ var srcElements,
7608
+ destElements,
7609
+ i,
7610
+ clone;
7611
+
7612
+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
7613
+ clone = elem.cloneNode( true );
7614
+
7615
+ // IE<=8 does not properly clone detached, unknown element nodes
7616
+ } else {
7617
+ fragmentDiv.innerHTML = elem.outerHTML;
7618
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
7619
+ }
7620
+
7621
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
7622
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
7623
+ // IE copies events bound via attachEvent when using cloneNode.
7624
+ // Calling detachEvent on the clone will also remove the events
7625
+ // from the original. In order to get around this, we use some
7626
+ // proprietary methods to clear the events. Thanks to MooTools
7627
+ // guys for this hotness.
7628
+
7629
+ cloneFixAttributes( elem, clone );
7630
+
7631
+ // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
7632
+ srcElements = getAll( elem );
7633
+ destElements = getAll( clone );
7634
+
7635
+ // Weird iteration because IE will replace the length property
7636
+ // with an element if you are cloning the body and one of the
7637
+ // elements on the page has a name or id of "length"
7638
+ for ( i = 0; srcElements[i]; ++i ) {
7639
+ // Ensure that the destination node is not null; Fixes #9587
7640
+ if ( destElements[i] ) {
7641
+ cloneFixAttributes( srcElements[i], destElements[i] );
7642
+ }
7643
+ }
7644
+ }
7645
+
7646
+ // Copy the events from the original to the clone
7647
+ if ( dataAndEvents ) {
7648
+ cloneCopyEvent( elem, clone );
7649
+
7650
+ if ( deepDataAndEvents ) {
7651
+ srcElements = getAll( elem );
7652
+ destElements = getAll( clone );
7653
+
7654
+ for ( i = 0; srcElements[i]; ++i ) {
7655
+ cloneCopyEvent( srcElements[i], destElements[i] );
7656
+ }
7657
+ }
7658
+ }
7659
+
7660
+ srcElements = destElements = null;
7661
+
7662
+ // Return the cloned set
7663
+ return clone;
7664
+ },
7665
+
7666
+ clean: function( elems, context, fragment, scripts ) {
7667
+ var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,
7668
+ safe = context === document && safeFragment,
7669
+ ret = [];
7670
+
7671
+ // Ensure that context is a document
7672
+ if ( !context || typeof context.createDocumentFragment === "undefined" ) {
7673
+ context = document;
7674
+ }
7675
+
7676
+ // Use the already-created safe fragment if context permits
7677
+ for ( i = 0; (elem = elems[i]) != null; i++ ) {
7678
+ if ( typeof elem === "number" ) {
7679
+ elem += "";
7680
+ }
7681
+
7682
+ if ( !elem ) {
7683
+ continue;
7684
+ }
7685
+
7686
+ // Convert html string into DOM nodes
7687
+ if ( typeof elem === "string" ) {
7688
+ if ( !rhtml.test( elem ) ) {
7689
+ elem = context.createTextNode( elem );
7690
+ } else {
7691
+ // Ensure a safe container in which to render the html
7692
+ safe = safe || createSafeFragment( context );
7693
+ div = context.createElement("div");
7694
+ safe.appendChild( div );
7695
+
7696
+ // Fix "XHTML"-style tags in all browsers
7697
+ elem = elem.replace(rxhtmlTag, "<$1></$2>");
7698
+
7699
+ // Go to html and back, then peel off extra wrappers
7700
+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
7701
+ wrap = wrapMap[ tag ] || wrapMap._default;
7702
+ depth = wrap[0];
7703
+ div.innerHTML = wrap[1] + elem + wrap[2];
7704
+
7705
+ // Move to the right depth
7706
+ while ( depth-- ) {
7707
+ div = div.lastChild;
7708
+ }
7709
+
7710
+ // Remove IE's autoinserted <tbody> from table fragments
7711
+ if ( !jQuery.support.tbody ) {
7712
+
7713
+ // String was a <table>, *may* have spurious <tbody>
7714
+ hasBody = rtbody.test(elem);
7715
+ tbody = tag === "table" && !hasBody ?
7716
+ div.firstChild && div.firstChild.childNodes :
7717
+
7718
+ // String was a bare <thead> or <tfoot>
7719
+ wrap[1] === "<table>" && !hasBody ?
7720
+ div.childNodes :
7721
+ [];
7722
+
7723
+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
7724
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
7725
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
7726
+ }
7727
+ }
7728
+ }
7729
+
7730
+ // IE completely kills leading whitespace when innerHTML is used
7731
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
7732
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
7733
+ }
7734
+
7735
+ elem = div.childNodes;
7736
+
7737
+ // Take out of fragment container (we need a fresh div each time)
7738
+ div.parentNode.removeChild( div );
7739
+ }
7740
+ }
7741
+
7742
+ if ( elem.nodeType ) {
7743
+ ret.push( elem );
7744
+ } else {
7745
+ jQuery.merge( ret, elem );
7746
+ }
7747
+ }
7748
+
7749
+ // Fix #11356: Clear elements from safeFragment
7750
+ if ( div ) {
7751
+ elem = div = safe = null;
7752
+ }
7753
+
7754
+ // Reset defaultChecked for any radios and checkboxes
7755
+ // about to be appended to the DOM in IE 6/7 (#8060)
7756
+ if ( !jQuery.support.appendChecked ) {
7757
+ for ( i = 0; (elem = ret[i]) != null; i++ ) {
7758
+ if ( jQuery.nodeName( elem, "input" ) ) {
7759
+ fixDefaultChecked( elem );
7760
+ } else if ( typeof elem.getElementsByTagName !== "undefined" ) {
7761
+ jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
7762
+ }
7763
+ }
7764
+ }
7765
+
7766
+ // Append elements to a provided document fragment
7767
+ if ( fragment ) {
7768
+ // Special handling of each script element
7769
+ handleScript = function( elem ) {
7770
+ // Check if we consider it executable
7771
+ if ( !elem.type || rscriptType.test( elem.type ) ) {
7772
+ // Detach the script and store it in the scripts array (if provided) or the fragment
7773
+ // Return truthy to indicate that it has been handled
7774
+ return scripts ?
7775
+ scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
7776
+ fragment.appendChild( elem );
7777
+ }
7778
+ };
7779
+
7780
+ for ( i = 0; (elem = ret[i]) != null; i++ ) {
7781
+ // Check if we're done after handling an executable script
7782
+ if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
7783
+ // Append to fragment and handle embedded scripts
7784
+ fragment.appendChild( elem );
7785
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
7786
+ // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
7787
+ jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
7788
+
7789
+ // Splice the scripts into ret after their former ancestor and advance our index beyond them
7790
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
7791
+ i += jsTags.length;
7792
+ }
7793
+ }
7794
+ }
7795
+ }
7796
+
7797
+ return ret;
7798
+ },
7799
+
7800
+ cleanData: function( elems, /* internal */ acceptData ) {
7801
+ var data, id, elem, type,
7802
+ i = 0,
7803
+ internalKey = jQuery.expando,
7804
+ cache = jQuery.cache,
7805
+ deleteExpando = jQuery.support.deleteExpando,
7806
+ special = jQuery.event.special;
7807
+
7808
+ for ( ; (elem = elems[i]) != null; i++ ) {
7809
+
7810
+ if ( acceptData || jQuery.acceptData( elem ) ) {
7811
+
7812
+ id = elem[ internalKey ];
7813
+ data = id && cache[ id ];
7814
+
7815
+ if ( data ) {
7816
+ if ( data.events ) {
7817
+ for ( type in data.events ) {
7818
+ if ( special[ type ] ) {
7819
+ jQuery.event.remove( elem, type );
7820
+
7821
+ // This is a shortcut to avoid jQuery.event.remove's overhead
7822
+ } else {
7823
+ jQuery.removeEvent( elem, type, data.handle );
7824
+ }
7825
+ }
7826
+ }
7827
+
7828
+ // Remove cache only if it was not already removed by jQuery.event.remove
7829
+ if ( cache[ id ] ) {
7830
+
7831
+ delete cache[ id ];
7832
+
7833
+ // IE does not allow us to delete expando properties from nodes,
7834
+ // nor does it have a removeAttribute function on Document nodes;
7835
+ // we must handle all of these cases
7836
+ if ( deleteExpando ) {
7837
+ delete elem[ internalKey ];
7838
+
7839
+ } else if ( elem.removeAttribute ) {
7840
+ elem.removeAttribute( internalKey );
7841
+
7842
+ } else {
7843
+ elem[ internalKey ] = null;
7844
+ }
7845
+
7846
+ jQuery.deletedIds.push( id );
7847
+ }
7848
+ }
7849
+ }
7850
+ }
7851
+ }
7852
+ });
7853
+ // Limit scope pollution from any deprecated API
7854
+ (function() {
7855
+
7856
+ var matched, browser;
7857
+
7858
+ // Use of jQuery.browser is frowned upon.
7859
+ // More details: http://api.jquery.com/jQuery.browser
7860
+ // jQuery.uaMatch maintained for back-compat
7861
+ jQuery.uaMatch = function( ua ) {
7862
+ ua = ua.toLowerCase();
7863
+
7864
+ var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
7865
+ /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
7866
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
7867
+ /(msie) ([\w.]+)/.exec( ua ) ||
7868
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
7869
+ [];
7870
+
7871
+ return {
7872
+ browser: match[ 1 ] || "",
7873
+ version: match[ 2 ] || "0"
7874
+ };
7875
+ };
7876
+
7877
+ matched = jQuery.uaMatch( navigator.userAgent );
7878
+ browser = {};
7879
+
7880
+ if ( matched.browser ) {
7881
+ browser[ matched.browser ] = true;
7882
+ browser.version = matched.version;
7883
+ }
7884
+
7885
+ // Chrome is Webkit, but Webkit is also Safari.
7886
+ if ( browser.chrome ) {
7887
+ browser.webkit = true;
7888
+ } else if ( browser.webkit ) {
7889
+ browser.safari = true;
7890
+ }
7891
+
7892
+ jQuery.browser = browser;
7893
+
7894
+ jQuery.sub = function() {
7895
+ function jQuerySub( selector, context ) {
7896
+ return new jQuerySub.fn.init( selector, context );
7897
+ }
7898
+ jQuery.extend( true, jQuerySub, this );
7899
+ jQuerySub.superclass = this;
7900
+ jQuerySub.fn = jQuerySub.prototype = this();
7901
+ jQuerySub.fn.constructor = jQuerySub;
7902
+ jQuerySub.sub = this.sub;
7903
+ jQuerySub.fn.init = function init( selector, context ) {
7904
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
7905
+ context = jQuerySub( context );
7906
+ }
7907
+
7908
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
7909
+ };
7910
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
7911
+ var rootjQuerySub = jQuerySub(document);
7912
+ return jQuerySub;
7913
+ };
7914
+
7915
+ })();
7916
+ var curCSS, iframe, iframeDoc,
7917
+ ralpha = /alpha\([^)]*\)/i,
7918
+ ropacity = /opacity=([^)]*)/,
7919
+ rposition = /^(top|right|bottom|left)$/,
7920
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
7921
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
7922
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
7923
+ rmargin = /^margin/,
7924
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
7925
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
7926
+ rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
7927
+ elemdisplay = {},
7928
+
7929
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
7930
+ cssNormalTransform = {
7931
+ letterSpacing: 0,
7932
+ fontWeight: 400
7933
+ },
7934
+
7935
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
7936
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
7937
+
7938
+ eventsToggle = jQuery.fn.toggle;
7939
+
7940
+ // return a css property mapped to a potentially vendor prefixed property
7941
+ function vendorPropName( style, name ) {
7942
+
7943
+ // shortcut for names that are not vendor prefixed
7944
+ if ( name in style ) {
7945
+ return name;
7946
+ }
7947
+
7948
+ // check for vendor prefixed names
7949
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
7950
+ origName = name,
7951
+ i = cssPrefixes.length;
7952
+
7953
+ while ( i-- ) {
7954
+ name = cssPrefixes[ i ] + capName;
7955
+ if ( name in style ) {
7956
+ return name;
7957
+ }
7958
+ }
7959
+
7960
+ return origName;
7961
+ }
7962
+
7963
+ function isHidden( elem, el ) {
7964
+ elem = el || elem;
7965
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
7966
+ }
7967
+
7968
+ function showHide( elements, show ) {
7969
+ var elem, display,
7970
+ values = [],
7971
+ index = 0,
7972
+ length = elements.length;
7973
+
7974
+ for ( ; index < length; index++ ) {
7975
+ elem = elements[ index ];
7976
+ if ( !elem.style ) {
7977
+ continue;
7978
+ }
7979
+ values[ index ] = jQuery._data( elem, "olddisplay" );
7980
+ if ( show ) {
7981
+ // Reset the inline display of this element to learn if it is
7982
+ // being hidden by cascaded rules or not
7983
+ if ( !values[ index ] && elem.style.display === "none" ) {
7984
+ elem.style.display = "";
7985
+ }
7986
+
7987
+ // Set elements which have been overridden with display: none
7988
+ // in a stylesheet to whatever the default browser style is
7989
+ // for such an element
7990
+ if ( elem.style.display === "" && isHidden( elem ) ) {
7991
+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
7992
+ }
7993
+ } else {
7994
+ display = curCSS( elem, "display" );
7995
+
7996
+ if ( !values[ index ] && display !== "none" ) {
7997
+ jQuery._data( elem, "olddisplay", display );
7998
+ }
7999
+ }
8000
+ }
8001
+
8002
+ // Set the display of most of the elements in a second loop
8003
+ // to avoid the constant reflow
8004
+ for ( index = 0; index < length; index++ ) {
8005
+ elem = elements[ index ];
8006
+ if ( !elem.style ) {
8007
+ continue;
8008
+ }
8009
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
8010
+ elem.style.display = show ? values[ index ] || "" : "none";
8011
+ }
8012
+ }
8013
+
8014
+ return elements;
8015
+ }
8016
+
8017
+ jQuery.fn.extend({
8018
+ css: function( name, value ) {
8019
+ return jQuery.access( this, function( elem, name, value ) {
8020
+ return value !== undefined ?
8021
+ jQuery.style( elem, name, value ) :
8022
+ jQuery.css( elem, name );
8023
+ }, name, value, arguments.length > 1 );
8024
+ },
8025
+ show: function() {
8026
+ return showHide( this, true );
8027
+ },
8028
+ hide: function() {
8029
+ return showHide( this );
8030
+ },
8031
+ toggle: function( state, fn2 ) {
8032
+ var bool = typeof state === "boolean";
8033
+
8034
+ if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
8035
+ return eventsToggle.apply( this, arguments );
8036
+ }
8037
+
8038
+ return this.each(function() {
8039
+ if ( bool ? state : isHidden( this ) ) {
8040
+ jQuery( this ).show();
8041
+ } else {
8042
+ jQuery( this ).hide();
8043
+ }
8044
+ });
8045
+ }
8046
+ });
8047
+
8048
+ jQuery.extend({
8049
+ // Add in style property hooks for overriding the default
8050
+ // behavior of getting and setting a style property
8051
+ cssHooks: {
8052
+ opacity: {
8053
+ get: function( elem, computed ) {
8054
+ if ( computed ) {
8055
+ // We should always get a number back from opacity
8056
+ var ret = curCSS( elem, "opacity" );
8057
+ return ret === "" ? "1" : ret;
8058
+
8059
+ }
8060
+ }
8061
+ }
8062
+ },
8063
+
8064
+ // Exclude the following css properties to add px
8065
+ cssNumber: {
8066
+ "fillOpacity": true,
8067
+ "fontWeight": true,
8068
+ "lineHeight": true,
8069
+ "opacity": true,
8070
+ "orphans": true,
8071
+ "widows": true,
8072
+ "zIndex": true,
8073
+ "zoom": true
8074
+ },
8075
+
8076
+ // Add in properties whose names you wish to fix before
8077
+ // setting or getting the value
8078
+ cssProps: {
8079
+ // normalize float css property
8080
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
8081
+ },
8082
+
8083
+ // Get and set the style property on a DOM Node
8084
+ style: function( elem, name, value, extra ) {
8085
+ // Don't set styles on text and comment nodes
8086
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
8087
+ return;
8088
+ }
8089
+
8090
+ // Make sure that we're working with the right name
8091
+ var ret, type, hooks,
8092
+ origName = jQuery.camelCase( name ),
8093
+ style = elem.style;
8094
+
8095
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
8096
+
8097
+ // gets hook for the prefixed version
8098
+ // followed by the unprefixed version
8099
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
8100
+
8101
+ // Check if we're setting a value
8102
+ if ( value !== undefined ) {
8103
+ type = typeof value;
8104
+
8105
+ // convert relative number strings (+= or -=) to relative numbers. #7345
8106
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
8107
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
8108
+ // Fixes bug #9237
8109
+ type = "number";
8110
+ }
8111
+
8112
+ // Make sure that NaN and null values aren't set. See: #7116
8113
+ if ( value == null || type === "number" && isNaN( value ) ) {
8114
+ return;
8115
+ }
8116
+
8117
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
8118
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
8119
+ value += "px";
8120
+ }
8121
+
8122
+ // If a hook was provided, use that value, otherwise just set the specified value
8123
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
8124
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
8125
+ // Fixes bug #5509
8126
+ try {
8127
+ style[ name ] = value;
8128
+ } catch(e) {}
8129
+ }
8130
+
8131
+ } else {
8132
+ // If a hook was provided get the non-computed value from there
8133
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
8134
+ return ret;
8135
+ }
8136
+
8137
+ // Otherwise just get the value from the style object
8138
+ return style[ name ];
8139
+ }
8140
+ },
8141
+
8142
+ css: function( elem, name, numeric, extra ) {
8143
+ var val, num, hooks,
8144
+ origName = jQuery.camelCase( name );
8145
+
8146
+ // Make sure that we're working with the right name
8147
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
8148
+
8149
+ // gets hook for the prefixed version
8150
+ // followed by the unprefixed version
8151
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
8152
+
8153
+ // If a hook was provided get the computed value from there
8154
+ if ( hooks && "get" in hooks ) {
8155
+ val = hooks.get( elem, true, extra );
8156
+ }
8157
+
8158
+ // Otherwise, if a way to get the computed value exists, use that
8159
+ if ( val === undefined ) {
8160
+ val = curCSS( elem, name );
8161
+ }
8162
+
8163
+ //convert "normal" to computed value
8164
+ if ( val === "normal" && name in cssNormalTransform ) {
8165
+ val = cssNormalTransform[ name ];
8166
+ }
8167
+
8168
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
8169
+ if ( numeric || extra !== undefined ) {
8170
+ num = parseFloat( val );
8171
+ return numeric || jQuery.isNumeric( num ) ? num || 0 : val;
8172
+ }
8173
+ return val;
8174
+ },
8175
+
8176
+ // A method for quickly swapping in/out CSS properties to get correct calculations
8177
+ swap: function( elem, options, callback ) {
8178
+ var ret, name,
8179
+ old = {};
8180
+
8181
+ // Remember the old values, and insert the new ones
8182
+ for ( name in options ) {
8183
+ old[ name ] = elem.style[ name ];
8184
+ elem.style[ name ] = options[ name ];
8185
+ }
8186
+
8187
+ ret = callback.call( elem );
8188
+
8189
+ // Revert the old values
8190
+ for ( name in options ) {
8191
+ elem.style[ name ] = old[ name ];
8192
+ }
8193
+
8194
+ return ret;
8195
+ }
8196
+ });
8197
+
8198
+ // NOTE: To any future maintainer, we've window.getComputedStyle
8199
+ // because jsdom on node.js will break without it.
8200
+ if ( window.getComputedStyle ) {
8201
+ curCSS = function( elem, name ) {
8202
+ var ret, width, minWidth, maxWidth,
8203
+ computed = window.getComputedStyle( elem, null ),
8204
+ style = elem.style;
8205
+
8206
+ if ( computed ) {
8207
+
8208
+ ret = computed[ name ];
8209
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
8210
+ ret = jQuery.style( elem, name );
8211
+ }
8212
+
8213
+ // A tribute to the "awesome hack by Dean Edwards"
8214
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
8215
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
8216
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
8217
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
8218
+ width = style.width;
8219
+ minWidth = style.minWidth;
8220
+ maxWidth = style.maxWidth;
8221
+
8222
+ style.minWidth = style.maxWidth = style.width = ret;
8223
+ ret = computed.width;
8224
+
8225
+ style.width = width;
8226
+ style.minWidth = minWidth;
8227
+ style.maxWidth = maxWidth;
8228
+ }
8229
+ }
8230
+
8231
+ return ret;
8232
+ };
8233
+ } else if ( document.documentElement.currentStyle ) {
8234
+ curCSS = function( elem, name ) {
8235
+ var left, rsLeft,
8236
+ ret = elem.currentStyle && elem.currentStyle[ name ],
8237
+ style = elem.style;
8238
+
8239
+ // Avoid setting ret to empty string here
8240
+ // so we don't default to auto
8241
+ if ( ret == null && style && style[ name ] ) {
8242
+ ret = style[ name ];
8243
+ }
8244
+
8245
+ // From the awesome hack by Dean Edwards
8246
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
8247
+
8248
+ // If we're not dealing with a regular pixel number
8249
+ // but a number that has a weird ending, we need to convert it to pixels
8250
+ // but not position css attributes, as those are proportional to the parent element instead
8251
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
8252
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
8253
+
8254
+ // Remember the original values
8255
+ left = style.left;
8256
+ rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
8257
+
8258
+ // Put in the new values to get a computed value out
8259
+ if ( rsLeft ) {
8260
+ elem.runtimeStyle.left = elem.currentStyle.left;
8261
+ }
8262
+ style.left = name === "fontSize" ? "1em" : ret;
8263
+ ret = style.pixelLeft + "px";
8264
+
8265
+ // Revert the changed values
8266
+ style.left = left;
8267
+ if ( rsLeft ) {
8268
+ elem.runtimeStyle.left = rsLeft;
8269
+ }
8270
+ }
8271
+
8272
+ return ret === "" ? "auto" : ret;
8273
+ };
8274
+ }
8275
+
8276
+ function setPositiveNumber( elem, value, subtract ) {
8277
+ var matches = rnumsplit.exec( value );
8278
+ return matches ?
8279
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
8280
+ value;
8281
+ }
8282
+
8283
+ function augmentWidthOrHeight( elem, name, extra, isBorderBox ) {
8284
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
8285
+ // If we already have the right measurement, avoid augmentation
8286
+ 4 :
8287
+ // Otherwise initialize for horizontal or vertical properties
8288
+ name === "width" ? 1 : 0,
8289
+
8290
+ val = 0;
8291
+
8292
+ for ( ; i < 4; i += 2 ) {
8293
+ // both box models exclude margin, so add it if we want it
8294
+ if ( extra === "margin" ) {
8295
+ // we use jQuery.css instead of curCSS here
8296
+ // because of the reliableMarginRight CSS hook!
8297
+ val += jQuery.css( elem, extra + cssExpand[ i ], true );
8298
+ }
8299
+
8300
+ // From this point on we use curCSS for maximum performance (relevant in animations)
8301
+ if ( isBorderBox ) {
8302
+ // border-box includes padding, so remove it if we want content
8303
+ if ( extra === "content" ) {
8304
+ val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
8305
+ }
8306
+
8307
+ // at this point, extra isn't border nor margin, so remove border
8308
+ if ( extra !== "margin" ) {
8309
+ val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
8310
+ }
8311
+ } else {
8312
+ // at this point, extra isn't content, so add padding
8313
+ val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
8314
+
8315
+ // at this point, extra isn't content nor padding, so add border
8316
+ if ( extra !== "padding" ) {
8317
+ val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
8318
+ }
8319
+ }
8320
+ }
8321
+
8322
+ return val;
8323
+ }
8324
+
8325
+ function getWidthOrHeight( elem, name, extra ) {
8326
+
8327
+ // Start with offset property, which is equivalent to the border-box value
8328
+ var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
8329
+ valueIsBorderBox = true,
8330
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
8331
+
8332
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
8333
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
8334
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
8335
+ if ( val <= 0 || val == null ) {
8336
+ // Fall back to computed then uncomputed css if necessary
8337
+ val = curCSS( elem, name );
8338
+ if ( val < 0 || val == null ) {
8339
+ val = elem.style[ name ];
8340
+ }
8341
+
8342
+ // Computed unit is not pixels. Stop here and return.
8343
+ if ( rnumnonpx.test(val) ) {
8344
+ return val;
8345
+ }
8346
+
8347
+ // we need the check for style in case a browser which returns unreliable values
8348
+ // for getComputedStyle silently falls back to the reliable elem.style
8349
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
8350
+
8351
+ // Normalize "", auto, and prepare for extra
8352
+ val = parseFloat( val ) || 0;
8353
+ }
8354
+
8355
+ // use the active box-sizing model to add/subtract irrelevant styles
8356
+ return ( val +
8357
+ augmentWidthOrHeight(
8358
+ elem,
8359
+ name,
8360
+ extra || ( isBorderBox ? "border" : "content" ),
8361
+ valueIsBorderBox
8362
+ )
8363
+ ) + "px";
8364
+ }
8365
+
8366
+
8367
+ // Try to determine the default display value of an element
8368
+ function css_defaultDisplay( nodeName ) {
8369
+ if ( elemdisplay[ nodeName ] ) {
8370
+ return elemdisplay[ nodeName ];
8371
+ }
8372
+
8373
+ var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
8374
+ display = elem.css("display");
8375
+ elem.remove();
8376
+
8377
+ // If the simple way fails,
8378
+ // get element's real default display by attaching it to a temp iframe
8379
+ if ( display === "none" || display === "" ) {
8380
+ // Use the already-created iframe if possible
8381
+ iframe = document.body.appendChild(
8382
+ iframe || jQuery.extend( document.createElement("iframe"), {
8383
+ frameBorder: 0,
8384
+ width: 0,
8385
+ height: 0
8386
+ })
8387
+ );
8388
+
8389
+ // Create a cacheable copy of the iframe document on first call.
8390
+ // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
8391
+ // document to it; WebKit & Firefox won't allow reusing the iframe document.
8392
+ if ( !iframeDoc || !iframe.createElement ) {
8393
+ iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
8394
+ iframeDoc.write("<!doctype html><html><body>");
8395
+ iframeDoc.close();
8396
+ }
8397
+
8398
+ elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );
8399
+
8400
+ display = curCSS( elem, "display" );
8401
+ document.body.removeChild( iframe );
8402
+ }
8403
+
8404
+ // Store the correct default display
8405
+ elemdisplay[ nodeName ] = display;
8406
+
8407
+ return display;
8408
+ }
8409
+
8410
+ jQuery.each([ "height", "width" ], function( i, name ) {
8411
+ jQuery.cssHooks[ name ] = {
8412
+ get: function( elem, computed, extra ) {
8413
+ if ( computed ) {
8414
+ // certain elements can have dimension info if we invisibly show them
8415
+ // however, it must have a current display style that would benefit from this
8416
+ if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) {
8417
+ return jQuery.swap( elem, cssShow, function() {
8418
+ return getWidthOrHeight( elem, name, extra );
8419
+ });
8420
+ } else {
8421
+ return getWidthOrHeight( elem, name, extra );
8422
+ }
8423
+ }
8424
+ },
8425
+
8426
+ set: function( elem, value, extra ) {
8427
+ return setPositiveNumber( elem, value, extra ?
8428
+ augmentWidthOrHeight(
8429
+ elem,
8430
+ name,
8431
+ extra,
8432
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"
8433
+ ) : 0
8434
+ );
8435
+ }
8436
+ };
8437
+ });
8438
+
8439
+ if ( !jQuery.support.opacity ) {
8440
+ jQuery.cssHooks.opacity = {
8441
+ get: function( elem, computed ) {
8442
+ // IE uses filters for opacity
8443
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
8444
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
8445
+ computed ? "1" : "";
8446
+ },
8447
+
8448
+ set: function( elem, value ) {
8449
+ var style = elem.style,
8450
+ currentStyle = elem.currentStyle,
8451
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
8452
+ filter = currentStyle && currentStyle.filter || style.filter || "";
8453
+
8454
+ // IE has trouble with opacity if it does not have layout
8455
+ // Force it by setting the zoom level
8456
+ style.zoom = 1;
8457
+
8458
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
8459
+ if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
8460
+ style.removeAttribute ) {
8461
+
8462
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
8463
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
8464
+ // style.removeAttribute is IE Only, but so apparently is this code path...
8465
+ style.removeAttribute( "filter" );
8466
+
8467
+ // if there there is no filter style applied in a css rule, we are done
8468
+ if ( currentStyle && !currentStyle.filter ) {
8469
+ return;
8470
+ }
8471
+ }
8472
+
8473
+ // otherwise, set new filter values
8474
+ style.filter = ralpha.test( filter ) ?
8475
+ filter.replace( ralpha, opacity ) :
8476
+ filter + " " + opacity;
8477
+ }
8478
+ };
8479
+ }
8480
+
8481
+ // These hooks cannot be added until DOM ready because the support test
8482
+ // for it is not run until after DOM ready
8483
+ jQuery(function() {
8484
+ if ( !jQuery.support.reliableMarginRight ) {
8485
+ jQuery.cssHooks.marginRight = {
8486
+ get: function( elem, computed ) {
8487
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
8488
+ // Work around by temporarily setting element display to inline-block
8489
+ return jQuery.swap( elem, { "display": "inline-block" }, function() {
8490
+ if ( computed ) {
8491
+ return curCSS( elem, "marginRight" );
8492
+ }
8493
+ });
8494
+ }
8495
+ };
8496
+ }
8497
+
8498
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
8499
+ // getComputedStyle returns percent when specified for top/left/bottom/right
8500
+ // rather than make the css module depend on the offset module, we just check for it here
8501
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
8502
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
8503
+ jQuery.cssHooks[ prop ] = {
8504
+ get: function( elem, computed ) {
8505
+ if ( computed ) {
8506
+ var ret = curCSS( elem, prop );
8507
+ // if curCSS returns percentage, fallback to offset
8508
+ return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret;
8509
+ }
8510
+ }
8511
+ };
8512
+ });
8513
+ }
8514
+
8515
+ });
8516
+
8517
+ if ( jQuery.expr && jQuery.expr.filters ) {
8518
+ jQuery.expr.filters.hidden = function( elem ) {
8519
+ return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none");
8520
+ };
8521
+
8522
+ jQuery.expr.filters.visible = function( elem ) {
8523
+ return !jQuery.expr.filters.hidden( elem );
8524
+ };
8525
+ }
8526
+
8527
+ // These hooks are used by animate to expand properties
8528
+ jQuery.each({
8529
+ margin: "",
8530
+ padding: "",
8531
+ border: "Width"
8532
+ }, function( prefix, suffix ) {
8533
+ jQuery.cssHooks[ prefix + suffix ] = {
8534
+ expand: function( value ) {
8535
+ var i,
8536
+
8537
+ // assumes a single number if not a string
8538
+ parts = typeof value === "string" ? value.split(" ") : [ value ],
8539
+ expanded = {};
8540
+
8541
+ for ( i = 0; i < 4; i++ ) {
8542
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
8543
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
8544
+ }
8545
+
8546
+ return expanded;
8547
+ }
8548
+ };
8549
+
8550
+ if ( !rmargin.test( prefix ) ) {
8551
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
8552
+ }
8553
+ });
8554
+ var r20 = /%20/g,
8555
+ rbracket = /\[\]$/,
8556
+ rCRLF = /\r?\n/g,
8557
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
8558
+ rselectTextarea = /^(?:select|textarea)/i;
8559
+
8560
+ jQuery.fn.extend({
8561
+ serialize: function() {
8562
+ return jQuery.param( this.serializeArray() );
8563
+ },
8564
+ serializeArray: function() {
8565
+ return this.map(function(){
8566
+ return this.elements ? jQuery.makeArray( this.elements ) : this;
8567
+ })
8568
+ .filter(function(){
8569
+ return this.name && !this.disabled &&
8570
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
8571
+ rinput.test( this.type ) );
8572
+ })
8573
+ .map(function( i, elem ){
8574
+ var val = jQuery( this ).val();
8575
+
8576
+ return val == null ?
8577
+ null :
8578
+ jQuery.isArray( val ) ?
8579
+ jQuery.map( val, function( val, i ){
8580
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8581
+ }) :
8582
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8583
+ }).get();
8584
+ }
8585
+ });
8586
+
8587
+ //Serialize an array of form elements or a set of
8588
+ //key/values into a query string
8589
+ jQuery.param = function( a, traditional ) {
8590
+ var prefix,
8591
+ s = [],
8592
+ add = function( key, value ) {
8593
+ // If value is a function, invoke it and return its value
8594
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
8595
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
8596
+ };
8597
+
8598
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
8599
+ if ( traditional === undefined ) {
8600
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
8601
+ }
8602
+
8603
+ // If an array was passed in, assume that it is an array of form elements.
8604
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8605
+ // Serialize the form elements
8606
+ jQuery.each( a, function() {
8607
+ add( this.name, this.value );
8608
+ });
8609
+
8610
+ } else {
8611
+ // If traditional, encode the "old" way (the way 1.3.2 or older
8612
+ // did it), otherwise encode params recursively.
8613
+ for ( prefix in a ) {
8614
+ buildParams( prefix, a[ prefix ], traditional, add );
8615
+ }
8616
+ }
8617
+
8618
+ // Return the resulting serialization
8619
+ return s.join( "&" ).replace( r20, "+" );
8620
+ };
8621
+
8622
+ function buildParams( prefix, obj, traditional, add ) {
8623
+ var name;
8624
+
8625
+ if ( jQuery.isArray( obj ) ) {
8626
+ // Serialize array item.
8627
+ jQuery.each( obj, function( i, v ) {
8628
+ if ( traditional || rbracket.test( prefix ) ) {
8629
+ // Treat each array item as a scalar.
8630
+ add( prefix, v );
8631
+
8632
+ } else {
8633
+ // If array item is non-scalar (array or object), encode its
8634
+ // numeric index to resolve deserialization ambiguity issues.
8635
+ // Note that rack (as of 1.0.0) can't currently deserialize
8636
+ // nested arrays properly, and attempting to do so may cause
8637
+ // a server error. Possible fixes are to modify rack's
8638
+ // deserialization algorithm or to provide an option or flag
8639
+ // to force array serialization to be shallow.
8640
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
8641
+ }
8642
+ });
8643
+
8644
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
8645
+ // Serialize object item.
8646
+ for ( name in obj ) {
8647
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8648
+ }
8649
+
8650
+ } else {
8651
+ // Serialize scalar item.
8652
+ add( prefix, obj );
8653
+ }
8654
+ }
8655
+ var // Document location
8656
+ ajaxLocation,
8657
+ // Document location segments
8658
+ ajaxLocParts,
8659
+
8660
+ rhash = /#.*$/,
8661
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
8662
+ // #7653, #8125, #8152: local protocol detection
8663
+ rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
8664
+ rnoContent = /^(?:GET|HEAD)$/,
8665
+ rprotocol = /^\/\//,
8666
+ rquery = /\?/,
8667
+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
8668
+ rts = /([?&])_=[^&]*/,
8669
+ rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
8670
+
8671
+ // Keep a copy of the old load method
8672
+ _load = jQuery.fn.load,
8673
+
8674
+ /* Prefilters
8675
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8676
+ * 2) These are called:
8677
+ * - BEFORE asking for a transport
8678
+ * - AFTER param serialization (s.data is a string if s.processData is true)
8679
+ * 3) key is the dataType
8680
+ * 4) the catchall symbol "*" can be used
8681
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8682
+ */
8683
+ prefilters = {},
8684
+
8685
+ /* Transports bindings
8686
+ * 1) key is the dataType
8687
+ * 2) the catchall symbol "*" can be used
8688
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
8689
+ */
8690
+ transports = {},
8691
+
8692
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
8693
+ allTypes = ["*/"] + ["*"];
8694
+
8695
+ // #8138, IE may throw an exception when accessing
8696
+ // a field from window.location if document.domain has been set
8697
+ try {
8698
+ ajaxLocation = location.href;
8699
+ } catch( e ) {
8700
+ // Use the href attribute of an A element
8701
+ // since IE will modify it given document.location
8702
+ ajaxLocation = document.createElement( "a" );
8703
+ ajaxLocation.href = "";
8704
+ ajaxLocation = ajaxLocation.href;
8705
+ }
8706
+
8707
+ // Segment location into parts
8708
+ ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
8709
+
8710
+ // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8711
+ function addToPrefiltersOrTransports( structure ) {
8712
+
8713
+ // dataTypeExpression is optional and defaults to "*"
8714
+ return function( dataTypeExpression, func ) {
8715
+
8716
+ if ( typeof dataTypeExpression !== "string" ) {
8717
+ func = dataTypeExpression;
8718
+ dataTypeExpression = "*";
8719
+ }
8720
+
8721
+ var dataType, list, placeBefore,
8722
+ dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),
8723
+ i = 0,
8724
+ length = dataTypes.length;
8725
+
8726
+ if ( jQuery.isFunction( func ) ) {
8727
+ // For each dataType in the dataTypeExpression
8728
+ for ( ; i < length; i++ ) {
8729
+ dataType = dataTypes[ i ];
8730
+ // We control if we're asked to add before
8731
+ // any existing element
8732
+ placeBefore = /^\+/.test( dataType );
8733
+ if ( placeBefore ) {
8734
+ dataType = dataType.substr( 1 ) || "*";
8735
+ }
8736
+ list = structure[ dataType ] = structure[ dataType ] || [];
8737
+ // then we add to the structure accordingly
8738
+ list[ placeBefore ? "unshift" : "push" ]( func );
8739
+ }
8740
+ }
8741
+ };
8742
+ }
8743
+
8744
+ // Base inspection function for prefilters and transports
8745
+ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
8746
+ dataType /* internal */, inspected /* internal */ ) {
8747
+
8748
+ dataType = dataType || options.dataTypes[ 0 ];
8749
+ inspected = inspected || {};
8750
+
8751
+ inspected[ dataType ] = true;
8752
+
8753
+ var selection,
8754
+ list = structure[ dataType ],
8755
+ i = 0,
8756
+ length = list ? list.length : 0,
8757
+ executeOnly = ( structure === prefilters );
8758
+
8759
+ for ( ; i < length && ( executeOnly || !selection ); i++ ) {
8760
+ selection = list[ i ]( options, originalOptions, jqXHR );
8761
+ // If we got redirected to another dataType
8762
+ // we try there if executing only and not done already
8763
+ if ( typeof selection === "string" ) {
8764
+ if ( !executeOnly || inspected[ selection ] ) {
8765
+ selection = undefined;
8766
+ } else {
8767
+ options.dataTypes.unshift( selection );
8768
+ selection = inspectPrefiltersOrTransports(
8769
+ structure, options, originalOptions, jqXHR, selection, inspected );
8770
+ }
8771
+ }
8772
+ }
8773
+ // If we're only executing or nothing was selected
8774
+ // we try the catchall dataType if not done already
8775
+ if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
8776
+ selection = inspectPrefiltersOrTransports(
8777
+ structure, options, originalOptions, jqXHR, "*", inspected );
8778
+ }
8779
+ // unnecessary when only executing (prefilters)
8780
+ // but it'll be ignored by the caller in that case
8781
+ return selection;
8782
+ }
8783
+
8784
+ // A special extend for ajax options
8785
+ // that takes "flat" options (not to be deep extended)
8786
+ // Fixes #9887
8787
+ function ajaxExtend( target, src ) {
8788
+ var key, deep,
8789
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
8790
+ for ( key in src ) {
8791
+ if ( src[ key ] !== undefined ) {
8792
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
8793
+ }
8794
+ }
8795
+ if ( deep ) {
8796
+ jQuery.extend( true, target, deep );
8797
+ }
8798
+ }
8799
+
8800
+ jQuery.fn.load = function( url, params, callback ) {
8801
+ if ( typeof url !== "string" && _load ) {
8802
+ return _load.apply( this, arguments );
8803
+ }
8804
+
8805
+ // Don't do a request if no elements are being requested
8806
+ if ( !this.length ) {
8807
+ return this;
8808
+ }
8809
+
8810
+ var selector, type, response,
8811
+ self = this,
8812
+ off = url.indexOf(" ");
8813
+
8814
+ if ( off >= 0 ) {
8815
+ selector = url.slice( off, url.length );
8816
+ url = url.slice( 0, off );
8817
+ }
8818
+
8819
+ // If it's a function
8820
+ if ( jQuery.isFunction( params ) ) {
8821
+
8822
+ // We assume that it's the callback
8823
+ callback = params;
8824
+ params = undefined;
8825
+
8826
+ // Otherwise, build a param string
8827
+ } else if ( params && typeof params === "object" ) {
8828
+ type = "POST";
8829
+ }
8830
+
8831
+ // Request the remote document
8832
+ jQuery.ajax({
8833
+ url: url,
8834
+
8835
+ // if "type" variable is undefined, then "GET" method will be used
8836
+ type: type,
8837
+ dataType: "html",
8838
+ data: params,
8839
+ complete: function( jqXHR, status ) {
8840
+ if ( callback ) {
8841
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
8842
+ }
8843
+ }
8844
+ }).done(function( responseText ) {
8845
+
8846
+ // Save response for use in complete callback
8847
+ response = arguments;
8848
+
8849
+ // See if a selector was specified
8850
+ self.html( selector ?
8851
+
8852
+ // Create a dummy div to hold the results
8853
+ jQuery("<div>")
8854
+
8855
+ // inject the contents of the document in, removing the scripts
8856
+ // to avoid any 'Permission Denied' errors in IE
8857
+ .append( responseText.replace( rscript, "" ) )
8858
+
8859
+ // Locate the specified elements
8860
+ .find( selector ) :
8861
+
8862
+ // If not, just inject the full result
8863
+ responseText );
8864
+
8865
+ });
8866
+
8867
+ return this;
8868
+ };
8869
+
8870
+ // Attach a bunch of functions for handling common AJAX events
8871
+ jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
8872
+ jQuery.fn[ o ] = function( f ){
8873
+ return this.on( o, f );
8874
+ };
8875
+ });
8876
+
8877
+ jQuery.each( [ "get", "post" ], function( i, method ) {
8878
+ jQuery[ method ] = function( url, data, callback, type ) {
8879
+ // shift arguments if data argument was omitted
8880
+ if ( jQuery.isFunction( data ) ) {
8881
+ type = type || callback;
8882
+ callback = data;
8883
+ data = undefined;
8884
+ }
8885
+
8886
+ return jQuery.ajax({
8887
+ type: method,
8888
+ url: url,
8889
+ data: data,
8890
+ success: callback,
8891
+ dataType: type
8892
+ });
8893
+ };
8894
+ });
8895
+
8896
+ jQuery.extend({
8897
+
8898
+ getScript: function( url, callback ) {
8899
+ return jQuery.get( url, undefined, callback, "script" );
8900
+ },
8901
+
8902
+ getJSON: function( url, data, callback ) {
8903
+ return jQuery.get( url, data, callback, "json" );
8904
+ },
8905
+
8906
+ // Creates a full fledged settings object into target
8907
+ // with both ajaxSettings and settings fields.
8908
+ // If target is omitted, writes into ajaxSettings.
8909
+ ajaxSetup: function( target, settings ) {
8910
+ if ( settings ) {
8911
+ // Building a settings object
8912
+ ajaxExtend( target, jQuery.ajaxSettings );
8913
+ } else {
8914
+ // Extending ajaxSettings
8915
+ settings = target;
8916
+ target = jQuery.ajaxSettings;
8917
+ }
8918
+ ajaxExtend( target, settings );
8919
+ return target;
8920
+ },
8921
+
8922
+ ajaxSettings: {
8923
+ url: ajaxLocation,
8924
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
8925
+ global: true,
8926
+ type: "GET",
8927
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
8928
+ processData: true,
8929
+ async: true,
8930
+ /*
8931
+ timeout: 0,
8932
+ data: null,
8933
+ dataType: null,
8934
+ username: null,
8935
+ password: null,
8936
+ cache: null,
8937
+ throws: false,
8938
+ traditional: false,
8939
+ headers: {},
8940
+ */
8941
+
8942
+ accepts: {
8943
+ xml: "application/xml, text/xml",
8944
+ html: "text/html",
8945
+ text: "text/plain",
8946
+ json: "application/json, text/javascript",
8947
+ "*": allTypes
8948
+ },
8949
+
8950
+ contents: {
8951
+ xml: /xml/,
8952
+ html: /html/,
8953
+ json: /json/
8954
+ },
8955
+
8956
+ responseFields: {
8957
+ xml: "responseXML",
8958
+ text: "responseText"
8959
+ },
8960
+
8961
+ // List of data converters
8962
+ // 1) key format is "source_type destination_type" (a single space in-between)
8963
+ // 2) the catchall symbol "*" can be used for source_type
8964
+ converters: {
8965
+
8966
+ // Convert anything to text
8967
+ "* text": window.String,
8968
+
8969
+ // Text to html (true = no transformation)
8970
+ "text html": true,
8971
+
8972
+ // Evaluate text as a json expression
8973
+ "text json": jQuery.parseJSON,
8974
+
8975
+ // Parse text as xml
8976
+ "text xml": jQuery.parseXML
8977
+ },
8978
+
8979
+ // For options that shouldn't be deep extended:
8980
+ // you can add your own custom options here if
8981
+ // and when you create one that shouldn't be
8982
+ // deep extended (see ajaxExtend)
8983
+ flatOptions: {
8984
+ context: true,
8985
+ url: true
8986
+ }
8987
+ },
8988
+
8989
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
8990
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
8991
+
8992
+ // Main method
8993
+ ajax: function( url, options ) {
8994
+
8995
+ // If url is an object, simulate pre-1.5 signature
8996
+ if ( typeof url === "object" ) {
8997
+ options = url;
8998
+ url = undefined;
8999
+ }
9000
+
9001
+ // Force options to be an object
9002
+ options = options || {};
9003
+
9004
+ var // ifModified key
9005
+ ifModifiedKey,
9006
+ // Response headers
9007
+ responseHeadersString,
9008
+ responseHeaders,
9009
+ // transport
9010
+ transport,
9011
+ // timeout handle
9012
+ timeoutTimer,
9013
+ // Cross-domain detection vars
9014
+ parts,
9015
+ // To know if global events are to be dispatched
9016
+ fireGlobals,
9017
+ // Loop variable
9018
+ i,
9019
+ // Create the final options object
9020
+ s = jQuery.ajaxSetup( {}, options ),
9021
+ // Callbacks context
9022
+ callbackContext = s.context || s,
9023
+ // Context for global events
9024
+ // It's the callbackContext if one was provided in the options
9025
+ // and if it's a DOM node or a jQuery collection
9026
+ globalEventContext = callbackContext !== s &&
9027
+ ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
9028
+ jQuery( callbackContext ) : jQuery.event,
9029
+ // Deferreds
9030
+ deferred = jQuery.Deferred(),
9031
+ completeDeferred = jQuery.Callbacks( "once memory" ),
9032
+ // Status-dependent callbacks
9033
+ statusCode = s.statusCode || {},
9034
+ // Headers (they are sent all at once)
9035
+ requestHeaders = {},
9036
+ requestHeadersNames = {},
9037
+ // The jqXHR state
9038
+ state = 0,
9039
+ // Default abort message
9040
+ strAbort = "canceled",
9041
+ // Fake xhr
9042
+ jqXHR = {
9043
+
9044
+ readyState: 0,
9045
+
9046
+ // Caches the header
9047
+ setRequestHeader: function( name, value ) {
9048
+ if ( !state ) {
9049
+ var lname = name.toLowerCase();
9050
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
9051
+ requestHeaders[ name ] = value;
9052
+ }
9053
+ return this;
9054
+ },
9055
+
9056
+ // Raw string
9057
+ getAllResponseHeaders: function() {
9058
+ return state === 2 ? responseHeadersString : null;
9059
+ },
9060
+
9061
+ // Builds headers hashtable if needed
9062
+ getResponseHeader: function( key ) {
9063
+ var match;
9064
+ if ( state === 2 ) {
9065
+ if ( !responseHeaders ) {
9066
+ responseHeaders = {};
9067
+ while( ( match = rheaders.exec( responseHeadersString ) ) ) {
9068
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
9069
+ }
9070
+ }
9071
+ match = responseHeaders[ key.toLowerCase() ];
9072
+ }
9073
+ return match === undefined ? null : match;
9074
+ },
9075
+
9076
+ // Overrides response content-type header
9077
+ overrideMimeType: function( type ) {
9078
+ if ( !state ) {
9079
+ s.mimeType = type;
9080
+ }
9081
+ return this;
9082
+ },
9083
+
9084
+ // Cancel the request
9085
+ abort: function( statusText ) {
9086
+ statusText = statusText || strAbort;
9087
+ if ( transport ) {
9088
+ transport.abort( statusText );
9089
+ }
9090
+ done( 0, statusText );
9091
+ return this;
9092
+ }
9093
+ };
9094
+
9095
+ // Callback for when everything is done
9096
+ // It is defined here because jslint complains if it is declared
9097
+ // at the end of the function (which would be more logical and readable)
9098
+ function done( status, nativeStatusText, responses, headers ) {
9099
+ var isSuccess, success, error, response, modified,
9100
+ statusText = nativeStatusText;
9101
+
9102
+ // Called once
9103
+ if ( state === 2 ) {
9104
+ return;
9105
+ }
9106
+
9107
+ // State is "done" now
9108
+ state = 2;
9109
+
9110
+ // Clear timeout if it exists
9111
+ if ( timeoutTimer ) {
9112
+ clearTimeout( timeoutTimer );
9113
+ }
9114
+
9115
+ // Dereference transport for early garbage collection
9116
+ // (no matter how long the jqXHR object will be used)
9117
+ transport = undefined;
9118
+
9119
+ // Cache response headers
9120
+ responseHeadersString = headers || "";
9121
+
9122
+ // Set readyState
9123
+ jqXHR.readyState = status > 0 ? 4 : 0;
9124
+
9125
+ // Get response data
9126
+ if ( responses ) {
9127
+ response = ajaxHandleResponses( s, jqXHR, responses );
9128
+ }
9129
+
9130
+ // If successful, handle type chaining
9131
+ if ( status >= 200 && status < 300 || status === 304 ) {
9132
+
9133
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9134
+ if ( s.ifModified ) {
9135
+
9136
+ modified = jqXHR.getResponseHeader("Last-Modified");
9137
+ if ( modified ) {
9138
+ jQuery.lastModified[ ifModifiedKey ] = modified;
9139
+ }
9140
+ modified = jqXHR.getResponseHeader("Etag");
9141
+ if ( modified ) {
9142
+ jQuery.etag[ ifModifiedKey ] = modified;
9143
+ }
9144
+ }
9145
+
9146
+ // If not modified
9147
+ if ( status === 304 ) {
9148
+
9149
+ statusText = "notmodified";
9150
+ isSuccess = true;
9151
+
9152
+ // If we have data
9153
+ } else {
9154
+
9155
+ isSuccess = ajaxConvert( s, response );
9156
+ statusText = isSuccess.state;
9157
+ success = isSuccess.data;
9158
+ error = isSuccess.error;
9159
+ isSuccess = !error;
9160
+ }
9161
+ } else {
9162
+ // We extract error from statusText
9163
+ // then normalize statusText and status for non-aborts
9164
+ error = statusText;
9165
+ if ( !statusText || status ) {
9166
+ statusText = "error";
9167
+ if ( status < 0 ) {
9168
+ status = 0;
9169
+ }
9170
+ }
9171
+ }
9172
+
9173
+ // Set data for the fake xhr object
9174
+ jqXHR.status = status;
9175
+ jqXHR.statusText = "" + ( nativeStatusText || statusText );
9176
+
9177
+ // Success/Error
9178
+ if ( isSuccess ) {
9179
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9180
+ } else {
9181
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9182
+ }
9183
+
9184
+ // Status-dependent callbacks
9185
+ jqXHR.statusCode( statusCode );
9186
+ statusCode = undefined;
9187
+
9188
+ if ( fireGlobals ) {
9189
+ globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
9190
+ [ jqXHR, s, isSuccess ? success : error ] );
9191
+ }
9192
+
9193
+ // Complete
9194
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9195
+
9196
+ if ( fireGlobals ) {
9197
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9198
+ // Handle the global AJAX counter
9199
+ if ( !( --jQuery.active ) ) {
9200
+ jQuery.event.trigger( "ajaxStop" );
9201
+ }
9202
+ }
9203
+ }
9204
+
9205
+ // Attach deferreds
9206
+ deferred.promise( jqXHR );
9207
+ jqXHR.success = jqXHR.done;
9208
+ jqXHR.error = jqXHR.fail;
9209
+ jqXHR.complete = completeDeferred.add;
9210
+
9211
+ // Status-dependent callbacks
9212
+ jqXHR.statusCode = function( map ) {
9213
+ if ( map ) {
9214
+ var tmp;
9215
+ if ( state < 2 ) {
9216
+ for ( tmp in map ) {
9217
+ statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
9218
+ }
9219
+ } else {
9220
+ tmp = map[ jqXHR.status ];
9221
+ jqXHR.always( tmp );
9222
+ }
9223
+ }
9224
+ return this;
9225
+ };
9226
+
9227
+ // Remove hash character (#7531: and string promotion)
9228
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
9229
+ // We also use the url parameter if available
9230
+ s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
9231
+
9232
+ // Extract dataTypes list
9233
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace );
9234
+
9235
+ // Determine if a cross-domain request is in order
9236
+ if ( s.crossDomain == null ) {
9237
+ parts = rurl.exec( s.url.toLowerCase() );
9238
+ s.crossDomain = !!( parts &&
9239
+ ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
9240
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
9241
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
9242
+ );
9243
+ }
9244
+
9245
+ // Convert data if not already a string
9246
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
9247
+ s.data = jQuery.param( s.data, s.traditional );
9248
+ }
9249
+
9250
+ // Apply prefilters
9251
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9252
+
9253
+ // If request was aborted inside a prefilter, stop there
9254
+ if ( state === 2 ) {
9255
+ return jqXHR;
9256
+ }
9257
+
9258
+ // We can fire global events as of now if asked to
9259
+ fireGlobals = s.global;
9260
+
9261
+ // Uppercase the type
9262
+ s.type = s.type.toUpperCase();
9263
+
9264
+ // Determine if request has content
9265
+ s.hasContent = !rnoContent.test( s.type );
9266
+
9267
+ // Watch for a new set of requests
9268
+ if ( fireGlobals && jQuery.active++ === 0 ) {
9269
+ jQuery.event.trigger( "ajaxStart" );
9270
+ }
9271
+
9272
+ // More options handling for requests with no content
9273
+ if ( !s.hasContent ) {
9274
+
9275
+ // If data is available, append data to url
9276
+ if ( s.data ) {
9277
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
9278
+ // #9682: remove data so that it's not used in an eventual retry
9279
+ delete s.data;
9280
+ }
9281
+
9282
+ // Get ifModifiedKey before adding the anti-cache parameter
9283
+ ifModifiedKey = s.url;
9284
+
9285
+ // Add anti-cache in url if needed
9286
+ if ( s.cache === false ) {
9287
+
9288
+ var ts = jQuery.now(),
9289
+ // try replacing _= if it is there
9290
+ ret = s.url.replace( rts, "$1_=" + ts );
9291
+
9292
+ // if nothing was replaced, add timestamp to the end
9293
+ s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
9294
+ }
9295
+ }
9296
+
9297
+ // Set the correct header, if data is being sent
9298
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9299
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
9300
+ }
9301
+
9302
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9303
+ if ( s.ifModified ) {
9304
+ ifModifiedKey = ifModifiedKey || s.url;
9305
+ if ( jQuery.lastModified[ ifModifiedKey ] ) {
9306
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
9307
+ }
9308
+ if ( jQuery.etag[ ifModifiedKey ] ) {
9309
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
9310
+ }
9311
+ }
9312
+
9313
+ // Set the Accepts header for the server, depending on the dataType
9314
+ jqXHR.setRequestHeader(
9315
+ "Accept",
9316
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
9317
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9318
+ s.accepts[ "*" ]
9319
+ );
9320
+
9321
+ // Check for headers option
9322
+ for ( i in s.headers ) {
9323
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
9324
+ }
9325
+
9326
+ // Allow custom headers/mimetypes and early abort
9327
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
9328
+ // Abort if not done already and return
9329
+ return jqXHR.abort();
9330
+
9331
+ }
9332
+
9333
+ // aborting is no longer a cancellation
9334
+ strAbort = "abort";
9335
+
9336
+ // Install callbacks on deferreds
9337
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
9338
+ jqXHR[ i ]( s[ i ] );
9339
+ }
9340
+
9341
+ // Get transport
9342
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9343
+
9344
+ // If no transport, we auto-abort
9345
+ if ( !transport ) {
9346
+ done( -1, "No Transport" );
9347
+ } else {
9348
+ jqXHR.readyState = 1;
9349
+ // Send global event
9350
+ if ( fireGlobals ) {
9351
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9352
+ }
9353
+ // Timeout
9354
+ if ( s.async && s.timeout > 0 ) {
9355
+ timeoutTimer = setTimeout( function(){
9356
+ jqXHR.abort( "timeout" );
9357
+ }, s.timeout );
9358
+ }
9359
+
9360
+ try {
9361
+ state = 1;
9362
+ transport.send( requestHeaders, done );
9363
+ } catch (e) {
9364
+ // Propagate exception as error if not done
9365
+ if ( state < 2 ) {
9366
+ done( -1, e );
9367
+ // Simply rethrow otherwise
9368
+ } else {
9369
+ throw e;
9370
+ }
9371
+ }
9372
+ }
9373
+
9374
+ return jqXHR;
9375
+ },
9376
+
9377
+ // Counter for holding the number of active queries
9378
+ active: 0,
9379
+
9380
+ // Last-Modified header cache for next request
9381
+ lastModified: {},
9382
+ etag: {}
9383
+
9384
+ });
9385
+
9386
+ /* Handles responses to an ajax request:
9387
+ * - sets all responseXXX fields accordingly
9388
+ * - finds the right dataType (mediates between content-type and expected dataType)
9389
+ * - returns the corresponding response
9390
+ */
9391
+ function ajaxHandleResponses( s, jqXHR, responses ) {
9392
+
9393
+ var ct, type, finalDataType, firstDataType,
9394
+ contents = s.contents,
9395
+ dataTypes = s.dataTypes,
9396
+ responseFields = s.responseFields;
9397
+
9398
+ // Fill responseXXX fields
9399
+ for ( type in responseFields ) {
9400
+ if ( type in responses ) {
9401
+ jqXHR[ responseFields[type] ] = responses[ type ];
9402
+ }
9403
+ }
9404
+
9405
+ // Remove auto dataType and get content-type in the process
9406
+ while( dataTypes[ 0 ] === "*" ) {
9407
+ dataTypes.shift();
9408
+ if ( ct === undefined ) {
9409
+ ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
9410
+ }
9411
+ }
9412
+
9413
+ // Check if we're dealing with a known content-type
9414
+ if ( ct ) {
9415
+ for ( type in contents ) {
9416
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
9417
+ dataTypes.unshift( type );
9418
+ break;
9419
+ }
9420
+ }
9421
+ }
9422
+
9423
+ // Check to see if we have a response for the expected dataType
9424
+ if ( dataTypes[ 0 ] in responses ) {
9425
+ finalDataType = dataTypes[ 0 ];
9426
+ } else {
9427
+ // Try convertible dataTypes
9428
+ for ( type in responses ) {
9429
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
9430
+ finalDataType = type;
9431
+ break;
9432
+ }
9433
+ if ( !firstDataType ) {
9434
+ firstDataType = type;
9435
+ }
9436
+ }
9437
+ // Or just use first one
9438
+ finalDataType = finalDataType || firstDataType;
9439
+ }
9440
+
9441
+ // If we found a dataType
9442
+ // We add the dataType to the list if needed
9443
+ // and return the corresponding response
9444
+ if ( finalDataType ) {
9445
+ if ( finalDataType !== dataTypes[ 0 ] ) {
9446
+ dataTypes.unshift( finalDataType );
9447
+ }
9448
+ return responses[ finalDataType ];
9449
+ }
9450
+ }
9451
+
9452
+ // Chain conversions given the request and the original response
9453
+ function ajaxConvert( s, response ) {
9454
+
9455
+ var conv, conv2, current, tmp,
9456
+ // Work with a copy of dataTypes in case we need to modify it for conversion
9457
+ dataTypes = s.dataTypes.slice(),
9458
+ prev = dataTypes[ 0 ],
9459
+ converters = {},
9460
+ i = 0;
9461
+
9462
+ // Apply the dataFilter if provided
9463
+ if ( s.dataFilter ) {
9464
+ response = s.dataFilter( response, s.dataType );
9465
+ }
9466
+
9467
+ // Create converters map with lowercased keys
9468
+ if ( dataTypes[ 1 ] ) {
9469
+ for ( conv in s.converters ) {
9470
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
9471
+ }
9472
+ }
9473
+
9474
+ // Convert to each sequential dataType, tolerating list modification
9475
+ for ( ; (current = dataTypes[++i]); ) {
9476
+
9477
+ // There's only work to do if current dataType is non-auto
9478
+ if ( current !== "*" ) {
9479
+
9480
+ // Convert response if prev dataType is non-auto and differs from current
9481
+ if ( prev !== "*" && prev !== current ) {
9482
+
9483
+ // Seek a direct converter
9484
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
9485
+
9486
+ // If none found, seek a pair
9487
+ if ( !conv ) {
9488
+ for ( conv2 in converters ) {
9489
+
9490
+ // If conv2 outputs current
9491
+ tmp = conv2.split(" ");
9492
+ if ( tmp[ 1 ] === current ) {
9493
+
9494
+ // If prev can be converted to accepted input
9495
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
9496
+ converters[ "* " + tmp[ 0 ] ];
9497
+ if ( conv ) {
9498
+ // Condense equivalence converters
9499
+ if ( conv === true ) {
9500
+ conv = converters[ conv2 ];
9501
+
9502
+ // Otherwise, insert the intermediate dataType
9503
+ } else if ( converters[ conv2 ] !== true ) {
9504
+ current = tmp[ 0 ];
9505
+ dataTypes.splice( i--, 0, current );
9506
+ }
9507
+
9508
+ break;
9509
+ }
9510
+ }
9511
+ }
9512
+ }
9513
+
9514
+ // Apply converter (if not an equivalence)
9515
+ if ( conv !== true ) {
9516
+
9517
+ // Unless errors are allowed to bubble, catch and return them
9518
+ if ( conv && s["throws"] ) {
9519
+ response = conv( response );
9520
+ } else {
9521
+ try {
9522
+ response = conv( response );
9523
+ } catch ( e ) {
9524
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
9525
+ }
9526
+ }
9527
+ }
9528
+ }
9529
+
9530
+ // Update prev for next iteration
9531
+ prev = current;
9532
+ }
9533
+ }
9534
+
9535
+ return { state: "success", data: response };
9536
+ }
9537
+ var oldCallbacks = [],
9538
+ rquestion = /\?/,
9539
+ rjsonp = /(=)\?(?=&|$)|\?\?/,
9540
+ nonce = jQuery.now();
9541
+
9542
+ // Default jsonp settings
9543
+ jQuery.ajaxSetup({
9544
+ jsonp: "callback",
9545
+ jsonpCallback: function() {
9546
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
9547
+ this[ callback ] = true;
9548
+ return callback;
9549
+ }
9550
+ });
9551
+
9552
+ // Detect, normalize options and install callbacks for jsonp requests
9553
+ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
9554
+
9555
+ var callbackName, overwritten, responseContainer,
9556
+ data = s.data,
9557
+ url = s.url,
9558
+ hasCallback = s.jsonp !== false,
9559
+ replaceInUrl = hasCallback && rjsonp.test( url ),
9560
+ replaceInData = hasCallback && !replaceInUrl && typeof data === "string" &&
9561
+ !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") &&
9562
+ rjsonp.test( data );
9563
+
9564
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
9565
+ if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) {
9566
+
9567
+ // Get callback name, remembering preexisting value associated with it
9568
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
9569
+ s.jsonpCallback() :
9570
+ s.jsonpCallback;
9571
+ overwritten = window[ callbackName ];
9572
+
9573
+ // Insert callback into url or form data
9574
+ if ( replaceInUrl ) {
9575
+ s.url = url.replace( rjsonp, "$1" + callbackName );
9576
+ } else if ( replaceInData ) {
9577
+ s.data = data.replace( rjsonp, "$1" + callbackName );
9578
+ } else if ( hasCallback ) {
9579
+ s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
9580
+ }
9581
+
9582
+ // Use data converter to retrieve json after script execution
9583
+ s.converters["script json"] = function() {
9584
+ if ( !responseContainer ) {
9585
+ jQuery.error( callbackName + " was not called" );
9586
+ }
9587
+ return responseContainer[ 0 ];
9588
+ };
9589
+
9590
+ // force json dataType
9591
+ s.dataTypes[ 0 ] = "json";
9592
+
9593
+ // Install callback
9594
+ window[ callbackName ] = function() {
9595
+ responseContainer = arguments;
9596
+ };
9597
+
9598
+ // Clean-up function (fires after converters)
9599
+ jqXHR.always(function() {
9600
+ // Restore preexisting value
9601
+ window[ callbackName ] = overwritten;
9602
+
9603
+ // Save back as free
9604
+ if ( s[ callbackName ] ) {
9605
+ // make sure that re-using the options doesn't screw things around
9606
+ s.jsonpCallback = originalSettings.jsonpCallback;
9607
+
9608
+ // save the callback name for future use
9609
+ oldCallbacks.push( callbackName );
9610
+ }
9611
+
9612
+ // Call if it was a function and we have a response
9613
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
9614
+ overwritten( responseContainer[ 0 ] );
9615
+ }
9616
+
9617
+ responseContainer = overwritten = undefined;
9618
+ });
9619
+
9620
+ // Delegate to script
9621
+ return "script";
9622
+ }
9623
+ });
9624
+ // Install script dataType
9625
+ jQuery.ajaxSetup({
9626
+ accepts: {
9627
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
9628
+ },
9629
+ contents: {
9630
+ script: /javascript|ecmascript/
9631
+ },
9632
+ converters: {
9633
+ "text script": function( text ) {
9634
+ jQuery.globalEval( text );
9635
+ return text;
9636
+ }
9637
+ }
9638
+ });
9639
+
9640
+ // Handle cache's special case and global
9641
+ jQuery.ajaxPrefilter( "script", function( s ) {
9642
+ if ( s.cache === undefined ) {
9643
+ s.cache = false;
9644
+ }
9645
+ if ( s.crossDomain ) {
9646
+ s.type = "GET";
9647
+ s.global = false;
9648
+ }
9649
+ });
9650
+
9651
+ // Bind script tag hack transport
9652
+ jQuery.ajaxTransport( "script", function(s) {
9653
+
9654
+ // This transport only deals with cross domain requests
9655
+ if ( s.crossDomain ) {
9656
+
9657
+ var script,
9658
+ head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
9659
+
9660
+ return {
9661
+
9662
+ send: function( _, callback ) {
9663
+
9664
+ script = document.createElement( "script" );
9665
+
9666
+ script.async = "async";
9667
+
9668
+ if ( s.scriptCharset ) {
9669
+ script.charset = s.scriptCharset;
9670
+ }
9671
+
9672
+ script.src = s.url;
9673
+
9674
+ // Attach handlers for all browsers
9675
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
9676
+
9677
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
9678
+
9679
+ // Handle memory leak in IE
9680
+ script.onload = script.onreadystatechange = null;
9681
+
9682
+ // Remove the script
9683
+ if ( head && script.parentNode ) {
9684
+ head.removeChild( script );
9685
+ }
9686
+
9687
+ // Dereference the script
9688
+ script = undefined;
9689
+
9690
+ // Callback if not abort
9691
+ if ( !isAbort ) {
9692
+ callback( 200, "success" );
9693
+ }
9694
+ }
9695
+ };
9696
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
9697
+ // This arises when a base node is used (#2709 and #4378).
9698
+ head.insertBefore( script, head.firstChild );
9699
+ },
9700
+
9701
+ abort: function() {
9702
+ if ( script ) {
9703
+ script.onload( 0, 1 );
9704
+ }
9705
+ }
9706
+ };
9707
+ }
9708
+ });
9709
+ var xhrCallbacks,
9710
+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
9711
+ xhrOnUnloadAbort = window.ActiveXObject ? function() {
9712
+ // Abort all pending requests
9713
+ for ( var key in xhrCallbacks ) {
9714
+ xhrCallbacks[ key ]( 0, 1 );
9715
+ }
9716
+ } : false,
9717
+ xhrId = 0;
9718
+
9719
+ // Functions to create xhrs
9720
+ function createStandardXHR() {
9721
+ try {
9722
+ return new window.XMLHttpRequest();
9723
+ } catch( e ) {}
9724
+ }
9725
+
9726
+ function createActiveXHR() {
9727
+ try {
9728
+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
9729
+ } catch( e ) {}
9730
+ }
9731
+
9732
+ // Create the request object
9733
+ // (This is still attached to ajaxSettings for backward compatibility)
9734
+ jQuery.ajaxSettings.xhr = window.ActiveXObject ?
9735
+ /* Microsoft failed to properly
9736
+ * implement the XMLHttpRequest in IE7 (can't request local files),
9737
+ * so we use the ActiveXObject when it is available
9738
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
9739
+ * we need a fallback.
9740
+ */
9741
+ function() {
9742
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
9743
+ } :
9744
+ // For all other browsers, use the standard XMLHttpRequest object
9745
+ createStandardXHR;
9746
+
9747
+ // Determine support properties
9748
+ (function( xhr ) {
9749
+ jQuery.extend( jQuery.support, {
9750
+ ajax: !!xhr,
9751
+ cors: !!xhr && ( "withCredentials" in xhr )
9752
+ });
9753
+ })( jQuery.ajaxSettings.xhr() );
9754
+
9755
+ // Create transport if the browser can provide an xhr
9756
+ if ( jQuery.support.ajax ) {
9757
+
9758
+ jQuery.ajaxTransport(function( s ) {
9759
+ // Cross domain only allowed if supported through XMLHttpRequest
9760
+ if ( !s.crossDomain || jQuery.support.cors ) {
9761
+
9762
+ var callback;
9763
+
9764
+ return {
9765
+ send: function( headers, complete ) {
9766
+
9767
+ // Get a new xhr
9768
+ var handle, i,
9769
+ xhr = s.xhr();
9770
+
9771
+ // Open the socket
9772
+ // Passing null username, generates a login popup on Opera (#2865)
9773
+ if ( s.username ) {
9774
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
9775
+ } else {
9776
+ xhr.open( s.type, s.url, s.async );
9777
+ }
9778
+
9779
+ // Apply custom fields if provided
9780
+ if ( s.xhrFields ) {
9781
+ for ( i in s.xhrFields ) {
9782
+ xhr[ i ] = s.xhrFields[ i ];
9783
+ }
9784
+ }
9785
+
9786
+ // Override mime type if needed
9787
+ if ( s.mimeType && xhr.overrideMimeType ) {
9788
+ xhr.overrideMimeType( s.mimeType );
9789
+ }
9790
+
9791
+ // X-Requested-With header
9792
+ // For cross-domain requests, seeing as conditions for a preflight are
9793
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
9794
+ // (it can always be set on a per-request basis or even using ajaxSetup)
9795
+ // For same-domain requests, won't change header if already provided.
9796
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
9797
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
9798
+ }
9799
+
9800
+ // Need an extra try/catch for cross domain requests in Firefox 3
9801
+ try {
9802
+ for ( i in headers ) {
9803
+ xhr.setRequestHeader( i, headers[ i ] );
9804
+ }
9805
+ } catch( _ ) {}
9806
+
9807
+ // Do send the request
9808
+ // This may raise an exception which is actually
9809
+ // handled in jQuery.ajax (so no try/catch here)
9810
+ xhr.send( ( s.hasContent && s.data ) || null );
9811
+
9812
+ // Listener
9813
+ callback = function( _, isAbort ) {
9814
+
9815
+ var status,
9816
+ statusText,
9817
+ responseHeaders,
9818
+ responses,
9819
+ xml;
9820
+
9821
+ // Firefox throws exceptions when accessing properties
9822
+ // of an xhr when a network error occurred
9823
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
9824
+ try {
9825
+
9826
+ // Was never called and is aborted or complete
9827
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
9828
+
9829
+ // Only called once
9830
+ callback = undefined;
9831
+
9832
+ // Do not keep as active anymore
9833
+ if ( handle ) {
9834
+ xhr.onreadystatechange = jQuery.noop;
9835
+ if ( xhrOnUnloadAbort ) {
9836
+ delete xhrCallbacks[ handle ];
9837
+ }
9838
+ }
9839
+
9840
+ // If it's an abort
9841
+ if ( isAbort ) {
9842
+ // Abort it manually if needed
9843
+ if ( xhr.readyState !== 4 ) {
9844
+ xhr.abort();
9845
+ }
9846
+ } else {
9847
+ status = xhr.status;
9848
+ responseHeaders = xhr.getAllResponseHeaders();
9849
+ responses = {};
9850
+ xml = xhr.responseXML;
9851
+
9852
+ // Construct response list
9853
+ if ( xml && xml.documentElement /* #4958 */ ) {
9854
+ responses.xml = xml;
9855
+ }
9856
+
9857
+ // When requesting binary data, IE6-9 will throw an exception
9858
+ // on any attempt to access responseText (#11426)
9859
+ try {
9860
+ responses.text = xhr.responseText;
9861
+ } catch( _ ) {
9862
+ }
9863
+
9864
+ // Firefox throws an exception when accessing
9865
+ // statusText for faulty cross-domain requests
9866
+ try {
9867
+ statusText = xhr.statusText;
9868
+ } catch( e ) {
9869
+ // We normalize with Webkit giving an empty statusText
9870
+ statusText = "";
9871
+ }
9872
+
9873
+ // Filter status for non standard behaviors
9874
+
9875
+ // If the request is local and we have data: assume a success
9876
+ // (success with no data won't get notified, that's the best we
9877
+ // can do given current implementations)
9878
+ if ( !status && s.isLocal && !s.crossDomain ) {
9879
+ status = responses.text ? 200 : 404;
9880
+ // IE - #1450: sometimes returns 1223 when it should be 204
9881
+ } else if ( status === 1223 ) {
9882
+ status = 204;
9883
+ }
9884
+ }
9885
+ }
9886
+ } catch( firefoxAccessException ) {
9887
+ if ( !isAbort ) {
9888
+ complete( -1, firefoxAccessException );
9889
+ }
9890
+ }
9891
+
9892
+ // Call complete if needed
9893
+ if ( responses ) {
9894
+ complete( status, statusText, responses, responseHeaders );
9895
+ }
9896
+ };
9897
+
9898
+ if ( !s.async ) {
9899
+ // if we're in sync mode we fire the callback
9900
+ callback();
9901
+ } else if ( xhr.readyState === 4 ) {
9902
+ // (IE6 & IE7) if it's in cache and has been
9903
+ // retrieved directly we need to fire the callback
9904
+ setTimeout( callback, 0 );
9905
+ } else {
9906
+ handle = ++xhrId;
9907
+ if ( xhrOnUnloadAbort ) {
9908
+ // Create the active xhrs callbacks list if needed
9909
+ // and attach the unload handler
9910
+ if ( !xhrCallbacks ) {
9911
+ xhrCallbacks = {};
9912
+ jQuery( window ).unload( xhrOnUnloadAbort );
9913
+ }
9914
+ // Add to list of active xhrs callbacks
9915
+ xhrCallbacks[ handle ] = callback;
9916
+ }
9917
+ xhr.onreadystatechange = callback;
9918
+ }
9919
+ },
9920
+
9921
+ abort: function() {
9922
+ if ( callback ) {
9923
+ callback(0,1);
9924
+ }
9925
+ }
9926
+ };
9927
+ }
9928
+ });
9929
+ }
9930
+ var fxNow, timerId,
9931
+ rfxtypes = /^(?:toggle|show|hide)$/,
9932
+ rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
9933
+ rrun = /queueHooks$/,
9934
+ animationPrefilters = [ defaultPrefilter ],
9935
+ tweeners = {
9936
+ "*": [function( prop, value ) {
9937
+ var end, unit, prevScale,
9938
+ tween = this.createTween( prop, value ),
9939
+ parts = rfxnum.exec( value ),
9940
+ target = tween.cur(),
9941
+ start = +target || 0,
9942
+ scale = 1;
9943
+
9944
+ if ( parts ) {
9945
+ end = +parts[2];
9946
+ unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
9947
+
9948
+ // We need to compute starting value
9949
+ if ( unit !== "px" && start ) {
9950
+ // Iteratively approximate from a nonzero starting point
9951
+ // Prefer the current property, because this process will be trivial if it uses the same units
9952
+ // Fallback to end or a simple constant
9953
+ start = jQuery.css( tween.elem, prop, true ) || end || 1;
9954
+
9955
+ do {
9956
+ // If previous iteration zeroed out, double until we get *something*
9957
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
9958
+ prevScale = scale = scale || ".5";
9959
+
9960
+ // Adjust and apply
9961
+ start = start / scale;
9962
+ jQuery.style( tween.elem, prop, start + unit );
9963
+
9964
+ // Update scale, tolerating zeroes from tween.cur()
9965
+ scale = tween.cur() / target;
9966
+
9967
+ // Stop looping if we've hit the mark or scale is unchanged
9968
+ } while ( scale !== 1 && scale !== prevScale );
9969
+ }
9970
+
9971
+ tween.unit = unit;
9972
+ tween.start = start;
9973
+ // If a +=/-= token was provided, we're doing a relative animation
9974
+ tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
9975
+ }
9976
+ return tween;
9977
+ }]
9978
+ };
9979
+
9980
+ // Animations created synchronously will run synchronously
9981
+ function createFxNow() {
9982
+ setTimeout(function() {
9983
+ fxNow = undefined;
9984
+ }, 0 );
9985
+ return ( fxNow = jQuery.now() );
9986
+ }
9987
+
9988
+ function createTweens( animation, props ) {
9989
+ jQuery.each( props, function( prop, value ) {
9990
+ var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
9991
+ index = 0,
9992
+ length = collection.length;
9993
+ for ( ; index < length; index++ ) {
9994
+ if ( collection[ index ].call( animation, prop, value ) ) {
9995
+
9996
+ // we're done with this property
9997
+ return;
9998
+ }
9999
+ }
10000
+ });
10001
+ }
10002
+
10003
+ function Animation( elem, properties, options ) {
10004
+ var result,
10005
+ index = 0,
10006
+ tweenerIndex = 0,
10007
+ length = animationPrefilters.length,
10008
+ deferred = jQuery.Deferred().always( function() {
10009
+ // don't match elem in the :animated selector
10010
+ delete tick.elem;
10011
+ }),
10012
+ tick = function() {
10013
+ var currentTime = fxNow || createFxNow(),
10014
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
10015
+ percent = 1 - ( remaining / animation.duration || 0 ),
10016
+ index = 0,
10017
+ length = animation.tweens.length;
10018
+
10019
+ for ( ; index < length ; index++ ) {
10020
+ animation.tweens[ index ].run( percent );
10021
+ }
10022
+
10023
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
10024
+
10025
+ if ( percent < 1 && length ) {
10026
+ return remaining;
10027
+ } else {
10028
+ deferred.resolveWith( elem, [ animation ] );
10029
+ return false;
10030
+ }
10031
+ },
10032
+ animation = deferred.promise({
10033
+ elem: elem,
10034
+ props: jQuery.extend( {}, properties ),
10035
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
10036
+ originalProperties: properties,
10037
+ originalOptions: options,
10038
+ startTime: fxNow || createFxNow(),
10039
+ duration: options.duration,
10040
+ tweens: [],
10041
+ createTween: function( prop, end, easing ) {
10042
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
10043
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
10044
+ animation.tweens.push( tween );
10045
+ return tween;
10046
+ },
10047
+ stop: function( gotoEnd ) {
10048
+ var index = 0,
10049
+ // if we are going to the end, we want to run all the tweens
10050
+ // otherwise we skip this part
10051
+ length = gotoEnd ? animation.tweens.length : 0;
10052
+
10053
+ for ( ; index < length ; index++ ) {
10054
+ animation.tweens[ index ].run( 1 );
10055
+ }
10056
+
10057
+ // resolve when we played the last frame
10058
+ // otherwise, reject
10059
+ if ( gotoEnd ) {
10060
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
10061
+ } else {
10062
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
10063
+ }
10064
+ return this;
10065
+ }
10066
+ }),
10067
+ props = animation.props;
10068
+
10069
+ propFilter( props, animation.opts.specialEasing );
10070
+
10071
+ for ( ; index < length ; index++ ) {
10072
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
10073
+ if ( result ) {
10074
+ return result;
10075
+ }
10076
+ }
10077
+
10078
+ createTweens( animation, props );
10079
+
10080
+ if ( jQuery.isFunction( animation.opts.start ) ) {
10081
+ animation.opts.start.call( elem, animation );
10082
+ }
10083
+
10084
+ jQuery.fx.timer(
10085
+ jQuery.extend( tick, {
10086
+ anim: animation,
10087
+ queue: animation.opts.queue,
10088
+ elem: elem
10089
+ })
10090
+ );
10091
+
10092
+ // attach callbacks from options
10093
+ return animation.progress( animation.opts.progress )
10094
+ .done( animation.opts.done, animation.opts.complete )
10095
+ .fail( animation.opts.fail )
10096
+ .always( animation.opts.always );
10097
+ }
10098
+
10099
+ function propFilter( props, specialEasing ) {
10100
+ var index, name, easing, value, hooks;
10101
+
10102
+ // camelCase, specialEasing and expand cssHook pass
10103
+ for ( index in props ) {
10104
+ name = jQuery.camelCase( index );
10105
+ easing = specialEasing[ name ];
10106
+ value = props[ index ];
10107
+ if ( jQuery.isArray( value ) ) {
10108
+ easing = value[ 1 ];
10109
+ value = props[ index ] = value[ 0 ];
10110
+ }
10111
+
10112
+ if ( index !== name ) {
10113
+ props[ name ] = value;
10114
+ delete props[ index ];
10115
+ }
10116
+
10117
+ hooks = jQuery.cssHooks[ name ];
10118
+ if ( hooks && "expand" in hooks ) {
10119
+ value = hooks.expand( value );
10120
+ delete props[ name ];
10121
+
10122
+ // not quite $.extend, this wont overwrite keys already present.
10123
+ // also - reusing 'index' from above because we have the correct "name"
10124
+ for ( index in value ) {
10125
+ if ( !( index in props ) ) {
10126
+ props[ index ] = value[ index ];
10127
+ specialEasing[ index ] = easing;
10128
+ }
10129
+ }
10130
+ } else {
10131
+ specialEasing[ name ] = easing;
10132
+ }
10133
+ }
10134
+ }
10135
+
10136
+ jQuery.Animation = jQuery.extend( Animation, {
10137
+
10138
+ tweener: function( props, callback ) {
10139
+ if ( jQuery.isFunction( props ) ) {
10140
+ callback = props;
10141
+ props = [ "*" ];
10142
+ } else {
10143
+ props = props.split(" ");
10144
+ }
10145
+
10146
+ var prop,
10147
+ index = 0,
10148
+ length = props.length;
10149
+
10150
+ for ( ; index < length ; index++ ) {
10151
+ prop = props[ index ];
10152
+ tweeners[ prop ] = tweeners[ prop ] || [];
10153
+ tweeners[ prop ].unshift( callback );
10154
+ }
10155
+ },
10156
+
10157
+ prefilter: function( callback, prepend ) {
10158
+ if ( prepend ) {
10159
+ animationPrefilters.unshift( callback );
10160
+ } else {
10161
+ animationPrefilters.push( callback );
10162
+ }
10163
+ }
10164
+ });
10165
+
10166
+ function defaultPrefilter( elem, props, opts ) {
10167
+ var index, prop, value, length, dataShow, tween, hooks, oldfire,
10168
+ anim = this,
10169
+ style = elem.style,
10170
+ orig = {},
10171
+ handled = [],
10172
+ hidden = elem.nodeType && isHidden( elem );
10173
+
10174
+ // handle queue: false promises
10175
+ if ( !opts.queue ) {
10176
+ hooks = jQuery._queueHooks( elem, "fx" );
10177
+ if ( hooks.unqueued == null ) {
10178
+ hooks.unqueued = 0;
10179
+ oldfire = hooks.empty.fire;
10180
+ hooks.empty.fire = function() {
10181
+ if ( !hooks.unqueued ) {
10182
+ oldfire();
10183
+ }
10184
+ };
10185
+ }
10186
+ hooks.unqueued++;
10187
+
10188
+ anim.always(function() {
10189
+ // doing this makes sure that the complete handler will be called
10190
+ // before this completes
10191
+ anim.always(function() {
10192
+ hooks.unqueued--;
10193
+ if ( !jQuery.queue( elem, "fx" ).length ) {
10194
+ hooks.empty.fire();
10195
+ }
10196
+ });
10197
+ });
10198
+ }
10199
+
10200
+ // height/width overflow pass
10201
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
10202
+ // Make sure that nothing sneaks out
10203
+ // Record all 3 overflow attributes because IE does not
10204
+ // change the overflow attribute when overflowX and
10205
+ // overflowY are set to the same value
10206
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
10207
+
10208
+ // Set display property to inline-block for height/width
10209
+ // animations on inline elements that are having width/height animated
10210
+ if ( jQuery.css( elem, "display" ) === "inline" &&
10211
+ jQuery.css( elem, "float" ) === "none" ) {
10212
+
10213
+ // inline-level elements accept inline-block;
10214
+ // block-level elements need to be inline with layout
10215
+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
10216
+ style.display = "inline-block";
10217
+
10218
+ } else {
10219
+ style.zoom = 1;
10220
+ }
10221
+ }
10222
+ }
10223
+
10224
+ if ( opts.overflow ) {
10225
+ style.overflow = "hidden";
10226
+ if ( !jQuery.support.shrinkWrapBlocks ) {
10227
+ anim.done(function() {
10228
+ style.overflow = opts.overflow[ 0 ];
10229
+ style.overflowX = opts.overflow[ 1 ];
10230
+ style.overflowY = opts.overflow[ 2 ];
10231
+ });
10232
+ }
10233
+ }
10234
+
10235
+
10236
+ // show/hide pass
10237
+ for ( index in props ) {
10238
+ value = props[ index ];
10239
+ if ( rfxtypes.exec( value ) ) {
10240
+ delete props[ index ];
10241
+ if ( value === ( hidden ? "hide" : "show" ) ) {
10242
+ continue;
10243
+ }
10244
+ handled.push( index );
10245
+ }
10246
+ }
10247
+
10248
+ length = handled.length;
10249
+ if ( length ) {
10250
+ dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
10251
+ if ( hidden ) {
10252
+ jQuery( elem ).show();
10253
+ } else {
10254
+ anim.done(function() {
10255
+ jQuery( elem ).hide();
10256
+ });
10257
+ }
10258
+ anim.done(function() {
10259
+ var prop;
10260
+ jQuery.removeData( elem, "fxshow", true );
10261
+ for ( prop in orig ) {
10262
+ jQuery.style( elem, prop, orig[ prop ] );
10263
+ }
10264
+ });
10265
+ for ( index = 0 ; index < length ; index++ ) {
10266
+ prop = handled[ index ];
10267
+ tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
10268
+ orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
10269
+
10270
+ if ( !( prop in dataShow ) ) {
10271
+ dataShow[ prop ] = tween.start;
10272
+ if ( hidden ) {
10273
+ tween.end = tween.start;
10274
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
10275
+ }
10276
+ }
10277
+ }
10278
+ }
10279
+ }
10280
+
10281
+ function Tween( elem, options, prop, end, easing ) {
10282
+ return new Tween.prototype.init( elem, options, prop, end, easing );
10283
+ }
10284
+ jQuery.Tween = Tween;
10285
+
10286
+ Tween.prototype = {
10287
+ constructor: Tween,
10288
+ init: function( elem, options, prop, end, easing, unit ) {
10289
+ this.elem = elem;
10290
+ this.prop = prop;
10291
+ this.easing = easing || "swing";
10292
+ this.options = options;
10293
+ this.start = this.now = this.cur();
10294
+ this.end = end;
10295
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
10296
+ },
10297
+ cur: function() {
10298
+ var hooks = Tween.propHooks[ this.prop ];
10299
+
10300
+ return hooks && hooks.get ?
10301
+ hooks.get( this ) :
10302
+ Tween.propHooks._default.get( this );
10303
+ },
10304
+ run: function( percent ) {
10305
+ var eased,
10306
+ hooks = Tween.propHooks[ this.prop ];
10307
+
10308
+ if ( this.options.duration ) {
10309
+ this.pos = eased = jQuery.easing[ this.easing ](
10310
+ percent, this.options.duration * percent, 0, 1, this.options.duration
10311
+ );
10312
+ } else {
10313
+ this.pos = eased = percent;
10314
+ }
10315
+ this.now = ( this.end - this.start ) * eased + this.start;
10316
+
10317
+ if ( this.options.step ) {
10318
+ this.options.step.call( this.elem, this.now, this );
10319
+ }
10320
+
10321
+ if ( hooks && hooks.set ) {
10322
+ hooks.set( this );
10323
+ } else {
10324
+ Tween.propHooks._default.set( this );
10325
+ }
10326
+ return this;
10327
+ }
10328
+ };
10329
+
10330
+ Tween.prototype.init.prototype = Tween.prototype;
10331
+
10332
+ Tween.propHooks = {
10333
+ _default: {
10334
+ get: function( tween ) {
10335
+ var result;
10336
+
10337
+ if ( tween.elem[ tween.prop ] != null &&
10338
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
10339
+ return tween.elem[ tween.prop ];
10340
+ }
10341
+
10342
+ // passing any value as a 4th parameter to .css will automatically
10343
+ // attempt a parseFloat and fallback to a string if the parse fails
10344
+ // so, simple values such as "10px" are parsed to Float.
10345
+ // complex values such as "rotate(1rad)" are returned as is.
10346
+ result = jQuery.css( tween.elem, tween.prop, false, "" );
10347
+ // Empty strings, null, undefined and "auto" are converted to 0.
10348
+ return !result || result === "auto" ? 0 : result;
10349
+ },
10350
+ set: function( tween ) {
10351
+ // use step hook for back compat - use cssHook if its there - use .style if its
10352
+ // available and use plain properties where available
10353
+ if ( jQuery.fx.step[ tween.prop ] ) {
10354
+ jQuery.fx.step[ tween.prop ]( tween );
10355
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
10356
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
10357
+ } else {
10358
+ tween.elem[ tween.prop ] = tween.now;
10359
+ }
10360
+ }
10361
+ }
10362
+ };
10363
+
10364
+ // Remove in 2.0 - this supports IE8's panic based approach
10365
+ // to setting things on disconnected nodes
10366
+
10367
+ Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
10368
+ set: function( tween ) {
10369
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
10370
+ tween.elem[ tween.prop ] = tween.now;
10371
+ }
10372
+ }
10373
+ };
10374
+
10375
+ jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
10376
+ var cssFn = jQuery.fn[ name ];
10377
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
10378
+ return speed == null || typeof speed === "boolean" ||
10379
+ // special check for .toggle( handler, handler, ... )
10380
+ ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?
10381
+ cssFn.apply( this, arguments ) :
10382
+ this.animate( genFx( name, true ), speed, easing, callback );
10383
+ };
10384
+ });
10385
+
10386
+ jQuery.fn.extend({
10387
+ fadeTo: function( speed, to, easing, callback ) {
10388
+
10389
+ // show any hidden elements after setting opacity to 0
10390
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
10391
+
10392
+ // animate to the value specified
10393
+ .end().animate({ opacity: to }, speed, easing, callback );
10394
+ },
10395
+ animate: function( prop, speed, easing, callback ) {
10396
+ var empty = jQuery.isEmptyObject( prop ),
10397
+ optall = jQuery.speed( speed, easing, callback ),
10398
+ doAnimation = function() {
10399
+ // Operate on a copy of prop so per-property easing won't be lost
10400
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
10401
+
10402
+ // Empty animations resolve immediately
10403
+ if ( empty ) {
10404
+ anim.stop( true );
10405
+ }
10406
+ };
10407
+
10408
+ return empty || optall.queue === false ?
10409
+ this.each( doAnimation ) :
10410
+ this.queue( optall.queue, doAnimation );
10411
+ },
10412
+ stop: function( type, clearQueue, gotoEnd ) {
10413
+ var stopQueue = function( hooks ) {
10414
+ var stop = hooks.stop;
10415
+ delete hooks.stop;
10416
+ stop( gotoEnd );
10417
+ };
10418
+
10419
+ if ( typeof type !== "string" ) {
10420
+ gotoEnd = clearQueue;
10421
+ clearQueue = type;
10422
+ type = undefined;
10423
+ }
10424
+ if ( clearQueue && type !== false ) {
10425
+ this.queue( type || "fx", [] );
10426
+ }
10427
+
10428
+ return this.each(function() {
10429
+ var dequeue = true,
10430
+ index = type != null && type + "queueHooks",
10431
+ timers = jQuery.timers,
10432
+ data = jQuery._data( this );
10433
+
10434
+ if ( index ) {
10435
+ if ( data[ index ] && data[ index ].stop ) {
10436
+ stopQueue( data[ index ] );
10437
+ }
10438
+ } else {
10439
+ for ( index in data ) {
10440
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
10441
+ stopQueue( data[ index ] );
10442
+ }
10443
+ }
10444
+ }
10445
+
10446
+ for ( index = timers.length; index--; ) {
10447
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
10448
+ timers[ index ].anim.stop( gotoEnd );
10449
+ dequeue = false;
10450
+ timers.splice( index, 1 );
10451
+ }
10452
+ }
10453
+
10454
+ // start the next in the queue if the last step wasn't forced
10455
+ // timers currently will call their complete callbacks, which will dequeue
10456
+ // but only if they were gotoEnd
10457
+ if ( dequeue || !gotoEnd ) {
10458
+ jQuery.dequeue( this, type );
10459
+ }
10460
+ });
10461
+ }
10462
+ });
10463
+
10464
+ // Generate parameters to create a standard animation
10465
+ function genFx( type, includeWidth ) {
10466
+ var which,
10467
+ attrs = { height: type },
10468
+ i = 0;
10469
+
10470
+ // if we include width, step value is 1 to do all cssExpand values,
10471
+ // if we don't include width, step value is 2 to skip over Left and Right
10472
+ includeWidth = includeWidth? 1 : 0;
10473
+ for( ; i < 4 ; i += 2 - includeWidth ) {
10474
+ which = cssExpand[ i ];
10475
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
10476
+ }
10477
+
10478
+ if ( includeWidth ) {
10479
+ attrs.opacity = attrs.width = type;
10480
+ }
10481
+
10482
+ return attrs;
10483
+ }
10484
+
10485
+ // Generate shortcuts for custom animations
10486
+ jQuery.each({
10487
+ slideDown: genFx("show"),
10488
+ slideUp: genFx("hide"),
10489
+ slideToggle: genFx("toggle"),
10490
+ fadeIn: { opacity: "show" },
10491
+ fadeOut: { opacity: "hide" },
10492
+ fadeToggle: { opacity: "toggle" }
10493
+ }, function( name, props ) {
10494
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
10495
+ return this.animate( props, speed, easing, callback );
10496
+ };
10497
+ });
10498
+
10499
+ jQuery.speed = function( speed, easing, fn ) {
10500
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
10501
+ complete: fn || !fn && easing ||
10502
+ jQuery.isFunction( speed ) && speed,
10503
+ duration: speed,
10504
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
10505
+ };
10506
+
10507
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
10508
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
10509
+
10510
+ // normalize opt.queue - true/undefined/null -> "fx"
10511
+ if ( opt.queue == null || opt.queue === true ) {
10512
+ opt.queue = "fx";
10513
+ }
10514
+
10515
+ // Queueing
10516
+ opt.old = opt.complete;
10517
+
10518
+ opt.complete = function() {
10519
+ if ( jQuery.isFunction( opt.old ) ) {
10520
+ opt.old.call( this );
10521
+ }
10522
+
10523
+ if ( opt.queue ) {
10524
+ jQuery.dequeue( this, opt.queue );
10525
+ }
10526
+ };
10527
+
10528
+ return opt;
10529
+ };
10530
+
10531
+ jQuery.easing = {
10532
+ linear: function( p ) {
10533
+ return p;
10534
+ },
10535
+ swing: function( p ) {
10536
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
10537
+ }
10538
+ };
10539
+
10540
+ jQuery.timers = [];
10541
+ jQuery.fx = Tween.prototype.init;
10542
+ jQuery.fx.tick = function() {
10543
+ var timer,
10544
+ timers = jQuery.timers,
10545
+ i = 0;
10546
+
10547
+ for ( ; i < timers.length; i++ ) {
10548
+ timer = timers[ i ];
10549
+ // Checks the timer has not already been removed
10550
+ if ( !timer() && timers[ i ] === timer ) {
10551
+ timers.splice( i--, 1 );
10552
+ }
10553
+ }
10554
+
10555
+ if ( !timers.length ) {
10556
+ jQuery.fx.stop();
10557
+ }
10558
+ };
10559
+
10560
+ jQuery.fx.timer = function( timer ) {
10561
+ if ( timer() && jQuery.timers.push( timer ) && !timerId ) {
10562
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
10563
+ }
10564
+ };
10565
+
10566
+ jQuery.fx.interval = 13;
10567
+
10568
+ jQuery.fx.stop = function() {
10569
+ clearInterval( timerId );
10570
+ timerId = null;
10571
+ };
10572
+
10573
+ jQuery.fx.speeds = {
10574
+ slow: 600,
10575
+ fast: 200,
10576
+ // Default speed
10577
+ _default: 400
10578
+ };
10579
+
10580
+ // Back Compat <1.8 extension point
10581
+ jQuery.fx.step = {};
10582
+
10583
+ if ( jQuery.expr && jQuery.expr.filters ) {
10584
+ jQuery.expr.filters.animated = function( elem ) {
10585
+ return jQuery.grep(jQuery.timers, function( fn ) {
10586
+ return elem === fn.elem;
10587
+ }).length;
10588
+ };
10589
+ }
10590
+ var rroot = /^(?:body|html)$/i;
10591
+
10592
+ jQuery.fn.offset = function( options ) {
10593
+ if ( arguments.length ) {
10594
+ return options === undefined ?
10595
+ this :
10596
+ this.each(function( i ) {
10597
+ jQuery.offset.setOffset( this, options, i );
10598
+ });
10599
+ }
10600
+
10601
+ var box, docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, top, left,
10602
+ elem = this[ 0 ],
10603
+ doc = elem && elem.ownerDocument;
10604
+
10605
+ if ( !doc ) {
10606
+ return;
10607
+ }
10608
+
10609
+ if ( (body = doc.body) === elem ) {
10610
+ return jQuery.offset.bodyOffset( elem );
10611
+ }
10612
+
10613
+ docElem = doc.documentElement;
10614
+
10615
+ // Make sure we're not dealing with a disconnected DOM node
10616
+ if ( !jQuery.contains( docElem, elem ) ) {
10617
+ return { top: 0, left: 0 };
10618
+ }
10619
+
10620
+ box = elem.getBoundingClientRect();
10621
+ win = getWindow( doc );
10622
+ clientTop = docElem.clientTop || body.clientTop || 0;
10623
+ clientLeft = docElem.clientLeft || body.clientLeft || 0;
10624
+ scrollTop = win.pageYOffset || docElem.scrollTop;
10625
+ scrollLeft = win.pageXOffset || docElem.scrollLeft;
10626
+ top = box.top + scrollTop - clientTop;
10627
+ left = box.left + scrollLeft - clientLeft;
10628
+
10629
+ return { top: top, left: left };
10630
+ };
10631
+
10632
+ jQuery.offset = {
10633
+
10634
+ bodyOffset: function( body ) {
10635
+ var top = body.offsetTop,
10636
+ left = body.offsetLeft;
10637
+
10638
+ if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
10639
+ top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
10640
+ left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
10641
+ }
10642
+
10643
+ return { top: top, left: left };
10644
+ },
10645
+
10646
+ setOffset: function( elem, options, i ) {
10647
+ var position = jQuery.css( elem, "position" );
10648
+
10649
+ // set position first, in-case top/left are set even on static elem
10650
+ if ( position === "static" ) {
10651
+ elem.style.position = "relative";
10652
+ }
10653
+
10654
+ var curElem = jQuery( elem ),
10655
+ curOffset = curElem.offset(),
10656
+ curCSSTop = jQuery.css( elem, "top" ),
10657
+ curCSSLeft = jQuery.css( elem, "left" ),
10658
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
10659
+ props = {}, curPosition = {}, curTop, curLeft;
10660
+
10661
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
10662
+ if ( calculatePosition ) {
10663
+ curPosition = curElem.position();
10664
+ curTop = curPosition.top;
10665
+ curLeft = curPosition.left;
10666
+ } else {
10667
+ curTop = parseFloat( curCSSTop ) || 0;
10668
+ curLeft = parseFloat( curCSSLeft ) || 0;
10669
+ }
10670
+
10671
+ if ( jQuery.isFunction( options ) ) {
10672
+ options = options.call( elem, i, curOffset );
10673
+ }
10674
+
10675
+ if ( options.top != null ) {
10676
+ props.top = ( options.top - curOffset.top ) + curTop;
10677
+ }
10678
+ if ( options.left != null ) {
10679
+ props.left = ( options.left - curOffset.left ) + curLeft;
10680
+ }
10681
+
10682
+ if ( "using" in options ) {
10683
+ options.using.call( elem, props );
10684
+ } else {
10685
+ curElem.css( props );
10686
+ }
10687
+ }
10688
+ };
10689
+
10690
+
10691
+ jQuery.fn.extend({
10692
+
10693
+ position: function() {
10694
+ if ( !this[0] ) {
10695
+ return;
10696
+ }
10697
+
10698
+ var elem = this[0],
10699
+
10700
+ // Get *real* offsetParent
10701
+ offsetParent = this.offsetParent(),
10702
+
10703
+ // Get correct offsets
10704
+ offset = this.offset(),
10705
+ parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
10706
+
10707
+ // Subtract element margins
10708
+ // note: when an element has margin: auto the offsetLeft and marginLeft
10709
+ // are the same in Safari causing offset.left to incorrectly be 0
10710
+ offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
10711
+ offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
10712
+
10713
+ // Add offsetParent borders
10714
+ parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
10715
+ parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
10716
+
10717
+ // Subtract the two offsets
10718
+ return {
10719
+ top: offset.top - parentOffset.top,
10720
+ left: offset.left - parentOffset.left
10721
+ };
10722
+ },
10723
+
10724
+ offsetParent: function() {
10725
+ return this.map(function() {
10726
+ var offsetParent = this.offsetParent || document.body;
10727
+ while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
10728
+ offsetParent = offsetParent.offsetParent;
10729
+ }
10730
+ return offsetParent || document.body;
10731
+ });
10732
+ }
10733
+ });
10734
+
10735
+
10736
+ // Create scrollLeft and scrollTop methods
10737
+ jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
10738
+ var top = /Y/.test( prop );
10739
+
10740
+ jQuery.fn[ method ] = function( val ) {
10741
+ return jQuery.access( this, function( elem, method, val ) {
10742
+ var win = getWindow( elem );
10743
+
10744
+ if ( val === undefined ) {
10745
+ return win ? (prop in win) ? win[ prop ] :
10746
+ win.document.documentElement[ method ] :
10747
+ elem[ method ];
10748
+ }
10749
+
10750
+ if ( win ) {
10751
+ win.scrollTo(
10752
+ !top ? val : jQuery( win ).scrollLeft(),
10753
+ top ? val : jQuery( win ).scrollTop()
10754
+ );
10755
+
10756
+ } else {
10757
+ elem[ method ] = val;
10758
+ }
10759
+ }, method, val, arguments.length, null );
10760
+ };
10761
+ });
10762
+
10763
+ function getWindow( elem ) {
10764
+ return jQuery.isWindow( elem ) ?
10765
+ elem :
10766
+ elem.nodeType === 9 ?
10767
+ elem.defaultView || elem.parentWindow :
10768
+ false;
10769
+ }
10770
+ // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10771
+ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10772
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
10773
+ // margin is only for outerHeight, outerWidth
10774
+ jQuery.fn[ funcName ] = function( margin, value ) {
10775
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10776
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10777
+
10778
+ return jQuery.access( this, function( elem, type, value ) {
10779
+ var doc;
10780
+
10781
+ if ( jQuery.isWindow( elem ) ) {
10782
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
10783
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
10784
+ // https://github.com/jquery/jquery/pull/764
10785
+ return elem.document.documentElement[ "client" + name ];
10786
+ }
10787
+
10788
+ // Get document width or height
10789
+ if ( elem.nodeType === 9 ) {
10790
+ doc = elem.documentElement;
10791
+
10792
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
10793
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
10794
+ return Math.max(
10795
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10796
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
10797
+ doc[ "client" + name ]
10798
+ );
10799
+ }
10800
+
10801
+ return value === undefined ?
10802
+ // Get width or height on the element, requesting but not forcing parseFloat
10803
+ jQuery.css( elem, type, value, extra ) :
10804
+
10805
+ // Set width or height on the element
10806
+ jQuery.style( elem, type, value, extra );
10807
+ }, type, chainable ? margin : undefined, chainable, null );
10808
+ };
10809
+ });
10810
+ });
10811
+ // Expose jQuery to the global object
10812
+ window.jQuery = window.$ = jQuery;
10813
+
10814
+ // Expose jQuery as an AMD module, but only for AMD loaders that
10815
+ // understand the issues with loading multiple versions of jQuery
10816
+ // in a page that all might call define(). The loader will indicate
10817
+ // they have special allowances for multiple jQuery versions by
10818
+ // specifying define.amd.jQuery = true. Register as a named module,
10819
+ // since jQuery can be concatenated with other files that may use define,
10820
+ // but not use a proper concatenation script that understands anonymous
10821
+ // AMD modules. A named AMD is safest and most robust way to register.
10822
+ // Lowercase jquery is used because AMD module names are derived from
10823
+ // file names, and jQuery is normally delivered in a lowercase file name.
10824
+ // Do this after creating the global so that if an AMD module wants to call
10825
+ // noConflict to hide this version of jQuery, it will work.
10826
+ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
10827
+ define( "jquery", [], function () { return jQuery; } );
10828
+ }
10829
+
10830
+ })( window );
js/provide/md5.js ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ CryptoJS v3.0.2
3
+ code.google.com/p/crypto-js
4
+ (c) 2009-2012 by Jeff Mott. All rights reserved.
5
+ code.google.com/p/crypto-js/wiki/License
6
+ */
7
+ var CryptoJS=CryptoJS||function(o,q){var l={},m=l.lib={},n=m.Base=function(){function a(){}return{extend:function(e){a.prototype=this;var c=new a;e&&c.mixIn(e);c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.$super.extend(this)}}}(),j=m.WordArray=n.extend({init:function(a,e){a=
8
+ this.words=a||[];this.sigBytes=e!=q?e:4*a.length},toString:function(a){return(a||r).stringify(this)},concat:function(a){var e=this.words,c=a.words,d=this.sigBytes,a=a.sigBytes;this.clamp();if(d%4)for(var b=0;b<a;b++)e[d+b>>>2]|=(c[b>>>2]>>>24-8*(b%4)&255)<<24-8*((d+b)%4);else if(65535<c.length)for(b=0;b<a;b+=4)e[d+b>>>2]=c[b>>>2];else e.push.apply(e,c);this.sigBytes+=a;return this},clamp:function(){var a=this.words,e=this.sigBytes;a[e>>>2]&=4294967295<<32-8*(e%4);a.length=o.ceil(e/4)},clone:function(){var a=
9
+ n.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var e=[],c=0;c<a;c+=4)e.push(4294967296*o.random()|0);return j.create(e,a)}}),k=l.enc={},r=k.Hex={stringify:function(a){for(var e=a.words,a=a.sigBytes,c=[],d=0;d<a;d++){var b=e[d>>>2]>>>24-8*(d%4)&255;c.push((b>>>4).toString(16));c.push((b&15).toString(16))}return c.join("")},parse:function(a){for(var b=a.length,c=[],d=0;d<b;d+=2)c[d>>>3]|=parseInt(a.substr(d,2),16)<<24-4*(d%8);return j.create(c,b/2)}},p=k.Latin1={stringify:function(a){for(var b=
10
+ a.words,a=a.sigBytes,c=[],d=0;d<a;d++)c.push(String.fromCharCode(b[d>>>2]>>>24-8*(d%4)&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],d=0;d<b;d++)c[d>>>2]|=(a.charCodeAt(d)&255)<<24-8*(d%4);return j.create(c,b)}},h=k.Utf8={stringify:function(a){try{return decodeURIComponent(escape(p.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return p.parse(unescape(encodeURIComponent(a)))}},b=m.BufferedBlockAlgorithm=n.extend({reset:function(){this._data=j.create();
11
+ this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=h.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,c=b.words,d=b.sigBytes,f=this.blockSize,i=d/(4*f),i=a?o.ceil(i):o.max((i|0)-this._minBufferSize,0),a=i*f,d=o.min(4*a,d);if(a){for(var h=0;h<a;h+=f)this._doProcessBlock(c,h);h=c.splice(0,a);b.sigBytes-=d}return j.create(h,d)},clone:function(){var a=n.clone.call(this);a._data=this._data.clone();return a},_minBufferSize:0});m.Hasher=b.extend({init:function(){this.reset()},
12
+ reset:function(){b.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);this._doFinalize();return this._hash},clone:function(){var a=b.clone.call(this);a._hash=this._hash.clone();return a},blockSize:16,_createHelper:function(a){return function(b,c){return a.create(c).finalize(b)}},_createHmacHelper:function(a){return function(b,c){return f.HMAC.create(a,c).finalize(b)}}});var f=l.algo={};return l}(Math);
13
+ (function(o){function q(b,f,a,e,c,d,g){b=b+(f&a|~f&e)+c+g;return(b<<d|b>>>32-d)+f}function l(b,f,a,e,c,d,g){b=b+(f&e|a&~e)+c+g;return(b<<d|b>>>32-d)+f}function m(b,f,a,e,c,d,g){b=b+(f^a^e)+c+g;return(b<<d|b>>>32-d)+f}function n(b,f,a,e,c,d,g){b=b+(a^(f|~e))+c+g;return(b<<d|b>>>32-d)+f}var j=CryptoJS,k=j.lib,r=k.WordArray,k=k.Hasher,p=j.algo,h=[];(function(){for(var b=0;64>b;b++)h[b]=4294967296*o.abs(o.sin(b+1))|0})();p=p.MD5=k.extend({_doReset:function(){this._hash=r.create([1732584193,4023233417,
14
+ 2562383102,271733878])},_doProcessBlock:function(b,f){for(var a=0;16>a;a++){var e=f+a,c=b[e];b[e]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360}for(var e=this._hash.words,c=e[0],d=e[1],g=e[2],i=e[3],a=0;64>a;a+=4)16>a?(c=q(c,d,g,i,b[f+a],7,h[a]),i=q(i,c,d,g,b[f+a+1],12,h[a+1]),g=q(g,i,c,d,b[f+a+2],17,h[a+2]),d=q(d,g,i,c,b[f+a+3],22,h[a+3])):32>a?(c=l(c,d,g,i,b[f+(a+1)%16],5,h[a]),i=l(i,c,d,g,b[f+(a+6)%16],9,h[a+1]),g=l(g,i,c,d,b[f+(a+11)%16],14,h[a+2]),d=l(d,g,i,c,b[f+a%16],20,h[a+3])):48>a?(c=
15
+ m(c,d,g,i,b[f+(3*a+5)%16],4,h[a]),i=m(i,c,d,g,b[f+(3*a+8)%16],11,h[a+1]),g=m(g,i,c,d,b[f+(3*a+11)%16],16,h[a+2]),d=m(d,g,i,c,b[f+(3*a+14)%16],23,h[a+3])):(c=n(c,d,g,i,b[f+3*a%16],6,h[a]),i=n(i,c,d,g,b[f+(3*a+7)%16],10,h[a+1]),g=n(g,i,c,d,b[f+(3*a+14)%16],15,h[a+2]),d=n(d,g,i,c,b[f+(3*a+5)%16],21,h[a+3]));e[0]=e[0]+c|0;e[1]=e[1]+d|0;e[2]=e[2]+g|0;e[3]=e[3]+i|0},_doFinalize:function(){var b=this._data,f=b.words,a=8*this._nDataBytes,e=8*b.sigBytes;f[e>>>5]|=128<<24-e%32;f[(e+64>>>9<<4)+14]=(a<<8|a>>>
16
+ 24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(f.length+1);this._process();b=this._hash.words;for(f=0;4>f;f++)a=b[f],b[f]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360}});j.MD5=k._createHelper(p);j.HmacMD5=k._createHmacHelper(p)})(Math);
js/provide/provide.js ADDED
@@ -0,0 +1,939 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Developed by Ortus IT.
3
+ * Web: http://ortus-it.com
4
+ * Code part:#02-01-rev.004, October 2013.
5
+ * -All Rights of this product are belong to Provide Support, LLC.-
6
+ *
7
+ */
8
+
9
+
10
+ function generateRandomString(length) {
11
+ var text = "";
12
+ var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
13
+ for (var i = 0; i < length; i++)
14
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
15
+ return text;
16
+ };
17
+
18
+
19
+ jQuery(document).ready(function () {
20
+
21
+ jQuery('#f7main input').prop('checked',false);
22
+
23
+ var settingsLoaded = false;
24
+ var emulateCount = 0;
25
+ var depended = jQuery('#buttonAvailableAll,#buttonAvailablePost,#buttonAvailableWhole,.shortcodeSeparator').parent();
26
+
27
+ var form_key = window.FORM_KEY;
28
+ var f7php = new Object();
29
+ var f7acc = new Object();
30
+ var f7accc = new Object();
31
+ var f7settings = new Object();
32
+ var newExisting = false;
33
+ var autoLogin = false;
34
+ var setAccount = false;
35
+ var validation = true;
36
+ var validation2 = true;
37
+ var f7message = jQuery('#f7message');
38
+ var f7messageFlag = false;
39
+
40
+
41
+ jQuery('#selectPostMenus').hide();
42
+ jQuery('input[name=buttonAppearance]').parent().children('.settingInt').hide();
43
+ jQuery('input[name=customImages]').parent().children('.settingIntInt').hide();
44
+ jQuery('input[name=buttonLocation]').parent().children('.settingInt').hide();
45
+
46
+ jQuery('#buttonAvailablePost').parent().children('.settingInt').hide();
47
+
48
+ hideshow = function (obj, type) {
49
+
50
+
51
+ jQuery(obj).parent().on('click', function () {
52
+ jQuery(obj).parent().each(function () {
53
+ currentSetting = jQuery(this);
54
+ if (currentSetting.children('input').prop('checked')) {
55
+ currentSetting.children(type).slideDown('fast');
56
+ } else {
57
+ currentSetting.children(type).slideUp('fast');
58
+ }
59
+ });
60
+ });
61
+ }
62
+
63
+ hideshow('input[name=buttonAppearance]', '.settingInt');
64
+ hideshow('input[name=customImages]', '.settingIntInt');
65
+ hideshow('input[name=buttonLocation]', '.settingInt');
66
+
67
+ hideshow('#buttonAvailablePost', '.settingInt');
68
+ hideshow('input[name=optionPages]', '#selectPagesMenus');
69
+ hideshow('input[name=optionPost]', '#selectPostMenus');
70
+
71
+
72
+ jQuery('.f7control').on('click', function () {
73
+
74
+ if (jQuery(this).children('input').attr('checked') == 'checked') {
75
+ jQuery('#f7settings').children().not('.f7control').not('').slideDown('fast');
76
+ } else {
77
+ jQuery('#f7settings').children().not('.f7control').not('').slideUp('fast');
78
+ }
79
+ });
80
+
81
+
82
+ jQuery('.f7control').on('click', function () {
83
+ if (jQuery('input[location=shortcode]').attr('checked') == 'checked') {
84
+ nnot = depended;
85
+ } else {
86
+ nnot = '';
87
+ }
88
+ if (jQuery(this).children('input').attr('checked') == 'checked') {
89
+ jQuery('#f7settings').children().not('.f7control').not(nnot).slideDown('fast');
90
+ } else {
91
+ jQuery('#f7settings').children().not('.f7control').not(nnot).slideUp('fast');
92
+ }
93
+ });
94
+
95
+ jQuery('input[location]').on('click', function () {
96
+ shortcode = jQuery('input[location=shortcode]');
97
+ dep = depended;
98
+ if (shortcode.attr('checked') == 'checked') {
99
+ dep.hide('fast');
100
+ }
101
+ if (shortcode.attr('checked') != 'checked') {
102
+ dep.show('fast');
103
+ }
104
+ });
105
+
106
+ idInterval = setInterval(function () {
107
+ checkMessage()
108
+ }, 1000);
109
+
110
+
111
+ /*----------------------initializing--------------------------------
112
+ * initializing - function that gets data from db
113
+ * Get next param:
114
+ * f7php.db.accountName = accountName
115
+ * f7php.db.accountHash = accountHash
116
+ * f7php.db.settings = settings
117
+ * f7php.db.pluginsFolder = pluginsFolder
118
+ * urlAjax = ajaxurl
119
+ */
120
+ initializing = function () {
121
+
122
+
123
+ ajaxData = {
124
+ action: 'getaccount',
125
+ form_key: form_key
126
+ }
127
+
128
+ jQuery.ajax({
129
+ url: urlAjax,
130
+ type: 'POST',
131
+ data: ajaxData
132
+ }).done(function (data) {
133
+
134
+ f7php.db = JSON.parse(data);
135
+
136
+
137
+ // if no account set param
138
+ if ((f7php.db.settings + '' || f7php.db.account + '') == 'undefined') {
139
+
140
+ f7php.db.settings = 'null';
141
+ f7php.db.account = {};
142
+ f7php.db.account.accountName = '';
143
+ f7php.db.account.accountHash = '';
144
+
145
+ }
146
+
147
+ checkAccount();
148
+
149
+ })
150
+ }();
151
+
152
+
153
+ /*----------------------heckAccount---------------------------------
154
+ * checkAccount - function check login and pass than chek submit
155
+ * Set next param:
156
+ * f7php.db.account.accountName
157
+ * f7php.db.account.accountHash
158
+ */
159
+ checkAccount = function () {
160
+
161
+ if (f7php.db.account.accountName != '' && f7php.db.account.accountHash != '') {
162
+ jQuery('.f7fields:eq(0) > .f7field > input').val(f7php.db.account.accountName);
163
+ jQuery('.f7fields:eq(1) > .f7field > input').val(f7php.db.account.accountHash);
164
+
165
+ autoLogin = true;
166
+
167
+ setTimeout(function () {
168
+ jQuery('#f7accountSubmit').trigger('click');
169
+ }, 1500);
170
+ }else{
171
+
172
+ autoLogin = false;
173
+
174
+ }
175
+
176
+ };
177
+
178
+
179
+
180
+
181
+ f7emulate = function (obj, prop) {
182
+ emulateCount++;
183
+ if (emulateCount > 0) {
184
+ setTimeout(function () {
185
+ if (prop) jQuery(obj).prop('checked', true);
186
+ jQuery(obj).trigger('click');
187
+ }, 100 * emulateCount);
188
+ } else {
189
+ if (prop) jQuery(obj).prop('checked', true);
190
+ jQuery(obj).trigger('click');
191
+ }
192
+ }
193
+
194
+
195
+
196
+ jQuery('#f7buttonE').on('click', function () {
197
+ jQuery('.f7field input').removeClass('novalid').attr('placeholder', '');
198
+ jQuery('#f7buttonN').removeClass('f7buttonNoBorder');
199
+ jQuery(this).addClass('f7buttonNoBorder');
200
+ jQuery('.f7fields').eq(2).slideUp();
201
+ jQuery('#f7accountSubmit').html('Connect to Account');
202
+ });
203
+ jQuery('#f7buttonN').on('click', function () {
204
+ jQuery('.f7field input').removeClass('novalid').attr('placeholder', '');
205
+ jQuery('#f7buttonE').removeClass('f7buttonNoBorder');
206
+ jQuery(this).addClass('f7buttonNoBorder');
207
+ jQuery('.f7fields').eq(2).slideDown();
208
+ jQuery('#f7accountSubmit').html('Create Account and connect');
209
+ });
210
+
211
+
212
+
213
+ /*------------------------f7Login---------------------------------------
214
+ * f7Login - function that set data in db
215
+ * Set next param:
216
+ * action = setaccount,
217
+ * accountName = f7accc.login
218
+ * accountHash = f7acc.pass
219
+ */
220
+ f7Login = function () {
221
+
222
+ f7accc.login = f7acc.name;
223
+
224
+
225
+ if(newExisting == true){
226
+ var newPass = f7acc.pass;
227
+ f7acc.pass = CryptoJS.MD5(f7acc.pass)+'';
228
+ f7accc.md5 = CryptoJS.MD5(f7acc.pass) + '';
229
+ }
230
+
231
+ if(setAccount == true){
232
+ f7acc.pass = CryptoJS.MD5(f7acc.pass)+'';
233
+ }
234
+
235
+ accountInfo = '';
236
+ accountInfo += 'Connected to account : ';
237
+ accountInfo += '<b>' + f7accc.login + '</b>';
238
+ if(f7acc.type == 'existing'){
239
+ accountInfo += '<br /><br /><div id="f7oldaccountDetails">To go online and start answering chat requests, please install the <a target="_blank" href = "http://www.providesupport.com/downloads/index.html?utm_source=magento-plugin&utm_medium=settings&utm_campaign=Plugins" style="text-decoration: none">Operator Console</a> ';
240
+ accountInfo += 'and login <br /> with the credentials available on your account <a target="_blank" href="https://admin.providesupport.com/view/my-account/operators-and-departments?utm_source=magento-plugin&utm_medium=settings&utm_campaign=Plugins" style="text-decoration: none">Operators and Departments</a> page.';
241
+ accountInfo += '<br />To customize your live chat appearance, please use available settings <br /> in your account <a target="_blank" href = "https://admin.providesupport.com/view/my-account/dashboard?utm_source=magento-plugin&utm_medium=settings&utm_campaign=Plugins" style="text-decoration: none">Control Panel</a>.';
242
+ accountInfo += '</div>';
243
+ }
244
+ if(f7acc.type == 'new'){
245
+ accountInfo += '<br /><br /><div id="f7newaccountDetails">To start using the live chat service and appear online please install the <a target="_blank" href = "http://www.providesupport.com/downloads/index.html?utm_source=magento-plugin&utm_medium=settings&utm_campaign=Plugins" style="text-decoration: none">Operator Console</a> ';
246
+ accountInfo += '<br />and login with the following credentials:';
247
+ accountInfo += '<br /><br />Account Name: <b>' + f7acc.name + '</b>';
248
+ accountInfo += '<br />Operator Login: <b>' + f7acc.name + '</b>';
249
+ accountInfo += '<br />Operator Password: <b>' + newPass + '</b>';
250
+ accountInfo += '<br /><br />To customize your live chat appearance and configure other settings, <br />please use your account <a target="_blank" href = "https://admin.providesupport.com/action/main/company/company-login?login=' + f7acc.name + '&password=' + newPass + '" style="text-decoration: none">Control Panel</a>.';
251
+ accountInfo += '</div>';
252
+ }
253
+ accountInfo += '<br /><div id="f7anotherAccount" style="margin:5px auto;width:285px;">Connect to another Provide Support account</div>';
254
+ jQuery('#f7accountInfo').html(accountInfo);
255
+
256
+
257
+
258
+ jQuery('#f7anotherAccount').on('click', function () {
259
+
260
+ ajaxData = {
261
+ action: 'clearall',
262
+ form_key: form_key
263
+ }
264
+ func = function(){
265
+ location.reload();
266
+ }
267
+ ajaxSend(ajaxData, func);
268
+
269
+ });
270
+
271
+
272
+ f7opensettings();
273
+
274
+
275
+
276
+ ajaxData = {
277
+ action: 'setaccount',
278
+ form_key: form_key,
279
+ accountName: f7accc.login,
280
+ accountHash: f7acc.pass
281
+ }
282
+
283
+ func = function(){};
284
+ ajaxSend(ajaxData, func);
285
+
286
+ }
287
+
288
+ ajaxSend = function(ajaxData, func){
289
+
290
+ //console.log(f7php);
291
+ //console.log(ajaxData);
292
+ jQuery.ajax({
293
+ url: urlAjax,
294
+ type: 'POST',
295
+ data: ajaxData
296
+ }).done(function (msg) {
297
+ func();
298
+ });
299
+
300
+ }
301
+
302
+
303
+
304
+ //-------------------------- 7php settings -------------------------------
305
+ f7opensettings = function () {
306
+
307
+
308
+ f7php.db.settings = JSON.parse(f7php.db.settings);
309
+
310
+ if (f7php.db.settings + '' == 'null'){
311
+
312
+ f7php.db.settings = new Object();
313
+ f7php.db.settings.pluginEnabled = true;
314
+ f7php.db.settings.buttonImageType = 'graphic';
315
+ f7php.db.settings.buttonImageSource = 'account';
316
+ f7php.db.settings.buttonLocation = 'fixed';
317
+ f7php.db.settings.buttonLocationVerticalBy = '%';
318
+ f7php.db.settings.buttonLocationVerticalValue = '50';
319
+ f7php.db.settings.buttonLocationVerticalFrom = 'bottom';
320
+ f7php.db.settings.buttonLocationHorizontalBy = '%';
321
+ f7php.db.settings.buttonLocationHorizontalValue = '0';
322
+ f7php.db.settings.buttonLocationHorizontalFrom = 'right';
323
+ f7php.db.settings.buttonAvailableMenus = true
324
+ f7php.db.settings.buttonAvailableMenusWhich = 'all';
325
+ f7php.db.settings.buttonAvailablePost = true
326
+ f7php.db.settings.buttonAvailablePostWhich = 'all';
327
+ f7php.db.settings.buttonAvailableWhole = true;
328
+ f7php.db.settings.buttonAvailableAll = true;
329
+ }
330
+
331
+ if (f7php.db.settings.pluginEnabled + '' == 'true') {
332
+
333
+ jQuery('#f7settings').slideDown();
334
+ } else {
335
+ jQuery('#f7wait').html('<img src="' + f7php.db.pluginsFolder + '/img/wait.gif" width="30px" height="30px">');
336
+
337
+ }
338
+ jQuery('#f7submit').slideDown();
339
+ jQuery('#f7account').slideUp();
340
+ jQuery('#f7accountInfo').slideDown();
341
+
342
+
343
+ loadSettings(f7php.db.settings);
344
+ }
345
+
346
+
347
+ loadSettings = function (sett) {
348
+
349
+
350
+ if (!settingsLoaded) {
351
+
352
+
353
+ if (sett.pluginEnabled) {
354
+ jQuery('#f7pluginEnabled').attr('checked', true);
355
+ f7emulate('.f7control');
356
+ }
357
+ if (sett.buttonImageType == 'graphic') {
358
+ f7emulate('.f7button1', true);
359
+ }
360
+ if (sett.buttonImageType == 'text')
361
+ {
362
+ f7emulate('.f7button2', true);
363
+
364
+ jQuery('#buttonImageTextOnline').val(sett.buttonImageTextOnline);
365
+ jQuery('#buttonImageTextOffline').val(sett.buttonImageTextOffline);
366
+ }
367
+ if (sett.buttonImageSource == 'account') {
368
+ f7emulate('.f7button3', true);
369
+ }
370
+
371
+ if (sett.buttonImageSource == 'custom') {
372
+ f7emulate('.f7button4', true);
373
+
374
+ jQuery('#buttonImageUrlOnline').val(sett.buttonImageUrlOnline);
375
+ jQuery('#buttonImageUrlOffline').val(sett.buttonImageUrlOffline);
376
+
377
+ }
378
+ if (sett.buttonLocation) {
379
+ string = 'input[location=' + sett.buttonLocation + ']';
380
+ f7emulate(string, true);
381
+ if (sett.buttonLocation == 'fixed') {
382
+ jQuery('#buttonLocationVerticalValue').val(sett.buttonLocationVerticalValue);
383
+ jQuery('#buttonLocationHorizontalValue').val(sett.buttonLocationHorizontalValue);
384
+ //---------------------------------
385
+ if (sett.buttonLocationVerticalBy == 'px') {
386
+ f7emulate('.f7button5');
387
+ } else {
388
+ f7emulate('.f7button6');
389
+ }
390
+ if (sett.buttonLocationHorizontalBy == 'px') {
391
+ f7emulate('.f7button7');
392
+ } else {
393
+ f7emulate('.f7button8');
394
+ }
395
+ //---------------------------------
396
+ if (sett.buttonLocationVerticalFrom == 'top') {
397
+ f7emulate('.f7button9');
398
+ } else {
399
+ f7emulate('.f7button10');
400
+ }
401
+ if (sett.buttonLocationHorizontalFrom == 'left') {
402
+ f7emulate('.f7button11');
403
+ } else {
404
+ f7emulate('.f7button12');
405
+ }
406
+ }else{
407
+
408
+ jQuery("#selectedBlock option").filter(function() {
409
+ return jQuery(this).val() == sett.buttonAvailableMenusList;
410
+ }).attr('selected', true);
411
+
412
+ }
413
+
414
+ }
415
+
416
+
417
+ if (sett.buttonAvailablePost) {
418
+ f7emulate('#buttonAvailablePost');
419
+ if (sett.buttonAvailablePostWhich == 'all') {
420
+ f7emulate('.f7button15', true);
421
+ } else {
422
+ f7emulate('.f7button16', true);
423
+ for (var i=0; i<sett.buttonAvailablePostList.length ; i++){
424
+ jQuery('input[postid=' + sett.buttonAvailablePostList[i] + ']').trigger('click');
425
+
426
+ }
427
+ }
428
+ }
429
+ if (sett.buttonAvailableWhole) {
430
+
431
+ f7emulate('#buttonAvailableWhole');
432
+ }
433
+
434
+ if (sett.buttonAvailableAll) {
435
+
436
+ f7emulate('#buttonAvailableAll');
437
+ }
438
+
439
+
440
+ settingsLoaded = true;
441
+
442
+ if (!sett.pluginEnabled) {
443
+ f7emulate('.f7control');
444
+ f7emulate('.f7control');
445
+ }
446
+
447
+ setTimeout(function () {
448
+ jQuery('#f7submit').trigger('click');
449
+ }, 2000);
450
+ setTimeout(function () {
451
+ jQuery('#f7settings').fadeIn();
452
+ jQuery('#f7wait').remove();
453
+ }, 100 * emulateCount + 200);
454
+ }
455
+
456
+ }
457
+
458
+
459
+
460
+ //--------------------------------------- accErase ------------------------------------------//
461
+ accErase = function () {
462
+ f7acc.type = '';
463
+ f7acc.name = '';
464
+ f7acc.pass = '';
465
+ f7acc.mail = '';
466
+ };
467
+
468
+ //--------------------------------------- accGrub ------------------------------------------//
469
+ accGrub = function () {
470
+ f7acc.type = (jQuery('#f7buttonE').hasClass('f7buttonNoBorder')) ? 'existing' : 'new';
471
+ f7acc.name = jQuery('.f7fields').eq(0).children('.f7field').children('input').val() || '';
472
+ f7acc.pass = jQuery('.f7fields').eq(1).children('.f7field').children('input').val() || '';
473
+ f7acc.mail = jQuery('.f7fields').eq(2).children('.f7field').children('input').val() || '';
474
+ }
475
+
476
+
477
+ //--------------------------------------- validate ------------------------------------------//
478
+ validate = function () { //
479
+ validation = true;
480
+ if (f7settings.buttonImageType == 'graphic' && f7settings.buttonImageSource == 'custom') {
481
+ valid('#buttonImageUrlOnline');
482
+ valid('#buttonImageUrlOffline');
483
+ }
484
+ if (f7settings.buttonImageType == 'text') {
485
+ valid('#buttonImageTextOnline');
486
+ valid('#buttonImageTextOffline');
487
+ }
488
+ if (f7settings.buttonLocation == 'fixed') {
489
+ valid('#buttonLocationVerticalValue');
490
+ valid('#buttonLocationHorizontalValue');
491
+ }
492
+ }
493
+
494
+ //--------------------------------------- validate2 ------------------------------------------//
495
+ validate2 = function (number){
496
+ validation2 = true;
497
+ jQuery('.f7fields > .f7field > input').removeClass('novalid');
498
+ valid('.f7fields:eq(0) > .f7field > input',true);
499
+ name = jQuery('.f7fields:eq(0) > .f7field > input').val();
500
+ pattern = new RegExp(/^[-a-z0-9_]{0,20}$/i);
501
+ if(pattern.test(name)){
502
+ }else if(name != ''){
503
+ textMessage('The account name should contain no more than 20 alphanumeric characters <br> (Latin letters or digits), \'-\' (dashes), or \'_\' (underscore) characters. Spaces are not allowed.','warning');
504
+ jQuery('.f7fields:eq(0) > .f7field > input').addClass('novalid');
505
+ validation2 = false;
506
+ }
507
+ valid('.f7fields:eq(1) > .f7field > input',true);
508
+ pass = jQuery('.f7fields:eq(1) > .f7field > input').val();
509
+ if(pass.length > number) {validation2 = false;jQuery('.f7fields:eq(1) > .f7field > input').addClass('novalid');textMessage('The account password should contain no more than 20 characters.','warning');}
510
+ if(f7acc.type == 'new') {
511
+ valid('.f7fields:eq(2) > .f7field > input',true);
512
+ pattern = new RegExp(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i);
513
+ if(pattern.test(jQuery('.f7fields:eq(2) > .f7field > input').val())){
514
+ }else{
515
+ validation2 = false;
516
+ jQuery('.f7fields:eq(2) > .f7field > input').addClass('novalid');
517
+ textMessage('Please enter a correct e-mail address','warning');
518
+ }
519
+ }
520
+ checkFields();
521
+ }
522
+
523
+
524
+ checkFields = function () {
525
+ jQuery('.f7field input').each(function () {
526
+ if (jQuery(this).hasClass('novalid')) {
527
+ jQuery(this).attr('placeholder', 'This field is required!');
528
+ } else {
529
+
530
+ }
531
+ });
532
+ }
533
+
534
+
535
+ valid = function (obj, type) {
536
+ type = type || false;
537
+ if (jQuery(obj).val() == '') {
538
+ jQuery(obj).addClass('novalid');
539
+ if (!type) {
540
+ validation = false;
541
+ } else {
542
+ validation2 = false;
543
+ }
544
+ } else {
545
+ jQuery(obj).removeClass('novalid');
546
+ }
547
+ }
548
+
549
+ textMessage = function (message, type) {
550
+ jQuery('#f7message').html(message);
551
+ type = type || 'info';
552
+ if (type == 'warning') {
553
+ f7message.addClass('f7warning');
554
+ } else {
555
+ f7message.removeClass('f7warning');
556
+ }
557
+ }
558
+
559
+ checkMessage = function () {
560
+ if (f7message.html() != '' && !f7messageFlag) {
561
+ f7messageFlag = true;
562
+ f7message.slideDown('fast');
563
+ setTimeout(function () {
564
+ f7message.slideUp('fast');
565
+ f7message.empty();
566
+ f7messageFlag = !f7messageFlag
567
+ }, 8000);
568
+ }
569
+ }
570
+
571
+
572
+ //--------------------------------------- submit to account ------------------------------------------//
573
+ jQuery('#f7accountSubmit').on('click', function () {
574
+ accErase();
575
+ accGrub();
576
+
577
+ if(autoLogin == true){
578
+ validate2(32);
579
+ }else{
580
+ validate2(20);
581
+ }
582
+
583
+ if (validation2){
584
+
585
+ jQuery('#f7accountSubmit').append('<img id="accountWait" style="position:absolute;top:-2px;right:-38px;" src="data:image/gif;base64,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" width="30px" height="30px">');
586
+ var accSet = {};
587
+ if (f7acc.type == 'existing') {
588
+
589
+ var siteUrl = 'https://www.providesupport.com/api/account/v1/companies/';
590
+ var companyLogin = '?companyLogin=';
591
+ var companyPasswords = '&companyPasswordMD5Hash=';
592
+
593
+ if(autoLogin == true){
594
+ url = siteUrl + f7acc.name + companyLogin + f7acc.name + companyPasswords + f7acc.pass;
595
+ }else{
596
+ url = siteUrl + f7acc.name + companyLogin + f7acc.name + companyPasswords + CryptoJS.MD5(f7acc.pass);
597
+ }
598
+
599
+
600
+
601
+
602
+ jQuery.ajax({
603
+ type: 'GET',
604
+ url: url,
605
+ dataType: 'jsonp',
606
+ data: {},
607
+ async: false,
608
+ success: function (msg) {
609
+
610
+ if (typeof msg.company != 'undefined') {
611
+
612
+ f7message.slideUp('fast');
613
+ clearInterval(idInterval);
614
+
615
+ newExisting = false;
616
+
617
+ if(autoLogin == false){
618
+ setAccount = true;
619
+ }else{
620
+ setAccount = false;
621
+ }
622
+ f7Login();
623
+
624
+ }
625
+ if (msg.error == 'incorrect-password-md5-hash') {
626
+ textMessage('Incorrect password', 'warning');
627
+ } else if (msg.error == 'no-such-company') {
628
+ textMessage(msg.errorDescription, 'warning');
629
+ } else {
630
+ if (msg.errorDescription != '') {
631
+ textMessage(msg.errorDescription, 'warning')
632
+ } else {
633
+ textMessage(msg.error, 'warning')
634
+ }
635
+ }
636
+
637
+ jQuery('#accountWait').remove();
638
+ }
639
+ }).done(function () {
640
+ jQuery('#accountWait').remove();
641
+ }); //?
642
+
643
+ }
644
+ if (f7acc.type == 'new') {
645
+ accSet = {}
646
+ accSet.companyLogin = f7acc.name;
647
+ //accSet.companyPassword = CryptoJS.MD5(f7acc.pass)+'';
648
+ accSet.companyPassword = f7acc.pass;
649
+ accSet.email = f7acc.mail;
650
+ accSet.caller = 'magento-plugin-1.0';
651
+ accSet.accountSettings = {
652
+ "chatIconOnline": "57/chat-icon-57-online-en.gif",
653
+ "chatIconOffline": "57/chat-icon-57-offline-en.gif"
654
+ }
655
+
656
+
657
+
658
+ jQuery.ajax({
659
+ url: 'https://www.providesupport.com/api/account/v1/companies/?method=post',
660
+ dataType: 'jsonp',
661
+ data: {
662
+ params: JSON.stringify(accSet)
663
+ },
664
+ success: function (msg) {
665
+
666
+ if (msg.error == 'duplicate-company-login') {
667
+ textMessage('Account name "' + f7acc.name + '" is taken', 'warning')
668
+ } else if (msg.result == 'success') {
669
+
670
+
671
+ f7message.slideUp('fast');
672
+ clearInterval(idInterval);
673
+
674
+ newExisting = true;
675
+ f7Login();
676
+ } else {
677
+ if (msg.errorDescription != '') {
678
+ textMessage(msg.errorDescription, 'warning')
679
+ } else {
680
+ textMessage(msg.error, 'warning')
681
+ }
682
+ }
683
+ jQuery('#accountWait').remove();
684
+ }
685
+ }).done(function () {
686
+ jQuery('#accountWait').remove();
687
+ }); //?
688
+ }
689
+ }
690
+ });
691
+
692
+
693
+ jQuery('#f7submit').on('click', function () {
694
+ eraseSettings();
695
+ grabSettings();
696
+ validate();
697
+ if (f7settings.pluginEnabled + '' == 'false') validation = true;
698
+ if (validation) {
699
+ jQuery('#f7livePreview').html('<img src="' + f7php.db.pluginsFolder + '/img/wait.gif" width="30px" height="30px">');
700
+ jQuery(this).removeClass('novalidButton');
701
+ ajaxData = {
702
+ action: 'setsettings',
703
+ form_key: form_key,
704
+ settings: JSON.stringify(f7settings)
705
+ }
706
+ jQuery.ajax({
707
+ url: urlAjax,
708
+ type: 'POST',
709
+ data: ajaxData
710
+ }).done(function (msg) {
711
+ });
712
+
713
+ var json = {};
714
+ json.hash = generateRandomString(4);
715
+
716
+ json.locale = location.language || 'en';
717
+ json.fixed = false;
718
+ json.codeType = 'script';
719
+ json.appearance = 'graphics';
720
+ json.companyLogin = f7accc.login;
721
+ //json.companyPasswordMD5Hash = f7acc.pass;
722
+
723
+
724
+ json.fixed = f7settings.buttonLocation == 'fixed' ? true : false;
725
+ json.fixedPosition = {
726
+ "horizontal": {
727
+ "value":f7settings.buttonLocationHorizontalValue,
728
+ "units":f7settings.buttonLocationHorizontalBy,
729
+ "startAt":f7settings.buttonLocationHorizontalFrom
730
+ },
731
+ "vertical": {
732
+ "value":f7settings.buttonLocationVerticalValue,
733
+ "units":f7settings.buttonLocationVerticalBy,
734
+ "startAt":f7settings.buttonLocationVerticalFrom
735
+ }
736
+ };
737
+
738
+ console.log('json.fixed = '+json.fixed);
739
+ console.log('json.fixedPosition : '+json.fixedPosition);
740
+
741
+
742
+
743
+
744
+ if(autoLogin == true){
745
+ json.companyPasswordMD5Hash = f7acc.pass;
746
+ }else{
747
+ if(setAccount == true){
748
+ json.companyPasswordMD5Hash = f7acc.pass;
749
+ //json.companyPasswordMD5Hash = CryptoJS.MD5(f7acc.pass)+'';
750
+ }
751
+
752
+ if(newExisting == true){
753
+ json.companyPasswordMD5Hash = f7acc.pass;
754
+ }
755
+ }
756
+
757
+
758
+ var f7url = new Object();
759
+ f7url.hidden = 'http://www.providesupport.com/api/chat-button/v1/get-code';
760
+ f7url.text = 'http://www.providesupport.com/api/chat-button/v1/get-code';
761
+ f7url.graphic = 'http://www.providesupport.com/api/chat-button/v1/get-code';
762
+ f7url.featured = 'http://www.providesupport.com/api/chat-button/v1/get-code';
763
+ //console.log(':::START');
764
+ if (f7settings.buttonImageType == 'graphic') {
765
+ if (f7settings.buttonImageSource == 'account') {
766
+ requestCode(json, f7url.featured);
767
+ console.log('featured');
768
+ }
769
+ if (f7settings.buttonImageSource == 'custom') {
770
+ json.customImageUrls = {};
771
+ json.customImageUrls.online = f7settings.buttonImageUrlOnline;
772
+ json.customImageUrls.offline = f7settings.buttonImageUrlOffline;
773
+ requestCode(json, f7url.graphic);
774
+ console.log('custom');
775
+
776
+ }
777
+ } else {
778
+ json.appearance = 'text';
779
+ json.chatLinkHtmls = {};
780
+ json.chatLinkHtmls.online = f7settings.buttonImageTextOnline;
781
+ json.chatLinkHtmls.offline = f7settings.buttonImageTextOffline;
782
+ requestCode(json, f7url.text);
783
+ console.log('text');
784
+ }
785
+ if (f7settings.buttonAvailableWhole) {
786
+ json.appearance = 'hidden';
787
+ requestCode(json, f7url.hidden, true);
788
+ }
789
+
790
+
791
+ } else {
792
+ jQuery(this).addClass('novalidButton');
793
+ }
794
+ });
795
+
796
+
797
+
798
+
799
+ eraseSettings = function () {
800
+ f7settings.pluginEnabled = false; // false || true
801
+ f7settings.buttonImageType = false; // graphic || text
802
+ f7settings.buttonImageSource = false; // account || custom
803
+ f7settings.buttonImageUrlOnline = false; // url
804
+ f7settings.buttonImageUrlOffline = false; // url
805
+ f7settings.buttonImageTextOnline = false; // text
806
+ f7settings.buttonImageTextOffline = false; // text
807
+ f7settings.buttonLocation = false // widget || fixed || shortcode
808
+ f7settings.buttonLocationVerticalBy = false // pixel || percent
809
+ f7settings.buttonLocationVerticalValue = false; // value
810
+ f7settings.buttonLocationVerticalFrom = false; // top || bottom
811
+ f7settings.buttonLocationHorizontalBy = false // pixel || percent
812
+ f7settings.buttonLocationHorizontalValue = false; // value
813
+ f7settings.buttonLocationHorizontalFrom = false; // top || bottom
814
+ f7settings.buttonAvailableMenus = false; // ||true
815
+ f7settings.buttonAvailableMenusWhich = false // all || selected
816
+ f7settings.buttonAvailableMenusList = new Array(); // array()
817
+ f7settings.buttonAvailablePost = false; // ||true
818
+ f7settings.buttonAvailablePostWhich = false // all || selected
819
+ f7settings.buttonAvailablePostList = new Array(); // array(page id, page id)
820
+ f7settings.buttonAvailableWhole = false // ||true
821
+ f7settings.buttonAvailableAll = false;
822
+ }
823
+ grabSettings = function () {
824
+ f7settings.pluginEnabled = (jQuery('#f7pluginEnabled').prop('checked')) ? true : false;
825
+ f7settings.buttonImageType = (jQuery('#buttonImageType').prop('checked')) ? 'graphic' : 'text';
826
+ f7settings.buttonImageSource = (jQuery('#buttonImageSource').prop('checked')) ? 'account' : 'custom';
827
+ f7settings.buttonImageUrlOnline = jQuery('#buttonImageUrlOnline').val() || false;
828
+ f7settings.buttonImageUrlOffline = jQuery('#buttonImageUrlOffline').val() || false;
829
+ f7settings.buttonImageTextOnline = jQuery('#buttonImageTextOnline').val() || false;
830
+ f7settings.buttonImageTextOffline = jQuery('#buttonImageTextOffline').val() || false;
831
+ jQuery('input[name=buttonLocation]').each(function (index) {
832
+ if (jQuery(this).prop('checked')) {
833
+ f7settings.buttonLocation = jQuery(this).attr('location');
834
+ }
835
+ });
836
+ f7settings.buttonLocationVerticalValue = jQuery('#buttonLocationVerticalValue').val() || false;
837
+ f7settings.buttonLocationVerticalBy = (jQuery('#buttonLocationVerticalBy').prop('checked')) ? 'px' : '%';
838
+ f7settings.buttonLocationVerticalFrom = (jQuery('#buttonLocationVerticalFrom').prop('checked')) ? 'top' : 'bottom';
839
+ f7settings.buttonLocationHorizontalValue = jQuery('#buttonLocationHorizontalValue').val() || false;
840
+ f7settings.buttonLocationHorizontalBy = (jQuery('#buttonLocationHorizontalBy').prop('checked')) ? 'px' : '%';
841
+ f7settings.buttonLocationHorizontalFrom = (jQuery('#buttonLocationHorizontalFrom').prop('checked')) ? 'left' : 'right';
842
+
843
+
844
+
845
+
846
+ //selected Block
847
+ f7settings.buttonAvailableMenusList.push(jQuery("#selectedBlock").val());
848
+
849
+
850
+ f7settings.buttonAvailablePost = (jQuery('#buttonAvailablePost').prop('checked')) ? true : false;
851
+ f7settings.buttonAvailablePostWhich = (jQuery('#buttonAvailablePostWhich').prop('checked')) ? 'all' : 'selected';
852
+ jQuery('#selectPostMenus > input').each(function () {
853
+ currentInput = jQuery(this);
854
+ //console.log(currentInput);
855
+ if (currentInput.prop('checked')) {
856
+ f7settings.buttonAvailablePostList.push(currentInput.attr('postid'));
857
+ }
858
+ });
859
+
860
+
861
+
862
+ f7settings.buttonAvailableWhole = (jQuery('#buttonAvailableWhole').prop('checked')) ? true : false;
863
+ f7settings.buttonAvailableAll = (jQuery('#buttonAvailableAll').prop('checked')) ? true : false;
864
+ };
865
+
866
+
867
+
868
+
869
+ requestCode = function (json, url, format) {
870
+
871
+
872
+ //json.fixed = false;
873
+ format = format || false;
874
+ url = location.protocol + '//www.providesupport.com/api/chat-button/v1/get-code';
875
+ jQuery.ajax({
876
+ type: 'GET',
877
+ url: url,
878
+ dataType: 'jsonp',
879
+ contentType: "application/json",
880
+ data: {
881
+ jsonParam: JSON.stringify(json)
882
+ },
883
+ async: false,
884
+ success: function (msg) {
885
+
886
+ console.log(msg);
887
+ setCode(msg.code, format);
888
+ }
889
+ });
890
+
891
+ json.fixed = false;
892
+
893
+ jQuery.ajax({
894
+ type: 'GET',
895
+ url: url,
896
+ dataType: 'jsonp',
897
+ contentType: "application/json",
898
+ data: {
899
+ jsonParam: JSON.stringify(json)
900
+ },
901
+ async: false,
902
+ success: function (msg) {
903
+
904
+ console.log(msg);
905
+
906
+ if (!format) {
907
+ jQuery('#f7livePreview').html('Your live chat link example: <br />' + msg.code);
908
+ }
909
+
910
+ }
911
+ });
912
+
913
+
914
+
915
+ }
916
+
917
+ setCode = function (value, type) {
918
+ type = type || false;
919
+ value = value || false;
920
+ // console.log(value);
921
+ ajaxData = {
922
+ action: 'setcode',
923
+ type: type,
924
+ form_key: form_key,
925
+ value: value
926
+ }
927
+ jQuery.ajax({
928
+ url: urlAjax,
929
+ type: 'POST',
930
+ data: ajaxData
931
+ }).done(function (msg) {
932
+ // console.log('EX :: '+msg);
933
+ });
934
+ }
935
+
936
+
937
+
938
+
939
+ })
package.xml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>ProvideSupport_Live_Chat</name>
4
+ <version>1.0.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.gnu.org/copyleft/gpl.html">GNU General Public License</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Live Chat module for Magento by Provide Support, LLC&#xD;
10
+ </summary>
11
+ <description>The module helps to integrate Provide Support Live Chat&#xD;
12
+ with Magento based websites. It offers flexible settings to customize&#xD;
13
+ the appearance of the Live Chat on your website according to your&#xD;
14
+ requirements.</description>
15
+ <notes>First public release&#xD;
16
+ </notes>
17
+ <authors><author><name>Provide Support, LLC</name><user>providesupport</user><email>magento@providesupport.com</email></author></authors>
18
+ <date>2013-11-13</date>
19
+ <time>12:06:28</time>
20
+ <contents><target name="magecommunity"><dir name="ProvideSupport"><dir name="Livechat"><dir name="Block"><file name="Help.php" hash="06a993b6ed92dc5a7c22445f65b72cd5"/><file name="Settings.php" hash="a900da0bd0bafc0b479d0aa0aaa4adaa"/></dir><dir name="Helper"><file name="Data.php" hash="306a5efc9bf9eae926c6ca693eca0367"/></dir><dir name="Model"><file name="Livechat.php" hash="668d641a7309fc7efc8d754f062c537b"/><dir name="Mysql4"><dir name="Livechat"><file name="Collection.php" hash="0a08b2c0c0c81f0afbbae08ea7b1095b"/></dir><file name="Livechat.php" hash="5cd46359fdf549c69dbf6cedd370a9a3"/></dir><file name="Observer.php" hash="b649cb16d354f61ccc4024f58dcc8a4f"/></dir><dir name="controllers"><file name="AdminController.php" hash="d60456baf0aee0c0c4d57181e3087f5f"/></dir><dir name="etc"><file name="config.xml" hash="b4af121d684f132f38a4817beb5ea603"/></dir><dir name="sql"><dir name="providelivechat_setup"><file name="mysql4-install-1.0.0.php" hash="b5bbd6a1e88814e3fca9112a1a55dab6"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="ProvideSupport_All.xml" hash="942a89517a99d55e014eba20bf6e27b9"/></dir></target><target name="mageweb"><dir name="js"><dir name="provide"><file name="jquery-noconflict.js" hash="e2060c4e5e5955c824723b13a212d3ec"/><file name="jquery.js" hash="41ca0b5d474117281973aeb249b944c8"/><file name="md5.js" hash="76b55cb1f28848b833083b2f19e6e088"/><file name="provide.js" hash="58d3c27112e65fff7265f61bf57eecb5"/></dir></dir></target></contents>
21
+ <compatible/>
22
+ <dependencies><required><php><min>5.1.0</min><max>5.7.0</max></php></required></dependencies>
23
+ </package>