PageSourceSearch

https://ogolnopolskiturniejwiedzy.edu.pl/scripts/static.8cfa7025.js

js ogolnopolskiturniejwiedzy.edu.pl collected 2026-09-28 13:21:39 UTC 702,456 bytes, 22,679 lines download raw bytes

1var staticMessages = {
2  "pl": {
3    "menu": "Menu",
4    "name": "Polski",
5    "contact_form_input_email": "E-mail lub nr telefonu",
6    "contact_form_input_message": "Treść wiadomości",
7    "contact_form_input_name": "Imię i nazwisko",
8    "contact_form_send_email": "Wyślij e-mail",
9    "language": "Język",
10    "add_download": "pobierz",
11    "bank_account": "Nr konta",
12    "nip": "NIP",
13    "city": "Miejscowość",
14    "comments": "Uwagi",
15    "from_text": "Od",
16    "order_text": "Zamów",
17    "order_no": "Zamówienie nr",
18    "regon": "REGON",
19    "street": "Ulica",
20    "tel_no": "Numer telefonu",
21    "to_text": "Do",
22    "visitor_counter_txt": "Odwiedzin",
23    "add_entry": "Dodaj wpis",
24    "author": "Autor",
25    "sendEntryFailed": "Dodawanie wpisów do księgi gości zostało zablokowane przez właściciela strony.",
26    "sendEntrySuccess": "Wpis został dodany. Pojawi się na stronie po zaakceptowaniu przez administratora.",
27    "cookie_box_text": "Używamy plików cookies (ciasteczek) w celach statystycznych oraz by ułatwić korzystanie z naszego serwisu.<br />W każdej chwili możesz zablokować lub ograniczyć zapisywanie plików cookies na Twoim urządzeniu zmieniając ustawienia przeglądarki internetowej.",
28    "cookie_box_short_text": "Polityka prywatności i plików Cookies",
29    "shop_add_to_cart_text": "Dodaj do koszyka",
30    "shop_back_text": "Wstecz",
31    "shop_cart_content_text": "Zawartość koszyka",
32    "shop_close_text": "Zamknij",
33    "shop_email_text": "Twój adres e-mail",
34    "shop_empty_cart_text": "Twój koszyk jest pusty.",
35    "shop_invalid_email_text": "Wpisz poprawny adres e-mail.",
36    "shop_message_text": "Dodatkowa wiadomość, np. adres do wysyłki, dane do faktury, etc.",
37    "shop_name_text": "Nazwa",
38    "shop_order_posting_text": "Wysyłanie zamówienia",
39    "shop_price_text": "Cena",
40    "shop_quantity_text": "Ilość",
41    "shop_send_message_error_text": "Nie udało się wysłać zamówienia. Jeśli problem wystąpi ponownie skontaktuj się z właścicielem strony.",
42    "shop_send_message_success_text": "Twoje zamówienie zostało wysłane. W ciągu kilku minut, na podany w nim adres, powinieneś otrzymać e-mail z potwierdzeniem.",
43    "shop_send_order_text": "Wyślij zamówienie",
44    "unsupported_audio_info_text": "Aby odtworzyć ten plik musisz zaktualizować przeglądarkę do najnowszej wersji bądź zainstalować wtyczkę Flash.",
45    "unsupported_back_sound_info_text": "Aby odtwarzać dźwięk na stronie musisz zaktualizować przeglądarkę do najnowszej wersji bądź zainstalować wtyczkę Flash.",
46    "field_required": "Pole wymagane!",
47    "invalid_email": "Nieprawidłowy e-mail",
48    "send_fail": "Wysyłanie nie powiodło się. Spróbuj ponownie za kilka minut.<br />Kliknij w tekst aby ukryć komunikat.",
49    "send_success": "Dziękujemy za skorzystanie z formularza.",
50    "sending": "Trwa wysyłanie...",
51    "news": "Aktualności",
52    "see_more": "Zobacz więcej...",
53    "contactUs": "Skontaktuj się z nami",
54    "siteExpiredTitle": 'Strona wygasła!',
55    "siteExpiredMessage": 'Twoja strona nadal znajduje się na serwerze, ale nie jest widoczna w Internecie dla innych użytkowników. Aby móc w pełni korzystać ze wszystkich funkcji naszego serwisu skontaktuj się z Biurem Obsługi Klienta.',
56  },
57  "gb": {
58    "menu": "Menu",
59    "name": "English",
60    "contact_form_input_email": "E-mail or phone number",
61    "contact_form_input_message": "Message",
62    "contact_form_input_name": "Full name",
63    "contact_form_send_email": "Send e-mail",
64    "language": "Language",
65    "add_download": "download",
66    "bank_account": "Bank account",
67    "nip": "VAT Reg No",
68    "city": "City",
69    "comments": "Comments",
70    "from_text": "From",
71    "order_text": "Order",
72    "order_no": "Order number",
73    "regon": "REGON",
74    "street": "Street",
75    "tel_no": "Phone number",
76    "to_text": "To",
77    "visitor_counter_txt": "Visits",
78    "add_entry": "Add news",
79    "author": "Author",
80    "sendEntryFailed": "Adding entries to the guestbook has been disabled by the site owner.",
81    "sendEntrySuccess": "Entry has been added. It will appear on the site after administrator's approval.",
82    "cookie_box_text": "We use cookie files for statistical purposes and to facilitate the use of our website.<br />At any time, you can prevent or limit cookie storage on your device by changing settings in your browser.",
83    "cookie_box_short_text": "Cookies and Privacy Policy",
84    "shop_add_to_cart_text": "Add to cart",
85    "shop_back_text": "Back",
86    "shop_cart_content_text": "Cart content",
87    "shop_close_text": "Close",
88    "shop_email_text": "Your e-mail",
89    "shop_empty_cart_text": "Your cart is empty.",
90    "shop_invalid_email_text": "Enter valid e-mail.",
91    "shop_message_text": "Additional message",
92    "shop_name_text": "Name",
93    "shop_order_posting_text": "Order posting",
94    "shop_price_text": "Price",
95    "shop_quantity_text": "Quantity",
96    "shop_send_message_error_text": "Failed to send your order. If problem persists contact the page's owner.",
97    "shop_send_message_success_text": "Your order has been send. In few minutes you should receive an email with confirmation at the given address.",
98    "shop_send_order_text": "Send order",
99    "unsupported_audio_info_text": "You have to update your browser or install Flash plugin if you want to play this file.",
100    "unsupported_back_sound_info_text": "You have to update your browser or install Flash plugin if you want to play sound on the site.",
101    "field_required": "Field required!",
102    "invalid_email": "Invalid e-mail",
103    "send_fail": "Sending failed. Try again later in a few minutes.<br />Click on text to hide this message.",
104    "send_success": "Thank you for using the form.",
105    "sending": "Sending...",
106    "news": "News",
107    "see_more": "See more...",
108    "contactUs": "Contact Us",
109    "siteExpiredTitle": 'Site expired!',
110    "siteExpiredMessage": 'Your website is still hosted on server but is not accessible to internauts. To activate the website please contact with our customer support.',
111  },
112  "us": {
113    "menu": "Menu",
114    "name": "English",
115    "contact_form_input_email": "E-mail or phone number",
116    "contact_form_input_message": "Message",
117    "contact_form_input_name": "Full name",
118    "contact_form_send_email": "Send e-mail",
119    "language": "Language",
120    "add_download": "download",
121    "bank_account": "Bank account",
122    "nip": "Tax ID",
123    "city": "City",
124    "comments": "Comments",
125    "from_text": "From",
126    "order_text": "Order",
127    "order_no": "Order number",
128    "regon": "REGON",
129    "street": "Street",
130    "tel_no": "Phone number",
131    "to_text": "To",
132    "visitor_counter_txt": "Visits",
133    "add_entry": "Add news",
134    "author": "Author",
135    "sendEntryFailed": "Adding entries to the guestbook has been disabled by the site owner.",
136    "sendEntrySuccess": "Entry has been added. It will apear on the site after administrator's approval.",
137    "cookie_box_text": "We use cookie files for statistical purposes and to facilitate the use of our website.<br />At any time, you can prevent or limit cookie storage on your device by changing settings in your browser.",
138    "cookie_box_short_text": "Cookies and Privacy Policy",
139    "shop_add_to_cart_text": "Add to cart",
140    "shop_back_text": "Back",
141    "shop_cart_content_text": "Cart content",
142    "shop_close_text": "Close",
143    "shop_email_text": "Your e-mail",
144    "shop_empty_cart_text": "Your cart is empty.",
145    "shop_invalid_email_text": "Enter valid e-mail.",
146    "shop_message_text": "Additional message",
147    "shop_name_text": "Name",
148    "shop_order_posting_text": "Order posting",
149    "shop_price_text": "Price",
150    "shop_quantity_text": "Quantity",
151    "shop_send_message_error_text": "Failed to send your order. If problem persists contact the page's owner.",
152    "shop_send_message_success_text": "Your order has been send. In few minutes you should receive an email with confirmation at the given address.",
153    "shop_send_order_text": "Send order",
154    "unsupported_audio_info_text": "You have to update your browser or install Flash plugin if you want to play this file.",
155    "unsupported_back_sound_info_text": "You have to update your browser or install Flash plugin if you want to play sound on the site.",
156    "field_required": "Field required!",
157    "invalid_email": "Invalid e-mail",
158    "send_fail": "Sending failed. Try again later in a few minutes.<br />Click on text to hide this message.",
159    "send_success": "Thank you for using form.",
160    "sending": "Sending...",
161    "news": "News",
162    "see_more": "See more...",
163    "contactUs": "Contact Us",
164    "siteExpiredTitle": 'Site expired!',
165    "siteExpiredMessage": 'Your website is still hosted on server but is not accessible to internauts. To activate the website please contact with our customer support.',
166
167  },
168  "de": {
169    "menu": "Menü",
170    "name": "Deutsch",
171    "contact_form_input_email": "E-Mail oder Telefonnummer",
172    "contact_form_input_message": "Nachricht",
173    "contact_form_input_name": "Vorname und Nachname",
174    "contact_form_send_email": "E-Mail senden",
175    "language": "Sprache",
176    "add_download": "download",
177    "bank_account": "Bankkonto",
178    "nip": "USt-IdNr.",
179    "city": "Stadt",
180    "comments": "Kommentare",
181    "from_text": "Von",
182    "order_text": "Bestellen",
183    "order_no": "Bestell-Nr",
184    "regon": "",
185    "street": "Strasse",
186    "tel_no": "Telefonnummer",
187    "to_text": "Bis",
188    "visitor_counter_txt": "Besuche",
189    "add_entry": "Eintrag hinzufügen",
190    "author": "Autor",
191    "sendEntryFailed": "Hinzufügen von Einträgen in das Gästebuch wurde durch den Webseiten-Inhaber wurde deaktiviert.",
192    "sendEntrySuccess": "Beitrag wurde hinzugefügt. Es wird auf der Website nach Administrator bestätigt werden angezeigt.",
193    "cookie_box_text": "Wir benutzen Cookies für statistische Zwecke und um die Nutzung unseres Dienstes zu erleichern.<br /> Sie können jederzeit das speichern von Cookies auf Ihrem Gerät durch Veränderung der Einstellungen Ihres Web-Browsers sperren oder einschränken.",
194    "cookie_box_short_text": "Datenschutz und Cookies-Dateien",
195    "shop_add_to_cart_text": "In den Warenkorb",
196    "shop_back_text": "Zurück",
197    "shop_cart_content_text": "Inhalt des Warenkorbs",
198    "shop_close_text": "Schließen",
199    "shop_email_text": "Ihre E-mail-adresse",
200    "shop_empty_cart_text": "Ihr Warenkorb ist leer",
201    "shop_invalid_email_text": "Korrekte E-Mail-Adresse eintragen",
202    "shop_message_text": "Zusätzliche Nachricht",
203    "shop_name_text": "Name",
204    "shop_order_posting_text": "Das Senden von Aufträgen",
205    "shop_price_text": "Preis",
206    "shop_quantity_text": "Anzahl",
207    "shop_send_message_error_text": "Bestellung misslungen. Wenn das Problem erneut erscheint, kontaktieren Sie den Inhaber der Seite.",
208    "shop_send_message_success_text": "Ihre Bestellung wurde erfolgreich versendet. Innerhalb weniger Minuten bekommen Sie eine Bestätigungsmail an die von Sie angegebene E-Mail-Adresse zugesendet.",
209    "shop_send_order_text": "Den Auftrag senden",
210    "unsupported_audio_info_text": "Um die Datei zu öffnen, brauchen Sie die neueste Version des Browsers oder müssen Sie das Flash-Plugin installieren.",
211    "unsupported_back_sound_info_text": "Um den Ton auf der Seite wiederzugeben, brauchen Sie die neueste Version des Browsers oder müssen Sie das Flash-Plugin installieren.",
212    "field_required": "Pflichtfelder!",
213    "invalid_email": "Falsche E-mail",
214    "send_fail": "Nachricht wurde nicht erfolgreich gesendent. Versuchen Sie es in ein paar Minten noch einmal.<br />Klicken Sie auf den Text um Hinweis zu verstecken.",
215    "send_success": "Vielen Dank, dass Sie unser Formular benutzt haben.",
216    "sending": "Senden...",
217    "news": "Nachrichten",
218    "see_more": "Mehr sehen...",
219    "contactUs": "Kontaktiere uns",
220    "siteExpiredTitle": 'Website abgelaufen!',
221    "siteExpiredMessage": 'Ihre Website wird weiterhin auf dem Server gehostet, ist jedoch für Internauten nicht zugänglich. Um die Website zu aktivieren, wenden Sie sich bitte an unseren Kundensupport.',
222
223  },
224  "fr": {
225    "menu": "Menu",
226    "name": "Français",
227    "contact_form_input_email": "E-mail ou numéro de téléphone",
228    "contact_form_input_message": "Votre message",
229    "contact_form_input_name": "Nom",
230    "contact_form_send_email": "Envoyer un e-mail",
231    "language": "Langue",
232    "add_download": "télécharger",
233    "bank_account": "Compte bancaire",
234    "nip": "n° TVA",
235    "city": "Ville",
236    "comments": "Commentaires",
237    "from_text": "De",
238    "order_text": "Commandez",
239    "order_no": "Numéro de commande",
240    "regon": "REGON",
241    "street": "Rue",
242    "tel_no": "Numéro de téléphone",
243    "to_text": "À",
244    "visitor_counter_txt": "Visites",
245    "add_entry": "Ajouter une entrée",
246    "author": "Auteur",
247    "sendEntryFailed": "Ajout d\\'entrées dans le livre d\\'or a été désactivé par le propriétaire du site.",
248    "sendEntrySuccess": "Message a été ajouté. Il apparaîtra sur le site après l\\'approbation de l\\'administrateur.",
249    "cookie_box_text": "Nous utilisons des cookies (biscuits) à des fins statistiques et pour faciliter l\\'utilisation de notre site Web.<br />A tout moment, vous pouvez éviter ou de limiter l\\'enregistrement de cookies sur votre appareil en modifiant les paramètres de votre navigateur.",
250    "cookie_box_short_text": "Politique de confidentialité et cookies",
251    "shop_add_to_cart_text": "Ajouter au panier",
252    "shop_back_text": "Arrière",
253    "shop_cart_content_text": "Panier",
254    "shop_close_text": "Proche",
255    "shop_email_text": "Votre adresse e-mail",
256    "shop_empty_cart_text": "Votre panier est vide.",
257    "shop_invalid_email_text": "S\\'il vous plaît entrer une adresse e-mail valide.",
258    "shop_message_text": "Message supplémentaire",
259    "shop_name_text": "Nom",
260    "shop_order_posting_text": "Ordre d\\'affichage",
261    "shop_price_text": "Prix",
262    "shop_quantity_text": "Nombre",
263    "shop_send_message_error_text": "Échec de l\\'envoi de votre commande. Si le problème persiste, contactez le propriétaire de la page.",
264    "shop_send_message_success_text": "Votre commande a été expédiée. En quelques minutes, à l\\'adresse indiquée, vous devriez recevoir une confirmation par e-mail.",
265    "shop_send_order_text": "Envoyer votre commande",
266    "unsupported_audio_info_text": "Vous devez mettre à jour votre navigateur ou installer plugin Flash si vous voulez lire ce fichier.",
267    "unsupported_back_sound_info_text": "Vous devez mettre à jour votre navigateur ou installer plugin Flash si vous voulez jouer son sur le site.",
268    "field_required": "Champ obligatoire!",
269    "invalid_email": "E-mail invalide",
270    "send_fail": "Envoi échoué. Réessayez plus tard dans quelques minutes.<br />Cliquez sur le texte pour masquer ce message.",
271    "send_success": "Merci d'utiliser le formulaire.",
272    "sending": "Envoi en cours ...",
273    "news": "Nouvelles",
274    "see_more": "Voir plus...",
275    "contactUs": "Nous contacter",
276    "siteExpiredTitle": 'Le site Web a expiré!',
277    "siteExpiredMessage": 'Votre site est toujours hébergé sur le serveur mais n\'est pas accessible aux internautes. Pour activer le site Web, veuillez contacter notre service client.',
278
279  },
280  "it": {
281    "menu": "Menù",
282    "name": "Italiano",
283    "contact_form_input_email": "E-mail o numero di telefono",
284    "contact_form_input_message": "Il tuo messaggio",
285    "contact_form_input_name": "Nome",
286    "contact_form_send_email": "Inviare e-mail",
287    "language": "Lingua",
288    "add_download": "download",
289    "bank_account": "Conto bancario",
290    "nip": "P.IVA",
291    "city": "Città",
292    "comments": "Commentaires",
293    "from_text": "Da",
294    "order_text": "Ordine",
295    "order_no": "Numero di ordinazione",
296    "regon": "REGON",
297    "street": "Strada",
298    "tel_no": "Numero telefonico",
299    "to_text": "A",
300    "visitor_counter_txt": "Visite",
301    "add_entry": "Aggiungi ingresso",
302    "author": "Autore",
303    "sendEntryFailed": "Aggiunta di voci al guestbook è stato disattivato dal proprietario del sito.",
304    "sendEntrySuccess": "Messaggio è stato aggiunto. Apparirà sul sito dopo l'approvazione dell'amministratore.",
305    "cookie_box_text": "Utilizziamo i cookie (biscotti) per fini statistici e per facilitare l'uso del nostro sito.<br />In qualsiasi momento, è possibile impedire o limitare la registrazione di cookies sul vostro dispositivo modificando le impostazioni del proprio browser.",
306    "cookie_box_short_text": "Sulla privacy e cookie",
307    "shop_add_to_cart_text": "Aggiungi al carrello",
308    "shop_back_text": "Indietro",
309    "shop_cart_content_text": "Cosa c'è nel carrello",
310    "shop_close_text": "Vicino",
311    "shop_email_text": "Il tuo indirizzo e-mail",
312    "shop_empty_cart_text": "Il carrello è vuoto.",
313    "shop_invalid_email_text": "Si prega di inserire un indirizzo e-mail valido.",
314    "shop_message_text": "Messaggio aggiuntivo",
315    "shop_name_text": "Nome",
316    "shop_order_posting_text": "Distacco ordine",
317    "shop_price_text": "Prezzo",
318    "shop_quantity_text": "Numero",
319    "shop_send_message_error_text": "Impossibile inviare il vostro ordine. Se il problema persiste contattare il proprietario della pagina.",
320    "shop_send_message_success_text": "Il tuo ordine è stato spedito. In pochi minuti, all'indirizzo indicato in, si dovrebbe ricevere una mail di conferma.",
321    "shop_send_order_text": "Invia il tuo ordine",
322    "unsupported_audio_info_text": "È necessario aggiornare il browser o installare plugin di Flash, se si desidera riprodurre il file.",
323    "unsupported_back_sound_info_text": "È necessario aggiornare il browser o installare Flash plugin se si vuole riprodurre l'audio sul sito.",
324    "field_required": "Campo richiesto!",
325    "invalid_email": "E-mail valido",
326    "send_fail": "Invio non riuscito. Riprovare più tardi in pochi minuti.<br />Clicca sul testo per nascondere questo messaggio.",
327    "send_success": "Grazie per avere utilizzato il modulo.",
328    "sending": "Invio...",
329    "news": "Notizia",
330    "see_more": "Vedi altro...",
331    "contactUs": "Contattaci",
332    "siteExpiredTitle": 'Sito web scaduto!',
333    "siteExpiredMessage": 'Il tuo sito web è ancora ospitato sul server ma non è accessibile agli internauti. Per attivare il sito web, contatta il nostro 
333servizio clienti.',
334  },
335  "es": {
336    "menu": "Menú",
337    "name": "Español",
338    "contact_form_input_email": "E-mail o número de teléfono",
339    "contact_form_input_message": "Tu mensaje",
340    "contact_form_input_name": "Nombre",
341    "contact_form_send_email": "Enviar mensaje",
342    "language": "Idioma",
343    "add_download": "descarga",
344    "bank_account": "Cuenta bancaria",
345    "nip": "NIF",
346    "city": "Ciudad",
347    "comments": "Comentarios",
348    "from_text": "Desde",
349    "order_text": "Orden",
350    "order_no": "Número de pedido",
351    "regon": "REGON",
352    "street": "Calle",
353    "tel_no": "Número de teléfono",
354    "to_text": "Hasta",
355    "visitor_counter_txt": "Visitas",
356    "add_entry": "Añadir entrada",
357    "author": "Autor",
358    "sendEntryFailed": "Agregar entradas para el libro de visitas ha sido desactivado por el propietario del sitio.",
359    "sendEntrySuccess": "Respuesta ha sido añadido. Aparecerá en el sitio después de la aprobación del administrador.",
360    "cookie_box_text": "Utilizamos cookies (galletas) para fines estadísticos y para facilitar el uso de nuestro sitio web.<br />En cualquier momento, usted puede prevenir o limitar la grabación de cookies en su dispositivo al cambiar la configuración de su navegador.",
361    "cookie_box_short_text": "Política de Privacidad y Cookies",
362    "shop_add_to_cart_text": "Añadir a la cesta",
363    "shop_back_text": "Espalda",
364    "shop_cart_content_text": "Cesta",
365    "shop_close_text": "Cerca",
366    "shop_email_text": "Su dirección de correo electrónico",
367    "shop_empty_cart_text": "Su carro está vacío.",
368    "shop_invalid_email_text": "Por favor, introduce una dirección de correo electrónico válida.",
369    "shop_message_text": "Mensaje adicional",
370    "shop_name_text": "Nombre",
371    "shop_order_posting_text": "Orden de publicación",
372    "shop_price_text": "Precio",
373    "shop_quantity_text": "Número",
374    "shop_send_message_error_text": "Error al enviar su solicitud. Si el problema persiste, póngase en contacto con el propietario de la página.",
375    "shop_send_message_success_text": "Su pedido ha sido enviado. A los pocos minutos, a la dirección indicada en el, usted debe recibir una confirmación por correo electrónico.",
376    "shop_send_order_text": "Envíe su pedido",
377    "unsupported_audio_info_text": "Usted tiene que actualice su navegador o instalar el plugin de Flash, si quieres jugar a este archivo.",
378    "unsupported_back_sound_info_text": "Usted tiene que actualice su navegador o instalar Flash plugin si desea reproducir el sonido en el sitio.",
379    "field_required": "Campo requerido!",
380    "invalid_email": "No válida de correo electrónico",
381    "send_fail": "Error al enviar. Inténtelo de nuevo más tarde en unos minutos.<br />Haga clic en el texto para ocultar este mensaje.",
382    "send_success": "Gracias por utilizar el formulario.",
383    "sending": "Enviando...",
384    "news": "Noticias",
385    "see_more": "Ver más...",
386    "contactUs": "Contáctenos",
387    "siteExpiredTitle": '¡Sitio web caducado!',
388    "siteExpiredMessage": 'Su sitio web todavía está alojado en el servidor pero no es accesible para los internautas. Para activar el sitio web, póngase en contacto con nuestro servicio de atención al cliente.',
389  },
390  "nl": {
391    "menu": "Menu",
392    "name": "Nederlands",
393    "contact_form_input_email": "E-mail of telefoonnummer",
394    "contact_form_input_message": "Bericht",
395    "contact_form_input_name": "Volledige naam",
396    "contact_form_send_email": "Stuur een e-mail",
397    "language": "Taal",
398    "add_download": "download",
399    "bank_account": "Bankrekening",
400    "nip": "BTW",
401    "city": "Stad",
402    "comments": "Reacties",
403    "from_text": "Van",
404    "order_text": "Bestel",
405    "order_no": "Bestelnummer",
406    "regon": "REGON",
407    "street": "Straat",
408    "tel_no": "Telefoonnummer",
409    "to_text": "Tot",
410    "visitor_counter_txt": "Bezoeken",
411    "add_entry": "Vermelding toevoegen",
412    "author": "Auteur",
413    "sendEntryFailed": "Het toevoegen van inzendingen voor de gastenboek is uitgeschakeld door de site-eigenaar.",
414    "sendEntrySuccess": "Bericht is toegevoegd. Het zal verschijnen op de site na goedkeuring beheerder.",
415    "cookie_box_text": "Wij gebruiken cookies (koekjes) ​​voor statistische doeleinden en om het gebruik van onze website te vergemakkelijken.<br />Op elk moment kunt u voorkomen of beperken opname van cookies op uw apparaat door het veranderen van de instellingen van uw browser.",
416    "cookie_box_short_text": "Privacybeleid en Cookies",
417    "shop_add_to_cart_text": "Bestellen",
418    "shop_back_text": "Terug",
419    "shop_cart_content_text": "Inhoud winkelwagen",
420    "shop_close_text": "Dicht",
421    "shop_email_text": "Uw e-mailadres",
422    "shop_empty_cart_text": "Uw winkelwagen is nog leeg.",
423    "shop_invalid_email_text": "Vul een geldig e-mail adres.",
424    "shop_message_text": "Extra bericht",
425    "shop_name_text": "Naam",
426    "shop_order_posting_text": "Posting Bestel",
427    "shop_price_text": "Prijs",
428    "shop_quantity_text": "Aantal",
429    "shop_send_message_error_text": "Mislukt om uw bestelling te verzenden. Als het probleem zich blijft voordoen contact op met de eigenaar van de pagina.",
430    "shop_send_message_success_text": "Uw bestelling is verzonden. Binnen een paar minuten, op het adres vermeld in, moet je een e-mail een bevestiging.",
431    "shop_send_order_text": "Stuur uw bestelling",
432    "unsupported_audio_info_text": "Je moet je browser te updaten of te installeren Flash plugin als je dit bestand wilt spelen.",
433    "unsupported_back_sound_info_text": "Je moet je browser te updaten of te installeren Flash plugin als je geluid wilt afspelen op de site.",
434    "field_required": "Veld vereist!",
435    "invalid_email": "Ongeldig e-mail",
436    "send_fail": "Het verzenden is mislukt. Probeer het later opnieuw in een paar minuten.<br />Klik op de tekst om deze boodschap te verbergen.",
437    "send_success": "Bedankt voor het gebruik van het formulier.",
438    "sending": "Verzenden...",
439    "news": "Nieuws",
440    "see_more": "Bekijk meer...",
441    "contactUs": "Neem contact op",
442    "siteExpiredTitle": 'Website verlopen!',
443    "siteExpiredMessage": 'Uw website wordt nog steeds op de server gehost, maar is niet toegankelijk voor internauts. Neem contact op met onze klantenservice om de website te activeren.',
444  },
445  "gr": {
446    "menu": "μενού",
447    "name": "Ελληνικά",
448    "contact_form_input_email": "Αποστολή ή τον αριθμό τηλεφώνου",
449    "contact_form_input_message": "Μήνυμα",
450    "contact_form_input_name": "Πλήρες όνομα",
451    "contact_form_send_email": "στείλετε e-mail",
452    "language": "Γλώσσα",
453    "add_download": "download",
454    "bank_account": "Τραπεζικός λογαριασμός",
455    "nip": "ΑΦΜ",
456    "city": "Πόλη",
457    "comments": "Σχόλια",
458    "from_text": "Από",
459    "order_text": "Παραγγελία",
460    "order_no": "Αύξων αριθμός",
461    "regon": "REGON",
462    "street": "Οδός",
463    "tel_no": "Τηλέφωνο επικοινωνίας",
464    "to_text": "μέχρι",
465    "visitor_counter_txt": "Επισκέψεις",
466    "add_entry": "Προσθήκη καταχώρησης",
467    "author": "Συντάκτης",
468    "sendEntryFailed": "Προσθέτοντας καταχωρήσεις στο βιβλίο επισκεπτών έχει απενεργοποιηθεί από τον κάτοχο της τοποθεσίας.",
469    "sendEntrySuccess": "Δημοσίευση έχει προστεθεί. Θα εμφανιστεί στην περιοχή μετά την έγκριση του διαχειριστή.",
470    "cookie_box_text": "Χρησιμοποιούμε cookies (μπισκότα) για στατιστικούς σκοπούς και για να διευκολυνθεί η χρήση της ιστοσελίδας μας.<br />Σε οποιαδήποτε στιγμή, μπορείτε να εμποδίσουν ή να περιορίσουν την καταγραφή των cookies για τη συσκευή σας αλλάζοντας τις ρυθμίσεις στον browser σας.",
471    "cookie_box_short_text": "Πολιτική Προστασίας Προσωπικών Δεδομένων και Cookies",
472    "shop_add_to_cart_text": "Προσθήκη στο καλάθι",
473    "shop_back_text": "Πίσω",
474    "shop_cart_content_text": "Περιεχόμενα Καλαθιού",
475    "shop_close_text": "Κοντά",
476    "shop_email_text": "Διεύθυνση e-mail σας",
477    "shop_empty_cart_text": "Το καλάθι σας είναι άδειο.",
478    "shop_invalid_email_text": "Παρακαλώ εισάγετε μια έγκυρη διεύθυνση e-mail.",
479    "shop_message_text": "Πρόσθετες μήνυμα",
480    "shop_name_text": "Ονομα",
481    "shop_order_posting_text": "Απόσπαση Παραγγελία",
482    "shop_price_text": "Τιμή",
483    "shop_quantity_text": "Αριθμός",
484    "shop_send_message_error_text": "Απέτυχε η αποστολή της παραγγελίας σας. Εάν το πρόβλημα επιμένει, επικοινωνήστε με τον ιδιοκτήτη της σελίδας.",
485    "shop_send_message_success_text": "Η παραγγελία σας έχει αποσταλεί. Μέσα σε λίγα λεπτά, στη διεύθυνση που αναφέρεται στο, θα λάβετε ένα e-mail επιβεβαίωσης.",
486    "shop_send_order_text": "Στείλτε την παραγγελία σας",
487    "unsupported_audio_info_text": "Θα πρέπει να ενημερώσετε το πρόγραμμα περιήγησής σας ή να εγκαταστήσετε το Flash plugin, αν θέλετε να παίξετε αυτό το αρχείο.",
488    "unsupported_back_sound_info_text": "Θα πρέπει να ενημερώσετε το πρόγραμμα περιήγησής σας ή να εγκαταστήσετε το Flash plugin, αν θέλετε να παίξετε ήχο στην ιστοσελίδα.",
489    "field_required": "Πεδίο που απαιτείται!",
490    "invalid_email": "Μη έγκυρο e-mail",
491    "send_fail": "Η αποστολή απέτυχε. Δοκιμάστε ξανά αργότερα μέσα σε λίγα λεπτά.<br />Κάντε κλικ στο κείμενο για να κρύψει αυτό το μήνυμα.",
492    "send_success": "Σας ευχαριστούμε που χρησιμοποιείτε την φόρμα.",
493    "sending": "Η αποστολή...",
494    "news": "Νέα",
495    "see_more": "Δείτε περισσότερα...",
496    "contactUs": "Επικοινωνήστε μαζί μας",
497    "siteExpiredTitle": 'Ο ιστότοπος έληξε!',
498    "siteExpiredMessage": 'Ο ιστότοπός σας εξακολουθεί να φιλοξενείται σε διακομιστή, αλλά δεν είναι προσβάσιμος σε εσωτερικούς συνεργάτες. Για να ενεργοποιήσετε τον ιστότοπο επικοινωνήστε με την υποστήριξη πελατών μας.',
499  },
500  "ru": {
501    "menu": "меню",
502    "name": "Русский",
503    "contact_form_input_email": "Электронной почты или номер телефона",
504    "contact_form_input_message": "Сообщение",
505    "contact_form_input_name": "Имя Фамилия",
506    "contact_form_send_email": "oтправить сообщение",
507    "language": "Язык",
508    "add_download": "cкачать",
509    "bank_account": "Банковский счет",
510    "nip": "ИНН",
511    "city": "Город",
512    "comments": "Комментарии",
513    "from_text": "От",
514    "order_text": "Закажи",
515    "order_no": "Номер заказа",
516    "regon": "REGON",
517    "street": "Улица",
518    "tel_no": "Номер телефона",
519    "to_text": "До",
520    "visitor_counter_txt": "Просмотров",
521    "add_entry": "Добавить запись",
522    "author": "Aвтор",
523    "sendEntryFailed": "Добавление записей в гостевую книгу было заблокировано владельцем сайта.",
524    "sendEntrySuccess": "Сообщение было добавлено. Оно появится на сайте после одобрения администратора.",
525    "cookie_box_text": "Мы используем cookies для статистики, чтоб облегчить пользование нашим порталом.<br />В любой момент Вы сможете заблокировать или ограничить записывание файлов cookies на Вашем устройстве путем изменения настроек браузера.",
526    "cookie_box_short_text": "политика конфиденциальности и файлы Cookies",
527    "shop_add_to_cart_text": "Добавь в корзину",
528    "shop_back_text": "Назад",
529    "shop_cart_content_text": "Содержимое корзины",
530    "shop_close_text": "Закрой",
531    "shop_email_text": "Твой адрес e-mail",
532    "shop_empty_cart_text": "Твоя корзина пуста.",
533    "shop_invalid_email_text": "Впиши правильный адрес e-mail.",
534    "shop_message_text": "Дополнительное сообщение",
535    "shop_name_text": "Название",
536    "shop_order_posting_text": "Высылка заказа",
537    "shop_price_text": "Цена",
538    "shop_quantity_text": "Количество",
539    "shop_send_message_error_text": "Не удалось выслать заказ. Если проблема появится опять свяжись с владельцем страницы.",
540    "shop_send_message_success_text": "Твой заказ выслан. В течении нескольких минут, на указанный адрес, Вы должны получишь подтверждение.",
541    "shop_send_order_text": "Вышли заказ",
542    "unsupported_audio_info_text": "Чтобы воспроизвести этот файл нужно обновить браузер до последней версии или установить Flash Player.",
543    "unsupported_back_sound_info_text": "Для прослушивания этого файла нужно обновить браузер до последней версии или установить Flash Player.",
544    "field_required": "Обязательное поле!",
545    "invalid_email": "Неправильный e-mail",
546    "send_fail": "Не удалось выслать сообщения. Попробуйте еще раз через несколько минут.<br />Нажмите, чтобы скрыть текст сообщения.",
547    "send_success": "Спасибо за использование формуляра.",
548    "sending": "Отправка...",
549    "news": "Новости",
550    "see_more": "Узнать больше...",
551    "contactUs": "Связаться с нами",
552    "siteExpiredTitle": 'Срок действия сайта истек!',
553    "siteExpiredMessage": 'Ваш веб-сайт по-прежнему размещен на сервере, но недоступен для международных пользователей. Для активации сайта обратитесь в нашу службу поддержки.',
554  },
555  "dk": {
556    "menu": "Menu",
557    "name": "Dansk",
558    "contact_form_input_email": "E-mail eller telefonnummer",
559    "contact_form_input_message": "Meddelelsesteksten",
560    "contact_form_input_name": "Navn",
561    "contact_form_send_email": "Send e-mail",
562    "language": "Sprog",
563    "add_download": "download",
564    "bank_account": "Bank account",
565    "nip": "CVR",
566    "city": "Stad",
567    "comments": "Kommentarer",
568    "from_text": "Fra",
569    "order_text": "Bestil",
570    "order_no": "Løbenummer",
571    "regon": "REGON",
572    "street": "Gaden",
573    "tel_no": "Telefonnummer",
574    "to_text": "Til",
575    "visitor_counter_txt": "Besøg",
576    "add_entry": "Tilføj post",
577    "author": "Forfatter",
578    "sendEntryFailed": "Tilføjelse af indgange til gæstebogen er blevet deaktiveret af ejeren af ​​webstedet.",
579    "sendEntrySuccess": "Indlæg er blevet tilføjet. Det vil blive vist på sitet efter administratorens godkendelse.",
580    "cookie_box_text": "Vi bruger cookies (kiks) til statistiske formål og for at lette brugen af ​​vores hjemmeside.<br />På ethvert tidspunkt kan du forhindre eller begrænse optagelsen af cookies på din enhed ved at ændre indstillingerne i din browser.",
581    "cookie_box_short_text": "Privatlivspolitik og cookies",
582    "shop_add_to_cart_text": "Tilføj til indkøbskurv",
583    "shop_back_text": "Tilbage",
584    "shop_cart_content_text": "Indkøbskurv",
585    "shop_close_text": "Luk",
586    "shop_email_text": "Din e-mail-adresse",
587    "shop_empty_cart_text": "Din indkøbskurv er tom.",
588    "shop_invalid_email_text": "Angiv en gyldig e-mail-adresse.",
589    "shop_message_text": "Ekstra besked",
590    "shop_name_text": "Navn",
591    "shop_order_posting_text": "Udstationering Order",
592    "shop_price_text": "Pris",
593    "shop_quantity_text": "Nummer",
594    "shop_send_message_error_text": "Kunne ikke sende din bestilling. Hvis problemet fortsætter kontakte ejeren af ​​siden.",
595    "shop_send_message_success_text": "Din ordre er blevet afsendt. Inden for et par minutter, på adressen i, bør du modtage en bekræftelse via e-mail.",
596    "shop_send_order_text": "Send din bestilling",
597    "unsupported_audio_info_text": "Du er nødt til at opdatere din browser eller installer Flash-plugin, hvis du ønsker at afspille denne fil.",
598    "unsupported_back_sound_info_text": "Du er nødt til at opdatere din browser eller installer Flash-plugin, hvis du vil afspille lyd på webstedet.",
599    "field_required": "Felt påkrævet!",
600    "invalid_email": "Ugyldig e-mail",
601    "send_fail": "Afsendelsen mislykkedes. Prøv igen senere i et par minutter.<br />Klik på tekst for at skjule denne meddelelse.",
602    "send_success": "Tak fordi du bruger formularen.",
603    "sending": "Sender...",
604    "news": "Nyheder",
605    "see_more": "Se mere...",
606    "contactUs": "Kontakt os",
607    "siteExpiredTitle": 'Hjemmesiden er udløbet!',
608    "siteExpiredMessage": 'Dit websted er stadig hostet på serveren, men er ikke tilgængeligt for internauts. For at aktivere hjemmesiden bedes du kontakte vores kundesupport.',
609
610  },
611  "no": {
612    "menu": "Meny",
613    "name": "Norsk",
614    "contact_form_input_email": "E-post eller telefon nummer",
615    "contact_form_input_message": "Din melding",
616    "contact_form_input_name": "Navn",
617    "contact_form_send_email": "Send e-post",
618    "language": "Språk",
619    "add_download": "nedlasting",
620    "bank_account": "Bankkonto",
621    "nip": "MVA",
622    "city": "Byen",
623    "comments": "Kommentarer",
624    "from_text": "Fra",
625    "order_text": "Bestill",
626    "order_no": "Bestillingsnummer",
627    "regon": "REGON",
628    "street": "Gatenavnet",
629    "tel_no": "Telefonnummer",
630    "to_text": "Til",
631    "visitor_counter_txt": "Besøk",
632    "add_entry": "Legg til oppføring",
633    "author": "Forfatter",
634    "sendEntryFailed": "Legge til oppføringer i gjesteboka har blitt deaktivert av eieren av nettstedet.",
635    "sendEntrySuccess": "Innlegg har blitt lagt til. Den vil vises på nettstedet etter administrator godkjenning.",
636    "cookie_box_text": "Vi bruker informasjonskapsler (kjeks) for statistiske formål og for å legge til rette for bruk av nettstedet vårt.<br />Til enhver tid, kan du forhindre eller begrense opptak av cookies på din enhet ved å endre innstillingene i nettleseren din.",
637    "cookie_box_short_text": "Personvern og Cookies",
638    "shop_add_to_cart_text": "Legg til kurv",
639    "shop_back_text": "Tilbake",
640    "shop_cart_content_text": "Handlevogn",
641    "shop_close_text": "Lukk",
642    "shop_email_text": "Din e-post adresse",
643    "shop_empty_cart_text": "Handlekurven er tom.",
644    "shop_invalid_email_text": "Vennligst skriv inn en gyldig e-postadresse.",
645    "shop_message_text": "Tilleggs melding",
646    "shop_name_text": "Navn",
647    "shop_order_posting_text": "Publisering Bestill",
648    "shop_price_text": "Pris",
649    "shop_quantity_text": "Antall",
650    "shop_send_message_error_text": "Klarte ikke å sende bestillingen. Hvis problemet vedvarer kontakt eieren av siden.",
651    "shop_send_message_success_text": "Bestillingen er sendt. Innen noen få minutter, på adressen som er oppgitt i, skal du motta en e-postbekreftelse.",
652    "shop_send_order_text": "Send din bestilling",
653    "unsupported_audio_info_text": "Du må oppdatere nettleseren eller installere Flash plugin hvis du ønsker å spille av denne filen.",
654    "unsupported_back_sound_info_text": "Du må oppdatere nettleseren eller installere Flash plugin hvis du ønsker å spille av lyd på nettstedet.",
655    "field_required": "Feltet er nødvendig!",
656    "invalid_email": "Ugyldig e-post",
657    "send_fail": "Sendingen mislyktes. Prøv igjen senere i løpet av få minutter.<br />Klikk på teksten for å skjule denne meldingen.",
658    "send_success": "Takk for at du ved hjelp av skjemaet.",
659    "sending": "Sender...",
660    "news": "Nyheter",
661    "see_more": "Se mer...",
662    "contactUs": "Kontakt oss",
663    "siteExpiredTitle": 'Nettstedet er utløpt!',
664    "siteExpiredMessage": 'Nettstedet ditt er fortsatt vert på serveren, men er ikke tilgjengelig for internauts. For å aktivere nettstedet, ta kontakt med vår kundesupport.',
665  },
666  "cz": {
667    "menu": "Menu",
668    "name": "Česky",
669    "contact_form_input_email": "E-mail nebo telefon",
670    "contact_form_input_message": "Vaše zpráva",
671    "contact_form_input_name": "Jméno a příjmení",
672    "contact_form_send_email": "Poslat e-mailem",
673    "language": "Jazyk",
674    "add_download": "ke stažení",
675    "bank_account": "Číslo účtu",
676    "nip": "DIČ",
677    "city": "Město",
678    "comments": "Poznámky",
679    "from_text": "Od",
680    "order_text": "Objednat",
681    "order_no": "Objednávka číslo",
682    "regon": "IČO",
683    "street": "Ulice",
684    "tel_no": "Telefonní číslo",
685    "to_text": "Do",
686    "visitor_counter_txt": "Návštěv",
687    "add_entry": "Přidat položku",
688    "author": "Autor",
689    "sendEntryFailed": "Přidávání položek do knihy hostů bylo blokováno vlastníkem webu.",
690    "sendEntrySuccess": "Příspěvek byl přidán. Objeví se na stránce po schválení administrátorem.",
691    "cookie_box_text": "Používáme soubory cookies pro statistické účely, a také abychom vám ulehčili používání našeho servisu.<br />V každé chvíli můžete zablokovat nebo omezit zapisování souborů cookies na vašem zařízení, pokud změníte nastavení vašeho internetového prohlížeče.",
692    "cookie_box_short_text": "Politika ochrany soukromí a souborů cookies",
693    "shop_add_to_cart_text": "Přidat do košíku",
694    "shop_back_text": "Zpět",
695    "shop_cart_content_text": "Obsah košíku",
696    "shop_close_text": "Zavřít",
697    "shop_email_text": "Vaše e-mailová adresa",
698    "shop_empty_cart_text": "Váš košík je prázdný.",
699    "shop_invalid_email_text": "Zadejte prosím platnou e-mailovou adresu.",
700    "shop_message_text": "Doplňující zpráva",
701    "shop_name_text": "Název",
702    "shop_order_posting_text": "Posílání objednávky",
703    "shop_price_text": "Cena",
704    "shop_quantity_text": "Počet",
705    "shop_send_message_error_text": "Nepodařilo se odeslat Vaši objednávku. Pokud problem zase nastane, kontaktujte majitele stránky.",
706    "shop_send_message_success_text": "Vaše objednávka byla odeslána. Během několika minut, na uvedenou adresu, měli byste obdržet potvrzení e-mailem.",
707    "shop_send_order_text": "Poslat objednávku",
708    "unsupported_audio_info_text": "Chcete-li otevřit tento soubor, musíte aktualizovat svůj prohlížeč na nejnovější verzi nebo si nainstalovat Flash plugin.",
709    "unsupported_back_sound_info_text": "Chcete-li přehrávat zvuk na webových stránkách, musíte aktualizovat svůj prohlížeč na nejnovější verzi nebo si nainstalovat Flash plugin.",
710    "field_required": "Povinná pole!",
711    "invalid_email": "Nesprávná adresa e-mail",
712    "send_fail": "Zpráva nebyla úspěšně odeslána. Zkuste akci zopakovat později.<br />Klepněte na text, aby skrýt zprávu.",
713    "send_success": "Děkujeme za použítí formuláře.",
714    "sending": "Odesílání...",
715    "news": "Zprávy",
716    "see_more": "Vidět víc...",
717    "contactUs": "Kontaktujte nás",
718    "siteExpiredTitle": 'Platnost webových stránek vypršela!',
719    "siteExpiredMessage": 'Váš web je stále hostován na serveru, ale není přístupný pro internauty. Chcete-li aktivovat web, kontaktujte naši zákaznickou podporu.',
720  },
721  "sk": {
722    "menu": "Meni",
723    "name": "Slovenčina",
724    "contact_form_input_email": "E-mail alebo telefónne číslo",
725    "contact_form_input_message": "Vaša správa",
726    "contact_form_input_name": "Meno",
727    "contact_form_send_email": "Poslať e-mailom",
728    "language": "Jazyk",
729    "add_download": "na stiahnutie",
730    "bank_account": "Číslo účtu",
731    "nip": "IČ DPH",
732    "city": "Mesto",
733    "comments": "Komentáre",
734    "from_text": "Od",
735    "order_text": "Objednat",
736    "order_no": "Objednávacie číslo",
737    "regon": "IČO",
738    "street": "Ulica",
739    "tel_no": "Telefónne číslo",
740    "to_text": "Do",
741    "visitor_counter_txt": "Návštevy",
742    "add_entry": "Pridať položku",
743    "author": "Autor",
744    "sendEntryFailed": "Pridávanie položiek do návštevnej knihy bolo zakázané vlastníkom webu.",
745    "sendEntrySuccess": "Príspevok bol pridaný. Objaví sa na stránkach po schválení administrátorom.",
746    "cookie_box_text": "Používame cookies (sušienky), pre štatistické účely a uľahčiť používanie našich webových stránok.<br />Kedykoľvek môžete zabrániť alebo obmedziť záznam cookies na vašom zariadení so zmenou nastavenia vo svojom prehliadači.",
747    "cookie_box_short_text": "Ochrana osobných údajov a súbory cookie",
748    "shop_add_to_cart_text": "Pridať do košíka",
749    "shop_back_text": "Staré",
750    "shop_cart_content_text": "Obsah košíka",
751    "shop_close_text": "Zavrieť",
752    "shop_email_text": "Vaša e-mailová adresa",
753    "shop_empty_cart_text": "Váš nákupný košík je prázdny.",
754    "shop_invalid_email_text": "Zadajte prosím platnú e-mailovú adresu.",
755    "shop_message_text": "Ďalšie správy",
756    "shop_name_text": "Názov",
757    "shop_order_posting_text": "Vysielanie Objednať",
758    "shop_price_text": "Cena",
759    "shop_quantity_text": "Číslo",
760    "shop_send_message_error_text": "Nepodarilo sa odoslať vašu objednávku. Ak problém pretrváva, obráťte sa na vlastníka stránky.",
761    "shop_send_message_success_text": "Vaša objednávka bola odoslaný. Počas niekoľkých minút, na adresu uvedenú v, mali by ste dostať potvrdenie e-mailom.",
762    "shop_send_order_text": "Poslať objednávku",
763    "unsupported_audio_info_text": "Musíte aktualizovať svoj ​​prehliadač alebo nainštalujte Flash plugin, ak chcete hrať tento súbor.",
764    "unsupported_back_sound_info_text": "Musíte aktualizovať svoj ​​prehliadač alebo nainštalujte Flash plugin, ak chcete prehrávať zvuk na mieste.",
765    "field_required": "Pole povinné!",
766    "invalid_email": "Chybná e-mail",
767    "send_fail": "Odoslanie zlyhalo. Skúste to znova neskôr počas niekoľkých minút. <br /> Kliknite na texte skryť túto správu.",
768    "send_success": "Ďakujeme, že používate formuláre.",
769    "sending": "Odosielanie...",
770    "news": "Novice",
771    "see_more": "Poglej več...",
772    "contactUs": "Kontaktuj nás",
773    "siteExpiredTitle": 'Platnosť webovej stránky vypršala!',
774    "siteExpiredMessage": 'Váš web je stále hostený na serveri, ale nie je prístupný pre internautov. Ak chcete aktivovať webovú stránku, kontaktujte našu zákaznícku podporu.',
775  },
776  "hu": {
777    "menu": "Menü",
778    "name": "Magyar",
779    "contact_form_input_email": "E-mail vagy telefonszám",
780    "contact_form_input_message": "Üzenet",
781    "contact_form_input_name": "Név",
782    "contact_form_send_email": "küldés e-mail",
783    "language": "Nyelv",
784    "add_download": "letöltés",
785    "bank_account": "Bankszámla",
786    "nip": "Közösségi adószám",
787    "city": "Város",
788    "comments": "Hozzászólások",
789    "from_text": "-Tól",
790    "order_text": "Rendelés",
791    "order_no": "Rendelési száma",
792    "regon": "REGON",
793    "street": "Utca",
794    "tel_no": "Telefonszám",
795    "to_text": "A",
796    "visitor_counter_txt": "Látogatók",
797    "add_entry": "Kosárba bejegyzés",
798    "author": "Szerző",
799    "sendEntryFailed": "Adatok beírása a vendégkönyvbe le van tiltva az oldal tulajdonosa.",
800    "sendEntrySuccess": "Hozzászólás került. Ez jelenik meg a helyszínen után adminisztrátori jóváhagyásra.",
801    "cookie_box_text": "A cookie-k (kekszek) statisztikai célokra, és segítsék elő a honlapunkon.<br />Bármikor, akkor megakadályozza vagy korlátozza felvétel cookie-kat a készülék a beállítások megváltoztatása a böngészőben.",
802    "cookie_box_short_text": "Adatvédelem és cookie-k",
803    "shop_add_to_cart_text": "Kosárba",
804    "shop_back_text": "Vissza",
805    "shop_cart_content_text": "Kosár tartalma",
806    "shop_close_text": "Szorosan",
807    "shop_email_text": "Az Ön e-mail címe",
808    "shop_empty_cart_text": "Az Ön kosara üres.",
809    "shop_invalid_email_text": "Adjon meg egy érvényes e-mail címét.",
810    "shop_message_text": "További üzenet",
811    "shop_name_text": "Név",
812    "shop_order_posting_text": "Hozzászólási rendelés",
813    "shop_price_text": "Ár",
814    "shop_quantity_text": "Szám",
815    "shop_send_message_error_text": "Nem sikerült elküldeni a megrendelést. Ha a probléma továbbra is fennáll, lépjen kapcsolatba a tulajdonossal az oldal.",
816    "shop_send_message_success_text": "Az, hogy szállításkor. Néhány percen belül, a megadott címre, akkor kap egy e-mail visszaigazolást.",
817    "shop_send_order_text": "Küldjön egy rendelés",
818    "unsupported_audio_info_text": "Meg kell frissíteni a böngésző vagy a Flash plugint, ha akarsz játszani ezt a fájlt.",
819    "unsupported_back_sound_info_text": "Meg kell frissíteni a böngésző vagy a Flash plugint, ha akarsz játszani hangot az oldalon.",
820    "field_required": "Helytelenül szükséges!",
821    "invalid_email": "Érvénytelen e-mail",
822    "send_fail": "Küldés nem sikerült. Próbálja újra később néhány perc. <br /> Kattints a szöveget, hogy elrejtse ezt az üzenetet.",
823    "send_success": "Köszönjük, hogy a formanyomtatványon.",
824    "sending": "Küldés...",
825    "news": "Hírek",
826    "see_more": "Többet látni...",
827    "contactUs": "Lépjen kapcsolatba velünk",
828    "siteExpiredTitle": 'A webhely lejárt!',
829    "siteExpiredMessage": 'Webhelyed továbbra is a szerveren van tárolva, de az internautok számára nem érhető el. A weboldal aktiválásához vegye fel a kapcsolatot ügyfélszolgálatunkkal.',
830  },
831  "pt": {
832    "menu": "Menu",
833    "name": "Português",
834    "contact_form_input_email": "E-mail ou número de telefone",
835    "contact_form_input_message": "Sua mensagem",
836    "contact_form_input_name": "Nome",
837    "contact_form_send_email": "Enviar e-mail",
838    "language": "Idioma",
839    "add_download": "baixar",
840    "bank_account": "Conta bancária",
841    "nip": "NIF",
842    "city": "Cidade",
843    "comments": "Comentários",
844    "from_text": "De",
845    "order_text": "Ordem",
846    "order_no": "Número de ordem",
847    "regon": "REGON",
848    "street": "Rua",
849    "tel_no": "Número de telefone",
850    "to_text": "Para",
851    "visitor_counter_txt": "Visitas",
852    "add_entry": "Adicionar entrada",
853    "author": "Autor",
854    "sendEntryFailed": "Adicionar entradas para o mesmo foi desativado pelo proprietário do site.",
855    "sendEntrySuccess": "Mensagem foi adicionado. Ele aparecerá no site após aprovação do administrador.",
856    "cookie_box_text": "Nós usamos cookies (biscoitos) para fins estatísticos e para facilitar o uso do nosso site.<br />A qualquer momento, você pode prevenir ou limitar a gravação de cookies no seu dispositivo alterando as configurações do seu navegador.",
857    "cookie_box_short_text": "Nova Política de Privacidade e Cookies",
858    "shop_add_to_cart_text": "Adicionar ao carrinho",
859    "shop_back_text": "Voltar",
860    "shop_cart_content_text": "Compras",
861    "shop_close_text": "Perto",
862    "shop_email_text": "O seu endereço de e-mail",
863    "shop_empty_cart_text": "O carrinho está vazio.",
864    "shop_invalid_email_text": "Por favor insira um endereço de e-mail válido.",
865    "shop_message_text": "Mensagem adicional",
866    "shop_name_text": "Nome",
867    "shop_order_posting_text": "Postando order",
868    "shop_price_text": "Preço",
869    "shop_quantity_text": "Número",
870    "shop_send_message_error_text": "Não foi possível enviar a sua encomenda. Se o problema persistir entre em contato com o proprietário da página.",
871    "shop_send_message_success_text": "O seu pedido foi enviado. Dentro de alguns minutos, no endereço fornecido, você deve receber uma confirmação por e-mail.",
872    "shop_send_order_text": "Envie o seu pedido",
873    "unsupported_audio_info_text": "Você tem que atualizar seu navegador ou instalar o plugin do Flash, se você quiser jogar este arquivo.",
874    "unsupported_back_sound_info_text": "Você tem que atualizar seu navegador ou instalar o plugin do Flash, se você quiser reproduzir o som no site.",
875    "field_required": "Campo Obrigatório!",
876    "invalid_email": "E-mail inválido",
877    "send_fail": "O envio falhou. Tente novamente mais tarde, em poucos minutos.<br />Clique no texto para ocultar esta mensagem.",
878    "send_success": "Obrigado por usar o formulário.",
879    "sending": "Enviando...",
880    "news": "Notícia",
881    "see_more": "Ver mais...",
882    "contactUs": "Contate-Nos",
883    "siteExpiredTitle": 'O site expirou!',
884    "siteExpiredMessage": 'Seu site ainda está hospedado no servidor, mas não está acessível aos internautas. Para ativar o site, entre em contato com nosso suporte ao cliente.',
885  },
886  "br": {
887    "menu": "Menu",
888    "name": "Brasil",
889    "contact_form_input_email": "E-mail ou número de telefone",
890    "contact_form_input_message": "Sua mensagem",
891    "contact_form_input_name": "Nome",
892    "contact_form_send_email": "Enviar e-mail",
893    "language": "Idioma",
894    "add_download": "baixar",
895    "bank_account": "Conta bancária",
896    "nip": "CNPJ",
897    "city": "Cidade",
898    "comments": "Comentários",
899    "from_text": "De",
900    "order_text": "Ordem",
901    "order_no": "Número de ordem",
902    "regon": "REGON",
903    "street": "Rua",
904    "tel_no": "Número de telefone",
905    "to_text": "Para",
906    "visitor_counter_txt": "Visitas",
907    "add_entry": "Adicionar entrada",
908    "author": "Autor",
909    "sendEntryFailed": "Adicionar entradas para o mesmo foi desativado pelo proprietário do site.",
910    "sendEntrySuccess": "Mensagem foi adicionado. Ele aparecerá no site após aprovação do administrador.",
911    "cookie_box_text": "Nós usamos cookies (biscoitos) para fins estatísticos e para facilitar o uso do nosso site.<br />A qualquer momento, você pode prevenir ou limitar a gravação de cookies no seu dispositivo alterando as configurações do seu navegador.",
912    "cookie_box_short_text": "Política de Privacidade e Cookies",
913    "shop_add_to_cart_text": "Adicionar ao carrinho",
914    "shop_back_text": "Voltar",
915    "shop_cart_content_text": "Compras",
916    "shop_close_text": "Perto",
917    "shop_email_text": "O seu endereço de e-mail",
918    "shop_empty_cart_text": "O carrinho está vazio.",
919    "shop_invalid_email_text": "Por favor insira um endereço de e-mail válido.",
920    "shop_message_text": "Mensagem adicional",
921    "shop_name_text": "Nome",
922    "shop_order_posting_text": "Postando order",
923    "shop_price_text": "Preço",
924    "shop_quantity_text": "Número",
925    "shop_send_message_error_text": "Não foi possível enviar a sua encomenda. Se o problema persistir entre em contato com o proprietário da página.",
926    "shop_send_message_success_text": "O seu pedido foi enviado. Dentro de alguns minutos, no endereço fornecido, você deve receber uma confirmação por e-mail.",
927    "shop_send_order_text": "Envie o seu pedido",
928    "unsupported_audio_info_text": "Você tem que atualizar seu navegador ou instalar o plugin do Flash, se você quiser jogar este arquivo.",
929    "unsupported_back_sound_info_text": "Você tem que atualizar seu navegador ou instalar o plugin do Flash, se você quiser reproduzir o som no site.",
930    "field_required": "Campo Obrigatório!",
931    "invalid_email": "E-mail inválido",
932    "send_fail": "O envio falhou. Tente novamente mais tarde, em poucos minutos.<br />Clique no texto para ocultar esta mensagem.",
933    "send_success": "Obrigado por usar o formulário.",
934    "sending": "Enviando...",
935    "news": "Notícia",
936    "see_more": "Ver mais...",
937    "contactUs": "Contate-Nos",
938    "siteExpiredTitle": 'O site expirou!',
939    "siteExpiredMessage": 'Seu site ainda está hospedado no servidor, mas não está acessível aos internautas. Para ativar o site, entre em contato com nosso suporte ao cliente.',
940  },
941  "se": {
942    "menu": "Meny",
943    "name": "Svenska",
944    "contact_form_input_email": "E-post eller telefonnummer",
945    "contact_form_input_message": "Ditt meddelande",
946    "contact_form_input_name": "Namn",
947    "contact_form_send_email": "Skicka e-post",
948    "language": "Språk",
949    "add_download": "nedladdning",
950    "bank_account": "Bankkonto",
951    "nip": "Momsnr.",
952    "city": "Stad",
953    "comments": "Kommentarer",
954    "from_text": "Från",
955    "order_text": "Beställ",
956    "order_no": "Beställningsnummer",
957    "regon": "REGON",
958    "street": "Gata",
959    "tel_no": "Telefonnummer",
960    "to_text": "Till",
961    "visitor_counter_txt": "Besök",
962    "add_entry": "Lägg till ny",
963    "author": "Författare",
964    "sendEntryFailed": "Lägga till poster i gästboken som har inaktiverats av ägaren.",
965    "sendEntrySuccess": "Post har lagts till. Den visas på webbplatsen efter administratörens godkännande.",
966    "cookie_box_text": "Vi använder cookies (kakor) för statistiska ändamål och för att underlätta användningen av vår hemsida.<br />Som helst, kan du förhindra eller begränsa inspelningen av cookies på din enhet genom att ändra inställningarna i din webbläsare.",
967    "cookie_box_short_text": "Personuppgifter och cookies",
968    "shop_add_to_cart_text": "Lägg i varukorg",
969    "shop_back_text": "Tillbaka",
970    "shop_cart_content_text": "Varukorg",
971    "shop_close_text": "Stäng",
972    "shop_email_text": "Din e-postadress",
973    "shop_empty_cart_text": "Din varukorg är tom.",
974    "shop_invalid_email_text": "Ange en giltig e-postadress.",
975    "shop_message_text": "Ytterligare meddelande",
976    "shop_name_text": "Namn",
977    "shop_order_posting_text": "Skriv Order",
978    "shop_price_text": "Pris",
979    "shop_quantity_text": "Antal",
980    "shop_send_message_error_text": "Det gick inte att skicka din beställning. Om problemet kvarstår kontakta ägaren på sidan.",
981    "shop_send_message_success_text": "Din beställning har skickats. Inom några minuter, på den adress som anges i, ska du få ett e-postbekräftelse.",
982    "shop_send_order_text": "Skicka din beställning",
983    "unsupported_audio_info_text": "Du måste uppdatera din browser eller installera Flash-plugin om du vill spela upp den här filen.",
984    "unsupported_back_sound_info_text": "Du måste uppdatera din browser eller installera Flash-plugin om du vill spela upp ljud på platsen.",
985    "field_required": "Fält som krävs!",
986    "invalid_email": "Ogiltig e-post",
987    "send_fail": "Gick inte att skicka. Försök igen senare i några minuter.<br />Klicka på texten för att dölja detta budskap.",
988    "send_success": "Tack för att du använder formuläret.",
989    "sending": "Skickar...",
990    "news": "Nyheter",
991    "see_more": "Se mer...",
992    "contactUs": "Kontakta oss",
993    "siteExpiredTitle": 'Webbplatsen har löpt ut!',
994    "siteExpiredMessage": 'Din webbplats är fortfarande värd på servern men är inte tillgänglig för internat. Kontakta vår kundsupport för att aktivera webbplatsen.',
995  },
996  "ua": {
997    "menu": "меню",
998    "name": "Українськa",
999    "contact_form_input_email": "Електронної пошти або номер телефону",
1000    "contact_form_input_message": "Ваше повідомлення",
1001    "contact_form_input_name": "Назва",
1002    "contact_form_send_email": "надіслати електронною поштою",
1003    "language": "Мова",
1004    "add_download": "завантажити",
1005    "bank_account": "Банківський рахунок",
1006    "nip": "ІНПП",
1007    "city": "Місто",
1008    "comments": "Коментарі",
1009    "from_text": "Від",
1010    "order_text": "Замовлення",
1011    "order_no": "Номер замовлення",
1012    "regon": "REGON",
1013    "street": "Bулиця",
1014    "tel_no": "Номер телефону",
1015    "to_text": "До",
1016    "visitor_counter_txt": "Відвідини",
1017    "add_entry": "Додати запис",
1018    "author": "Автор",
1019    "sendEntryFailed": "Додавання записів до гостьової книги було заблоковане власником сайту.",
1020    "sendEntrySuccess": "Зміст було додано. Він з\\'явиться на сайті після схвалення адміністратором.",
1021    "cookie_box_text": "Ми використовуємо cookies з метою ведення статистики, а також для полегшення користування нашим порталом.<br />В будь-який момент Ви зможете заблокувати або обмежити записування файлів cookies на Вашому пристрої шляхом зміни налаштувань браузера.",
1022    "cookie_box_short_text": "політика конфіденційності і файли Cookies",
1023    "shop_add_to_cart_text": "Додай до кошика",
1024    "shop_back_text": "Назад",
1025    "shop_cart_content_text": "Вміст кошика",
1026    "shop_close_text": "Замкнути",
1027    "shop_email_text": "Твоя адреса e-mail",
1028    "shop_empty_cart_text": "Твій кошик пустий.",
1029    "shop_invalid_email_text": "Впиши правильну адресу e-mail.",
1030    "shop_message_text": "Додаткове повідомлення",
1031    "shop_name_text": "Назва",
1032    "shop_order_posting_text": "Надсилання замовлення",
1033    "shop_price_text": "Ціна",
1034    "shop_quantity_text": "Кількість",
1035    "shop_send_message_error_text": "Не вдалося вислати замовлення. Якщо проблема з’явиться знову звернися до власника сторінки.",
1036    "shop_send_message_success_text": "Твоє замовлення вислано. Впродовж декількох хвилин, на поданий в ньому адрес, отримаєш мейл з підтвердженням.",
1037    "shop_send_order_text": "Вислати замовлення",
1038    "unsupported_audio_info_text": "Щоб відтворити цей файл потрібно обновити браузер до новішої версії, або встановити Flash Player.",
1039    "unsupported_back_sound_info_text": "Для прослуховування цього файлу потрібно обновити браузер до новішої версії, або встановити Flash Player.",
1040    "field_required": "Обов\\'язкове поле!",
1041    "invalid_email": "Неправильний e-mail",
1042    "send_fail": "Не вдалось надіслати повідомлення. Спробуйте ще раз за декілька хвилин.<br />Натисніть, щоб приховати текст повідомлення.",
1043    "send_success": "Дякуємо за використання формуляру.",
1044    "sending": "Відправка...",
1045    "news": "Новини",
1046    "see_more": "Побачити більше...",
1047    "contactUs": "Зв'яжіться з нами",
1048    "siteExpiredTitle": 'Термін дії веб-сайту закінчився!',
1049    "siteExpiredMessage": 'Ваш веб-сайт все ще розміщений на сервері, але не доступний для міжнародних організацій. Щоб активувати веб-сайт, зв’яжіться з нашою службою підтримки.',
1050  },
1051  "fi": {
1052    "menu": "valikko",
1053    "name": "Suomi",
1054    "contact_form_input_email": "Sähköpostiosoite tai puhelinnumero",
1055    "contact_form_input_message": "Viesti",
1056    "contact_form_input_name": "Nimi",
1057    "contact_form_send_email": "Lähetä sähköpostia",
1058    "language": "Kieli",
1059    "add_download": "lataa",
1060    "bank_account": "Pankkitili",
1061    "nip": "ALV nro",
1062    "city": "Paikka",
1063    "comments": "Kommentit",
1064    "from_text": "Alkaen",
1065    "order_text": "Tilaa",
1066    "order_no": "Tilausnumero",
1067    "regon": "REGON",
1068    "street": "Katu",
1069    "tel_no": "Puhelinnumero",
1070    "to_text": "Voit",
1071    "visitor_counter_txt": "Luettu",
1072    "add_entry": "Lisää uusi",
1073    "author": "Kirjoittaja",
1074    "sendEntryFailed": "Lisäämällä merkintöjä vieraskirjaan on poistanut sivuston omistaja.",
1075    "sendEntrySuccess": "Merkintä on lisätty. Se näkyy työmaalla ylläpitäjän hyväksyntää.",
1076    "cookie_box_text": "Käytämme evästeitä (keksit) tilastointia varten ja helpottaa käyttöä sivuillamme.<br />Milloin tahansa, voit estää tai rajoittaa tallentamista evästeitä laitteen muuttamalla selaimesi asetuksia.",
1077    "cookie_box_short_text": "Yksityisyydensuoja ja evästeet",
1078    "shop_add_to_cart_text": "Lisää ostoskoriin",
1079    "shop_back_text": "Takaisin",
1080    "shop_cart_content_text": "Ostoskorin sisältö",
1081    "shop_close_text": "Lähellä",
1082    "shop_email_text": "Your e-mail osoitetta",
1083    "shop_empty_cart_text": "Ostoskorisi on tyhjä.",
1084    "shop_invalid_email_text": "Kirjoita voimassa oleva sähköpostiosoite.",
1085    "shop_message_text": "Lisäviesti",
1086    "shop_name_text": "Nimi",
1087    "shop_order_posting_text": "lähettämistä Tilaa",
1088    "shop_price_text": "Hinta",
1089    "shop_quantity_text": "Numero",
1090    "shop_send_message_error_text": "Lähetys epäonnistui tilauksesi. Jos ongelma jatkuu, ota omistaja sivulla.",
1091    "shop_send_message_success_text": "Tilauksesi on lähetetty. Muutaman minuutin, osoitteessa annetaan, sinun pitäisi saada vahvistuksen sähköpostitse.",
1092    "shop_send_order_text": "Lähetä tilauksesi",
1093    "unsupported_audio_info_text": "Sinun täytyy päivittää selaimesi tai asentaa Flash-laajennus, jos haluat pelata tätä tiedostoa.",
1094    "unsupported_back_sound_info_text": "Sinun täytyy päivittää selaimesi tai asentaa Flash-laajennus, jos haluat pelata äänen päällä.",
1095    "field_required": "Vaaditaan!",
1096    "invalid_email": "Virheellinen e-mail",
1097    "send_fail": "Lähetys epäonnistui. Yritä myöhemmin uudelleen muutaman minuutin kuluttua.<br />Klikkaa tekstiä piilottaa tämän viestin.",
1098    "send_success": "Kiitos lomakkeella.",
1099    "sending": "Lähetetään...",
1100    "news": "Uutiset",
1101    "see_more": "Katso lisää...",
1102    "contactUs": "Ota meihin yhteyttä",
1103    "siteExpiredTitle": 'Sivusto on vanhentunut!',
1104    "siteExpiredMessage": 'Verkkosivustosi on edelleen palvelimella, mutta internautit eivät pääse siihen. Aktivoi verkkosivusto ottamalla yhteyttä asiakastukeen.',
1105  },
1106  "is": {
1107    "menu": "Matseðill",
1108    "name": "Íslenska",
1109    "contact_form_input_email": "E-mail eða símanúmer",
1110    "contact_form_input_message": "Message",
1111    "contact_form_input_name": "Nafn",
1112    "contact_form_send_email": "Senda tölvupóst",
1113    "language": "Tungumál",
1114    "add_download": "hlaða niður",
1115    "bank_account": "Bankareikningsnúmer",
1116    "nip": "Vsk",
1117    "city": "Borg",
1118    "comments": "Athugasemdir",
1119    "from_text": "Frá",
1120    "order_text": "Pöntun",
1121    "order_no": "Pöntun númer",
1122    "regon": "REGON",
1123    "street": "Gata",
1124    "tel_no": "Símanúmer",
1125    "to_text": "Til",
1126    "visitor_counter_txt": "Skoðað",
1127    "add_entry": "Bæta við færslu",
1128    "author": "Höfundur",
1129    "sendEntryFailed": "Bæti færslur í gestabókina hefur verið gerður óvirkur með eiganda.",
1130    "sendEntrySuccess": "Færsla hefur verið bætt við. Það mun birtast á vefnum eftir að samþykki stjórnandi.",
1131    "cookie_box_text": "Við notum kökur (kex) til hagskýrslugerðar og að auðvelda notkun heimasíðu okkar.<br />Á hverjum tíma, getur þú komið í veg fyrir eða takmarka upptöku af smákökum á tækinu með því að breyta stillingum í vafranum þínum.",
1132    "cookie_box_short_text": "Næði stefna og kökur",
1133    "shop_add_to_cart_text": "Setja í körfu",
1134    "shop_back_text": "Til baka",
1135    "shop_cart_content_text": "Í körfu",
1136    "shop_close_text": "Loka",
1137    "shop_email_text": "E-mail þitt",
1138    "shop_empty_cart_text": "Karfan þín er tóm.",
1139    "shop_invalid_email_text": "Vinsamlegast sláðu inn gilt tölvupóstfang.",
1140    "shop_message_text": "Viðbótarupplýsingar skilaboð",
1141    "shop_name_text": "Nafn",
1142    "shop_order_posting_text": "Staða Order",
1143    "shop_price_text": "Verð",
1144    "shop_quantity_text": "Fjöldi",
1145    "shop_send_message_error_text": "Mistókst að senda pöntunina. Ef vandamálið er viðvarandi samband við eiganda síðunnar.",
1146    "shop_send_message_success_text": "Til þín hefur verið send. Innan nokkurra mínútna, í ræðu í, ættir þú að fá e-mail staðfestingu.",
1147    "shop_send_order_text": "Senda pöntun",
1148    "unsupported_audio_info_text": "Þú þarft að uppfæra vafrann þinn eða setja Flash tappi ef þú vilt spila þessa skrá.",
1149    "unsupported_back_sound_info_text": "Þú þarft að uppfæra vafrann þinn eða setja Flash tappi ef þú vilt spila hljóð 
1149á síðuna.",
1150    "field_required": "Field þurfa!",
1151    "invalid_email": "Öryrki E-mail",
1152    "send_fail": "Sending mistókst. Prófaðu aftur síðar í nokkrar mínútur.<br />Smelltu á textann til að fela þessi skilaboð.",
1153    "send_success": "Takk fyrir að nota eyðublaðið.",
1154    "sending": "Sendi...",
1155    "news": "Fréttir",
1156    "see_more": "Sjá meira...",
1157    "contactUs": "Hafðu samband við okkur",
1158    "siteExpiredTitle": 'Vefsíða útrunnin!',
1159    "siteExpiredMessage": 'Vefsíðan þín er enn hýst á netþjóni en er ekki aðgengileg alþjóðamönnum. Til að virkja vefsíðuna skaltu hafa samband við þjónustuver okkar.',
1160  },
1161  "ro": {
1162    "menu": "Meniul",
1163    "name": "Română",
1164    "contact_form_input_email": "E-mail sau număr de telefon",
1165    "contact_form_input_message": "Mesaj",
1166    "contact_form_input_name": "Nume și prenume",
1167    "contact_form_send_email": "Trimite e-mail",
1168    "language": "Limbă",
1169    "add_download": "descarcă",
1170    "bank_account": "Contul bancar",
1171    "nip": "CF",
1172    "city": "Oraş",
1173    "comments": "Comentarii",
1174    "from_text": "Din",
1175    "order_text": "Comandă",
1176    "order_no": "Număr de ordine",
1177    "regon": "REGON",
1178    "street": "Stradă",
1179    "tel_no": "Număr de telefon",
1180    "to_text": "până la",
1181    "visitor_counter_txt": "Vizite",
1182    "add_entry": "Adaugă un comentariu",
1183    "author": "Autor",
1184    "sendEntryFailed": "Adăugarea de intrări în cartea de oaspeți a fost dezactivată de către proprietarul site-ului.",
1185    "sendEntrySuccess": "Intrarea a fost adăugată. Va apărea pe site după ce este aprobată de către administrator.",
1186    "cookie_box_text": "Folosim plicuri cookies în scopuri statistice şi pentru a uşura folosirea portalului nostru.<br />În orice moment puteţi să blocaţi sau să limitaţi înregistrarea fişierelor cookies pe calculatorul sau telefonul dumneavoastră, schimbând setările browser-ului.",
1187    "cookie_box_short_text": "Politică de confidenţialitate şi a plicurilor Cookies",
1188    "shop_add_to_cart_text": "Adaugă în coș",
1189    "shop_back_text": "Înapoi",
1190    "shop_cart_content_text": "Conținutul coșului",
1191    "shop_close_text": "Închide",
1192    "shop_email_text": "Adresa de e-mail",
1193    "shop_empty_cart_text": "Coșul dumneavoastră este gol.",
1194    "shop_invalid_email_text": "Introduceți adresa de e-mail corect.",
1195    "shop_message_text": "Mesaj suplimentar",
1196    "shop_name_text": "Nume",
1197    "shop_order_posting_text": "Trimiterea comenzii",
1198    "shop_price_text": "Preț",
1199    "shop_quantity_text": "Număr",
1200    "shop_send_message_error_text": "Comanda nu a fost trimisă. Dacă problema se va repeta, vă rugăm să contactați deținătorul paginii.",
1201    "shop_send_message_success_text": "Comanda dumneavoastră a fost trimisă. În câteva minute, la adresa trecută în comandă veți primi un e-mail de confirmare.",
1202    "shop_send_order_text": "Trimite comanda",
1203    "unsupported_audio_info_text": "Pentru a deschide acest fisier trebuie sa va actualizati broswer-ul cu cea mai recenta versiune sau să instalați Flash Player-ul.",
1204    "unsupported_back_sound_info_text": "Pentru a deschide fereastra de sunet pe pagina trebuie sa va actualizati broswer-ul cu cea mai recenta versiune sau să instalați Flash Player-ul.",
1205    "field_required": "Câmpuri necesare!",
1206    "invalid_email": "E-mail incorect",
1207    "send_fail": "Trimiterea mesajului nu s-a realizat. Încercați din nou peste câteva minute.<br />Click pe text pentru a ascunde comunicatul.",
1208    "send_success": "Vă mulțumim pentru utilizarea formularului.",
1209    "sending": "Trimiterea...",
1210    "news": "Știri",
1211    "see_more": "Vezi mai mult...",
1212    "contactUs": "Contactează-ne",
1213    "siteExpiredTitle": 'Site-ul a expirat!',
1214    "siteExpiredMessage": 'Site-ul dvs. web este încă găzduit pe server, dar nu este accesibil internauților. Pentru a activa site-ul web, vă rugăm să contactați asistența noastră pentru clienți.',
1215  },
1216  "cn": {
1217    "menu": "菜单",
1218    "name": "中文",
1219    "contact_form_input_email": "电子邮件或电话号码",
1220    "contact_form_input_message": "消息",
1221    "contact_form_input_name": "全名",
1222    "contact_form_send_email": "发送电子邮件",
1223    "language": "语言",
1224    "add_download": "下载",
1225    "bank_account": "银行帐户",
1226    "nip": "增值税",
1227    "city": "地点",
1228    "comments": "评论",
1229    "from_text": "从",
1230    "order_text": "订购",
1231    "order_no": "订购数量",
1232    "regon": "REGON",
1233    "street": "街",
1234    "tel_no": "电话号码",
1235    "to_text": "要",
1236    "visitor_counter_txt": "访问",
1237    "add_entry": "添加条目",
1238    "author": "作者",
1239    "sendEntryFailed": "新增条目的留言已被禁用的网站所有者。",
1240    "sendEntrySuccess": "该项目已添加。在网站上出现后,由管理员批准。",
1241    "cookie_box_text": "我们使用Cookie(饼干)作统计用途,以方便使用我们的网站。<br />任何时候,你可以阻止或限制您的设备上录制的饼干改变您的浏览器设置。",
1242    "cookie_box_short_text": "新的隐私政策和Cookies",
1243    "shop_add_to_cart_text": "添加到购物车",
1244    "shop_back_text": "后面",
1245    "shop_cart_content_text": "购物车内容",
1246    "shop_close_text": "关闭",
1247    "shop_email_text": "您的E-mail地址",
1248    "shop_empty_cart_text": "您的购物车是空的。",
1249    "shop_invalid_email_text": "请输入一个有效的e-mail地址。",
1250    "shop_message_text": "其他消息",
1251    "shop_name_text": "名称",
1252    "shop_order_posting_text": "张贴订购",
1253    "shop_price_text": "ä»·æ ¼",
1254    "shop_quantity_text": "数",
1255    "shop_send_message_error_text": "无法发送您的订单。如果问题无法解决,请洽询页面的所有者。",
1256    "shop_send_message_success_text": "您的订单已发货。在几分钟内,在给定的地址,你应该会收到一封电子邮件确认。",
1257    "shop_send_order_text": "发送您的订单",
1258    "unsupported_audio_info_text": "您必须更新您的浏览器或安装Flash插件,如果你要玩这个文件。",
1259    "unsupported_back_sound_info_text": "您必须更新您的浏览器或安装Flash插件,如果你想在网站上播放声音。",
1260    "field_required": "场需要的!",
1261    "invalid_email": "无效的电子邮件",
1262    "send_fail": "发送失败。再次尝试在几分钟后。<br />点击文本隐藏此消息。",
1263    "send_success": "感谢您使用的形式。",
1264    "sending": "发送中...",
1265    "news": "新聞",
1266    "see_more": "查看更多...",
1267    "contactUs": "聯繫我們",
1268    "siteExpiredTitle": '網站已過期!',
1269    "siteExpiredMessage": '您的網站仍託管在服務器上,但互不干預的人無法訪問。 要激活網站,請聯繫我們的客戶支持。',
1270  },
1271  "lt": {
1272    "menu": "Meniu",
1273    "name": "Lietuvių",
1274    "contact_form_input_email": "E-pašto adresas arba telefono numeris",
1275    "contact_form_input_message": "žinutė",
1276    "contact_form_input_name": "Pavadinimas",
1277    "contact_form_send_email": "Siųsti elektroninį laišką",
1278    "language": "Kalba",
1279    "add_download": "atsisiųsti",
1280    "bank_account": "Banko sąskaita",
1281    "nip": "PVM",
1282    "city": "Miestas",
1283    "comments": "Komentarai",
1284    "from_text": "Nuo",
1285    "order_text": "Užsakyti",
1286    "order_no": "Užsakymo numeris",
1287    "regon": "REGON",
1288    "street": "Gatvė",
1289    "tel_no": "Telefono numeris",
1290    "to_text": "į",
1291    "visitor_counter_txt": "Parodymų",
1292    "add_entry": "Pridėti atsiliepimą",
1293    "author": "Autorius",
1294    "sendEntryFailed": "Įrašyta įrašų svečių knygoje svetainės savininką buvo išjungta.",
1295    "sendEntrySuccess": "Įrašas. Pasirodys svetainėje po to, kai jį patvirtins administratorius.",
1296    "cookie_box_text": "Mes naudojame slapukus (sausainiai) statistikos tikslais ir siekiant palengvinti mūsų svetainės naudojimą.<br />Bet kuriuo metu, jums gali užkirsti kelią arba apriboti įrašinėti slapukus jūsų prietaise keisdami savo naršyklės nustatymus.",
1297    "cookie_box_short_text": "Privatumas ir slapukai",
1298    "shop_add_to_cart_text": "Į krepšelį",
1299    "shop_back_text": "Atpakaļ",
1300    "shop_cart_content_text": "Groza saturs",
1301    "shop_close_text": "Aizvērt",
1302    "shop_email_text": "Jūsu e-pasta adrese",
1303    "shop_empty_cart_text": "Jūsu grozs ir tukšs.",
1304    "shop_invalid_email_text": "Lūdzu, ievadiet derīgu e-pasta adresi.",
1305    "shop_message_text": "Papildu ziņa",
1306    "shop_name_text": "Nosaukums",
1307    "shop_order_posting_text": "Norīkošanu Pasūtīt",
1308    "shop_price_text": "Cena",
1309    "shop_quantity_text": "Numurs",
1310    "shop_send_message_error_text": "Neizdevās nosūtīt savu pasūtījumu. Ja problēma joprojām pastāv, sazinieties ar īpašnieku lapā.",
1311    "shop_send_message_success_text": "Jūsu pasūtījums ir nosūtīts. Dažu minūšu laikā, norādītajā adresē, jums vajadzētu saņemt e-pasta apstiprinājumu.",
1312    "shop_send_order_text": "Nosūtīt savu pasūtījumu",
1313    "unsupported_audio_info_text": "Jūs turite atnaujinti savo naršyklę arba įdiegti Flash įskiepio, jei norite žaisti šį failą.",
1314    "unsupported_back_sound_info_text": "Jūs turite atnaujinti savo naršyklę arba įdiegti Flash įskiepio, jei norite žaisti garsą svetainėje.",
1315    "field_required": "Lauko reikia!",
1316    "invalid_email": "Neteisingas e-mail",
1317    "send_fail": "Siuntimas nepavyko. Bandykite dar kartą vėliau per kelias minutes.<br />Spustelėkite tekstą paslėpti šį pranešimą.",
1318    "send_success": "Dėkojame, kad naudojatės formą.",
1319    "sending": "Siunčiama...",
1320    "news": "Žinios",
1321    "see_more": "Žiūrėti daugiau...",
1322    "contactUs": "Susisiekite su mumis",
1323    "siteExpiredTitle": 'Svetainės galiojimo laikas baigėsi!',
1324    "siteExpiredMessage": 'Jūsų svetainė vis dar priglobta serveryje, tačiau ji nėra prieinama internautams. Norėdami suaktyvinti svetainę, susisiekite su mūsų klientų palaikymo tarnyba.',
1325  },
1326  "tr": {
1327    "menu": "Menü",
1328    "name": "Türkçe",
1329    "contact_form_input_email": "E-posta  adresiniz yada telefon no",
1330    "contact_form_input_message": "Haber",
1331    "contact_form_input_name": "Isim ve soyisim",
1332    "contact_form_send_email": "E-posta gönderme",
1333    "language": "Dil",
1334    "add_download": "yükleme",
1335    "bank_account": "Banka hesap numarasi",
1336    "nip": "Vergi numarası",
1337    "city": "Sehir",
1338    "comments": "Yorumlar",
1339    "from_text": "Den",
1340    "order_text": "Siparis",
1341    "order_no": "Siparis numarasi",
1342    "regon": "REGON",
1343    "street": "Sokak",
1344    "tel_no": "Telefon numarasi",
1345    "to_text": "Dek",
1346    "visitor_counter_txt": "Ziyaret",
1347    "add_entry": "Ekle",
1348    "author": "Yazar",
1349    "sendEntryFailed": "Yorum ekleme su an sayfa yöneticisi tarafindan kapatilmistir.",
1350    "sendEntrySuccess": "Yaziniz sayfa yönetici tarafindan onaylandiginda, sayfaminda görüntülenecektir.",
1351    "cookie_box_text": "Biz istatistik amaçlı çerezleri (bisküvi) kullanımı ve web sitemizin kullanımını kolaylaştırmak için.<br />Herhangi bir zamanda, tarayıcınızda ayarlarını değiştirerek önlemek veya cihazınızda çerezleri kayıt sınırlayabilir.",
1352    "cookie_box_short_text": "Gizlilik Politikası ve Çerezler",
1353    "shop_add_to_cart_text": "Sepete ekle",
1354    "shop_back_text": "Geri",
1355    "shop_cart_content_text": "Sepetim",
1356    "shop_close_text": "Yakın",
1357    "shop_email_text": "E-posta adresiniz",
1358    "shop_empty_cart_text": "Sepetiniz boş.",
1359    "shop_invalid_email_text": "Geçerli bir e-posta adresinizi girin.",
1360    "shop_message_text": "Ek mesajı",
1361    "shop_name_text": "Isim",
1362    "shop_order_posting_text": "Gönderme Sipariş",
1363    "shop_price_text": "Fiyat",
1364    "shop_quantity_text": "Numara",
1365    "shop_send_message_error_text": "Sipariş gönderilemedi.Sorun sayfanın sahibiyle temasa geçin.",
1366    "shop_send_message_success_text": "Sipariş sevk edildi. Birkaç dakika içinde, verilen adreste, bir e-posta onayı almalıdır.",
1367    "shop_send_order_text": "Sipariş gönder",
1368    "unsupported_audio_info_text": "Tarayıcınızı güncelleyebilir veya bu dosyayı oynamak istiyorsanız Flash eklentisinin yüklü olması gerekmektedir.",
1369    "unsupported_back_sound_info_text": "Tarayıcınızı güncellemek veya sitede ses oynamak istiyorsanız Flash eklentisinin yüklü olması gerekmektedir.",
1370    "field_required": "Alan gerekli!",
1371    "invalid_email": "Geçersiz e-posta",
1372    "send_fail": "Gönderme işlemi başarısız. Daha sonra birkaç dakika içinde tekrar deneyin.<br />Bu mesajı gizlemek için metnin üzerine tıklayın.",
1373    "send_success": "Formunu kullanarak için teşekkür ederiz.",
1374    "sending": "Gönderme...",
1375    "news": "Haber",
1376    "see_more": "Daha fazla gör...",
1377    "contactUs": "Bize Ulaşın",
1378    "siteExpiredTitle": 'Web sitesinin süresi doldu!',
1379    "siteExpiredMessage": 'Web siteniz hala sunucuda barındırılıyor ancak stajyerler tarafından erişilebilir değil. Web sitesini etkinleştirmek için lütfen müşteri desteğimizle iletişime geçin.',
1380  },
1381  "by": {
1382    "menu": "меню",
1383    "name": "Беларуская",
1384    "contact_form_input_email": "E-mail або нумар тэлефона",
1385    "contact_form_input_message": "Паведамленне",
1386    "contact_form_input_name": "Поўнае імя",
1387    "contact_form_send_email": "адправіць e-mail",
1388    "language": "Мова",
1389    "add_download": "спампаваць",
1390    "bank_account": "Банкаўскі рахунак",
1391    "nip": "УНП",
1392    "city": "Сіці",
1393    "comments": "Каментары",
1394    "from_text": "Oд",
1395    "order_text": "Замовіць",
1396    "order_no": "Нумар заказу",
1397    "regon": "REGON",
1398    "street": "Вуліца",
1399    "tel_no": "Нумар тэлефона",
1400    "to_text": "Да",
1401    "visitor_counter_txt": "Наведванне",
1402    "add_entry": "Дадаць запіс",
1403    "author": "Аўтар",
1404    "sendEntryFailed": "Даданне запісаў у гасцявой кнізе быў адключаны уладальнікам сайта.",
1405    "sendEntrySuccess": "Запіс будзе дададзеная. З'явіцца на сайце пасля адабрэння адміністратарам.",
1406    "cookie_box_text": "Мы выкарыстоўваем печыва (печыва) ў статыстычных мэтах і для палягчэння выкарыстання нашага сайта.<br />У любы момант вы можаце прадухіліць ці абмежаваць запіс печыва на вашым прыладзе, змяніўшы налады ў Вашым браўзэры.",
1407    "cookie_box_short_text": "палітыка прыватнасці і Cookies",
1408    "shop_add_to_cart_text": "Дадаць у кошык",
1409    "shop_back_text": "Назад",
1410    "shop_cart_content_text": "Кошык",
1411    "shop_close_text": "Блізка",
1412    "shop_email_text": "Ваш адрас электроннай пошты",
1413    "shop_empty_cart_text": "Ваша кошык пустая.",
1414    "shop_invalid_email_text": "Калі ласка, увядзіце сапраўдны адрас электроннай пошты.",
1415    "shop_message_text": "Дадатковае паведамленне",
1416    "shop_name_text": "Назва",
1417    "shop_order_posting_text": "Сярэдняя Замовіць",
1418    "shop_price_text": "Кошт",
1419    "shop_quantity_text": "Лік",
1420    "shop_send_message_error_text": "Не атрымалася адправіць ваш заказ. Калі праблема не ўхіляецца, звяжыцеся з уладальнікам старонкі.",
1421    "shop_send_message_success_text": "Ваш заказ быў адпраўлены. На працягу некалькіх хвілін, па адрасе, паказанаму ў сістэму, вы павінны атрымаць ліст-пацверджанне.",
1422    "shop_send_order_text": "Адпраўце заказ",
1423    "unsupported_audio_info_text": "Вы павінны абнавіць браўзэр або ўсталяваць флэш-плагіна, калі вы хочаце прайграць гэты файл.",
1424    "unsupported_back_sound_info_text": "Вы павінны абнавіць браўзэр або ўсталяваць флэш-плагіна, калі вы жадаеце гуляць гук на сайце.",
1425    "field_required": "Поле не патрабуецца!",
1426    "invalid_email": "Няправільны адрас электроннай пошты",
1427    "send_fail": "Адпраўка не ўдалася. Паспрабуйце яшчэ раз пазней на працягу некалькіх хвілін.<br />Націсніце на тэкст, каб схаваць гэтае паведамленне.",
1428    "send_success": "Дзякуй за выкарыстанне форму.",
1429    "sending": "Адпраўка...",
1430    "news": "Навіны",
1431    "see_more": "Больш падрабязна...",
1432    "contactUs": "Звяжыцеся з намі",
1433    "siteExpiredTitle": 'Тэрмін дзеяння сайта скончыўся!',
1434    "siteExpiredMessage": 'Ваш вэб-сайт па-ранейшаму размешчаны на серверы, але недаступны для інтэрнаўтаў. Каб актываваць вэб-сайт, звяжыцеся з нашай службай падтрымкі.',
1435  },
1436  "hr": {
1437    "menu": "Meni",
1438    "name": "Hrvatski",
1439    "contact_form_input_email": "E-mail adresa ili telefonski broj",
1440    "contact_form_input_message": "Poruka",
1441    "contact_form_input_name": "Ime i prezime",
1442    "contact_form_send_email": "Pošaljite e-mail",
1443    "language": "Jezik",
1444    "add_download": "download",
1445    "bank_account": "IBAN",
1446    "nip": "OIB",
1447    "city": "Mjesto",
1448    "comments": "Komentari",
1449    "from_text": "Od",
1450    "order_text": "Naruči",
1451    "order_no": "Broj narudžbe",
1452    "regon": "REGON",
1453    "street": "Ulica",
1454    "tel_no": "Broj telefona",
1455    "to_text": "Do",
1456    "visitor_counter_txt": "Posjet",
1457    "add_entry": "Dodaj zapis",
1458    "author": "Autor",
1459    "sendEntryFailed": "Slanje poruke nije uspjelo. Pokušajte ponovno za nekoliko minuta.<br />Kliknite na obavijest kako bi ju sakrili.",
1460    "sendEntrySuccess": "Komentar je dodan. Bit će objavljen nakon odobrenja od strane administratora.",
1461    "cookie_box_text": "Za rad stranice i bolje korisničko iskustvo koristimo kolačiće.",
1462    "cookie_box_short_text": "Obavijest o  kolačićima",
1463    "shop_add_to_cart_text": "Dodaj u košaricu",
1464    "shop_back_text": "Nazad",
1465    "shop_cart_content_text": "Sadržaj košarice",
1466    "shop_close_text": "Zatvori",
1467    "shop_email_text": "Vaš e-mail adresa",
1468    "shop_empty_cart_text": "Vaša košarica je prazna.",
1469    "shop_invalid_email_text": "Molimo da unesete ispravnu e-mail adresu.",
1470    "shop_message_text": "Dodatna poruka",
1471    "shop_name_text": "Naziv",
1472    "shop_order_posting_text": "Šaljem narudžbu",
1473    "shop_price_text": "Cijena",
1474    "shop_quantity_text": "Količina",
1475    "shop_send_message_error_text": "Narudžba nije uspjela. Ukoliko se greška ponovi, obratite se vlasniku stranice.",
1476    "shop_send_message_success_text": "Vaša narudžba je uspješno poslana. Uskoro ćete primiti potvrdu na vaš e-mail.",
1477    "shop_send_order_text": "Pošaljite narudžbu",
1478    "unsupported_audio_info_text": "Za pregled ove datoteke morate nadograditi vaš pretraživač ili instalirati Flash plugin.",
1479    "unsupported_back_sound_info_text": "Za preslušavanje morate nadograditi na zadnju verziju ili instalirati Flash plugin.",
1480    "field_required": "Obvezna polja!",
1481    "invalid_email": "Pogrešan e-mail",
1482    "send_fail": "Slanje nije uspjelo. Pokušajte ponovno kasnije za nekoliko minuta.<br />Kliknite na tekst kako bi sakrili tu poruku.",
1483    "send_success": "Hvala što ste koristili naš kontaktni obrazac.",
1484    "sending": "Slanje u tijeku...",
1485    "news": "Vijesti",
1486    "see_more": "Vidi više...",
1487    "contactUs": "Kontaktirajte nas",
1488    "siteExpiredTitle": 'Web stranica je istekla!',
1489    "siteExpiredMessage": 'Vaša je web lokacija još uvijek hostirana na serveru, ali internautima nije dostupna. Da biste aktivirali web stranicu, kontaktirajte našu korisničku podršku.',
1490  },
1491  "th": {
1492    "menu": "เมนู",
1493    "name": "ประเทศไทย",
1494    "contact_form_input_email": "อีเมล์หรือหมายเลขโทรศัพท์",
1495    "contact_form_input_message": "ข่าวสาร",
1496    "contact_form_input_name": "ชื่อเต็ม",
1497    "contact_form_send_email": "ส่งอีเมล์",
1498    "language": "ภาษา",
1499    "add_download": "ดาวน์โหลด",
1500    "bank_account": "บัญชีเงินฝาก",
1501    "nip": "จำนวนภาษี",
1502    "city": "สถานที่",
1503    "comments": "ความเห็น",
1504    "from_text": "จาก",
1505    "order_text": "สั่ง",
1506    "order_no": "หมายเลขใบสั่งซื้อ",
1507    "regon": "REGON",
1508    "street": "ถนนหนทาง",
1509    "tel_no": "หมายเลขโทรศัพท์",
1510    "to_text": "สู่",
1511    "visitor_counter_txt": "การเข้าชม",
1512    "add_entry": "เพิ่มรายการ",
1513    "author": "ผู้เขียน",
1514    "sendEntryFailed": "การเพิ่มรายการในสมุดเยี่ยมถูกบล็อกโดยเจ้าของเว็บไซต์",
1515    "sendEntrySuccess": "รายการถูกเพิ่ม จะปรากฏขึ้นบนหน้าหลังจากที่ได้รับการอนุมัติโดยผู้ดูแลระบบ",
1516    "cookie_box_text": "เราใช้คุกกี้ (บิสกิต) เพื่อวัตถุประสงค์ทางสถิติและเพื่ออำนวยความสะดวกการใช้งานของเว็บไซต์ของเรา.<br />ณ เวลาใด ๆ คุณสามารถป้องกันหรือ จำกัด การบันทึกคุกกี้บนอุปกรณ์ของคุณโดยการเปลี่ยนการตั้งค่าในเบราว์เซอร์ของคุณ",
1517    "cookie_box_short_text": "นโยบายความเป็นส่วนตัวใหม่และคุà¸
1517à¸à¸µà¹‰",
1518    "shop_add_to_cart_text": "หยิบใส่รถเข็น",
1519    "shop_back_text": "กลับ",
1520    "shop_cart_content_text": "สินค้าในรถเข็น",
1521    "shop_close_text": "ใกล้",
1522    "shop_email_text": "ที่อยู่อีเมลของคุณ",
1523    "shop_empty_cart_text": "รถเข็นของคุณว่างเปล่า",
1524    "shop_invalid_email_text": "กรุณาใส่ที่อยู่อีเมลที่ถูกต้อง",
1525    "shop_message_text": "ข้อความเพิ่มเติม",
1526    "shop_name_text": "ชื่อ",
1527    "shop_order_posting_text": "การโพสต์การสั่งซื้อ",
1528    "shop_price_text": "ราคา",
1529    "shop_quantity_text": "จำนวน",
1530    "shop_send_message_error_text": "ล้มเหลวในการส่งคำสั่งซื้อของคุณ หากปัญหายังคงติดต่อกับเจ้าของของหน้า",
1531    "shop_send_message_success_text": "สั่งซื้อของคุณได้รับการจัดส่ง ภายในไม่กี่นาทีที่อยู่ที่ระบุในคุณควรได้รับอีเมลยืนยัน",
1532    "shop_send_order_text": "ส่งคำสั่งซื้อของคุณ",
1533    "unsupported_audio_info_text": "คุณต้องปรับปรุงเบราว์เซอร์ของคุณหรือติดตั้งปลั๊กอิน Flash ถ้าคุณต้องการที่จะเล่นไฟล์นี้",
1534    "unsupported_back_sound_info_text": "คุณต้องปรับปรุงเบราว์เซอร์ของคุณหรือติดตั้งปลั๊กอิน Flash ถ้าคุณต้องการที่จะเล่นเสียงในเว็บไซต์",
1535    "field_required": "ฟิลด์ที่จำเป็น",
1536    "invalid_email": "อีเมลที่ไม่ถูกต้อง",
1537    "send_fail": "การส่งล้มเหลว ลองใหม่อีกครั้งในไม่กี่นาที.<br />คลิกที่ข้อความเพื่อซ่อนข้อความนี้",
1538    "send_success": "ขอขอบคุณที่ใช้รูปแบบ",
1539    "sending": "กำลังส่ง...",
1540    "news": "ข่าว",
1541    "see_more": "ดูเพิ่มเติม...",
1542    "contactUs": "ติดต่อเรา",
1543    "siteExpiredTitle": 'เว็บไซต์หมดอายุ!',
1544    "siteExpiredMessage": 'เว็บไซต์ของคุณยังคงโฮสต์บนเซิร์ฟเวอร์ แต่ไม่สามารถเข้าถึงได้โดยบุคคลภายนอก หากต้องการเปิดใช้งานเว็บไซต์โปรดติดต่อฝ่ายสนับสนุนลูกค้าของเรา',
1545  },
1546  "si": {
1547    "menu": "Meni",
1548    "name": "Slovenščina",
1549    "contact_form_input_email": "E-Mail ali telefonska številka",
1550    "contact_form_input_message": "Sporočilo",
1551    "contact_form_input_name": "Ime in priimek",
1552    "contact_form_send_email": "Pošlji sporočilo",
1553    "language": "Jezik",
1554    "add_download": "prenos",
1555    "bank_account": "IBAN",
1556    "nip": "Id. št. DDV",
1557    "city": "Mesto",
1558    "comments": "Komentarji",
1559    "from_text": "Od",
1560    "order_text": "Naroči",
1561    "order_no": "Št- naročila",
1562    "regon": "REGON",
1563    "street": "Ulica",
1564    "tel_no": "Telefonska številka",
1565    "to_text": "Do",
1566    "visitor_counter_txt": "Obisk",
1567    "add_entry": "Dodaj vnos",
1568    "author": "Avtor",
1569    "sendEntryFailed": "Administrator je zavrnil objavo komentarja.",
1570    "sendEntrySuccess": "Komentar dodan. Objavljen bo takoj po potrditvi administratorja.",
1571    "cookie_box_text": "V namen zagotavljanja kvalitete storitev uporabljamo piškotke. Z nadaljno uporabo spletne strani soglašate z njihovo uporabo.",
1572    "cookie_box_short_text": "Obvestilo o piškotkih",
1573    "shop_add_to_cart_text": "V košarico",
vendor: 11,715 bytes, lines 1574-1930
1574    "shop_back_text": "Nazaj",
1575    "shop_cart_content_text": "Vaša košarica",
1576    "shop_close_text": "Zapri",
1577    "shop_email_text": "Vaš E-mail naslov",
1578    "shop_empty_cart_text": "Nakupovalna košarica je prazna",
1579    "shop_invalid_email_text": "Vnesite pravilni E-mail naslov",
1580    "shop_message_text": "Dodatno sporočilo",
1581    "shop_name_text": "Naziv",
1582    "shop_order_posting_text": "Pošljam naročilo",
1583    "shop_price_text": "Cena",
1584    "shop_quantity_text": "Količina",
1585    "shop_send_message_error_text": "Naročilo ni uspelo. V kolikor se napaka ponovi kontaktirajte lastnika spletne strani.",
1586    "shop_send_message_success_text": "Vaše naročilo je bilo uspešno oddano. V kratkem boste prejeli potrditveno sporočilo na naveden e-mail naslov.",
1587    "shop_send_order_text": "Pošlji naročilo",
1588    "unsupported_audio_info_text": "Za predvajanje te datoteke morate nadgraditi svoj brskalnik na zadnjo različico ali namestiti Flash predvajalnik.",
1589    "unsupported_back_sound_info_text": "Za poslušanje morate nadgraditi na zadnjo različico ali namestiti Flash predvajalnik.",
1590    "field_required": "Obvezna polja!",
1591    "invalid_email": "Napačen E-mail",
1592    "send_fail": "Sporočilo ni bilo uspešno poslano. Poskusite ponovno čez nekaj minut.<br />Kliknite na obvestilo da ga skrijete.",
1593    "send_success": "Hvala da ste uporabili naš kontaktni obrazec.",
1594    "sending": "Pošiljanje...",
1595    "news": "Novice",
1596    "see_more": "Poglej več...",
1597    "contactUs": "Kontaktiraj nas",
1598    "siteExpiredTitle": 'Spletno mesto je poteklo!',
1599    "siteExpiredMessage": 'Vaše spletno mesto še vedno gostuje na strežniku, vendar ni dostopno internautom. Če želite aktivirati spletno mesto, se obrnite na našo podporo strankam.',
1600  },
1601  "rs": {
1602    "menu": "мени",
1603    "name": "Srpski",
1604    "contact_form_input_email": "E-mail adresa ili broj telefona",
1605    "contact_form_input_message": "Poruka",
1606    "contact_form_input_name": "Ime i prezime",
1607    "contact_form_send_email": "Pošaljite e-mail",
1608    "language": "Jezik",
1609    "add_download": "prenos",
1610    "bank_account": "Broj računa",
1611    "nip": "Broj PDV",
1612    "city": "Mesto",
1613    "comments": "Komentari",
1614    "from_text": "Od",
1615    "order_text": "Naruči",
1616    "order_no": "Broj narudžbe",
1617    "regon": "REGON",
1618    "street": "Ulica",
1619    "tel_no": "Broj telefona",
1620    "to_text": "Do",
1621    "visitor_counter_txt": "Poseta",
1622    "add_entry": "Dodaj zapis",
1623    "author": "Autor",
1624    "sendEntryFailed": "Administrator je odbio objavljivanje komentara.",
1625    "sendEntrySuccess": "Zapis je dodan. Biće objavljen odmah nakon odobrenja od strane administratora.",
1626    "cookie_box_text": "Za delovanje stranice i bolje korisničko iskustvo koristimo kolačiće.",
1627    "cookie_box_short_text": "Obaveštenje o kolačićima",
1628    "shop_add_to_cart_text": "Dodaj u korpu",
1629    "shop_back_text": "Nazad",
1630    "shop_cart_content_text": "Sadržaj korpe",
1631    "shop_close_text": "Zatvori",
1632    "shop_email_text": "Vaša e-mail adresa",
1633    "shop_empty_cart_text": "Vaša korpa je prazna",
1634    "shop_invalid_email_text": "Molimo vas da unesete pravilnu e-mail adresu.",
1635    "shop_message_text": "Dodatna poruka",
1636    "shop_name_text": "Naziv",
1637    "shop_order_posting_text": "Šaljem  narudžbu",
1638    "shop_price_text": "Cena",
1639    "shop_quantity_text": "Količina",
1640    "shop_send_message_error_text": "Slanje narudžbe nije uspelo. Ako se greška ponovi, obratite se vlasniku internetne stranice.",
1641    "shop_send_message_success_text": "Vaša narudžba je uspešno poslana. Ubrzo ćete primiti potvrdu na vašu e-mail adresu.",
1642    "shop_send_order_text": "Pošaljite narudžbu",
1643    "unsupported_audio_info_text": "Za pretraživanje ove datoteke morate nadograditi svoj pretraživač na zadnju verziju ili instalirati Flash Plugin.",
1644    "unsupported_back_sound_info_text": "Za slušanje morate nadograditi na zadnju verziju ili instalirati Flash Plugin.",
1645    "field_required": "Obavezna polja!",
1646    "invalid_email": "Pogrešan e-mail",
1647    "send_fail": "Slanje nije uspelo. Pokušajte ponovo kroz nekoliko minuta.<br />Kliknite na tekst kako bi ga sakrili.",
1648    "send_success": "Hvala što koristite naš kontaktni obrazac.",
1649    "sending": "Slanje u toku...",
1650    "news": "Vijesti",
1651    "see_more": "Vidi više...",
1652    "contactUs": "Контактирајте нас",
1653    "siteExpiredTitle": 'Веб локација је истекла!',
1654    "siteExpiredMessage": 'Ваша веб локација је и даље хостована на серверу, али интернаутима није доступна. Да бисте активирали веб локацију, контактирајте нашу корисничку подршку.',
1655  }
1656};
1657
1658/*!
1659 * jQuery JavaScript Library v1.11.2
1660 * http://jquery.com/
1661 *
1662 * Includes Sizzle.js
1663 * http://sizzlejs.com/
1664 *
1665 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
1666 * Released under the MIT license
1667 * http://jquery.org/license
1668 *
1669 * Date: 2014-12-17T15:27Z
1670 */
1671
1672(function( global, factory ) {
1673
1674	if ( typeof module === "object" && typeof module.exports === "object" ) {
1675		// For CommonJS and CommonJS-like environments where a proper window is present,
1676		// execute the factory and get jQuery
1677		// For environments that do not inherently posses a window with a document
1678		// (such as Node.js), expose a jQuery-making factory as module.exports
1679		// This accentuates the need for the creation of a real window
1680		// e.g. var jQuery = require("jquery")(window);
1681		// See ticket #14549 for more info
1682		module.exports = global.document ?
1683			factory( global, true ) :
1684			function( w ) {
1685				if ( !w.document ) {
1686					throw new Error( "jQuery requires a window with a document" );
1687				}
1688				return factory( w );
1689			};
1690	} else {
1691		factory( global );
1692	}
1693
1694// Pass this if window is not defined yet
1695}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
1696
1697// Can't do this because several apps including ASP.NET trace
1698// the stack via arguments.caller.callee and Firefox dies if
1699// you try to trace through "use strict" call chains. (#13335)
1700// Support: Firefox 18+
1701//
1702
1703var deletedIds = [];
1704
1705var slice = deletedIds.slice;
1706
1707var concat = deletedIds.concat;
1708
1709var push = deletedIds.push;
1710
1711var indexOf = deletedIds.indexOf;
1712
1713var class2type = {};
1714
1715var toString = class2type.toString;
1716
1717var hasOwn = class2type.hasOwnProperty;
1718
1719var support = {};
1720
1721
1722
1723var
1724	version = "1.11.2",
1725
1726	// Define a local copy of jQuery
1727	jQuery = function( selector, context ) {
1728		// The jQuery object is actually just the init constructor 'enhanced'
1729		// Need init if jQuery is called (just allow error to be thrown if not included)
1730		return new jQuery.fn.init( selector, context );
1731	},
1732
1733	// Support: Android<4.1, IE<9
1734	// Make sure we trim BOM and NBSP
1735	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
1736
1737	// Matches dashed string for camelizing
1738	rmsPrefix = /^-ms-/,
1739	rdashAlpha = /-([\da-z])/gi,
1740
1741	// Used by jQuery.camelCase as callback to replace()
1742	fcamelCase = function( all, letter ) {
1743		return letter.toUpperCase();
1744	};
1745
1746jQuery.fn = jQuery.prototype = {
1747	// The current version of jQuery being used
1748	jquery: version,
1749
1750	constructor: jQuery,
1751
1752	// Start with an empty selector
1753	selector: "",
1754
1755	// The default length of a jQuery object is 0
1756	length: 0,
1757
1758	toArray: function() {
1759		return slice.call( this );
1760	},
1761
1762	// Get the Nth element in the matched element set OR
1763	// Get the whole matched element set as a clean array
1764	get: function( num ) {
1765		return num != null ?
1766
1767			// Return just the one element from the set
1768			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
1769
1770			// Return all the elements in a clean array
1771			slice.call( this );
1772	},
1773
1774	// Take an array of elements and push it onto the stack
1775	// (returning the new matched element set)
1776	pushStack: function( elems ) {
1777
1778		// Build a new jQuery matched element set
1779		var ret = jQuery.merge( this.constructor(), elems );
1780
1781		// Add the old object onto the stack (as a reference)
1782		ret.prevObject = this;
1783		ret.context = this.context;
1784
1785		// Return the newly-formed element set
1786		return ret;
1787	},
1788
1789	// Execute a callback for every element in the matched set.
1790	// (You can seed the arguments with an array of args, but this is
1791	// only used internally.)
1792	each: function( callback, args ) {
1793		return jQuery.each( this, callback, args );
1794	},
1795
1796	map: function( callback ) {
1797		return this.pushStack( jQuery.map(this, function( elem, i ) {
1798			return callback.call( elem, i, elem );
1799		}));
1800	},
1801
1802	slice: function() {
1803		return this.pushStack( slice.apply( this, arguments ) );
1804	},
1805
1806	first: function() {
1807		return this.eq( 0 );
1808	},
1809
1810	last: function() {
1811		return this.eq( -1 );
1812	},
1813
1814	eq: function( i ) {
1815		var len = this.length,
1816			j = +i + ( i < 0 ? len : 0 );
1817		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
1818	},
1819
1820	end: function() {
1821		return this.prevObject || this.constructor(null);
1822	},
1823
1824	// For internal use only.
1825	// Behaves like an Array's method, not like a jQuery method.
1826	push: push,
1827	sort: deletedIds.sort,
1828	splice: deletedIds.splice
1829};
1830
1831jQuery.extend = jQuery.fn.extend = function() {
1832	var src, copyIsArray, copy, name, options, clone,
1833		target = arguments[0] || {},
1834		i = 1,
1835		length = arguments.length,
1836		deep = false;
1837
1838	// Handle a deep copy situation
1839	if ( typeof target === "boolean" ) {
1840		deep = target;
1841
1842		// skip the boolean and the target
1843		target = arguments[ i ] || {};
1844		i++;
1845	}
1846
1847	// Handle case when target is a string or something (possible in deep copy)
1848	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
1849		target = {};
1850	}
1851
1852	// extend jQuery itself if only one argument is passed
1853	if ( i === length ) {
1854		target = this;
1855		i--;
1856	}
1857
1858	for ( ; i < length; i++ ) {
1859		// Only deal with non-null/undefined values
1860		if ( (options = arguments[ i ]) != null ) {
1861			// Extend the base object
1862			for ( name in options ) {
1863				src = target[ name ];
1864				copy = options[ name ];
1865
1866				// Prevent never-ending loop
1867				if ( target === copy ) {
1868					continue;
1869				}
1870
1871				// Recurse if we're merging plain objects or arrays
1872				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
1873					if ( copyIsArray ) {
1874						copyIsArray = false;
1875						clone = src && jQuery.isArray(src) ? src : [];
1876
1877					} else {
1878						clone = src && jQuery.isPlainObject(src) ? src : {};
1879					}
1880
1881					// Never move original objects, clone them
1882					target[ name ] = jQuery.extend( deep, clone, copy );
1883
1884				// Don't bring in undefined values
1885				} else if ( copy !== undefined ) {
1886					target[ name ] = copy;
1887				}
1888			}
1889		}
1890	}
1891
1892	// Return the modified object
1893	return target;
1894};
1895
1896jQuery.extend({
1897	// Unique for each copy of jQuery on the page
1898	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
1899
1900	// Assume jQuery is ready without the ready module
1901	isReady: true,
1902
1903	error: function( msg ) {
1904		throw new Error( msg );
1905	},
1906
1907	noop: function() {},
1908
1909	// See test/unit/core.js for details concerning isFunction.
1910	// Since version 1.3, DOM methods and functions like alert
1911	// aren't supported. They return false on IE (#2968).
1912	isFunction: function( obj ) {
1913		return jQuery.type(obj) === "function";
1914	},
1915
1916	isArray: Array.isArray || function( obj ) {
1917		return jQuery.type(obj) === "array";
1918	},
1919
1920	isWindow: function( obj ) {
1921		/* jshint eqeqeq: false */
1922		return obj != null && obj == obj.window;
1923	},
1924
1925	isNumeric: function( obj ) {
1926		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
1927		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
1928		// subtraction forces infinities to NaN
1929		// adding 1 corrects loss of precision from parseFloat (#15100)
1930		return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1
vendor: 6,809 bytes, lines 1930-2233
1930) >= 0;
1931	},
1932
1933	isEmptyObject: function( obj ) {
1934		var name;
1935		for ( name in obj ) {
1936			return false;
1937		}
1938		return true;
1939	},
1940
1941	isPlainObject: function( obj ) {
1942		var key;
1943
1944		// Must be an Object.
1945		// Because of IE, we also have to check the presence of the constructor property.
1946		// Make sure that DOM nodes and window objects don't pass through, as well
1947		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
1948			return false;
1949		}
1950
1951		try {
1952			// Not own constructor property must be Object
1953			if ( obj.constructor &&
1954				!hasOwn.call(obj, "constructor") &&
1955				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
1956				return false;
1957			}
1958		} catch ( e ) {
1959			// IE8,9 Will throw exceptions on certain host objects #9897
1960			return false;
1961		}
1962
1963		// Support: IE<9
1964		// Handle iteration over inherited properties before own properties.
1965		if ( support.ownLast ) {
1966			for ( key in obj ) {
1967				return hasOwn.call( obj, key );
1968			}
1969		}
1970
1971		// Own properties are enumerated firstly, so to speed up,
1972		// if last one is own, then all properties are own.
1973		for ( key in obj ) {}
1974
1975		return key === undefined || hasOwn.call( obj, key );
1976	},
1977
1978	type: function( obj ) {
1979		if ( obj == null ) {
1980			return obj + "";
1981		}
1982		return typeof obj === "object" || typeof obj === "function" ?
1983			class2type[ toString.call(obj) ] || "object" :
1984			typeof obj;
1985	},
1986
1987	// Evaluates a script in a global context
1988	// Workarounds based on findings by Jim Driscoll
1989	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
1990	globalEval: function( data ) {
1991		if ( data && jQuery.trim( data ) ) {
1992			// We use execScript on Internet Explorer
1993			// We use an anonymous function so that context is window
1994			// rather than jQuery in Firefox
1995			( window.execScript || function( data ) {
1996				window[ "eval" ].call( window, data );
1997			} )( data );
1998		}
1999	},
2000
2001	// Convert dashed to camelCase; used by the css and data modules
2002	// Microsoft forgot to hump their vendor prefix (#9572)
2003	camelCase: function( string ) {
2004		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
2005	},
2006
2007	nodeName: function( elem, name ) {
2008		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
2009	},
2010
2011	// args is for internal usage only
2012	each: function( obj, callback, args ) {
2013		var value,
2014			i = 0,
2015			length = obj.length,
2016			isArray = isArraylike( obj );
2017
2018		if ( args ) {
2019			if ( isArray ) {
2020				for ( ; i < length; i++ ) {
2021					value = callback.apply( obj[ i ], args );
2022
2023					if ( value === false ) {
2024						break;
2025					}
2026				}
2027			} else {
2028				for ( i in obj ) {
2029					value = callback.apply( obj[ i ], args );
2030
2031					if ( value === false ) {
2032						break;
2033					}
2034				}
2035			}
2036
2037		// A special, fast, case for the most common use of each
2038		} else {
2039			if ( isArray ) {
2040				for ( ; i < length; i++ ) {
2041					value = callback.call( obj[ i ], i, obj[ i ] );
2042
2043					if ( value === false ) {
2044						break;
2045					}
2046				}
2047			} else {
2048				for ( i in obj ) {
2049					value = callback.call( obj[ i ], i, obj[ i ] );
2050
2051					if ( value === false ) {
2052						break;
2053					}
2054				}
2055			}
2056		}
2057
2058		return obj;
2059	},
2060
2061	// Support: Android<4.1, IE<9
2062	trim: function( text ) {
2063		return text == null ?
2064			"" :
2065			( text + "" ).replace( rtrim, "" );
2066	},
2067
2068	// results is for internal usage only
2069	makeArray: function( arr, results ) {
2070		var ret = results || [];
2071
2072		if ( arr != null ) {
2073			if ( isArraylike( Object(arr) ) ) {
2074				jQuery.merge( ret,
2075					typeof arr === "string" ?
2076					[ arr ] : arr
2077				);
2078			} else {
2079				push.call( ret, arr );
2080			}
2081		}
2082
2083		return ret;
2084	},
2085
2086	inArray: function( elem, arr, i ) {
2087		var len;
2088
2089		if ( arr ) {
2090			if ( indexOf ) {
2091				return indexOf.call( arr, elem, i );
2092			}
2093
2094			len = arr.length;
2095			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
2096
2097			for ( ; i < len; i++ ) {
2098				// Skip accessing in sparse arrays
2099				if ( i in arr && arr[ i ] === elem ) {
2100					return i;
2101				}
2102			}
2103		}
2104
2105		return -1;
2106	},
2107
2108	merge: function( first, second ) {
2109		var len = +second.length,
2110			j = 0,
2111			i = first.length;
2112
2113		while ( j < len ) {
2114			first[ i++ ] = second[ j++ ];
2115		}
2116
2117		// Support: IE<9
2118		// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
2119		if ( len !== len ) {
2120			while ( second[j] !== undefined ) {
2121				first[ i++ ] = second[ j++ ];
2122			}
2123		}
2124
2125		first.length = i;
2126
2127		return first;
2128	},
2129
2130	grep: function( elems, callback, invert ) {
2131		var callbackInverse,
2132			matches = [],
2133			i = 0,
2134			length = elems.length,
2135			callbackExpect = !invert;
2136
2137		// Go through the array, only saving the items
2138		// that pass the validator function
2139		for ( ; i < length; i++ ) {
2140			callbackInverse = !callback( elems[ i ], i );
2141			if ( callbackInverse !== callbackExpect ) {
2142				matches.push( elems[ i ] );
2143			}
2144		}
2145
2146		return matches;
2147	},
2148
2149	// arg is for internal usage only
2150	map: function( elems, callback, arg ) {
2151		var value,
2152			i = 0,
2153			length = elems.length,
2154			isArray = isArraylike( elems ),
2155			ret = [];
2156
2157		// Go through the array, translating each of the items to their new values
2158		if ( isArray ) {
2159			for ( ; i < length; i++ ) {
2160				value = callback( elems[ i ], i, arg );
2161
2162				if ( value != null ) {
2163					ret.push( value );
2164				}
2165			}
2166
2167		// Go through every key on the object,
2168		} else {
2169			for ( i in elems ) {
2170				value = callback( elems[ i ], i, arg );
2171
2172				if ( value != null ) {
2173					ret.push( value );
2174				}
2175			}
2176		}
2177
2178		// Flatten any nested arrays
2179		return concat.apply( [], ret );
2180	},
2181
2182	// A global GUID counter for objects
2183	guid: 1,
2184
2185	// Bind a function to a context, optionally partially applying any
2186	// arguments.
2187	proxy: function( fn, context ) {
2188		var args, proxy, tmp;
2189
2190		if ( typeof context === "string" ) {
2191			tmp = fn[ context ];
2192			context = fn;
2193			fn = tmp;
2194		}
2195
2196		// Quick check to determine if target is callable, in the spec
2197		// this throws a TypeError, but we will just return undefined.
2198		if ( !jQuery.isFunction( fn ) ) {
2199			return undefined;
2200		}
2201
2202		// Simulated bind
2203		args = slice.call( arguments, 2 );
2204		proxy = function() {
2205			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
2206		};
2207
2208		// Set the guid of unique handler to the same of original handler, so it can be removed
2209		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
2210
2211		return proxy;
2212	},
2213
2214	now: function() {
2215		return +( new Date() );
2216	},
2217
2218	// jQuery.support is not used in Core but other projects attach their
2219	// properties to it so it needs to exist.
2220	support: support
2221});
2222
2223// Populate the class2type map
2224jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
2225	class2type[ "[object " + name + "]" ] = name.toLowerCase();
2226});
2227
2228function isArraylike( obj ) {
2229	var length = obj.length,
2230		type = jQuery.type( obj );
2231
2232	if ( type === "function" || jQuery.isWindow( obj ) ) {
2233		return false;
vendor: 27,621 bytes, lines 2234-3196
2234	}
2235
2236	if ( obj.nodeType === 1 && length ) {
2237		return true;
2238	}
2239
2240	return type === "array" || length === 0 ||
2241		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
2242}
2243var Sizzle =
2244/*!
2245 * Sizzle CSS Selector Engine v2.2.0-pre
2246 * http://sizzlejs.com/
2247 *
2248 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
2249 * Released under the MIT license
2250 * http://jquery.org/license
2251 *
2252 * Date: 2014-12-16
2253 */
2254(function( window ) {
2255
2256var i,
2257	support,
2258	Expr,
2259	getText,
2260	isXML,
2261	tokenize,
2262	compile,
2263	select,
2264	outermostContext,
2265	sortInput,
2266	hasDuplicate,
2267
2268	// Local document vars
2269	setDocument,
2270	document,
2271	docElem,
2272	documentIsHTML,
2273	rbuggyQSA,
2274	rbuggyMatches,
2275	matches,
2276	contains,
2277
2278	// Instance-specific data
2279	expando = "sizzle" + 1 * new Date(),
2280	preferredDoc = window.document,
2281	dirruns = 0,
2282	done = 0,
2283	classCache = createCache(),
2284	tokenCache = createCache(),
2285	compilerCache = createCache(),
2286	sortOrder = function( a, b ) {
2287		if ( a === b ) {
2288			hasDuplicate = true;
2289		}
2290		return 0;
2291	},
2292
2293	// General-purpose constants
2294	MAX_NEGATIVE = 1 << 31,
2295
2296	// Instance methods
2297	hasOwn = ({}).hasOwnProperty,
2298	arr = [],
2299	pop = arr.pop,
2300	push_native = arr.push,
2301	push = arr.push,
2302	slice = arr.slice,
2303	// Use a stripped-down indexOf as it's faster than native
2304	// http://jsperf.com/thor-indexof-vs-for/5
2305	indexOf = function( list, elem ) {
2306		var i = 0,
2307			len = list.length;
2308		for ( ; i < len; i++ ) {
2309			if ( list[i] === elem ) {
2310				return i;
2311			}
2312		}
2313		return -1;
2314	},
2315
2316	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
2317
2318	// Regular expressions
2319
2320	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
2321	whitespace = "[\\x20\\t\\r\\n\\f]",
2322	// http://www.w3.org/TR/css3-syntax/#characters
2323	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
2324
2325	// Loosely modeled on CSS identifier characters
2326	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
2327	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
2328	identifier = characterEncoding.replace( "w", "w#" ),
2329
2330	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
2331	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
2332		// Operator (capture 2)
2333		"*([*^$|!~]?=)" + whitespace +
2334		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
2335		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
2336		"*\\]",
2337
2338	pseudos = ":(" + characterEncoding + ")(?:\\((" +
2339		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
2340		// 1. quoted (capture 3; capture 4 or capture 5)
2341		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
2342		// 2. simple (capture 6)
2343		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
2344		// 3. anything else (capture 2)
2345		".*" +
2346		")\\)|)",
2347
2348	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
2349	rwhitespace = new RegExp( whitespace + "+", "g" ),
2350	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
2351
2352	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
2353	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
2354
2355	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
2356
2357	rpseudo = new RegExp( pseudos ),
2358	ridentifier = new RegExp( "^" + identifier + "$" ),
2359
2360	matchExpr = {
2361		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
2362		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
2363		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
2364		"ATTR": new RegExp( "^" + attributes ),
2365		"PSEUDO": new RegExp( "^" + pseudos ),
2366		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
2367			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
2368			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
2369		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
2370		// For use in libraries implementing .is()
2371		// We use this for POS matching in `select`
2372		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
2373			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
2374	},
2375
2376	rinputs = /^(?:input|select|textarea|button)$/i,
2377	rheader = /^h\d$/i,
2378
2379	rnative = /^[^{]+\{\s*\[native \w/,
2380
2381	// Easily-parseable/retrievable ID or TAG or CLASS selectors
2382	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
2383
2384	rsibling = /[+~]/,
2385	rescape = /'|\\/g,
2386
2387	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
2388	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
2389	funescape = function( _, escaped, escapedWhitespace ) {
2390		var high = "0x" + escaped - 0x10000;
2391		// NaN means non-codepoint
2392		// Support: Firefox<24
2393		// Workaround erroneous numeric interpretation of +"0x"
2394		return high !== high || escapedWhitespace ?
2395			escaped :
2396			high < 0 ?
2397				// BMP codepoint
2398				String.fromCharCode( high + 0x10000 ) :
2399				// Supplemental Plane codepoint (surrogate pair)
2400				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
2401	},
2402
2403	// Used for iframes
2404	// See setDocument()
2405	// Removing the function wrapper causes a "Permission Denied"
2406	// error in IE
2407	unloadHandler = function() {
2408		setDocument();
2409	};
2410
2411// Optimize for push.apply( _, NodeList )
2412try {
2413	push.apply(
2414		(arr = slice.call( preferredDoc.childNodes )),
2415		preferredDoc.childNodes
2416	);
2417	// Support: Android<4.0
2418	// Detect silently failing push.apply
2419	arr[ preferredDoc.childNodes.length ].nodeType;
2420} catch ( e ) {
2421	push = { apply: arr.length ?
2422
2423		// Leverage slice if possible
2424		function( target, els ) {
2425			push_native.apply( target, slice.call(els) );
2426		} :
2427
2428		// Support: IE<9
2429		// Otherwise append directly
2430		function( target, els ) {
2431			var j = target.length,
2432				i = 0;
2433			// Can't trust NodeList.length
2434			while ( (target[j++] = els[i++]) ) {}
2435			target.length = j - 1;
2436		}
2437	};
2438}
2439
2440function Sizzle( selector, context, results, seed ) {
2441	var match, elem, m, nodeType,
2442		// QSA vars
2443		i, groups, old, nid, newContext, newSelector;
2444
2445	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
2446		setDocument( context );
2447	}
2448
2449	context = context || document;
2450	results = results || [];
2451	nodeType = context.nodeType;
2452
2453	if ( typeof selector !== "string" || !selector ||
2454		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
2455
2456		return results;
2457	}
2458
2459	if ( !seed && documentIsHTML ) {
2460
2461		// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
2462		if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
2463			// Speed-up: Sizzle("#ID")
2464			if ( (m = match[1]) ) {
2465				if ( nodeType === 9 ) {
2466					elem = context.getElementById( m );
2467					// Check parentNode to catch when Blackberry 4.6 returns
2468					// nodes that are no longer in the document (jQuery #6963)
2469					if ( elem && elem.parentNode ) {
2470						// Handle the case where IE, Opera, and Webkit return items
2471						// by name instead of ID
2472						if ( elem.id === m ) {
2473							results.push( elem );
2474							return results;
2475						}
2476					} else {
2477						return results;
2478					}
2479				} else {
2480					// Context is not a document
2481					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
2482						contains( context, elem ) && elem.id === m ) {
2483						results.push( elem );
2484						return results;
2485					}
2486				}
2487
2488			// Speed-up: Sizzle("TAG")
2489			} else if ( match[2] ) {
2490				push.apply( results, context.getElementsByTagName( selector ) );
2491				return results;
2492
2493			// Speed-up: Sizzle(".CLASS")
2494			} else if ( (m = match[3]) && support.getElementsByClassName ) {
2495				push.apply( results, context.getElementsByClassName( m ) );
2496				return results;
2497			}
2498		}
2499
2500		// QSA path
2501		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
2502			nid = old = expando;
2503			newContext = context;
2504			newSelector = nodeType !== 1 && selector;
2505
2506			// qSA works strangely on Element-rooted queries
2507			// We can work around this by specifying an extra ID on the root
2508			// and working up from there (Thanks to Andrew Dupont for the technique)
2509			// IE 8 doesn't work on object elements
2510			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
2511				groups = tokenize( selector );
2512
2513				if ( (old = context.getAttribute("id")) ) {
2514					nid = old.replace( rescape, "\\$&" );
2515				} else {
2516					context.setAttribute( "id", nid );
2517				}
2518				nid = "[id='" + nid + "'] ";
2519
2520				i = groups.length;
2521				while ( i-- ) {
2522					groups[i] = nid + toSelector( groups[i] );
2523				}
2524				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
2525				newSelector = groups.join(",");
2526			}
2527
2528			if ( newSelector ) {
2529				try {
2530					push.apply( results,
2531						newContext.querySelectorAll( newSelector )
2532					);
2533					return results;
2534				} catch(qsaError) {
2535				} finally {
2536					if ( !old ) {
2537						context.removeAttribute("id");
2538					}
2539				}
2540			}
2541		}
2542	}
2543
2544	// All others
2545	return select( selector.replace( rtrim, "$1" ), context, results, seed );
2546}
2547
2548/**
2549 * Create key-value caches of limited size
2550 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
2551 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
2552 *	deleting the oldest entry
2553 */
2554function createCache() {
2555	var keys = [];
2556
2557	function cache( key, value ) {
2558		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
2559		if ( keys.push( key + " " ) > Expr.cacheLength ) {
2560			// Only keep the most recent entries
2561			delete cache[ keys.shift() ];
2562		}
2563		return (cache[ key + " " ] = value);
2564	}
2565	return cache;
2566}
2567
2568/**
2569 * Mark a function for special use by Sizzle
2570 * @param {Function} fn The function to mark
2571 */
2572function markFunction( fn ) {
2573	fn[ expando ] = true;
2574	return fn;
2575}
2576
2577/**
2578 * Support testing using an element
2579 * @param {Function} fn Passed the created div and expects a boolean result
2580 */
2581function assert( fn ) {
2582	var div = document.createElement("div");
2583
2584	try {
2585		return !!fn( div );
2586	} catch (e) {
2587		return false;
2588	} finally {
2589		// Remove from its parent by default
2590		if ( div.parentNode ) {
2591			div.parentNode.removeChild( div );
2592		}
2593		// release memory in IE
2594		div = null;
2595	}
2596}
2597
2598/**
2599 * Adds the same handler for all of the specified attrs
2600 * @param {String} attrs Pipe-separated list of attributes
2601 * @param {Function} handler The method that will be applied
2602 */
2603function addHandle( attrs, handler ) {
2604	var arr = attrs.split("|"),
2605		i = attrs.length;
2606
2607	while ( i-- ) {
2608		Expr.attrHandle[ arr[i] ] = handler;
2609	}
2610}
2611
2612/**
2613 * Checks document order of two siblings
2614 * @param {Element} a
2615 * @param {Element} b
2616 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
2617 */
2618function siblingCheck( a, b ) {
2619	var cur = b && a,
2620		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
2621			( ~b.sourceIndex || MAX_NEGATIVE ) -
2622			( ~a.sourceIndex || MAX_NEGATIVE );
2623
2624	// Use IE sourceIndex if available on both nodes
2625	if ( diff ) {
2626		return diff;
2627	}
2628
2629	// Check if b follows a
2630	if ( cur ) {
2631		while ( (cur = cur.nextSibling) ) {
2632			if ( cur === b ) {
2633				return -1;
2634			}
2635		}
2636	}
2637
2638	return a ? 1 : -1;
2639}
2640
2641/**
2642 * Returns a function to use in pseudos for input types
2643 * @param {String} type
2644 */
2645function createInputPseudo( type ) {
2646	return function( elem ) {
2647		var name = elem.nodeName.toLowerCase();
2648		return name === "input" && elem.type === type;
2649	};
2650}
2651
2652/**
2653 * Returns a function to use in pseudos for buttons
2654 * @param {String} type
2655 */
2656function createButtonPseudo( type ) {
2657	return function( elem ) {
2658		var name = elem.nodeName.toLowerCase();
2659		return (name === "input" || name === "button") && elem.type === type;
2660	};
2661}
2662
2663/**
2664 * Returns a function to use in pseudos for positionals
2665 * @param {Function} fn
2666 */
2667function createPositionalPseudo( fn ) {
2668	return markFunction(function( argument ) {
2669		argument = +argument;
2670		return markFunction(function( seed, matches ) {
2671			var j,
2672				matchIndexes = fn( [], seed.length, argument ),
2673				i = matchIndexes.length;
2674
2675			// Match elements found at the specified indexes
2676			while ( i-- ) {
2677				if ( seed[ (j = matchIndexes[i]) ] ) {
2678					seed[j] = !(matches[j] = seed[j]);
2679				}
2680			}
2681		});
2682	});
2683}
2684
2685/**
2686 * Checks a node for validity as a Sizzle context
2687 * @param {Element|Object=} context
2688 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
2689 */
2690function testContext( context ) {
2691	return context && typeof context.getElementsByTagName !== "undefined" && context;
2692}
2693
2694// Expose support vars for convenience
2695support = Sizzle.support = {};
2696
2697/**
2698 * Detects XML nodes
2699 * @param {Element|Object} elem An element or a document
2700 * @returns {Boolean} True iff elem is a non-HTML XML node
2701 */
2702isXML = Sizzle.isXML = function( elem ) {
2703	// documentElement is verified for cases where it doesn't yet exist
2704	// (such as loading iframes in IE - #4833)
2705	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
2706	return documentElement ? documentElement.nodeName !== "HTML" : false;
2707};
2708
2709/**
2710 * Sets document-related variables once based on the current document
2711 * @param {Element|Object} [doc] An element or document object to use to set the document
2712 * @returns {Object} Returns the current document
2713 */
2714setDocument = Sizzle.setDocument = function( node ) {
2715	var hasCompare, parent,
2716		doc = node ? node.ownerDocument || node : preferredDoc;
2717
2718	// If no document and documentElement is available, return
2719	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
2720		return document;
2721	}
2722
2723	// Set our document
2724	document = doc;
2725	docElem = doc.documentElement;
2726	parent = doc.defaultView;
2727
2728	// Support: IE>8
2729	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
2730	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
2731	// IE6-8 do not support the defaultView property so parent will be undefined
2732	if ( parent && parent !== parent.top ) {
2733		// IE11 does not have attachEvent, so all must suffer
2734		if ( parent.addEventListener ) {
2735			parent.addEventListener( "unload", unloadHandler, false );
2736		} else if ( parent.attachEvent ) {
2737			parent.attachEvent( "onunload", unloadHandler );
2738		}
2739	}
2740
2741	/* Support tests
2742	---------------------------------------------------------------------- */
2743	documentIsHTML = !isXML( doc );
2744
2745	/* Attributes
2746	---------------------------------------------------------------------- */
2747
2748	// Support: IE<8
2749	// Verify that getAttribute really returns attributes and not properties
2750	// (excepting IE8 booleans)
2751	support.attributes = assert(function( div ) {
2752		div.className = "i";
2753		return !div.getAttribute("className");
2754	});
2755
2756	/* getElement(s)By*
2757	---------------------------------------------------------------------- */
2758
2759	// Check if getElementsByTagName("*") returns only elements
2760	support.getElementsByTagName = assert(function( div ) {
2761		div.appendChild( doc.createComment("") );
2762		return !div.getElementsByTagName("*").length;
2763	});
2764
2765	// Support: IE<9
2766	support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
2767
2768	// Support: IE<10
2769	// Check if getElementById returns elements by name
2770	// The broken getElementById methods don't pick up programatically-set names,
2771	// so use a roundabout getElementsByName test
2772	support.getById = assert(function( div ) {
2773		docElem.appendChild( div ).id = expando;
2774		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
2775	});
2776
2777	// ID find and filter
2778	if ( support.getById ) {
2779		Expr.find["ID"] = function( id, context ) {
2780			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
2781				var m = context.getElementById( id );
2782				// Check parentNode to catch when Blackberry 4.6 returns
2783				// nodes that are no longer in the document #6963
2784				return m && m.parentNode ? [ m ] : [];
2785			}
2786		};
2787		Expr.filter["ID"] = function( id ) {
2788			var attrId = id.replace( runescape, funescape );
2789			return function( elem ) {
2790				return elem.getAttribute("id") === attrId;
2791			};
2792		};
2793	} else {
2794		// Support: IE6/7
2795		// getElementById is not reliable as a find shortcut
2796		delete Expr.find["ID"];
2797
2798		Expr.filter["ID"] =  function( id ) {
2799			var attrId = id.replace( runescape, funescape );
2800			return function( elem ) {
2801				var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
2802				return node && node.value === attrId;
2803			};
2804		};
2805	}
2806
2807	// Tag
2808	Expr.find["TAG"] = support.getElementsByTagName ?
2809		function( tag, context ) {
2810			if ( typeof context.getElementsByTagName !== "undefined" ) {
2811				return context.getElementsByTagName( tag );
2812
2813			// DocumentFragment nodes don't have gEBTN
2814			} else if ( support.qsa ) {
2815				return context.querySelectorAll( tag );
2816			}
2817		} :
2818
2819		function( tag, context ) {
2820			var elem,
2821				tmp = [],
2822				i = 0,
2823				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
2824				results = context.getElementsByTagName( tag );
2825
2826			// Filter out possible comments
2827			if ( tag === "*" ) {
2828				while ( (elem = results[i++]) ) {
2829					if ( elem.nodeType === 1 ) {
2830						tmp.push( elem );
2831					}
2832				}
2833
2834				return tmp;
2835			}
2836			return results;
2837		};
2838
2839	// Class
2840	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
2841		if ( documentIsHTML ) {
2842			return context.getElementsByClassName( className );
2843		}
2844	};
2845
2846	/* QSA/matchesSelector
2847	---------------------------------------------------------------------- */
2848
2849	// QSA and matchesSelector support
2850
2851	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
2852	rbuggyMatches = [];
2853
2854	// qSa(:focus) reports false when true (Chrome 21)
2855	// We allow this because of a bug in IE8/9 that throws an error
2856	// whenever `document.activeElement` is accessed on an iframe
2857	// So, we allow :focus to pass through QSA all the time to avoid the IE error
2858	// See http://bugs.jquery.com/ticket/13378
2859	rbuggyQSA = [];
2860
2861	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
2862		// Build QSA regex
2863		// Regex strategy adopted from Diego Perini
2864		assert(function( div ) {
2865			// Select is set to empty string on purpose
2866			// This is to test IE's treatment of not explicitly
2867			// setting a boolean content attribute,
2868			// since its presence should be enough
2869			// http://bugs.jquery.com/ticket/12359
2870			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
2871				"<select id='" + expando + "-\f]' msallowcapture=''>" +
2872				"<option selected=''></option></select>";
2873
2874			// Support: IE8, Opera 11-12.16
2875			// Nothing should be selected when empty strings follow ^= or $= or *=
2876			// The test attribute must be unknown in Opera but "safe" for WinRT
2877			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
2878			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
2879				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
2880			}
2881
2882			// Support: IE8
2883			// Boolean attributes and "value" are not treated correctly
2884			if ( !div.querySelectorAll("[selected]").length ) {
2885				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
2886			}
2887
2888			// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
2889			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
2890				rbuggyQSA.push("~=");
2891			}
2892
2893			// Webkit/Opera - :checked should return selected option elements
2894			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2895			// IE8 throws error here and will not see later tests
2896			if ( !div.querySelectorAll(":checked").length ) {
2897				rbuggyQSA.push(":checked");
2898			}
2899
2900			// Support: Safari 8+, iOS 8+
2901			// https://bugs.webkit.org/show_bug.cgi?id=136851
2902			// In-page `selector#id sibing-combinator selector` fails
2903			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
2904				rbuggyQSA.push(".#.+[+~]");
2905			}
2906		});
2907
2908		assert(function( div ) {
2909			// Support: Windows 8 Native Apps
2910			// The type and name attributes are restricted during .innerHTML assignment
2911			var input = doc.createElement("input");
2912			input.setAttribute( "type", "hidden" );
2913			div.appendChild( input ).setAttribute( "name", "D" );
2914
2915			// Support: IE8
2916			// Enforce case-sensitivity of name attribute
2917			if ( div.querySelectorAll("[name=d]").length ) {
2918				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
2919			}
2920
2921			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
2922			// IE8 throws error here and will not see later tests
2923			if ( !div.querySelectorAll(":enabled").length ) {
2924				rbuggyQSA.push( ":enabled", ":disabled" );
2925			}
2926
2927			// Opera 10-11 does not throw on post-comma invalid pseudos
2928			div.querySelectorAll("*,:x");
2929			rbuggyQSA.push(",.*:");
2930		});
2931	}
2932
2933	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
2934		docElem.webkitMatchesSelector ||
2935		docElem.mozMatchesSelector ||
2936		docElem.oMatchesSelector ||
2937		docElem.msMatchesSelector) )) ) {
2938
2939		assert(function( div ) {
2940			// Check to see if it's possible to do matchesSelector
2941			// on a disconnected node (IE 9)
2942			support.disconnectedMatch = matches.call( div, "div" );
2943
2944			// This should fail with an exception
2945			// Gecko does not error, returns false instead
2946			matches.call( div, "[s!='']:x" );
2947			rbuggyMatches.push( "!=", pseudos );
2948		});
2949	}
2950
2951	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
2952	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
2953
2954	/* Contains
2955	---------------------------------------------------------------------- */
2956	hasCompare = rnative.test( docElem.compareDocumentPosition );
2957
2958	// Element contains another
2959	// Purposefully does not implement inclusive descendent
2960	// As in, an element does not contain itself
2961	contains = hasCompare || rnative.test( docElem.contains ) ?
2962		function( a, b ) {
2963			var adown = a.nodeType === 9 ? a.documentElement : a,
2964				bup = b && b.parentNode;
2965			return a === bup || !!( bup && bup.nodeType === 1 && (
2966				adown.contains ?
2967					adown.contains( bup ) :
2968					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
2969			));
2970		} :
2971		function( a, b ) {
2972			if ( b ) {
2973				while ( (b = b.parentNode) ) {
2974					if ( b === a ) {
2975						return true;
2976					}
2977				}
2978			}
2979			return false;
2980		};
2981
2982	/* Sorting
2983	---------------------------------------------------------------------- */
2984
2985	// Document order sorting
2986	sortOrder = hasCompare ?
2987	function( a, b ) {
2988
2989		// Flag for duplicate removal
2990		if ( a === b ) {
2991			hasDuplicate = true;
2992			return 0;
2993		}
2994
2995		// Sort on method existence if only one input has compareDocumentPosition
2996		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
2997		if ( compare ) {
2998			return compare;
2999		}
3000
3001		// Calculate position if both inputs belong to the same document
3002		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
3003			a.compareDocumentPosition( b ) :
3004
3005			// Otherwise we know they are disconnected
3006			1;
3007
3008		// Disconnected nodes
3009		if ( compare & 1 ||
3010			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
3011
3012			// Choose the first element that is related to our preferred document
3013			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
3014				return -1;
3015			}
3016			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
3017				return 1;
3018			}
3019
3020			// Maintain original order
3021			return sortInput ?
3022				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
3023				0;
3024		}
3025
3026		return compare & 4 ? -1 : 1;
3027	} :
3028	function( a, b ) {
3029		// Exit early if the nodes are identical
3030		if ( a === b ) {
3031			hasDuplicate = true;
3032			return 0;
3033		}
3034
3035		var cur,
3036			i = 0,
3037			aup = a.parentNode,
3038			bup = b.parentNode,
3039			ap = [ a ],
3040			bp = [ b ];
3041
3042		// Parentless nodes are either documents or disconnected
3043		if ( !aup || !bup ) {
3044			return a === doc ? -1 :
3045				b === doc ? 1 :
3046				aup ? -1 :
3047				bup ? 1 :
3048				sortInput ?
3049				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
3050				0;
3051
3052		// If the nodes are siblings, we can do a quick check
3053		} else if ( aup === bup ) {
3054			return siblingCheck( a, b );
3055		}
3056
3057		// Otherwise we need full lists of their ancestors for comparison
3058		cur = a;
3059		while ( (cur = cur.parentNode) ) {
3060			ap.unshift( cur );
3061		}
3062		cur = b;
3063		while ( (cur = cur.parentNode) ) {
3064			bp.unshift( cur );
3065		}
3066
3067		// Walk down the tree looking for a discrepancy
3068		while ( ap[i] === bp[i] ) {
3069			i++;
3070		}
3071
3072		return i ?
3073			// Do a sibling check if the nodes have a common ancestor
3074			siblingCheck( ap[i], bp[i] ) :
3075
3076			// Otherwise nodes in our document sort first
3077			ap[i] === preferredDoc ? -1 :
3078			bp[i] === preferredDoc ? 1 :
3079			0;
3080	};
3081
3082	return doc;
3083};
3084
3085Sizzle.matches = function( expr, elements ) {
3086	return Sizzle( expr, null, null, elements );
3087};
3088
3089Sizzle.matchesSelector = function( elem, expr ) {
3090	// Set document vars if needed
3091	if ( ( elem.ownerDocument || elem ) !== document ) {
3092		setDocument( elem );
3093	}
3094
3095	// Make sure that attribute selectors are quoted
3096	expr = expr.replace( rattributeQuotes, "='$1']" );
3097
3098	if ( support.matchesSelector && documentIsHTML &&
3099		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
3100		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
3101
3102		try {
3103			var ret = matches.call( elem, expr );
3104
3105			// IE 9's matchesSelector returns false on disconnected nodes
3106			if ( ret || support.disconnectedMatch ||
3107					// As well, disconnected nodes are said to be in a document
3108					// fragment in IE 9
3109					elem.document && elem.document.nodeType !== 11 ) {
3110				return ret;
3111			}
3112		} catch (e) {}
3113	}
3114
3115	return Sizzle( expr, document, null, [ elem ] ).length > 0;
3116};
3117
3118Sizzle.contains = function( context, elem ) {
3119	// Set document vars if needed
3120	if ( ( context.ownerDocument || context ) !== document ) {
3121		setDocument( context );
3122	}
3123	return contains( context, elem );
3124};
3125
3126Sizzle.attr = function( elem, name ) {
3127	// Set document vars if needed
3128	if ( ( elem.ownerDocument || elem ) !== document ) {
3129		setDocument( elem );
3130	}
3131
3132	var fn = Expr.attrHandle[ name.toLowerCase() ],
3133		// Don't get fooled by Object.prototype properties (jQuery #13807)
3134		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
3135			fn( elem, name, !documentIsHTML ) :
3136			undefined;
3137
3138	return val !== undefined ?
3139		val :
3140		support.attributes || !documentIsHTML ?
3141			elem.getAttribute( name ) :
3142			(val = elem.getAttributeNode(name)) && val.specified ?
3143				val.value :
3144				null;
3145};
3146
3147Sizzle.error = function( msg ) {
3148	throw new Error( "Syntax error, unrecognized expression: " + msg );
3149};
3150
3151/**
3152 * Document sorting and removing duplicates
3153 * @param {ArrayLike} results
3154 */
3155Sizzle.uniqueSort = function( results ) {
3156	var elem,
3157		duplicates = [],
3158		j = 0,
3159		i = 0;
3160
3161	// Unless we *know* we can detect duplicates, assume their presence
3162	hasDuplicate = !support.detectDuplicates;
3163	sortInput = !support.sortStable && results.slice( 0 );
3164	results.sort( sortOrder );
3165
3166	if ( hasDuplicate ) {
3167		while ( (elem = results[i++]) ) {
3168			if ( elem === results[ i ] ) {
3169				j = duplicates.push( i );
3170			}
3171		}
3172		while ( j-- ) {
3173			results.splice( duplicates[ j ], 1 );
3174		}
3175	}
3176
3177	// Clear input after sorting to release objects
3178	// See https://github.com/jquery/sizzle/pull/225
3179	sortInput = null;
3180
3181	return results;
3182};
3183
3184/**
3185 * Utility function for retrieving the text value of an array of DOM nodes
3186 * @param {Array|Element} elem
3187 */
3188getText = Sizzle.getText = function( elem ) {
3189	var node,
3190		ret = "",
3191		i = 0,
3192		nodeType = elem.nodeType;
3193
3194	if ( !nodeType ) {
3195		// If no nodeType, this is expected to be an array
3196		while ( (node = elem[i++]) ) {
vendor: 4,161 bytes, lines 3197-3349
3197			// Do not traverse comment nodes
3198			ret += getText( node );
3199		}
3200	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
3201		// Use textContent for elements
3202		// innerText usage removed for consistency of new lines (jQuery #11153)
3203		if ( typeof elem.textContent === "string" ) {
3204			return elem.textContent;
3205		} else {
3206			// Traverse its children
3207			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
3208				ret += getText( elem );
3209			}
3210		}
3211	} else if ( nodeType === 3 || nodeType === 4 ) {
3212		return elem.nodeValue;
3213	}
3214	// Do not include comment or processing instruction nodes
3215
3216	return ret;
3217};
3218
3219Expr = Sizzle.selectors = {
3220
3221	// Can be adjusted by the user
3222	cacheLength: 50,
3223
3224	createPseudo: markFunction,
3225
3226	match: matchExpr,
3227
3228	attrHandle: {},
3229
3230	find: {},
3231
3232	relative: {
3233		">": { dir: "parentNode", first: true },
3234		" ": { dir: "parentNode" },
3235		"+": { dir: "previousSibling", first: true },
3236		"~": { dir: "previousSibling" }
3237	},
3238
3239	preFilter: {
3240		"ATTR": function( match ) {
3241			match[1] = match[1].replace( runescape, funescape );
3242
3243			// Move the given value to match[3] whether quoted or unquoted
3244			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
3245
3246			if ( match[2] === "~=" ) {
3247				match[3] = " " + match[3] + " ";
3248			}
3249
3250			return match.slice( 0, 4 );
3251		},
3252
3253		"CHILD": function( match ) {
3254			/* matches from matchExpr["CHILD"]
3255				1 type (only|nth|...)
3256				2 what (child|of-type)
3257				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
3258				4 xn-component of xn+y argument ([+-]?\d*n|)
3259				5 sign of xn-component
3260				6 x of xn-component
3261				7 sign of y-component
3262				8 y of y-component
3263			*/
3264			match[1] = match[1].toLowerCase();
3265
3266			if ( match[1].slice( 0, 3 ) === "nth" ) {
3267				// nth-* requires argument
3268				if ( !match[3] ) {
3269					Sizzle.error( match[0] );
3270				}
3271
3272				// numeric x and y parameters for Expr.filter.CHILD
3273				// remember that false/true cast respectively to 0/1
3274				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
3275				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
3276
3277			// other types prohibit arguments
3278			} else if ( match[3] ) {
3279				Sizzle.error( match[0] );
3280			}
3281
3282			return match;
3283		},
3284
3285		"PSEUDO": function( match ) {
3286			var excess,
3287				unquoted = !match[6] && match[2];
3288
3289			if ( matchExpr["CHILD"].test( match[0] ) ) {
3290				return null;
3291			}
3292
3293			// Accept quoted arguments as-is
3294			if ( match[3] ) {
3295				match[2] = match[4] || match[5] || "";
3296
3297			// Strip excess characters from unquoted arguments
3298			} else if ( unquoted && rpseudo.test( unquoted ) &&
3299				// Get excess from tokenize (recursively)
3300				(excess = tokenize( unquoted, true )) &&
3301				// advance to the next closing parenthesis
3302				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
3303
3304				// excess is a negative index
3305				match[0] = match[0].slice( 0, excess );
3306				match[2] = unquoted.slice( 0, excess );
3307			}
3308
3309			// Return only captures needed by the pseudo filter method (type and argument)
3310			return match.slice( 0, 3 );
3311		}
3312	},
3313
3314	filter: {
3315
3316		"TAG": function( nodeNameSelector ) {
3317			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
3318			return nodeNameSelector === "*" ?
3319				function() { return true; } :
3320				function( elem ) {
3321					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
3322				};
3323		},
3324
3325		"CLASS": function( className ) {
3326			var pattern = classCache[ className + " " ];
3327
3328			return pattern ||
3329				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
3330				classCache( className, function( elem ) {
3331					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
3332				});
3333		},
3334
3335		"ATTR": function( name, operator, check ) {
3336			return function( elem ) {
3337				var result = Sizzle.attr( elem, name );
3338
3339				if ( result == null ) {
3340					return operator === "!=";
3341				}
3342				if ( !operator ) {
3343					return true;
3344				}
3345
3346				result += "";
3347
3348				return operator === "=" ? result === check :
3349					operator === "!=" ? result !== check :
vendor: 6,854 bytes, lines 3350-3555
3350					operator === "^=" ? check && result.indexOf( check ) === 0 :
3351					operator === "*=" ? check && result.indexOf( check ) > -1 :
3352					operator === "$=" ? check && result.slice( -check.length ) === check :
3353					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
3354					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
3355					false;
3356			};
3357		},
3358
3359		"CHILD": function( type, what, argument, first, last ) {
3360			var simple = type.slice( 0, 3 ) !== "nth",
3361				forward = type.slice( -4 ) !== "last",
3362				ofType = what === "of-type";
3363
3364			return first === 1 && last === 0 ?
3365
3366				// Shortcut for :nth-*(n)
3367				function( elem ) {
3368					return !!elem.parentNode;
3369				} :
3370
3371				function( elem, context, xml ) {
3372					var cache, outerCache, node, diff, nodeIndex, start,
3373						dir = simple !== forward ? "nextSibling" : "previousSibling",
3374						parent = elem.parentNode,
3375						name = ofType && elem.nodeName.toLowerCase(),
3376						useCache = !xml && !ofType;
3377
3378					if ( parent ) {
3379
3380						// :(first|last|only)-(child|of-type)
3381						if ( simple ) {
3382							while ( dir ) {
3383								node = elem;
3384								while ( (node = node[ dir ]) ) {
3385									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
3386										return false;
3387									}
3388								}
3389								// Reverse direction for :only-* (if we haven't yet done so)
3390								start = dir = type === "only" && !start && "nextSibling";
3391							}
3392							return true;
3393						}
3394
3395						start = [ forward ? parent.firstChild : parent.lastChild ];
3396
3397						// non-xml :nth-child(...) stores cache data on `parent`
3398						if ( forward && useCache ) {
3399							// Seek `elem` from a previously-cached index
3400							outerCache = parent[ expando ] || (parent[ expando ] = {});
3401							cache = outerCache[ type ] || [];
3402							nodeIndex = cache[0] === dirruns && cache[1];
3403							diff = cache[0] === dirruns && cache[2];
3404							node = nodeIndex && parent.childNodes[ nodeIndex ];
3405
3406							while ( (node = ++nodeIndex && node && node[ dir ] ||
3407
3408								// Fallback to seeking `elem` from the start
3409								(diff = nodeIndex = 0) || start.pop()) ) {
3410
3411								// When found, cache indexes on `parent` and break
3412								if ( node.nodeType === 1 && ++diff && node === elem ) {
3413									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
3414									break;
3415								}
3416							}
3417
3418						// Use previously-cached element index if available
3419						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
3420							diff = cache[1];
3421
3422						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
3423						} else {
3424							// Use the same loop as above to seek `elem` from the start
3425							while ( (node = ++nodeIndex && node && node[ dir ] ||
3426								(diff = nodeIndex = 0) || start.pop()) ) {
3427
3428								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
3429									// Cache the index of each encountered element
3430									if ( useCache ) {
3431										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
3432									}
3433
3434									if ( node === elem ) {
3435										break;
3436									}
3437								}
3438							}
3439						}
3440
3441						// Incorporate the offset, then check against cycle size
3442						diff -= last;
3443						return diff === first || ( diff % first === 0 && diff / first >= 0 );
3444					}
3445				};
3446		},
3447
3448		"PSEUDO": function( pseudo, argument ) {
3449			// pseudo-class names are case-insensitive
3450			// http://www.w3.org/TR/selectors/#pseudo-classes
3451			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
3452			// Remember that setFilters inherits from pseudos
3453			var args,
3454				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
3455					Sizzle.error( "unsupported pseudo: " + pseudo );
3456
3457			// The user may use createPseudo to indicate that
3458			// arguments are needed to create the filter function
3459			// just as Sizzle does
3460			if ( fn[ expando ] ) {
3461				return fn( argument );
3462			}
3463
3464			// But maintain support for old signatures
3465			if ( fn.length > 1 ) {
3466				args = [ pseudo, pseudo, "", argument ];
3467				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
3468					markFunction(function( seed, matches ) {
3469						var idx,
3470							matched = fn( seed, argument ),
3471							i = matched.length;
3472						while ( i-- ) {
3473							idx = indexOf( seed, matched[i] );
3474							seed[ idx ] = !( matches[ idx ] = matched[i] );
3475						}
3476					}) :
3477					function( elem ) {
3478						return fn( elem, 0, args );
3479					};
3480			}
3481
3482			return fn;
3483		}
3484	},
3485
3486	pseudos: {
3487		// Potentially complex pseudos
3488		"not": markFunction(function( selector ) {
3489			// Trim the selector passed to compile
3490			// to avoid treating leading and trailing
3491			// spaces as combinators
3492			var input = [],
3493				results = [],
3494				matcher = compile( selector.replace( rtrim, "$1" ) );
3495
3496			return matcher[ expando ] ?
3497				markFunction(function( seed, matches, context, xml ) {
3498					var elem,
3499						unmatched = matcher( seed, null, xml, [] ),
3500						i = seed.length;
3501
3502					// Match elements unmatched by `matcher`
3503					while ( i-- ) {
3504						if ( (elem = unmatched[i]) ) {
3505							seed[i] = !(matches[i] = elem);
3506						}
3507					}
3508				}) :
3509				function( elem, context, xml ) {
3510					input[0] = elem;
3511					matcher( input, null, xml, results );
3512					// Don't keep the element (issue #299)
3513					input[0] = null;
3514					return !results.pop();
3515				};
3516		}),
3517
3518		"has": markFunction(function( selector ) {
3519			return function( elem ) {
3520				return Sizzle( selector, elem ).length > 0;
3521			};
3522		}),
3523
3524		"contains": markFunction(function( text ) {
3525			text = text.replace( runescape, funescape );
3526			return function( elem ) {
3527				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
3528			};
3529		}),
3530
3531		// "Whether an element is represented by a :lang() selector
3532		// is based solely on the element's language value
3533		// being equal to the identifier C,
3534		// or beginning with the identifier C immediately followed by "-".
3535		// The matching of C against the element's language value is performed case-insensitively.
3536		// The identifier C does not have to be a valid language name."
3537		// http://www.w3.org/TR/selectors/#lang-pseudo
3538		"lang": markFunction( function( lang ) {
3539			// lang value must be a valid identifier
3540			if ( !ridentifier.test(lang || "") ) {
3541				Sizzle.error( "unsupported lang: " + lang );
3542			}
3543			lang = lang.replace( runescape, funescape ).toLowerCase();
3544			return function( elem ) {
3545				var elemLang;
3546				do {
3547					if ( (elemLang = documentIsHTML ?
3548						elem.lang :
3549						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
3550
3551						elemLang = elemLang.toLowerCase();
3552						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
3553					}
3554				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
3555				return false;
vendor: 4,543 bytes, lines 3556-3727
3556			};
3557		}),
3558
3559		// Miscellaneous
3560		"target": function( elem ) {
3561			var hash = window.location && window.location.hash;
3562			return hash && hash.slice( 1 ) === elem.id;
3563		},
3564
3565		"root": function( elem ) {
3566			return elem === docElem;
3567		},
3568
3569		"focus": function( elem ) {
3570			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
3571		},
3572
3573		// Boolean properties
3574		"enabled": function( elem ) {
3575			return elem.disabled === false;
3576		},
3577
3578		"disabled": function( elem ) {
3579			return elem.disabled === true;
3580		},
3581
3582		"checked": function( elem ) {
3583			// In CSS3, :checked should return both checked and selected elements
3584			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
3585			var nodeName = elem.nodeName.toLowerCase();
3586			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
3587		},
3588
3589		"selected": function( elem ) {
3590			// Accessing this property makes selected-by-default
3591			// options in Safari work properly
3592			if ( elem.parentNode ) {
3593				elem.parentNode.selectedIndex;
3594			}
3595
3596			return elem.selected === true;
3597		},
3598
3599		// Contents
3600		"empty": function( elem ) {
3601			// http://www.w3.org/TR/selectors/#empty-pseudo
3602			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
3603			//   but not by others (comment: 8; processing instruction: 7; etc.)
3604			// nodeType < 6 works because attributes (2) do not appear as children
3605			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
3606				if ( elem.nodeType < 6 ) {
3607					return false;
3608				}
3609			}
3610			return true;
3611		},
3612
3613		"parent": function( elem ) {
3614			return !Expr.pseudos["empty"]( elem );
3615		},
3616
3617		// Element/input types
3618		"header": function( elem ) {
3619			return rheader.test( elem.nodeName );
3620		},
3621
3622		"input": function( elem ) {
3623			return rinputs.test( elem.nodeName );
3624		},
3625
3626		"button": function( elem ) {
3627			var name = elem.nodeName.toLowerCase();
3628			return name === "input" && elem.type === "button" || name === "button";
3629		},
3630
3631		"text": function( elem ) {
3632			var attr;
3633			return elem.nodeName.toLowerCase() === "input" &&
3634				elem.type === "text" &&
3635
3636				// Support: IE<8
3637				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
3638				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
3639		},
3640
3641		// Position-in-collection
3642		"first": createPositionalPseudo(function() {
3643			return [ 0 ];
3644		}),
3645
3646		"last": createPositionalPseudo(function( matchIndexes, length ) {
3647			return [ length - 1 ];
3648		}),
3649
3650		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
3651			return [ argument < 0 ? argument + length : argument ];
3652		}),
3653
3654		"even": createPositionalPseudo(function( matchIndexes, length ) {
3655			var i = 0;
3656			for ( ; i < length; i += 2 ) {
3657				matchIndexes.push( i );
3658			}
3659			return matchIndexes;
3660		}),
3661
3662		"odd": createPositionalPseudo(function( matchIndexes, length ) {
3663			var i = 1;
3664			for ( ; i < length; i += 2 ) {
3665				matchIndexes.push( i );
3666			}
3667			return matchIndexes;
3668		}),
3669
3670		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
3671			var i = argument < 0 ? argument + length : argument;
3672			for ( ; --i >= 0; ) {
3673				matchIndexes.push( i );
3674			}
3675			return matchIndexes;
3676		}),
3677
3678		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
3679			var i = argument < 0 ? argument + length : argument;
3680			for ( ; ++i < length; ) {
3681				matchIndexes.push( i );
3682			}
3683			return matchIndexes;
3684		})
3685	}
3686};
3687
3688Expr.pseudos["nth"] = Expr.pseudos["eq"];
3689
3690// Add button/input type pseudos
3691for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
3692	Expr.pseudos[ i ] = createInputPseudo( i );
3693}
3694for ( i in { submit: true, reset: true } ) {
3695	Expr.pseudos[ i ] = createButtonPseudo( i );
3696}
3697
3698// Easy API for creating new setFilters
3699function setFilters() {}
3700setFilters.prototype = Expr.filters = Expr.pseudos;
3701Expr.setFilters = new setFilters();
3702
3703tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
3704	var matched, match, tokens, type,
3705		soFar, groups, preFilters,
3706		cached = tokenCache[ selector + " " ];
3707
3708	if ( cached ) {
3709		return parseOnly ? 0 : cached.slice( 0 );
3710	}
3711
3712	soFar = selector;
3713	groups = [];
3714	preFilters = Expr.preFilter;
3715
3716	while ( soFar ) {
3717
3718		// Comma and first run
3719		if ( !matched || (match = rcomma.exec( soFar )) ) {
3720			if ( match ) {
3721				// Don't consume trailing commas as valid
3722				soFar = soFar.slice( match[0].length ) || soFar;
3723			}
3724			groups.push( (tokens = []) );
3725		}
3726
3727		matched = false;
vendor: 17,197 bytes, lines 3728-4349
3728
3729		// Combinators
3730		if ( (match = rcombinators.exec( soFar )) ) {
3731			matched = match.shift();
3732			tokens.push({
3733				value: matched,
3734				// Cast descendant combinators to space
3735				type: match[0].replace( rtrim, " " )
3736			});
3737			soFar = soFar.slice( matched.length );
3738		}
3739
3740		// Filters
3741		for ( type in Expr.filter ) {
3742			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
3743				(match = preFilters[ type ]( match ))) ) {
3744				matched = match.shift();
3745				tokens.push({
3746					value: matched,
3747					type: type,
3748					matches: match
3749				});
3750				soFar = soFar.slice( matched.length );
3751			}
3752		}
3753
3754		if ( !matched ) {
3755			break;
3756		}
3757	}
3758
3759	// Return the length of the invalid excess
3760	// if we're just parsing
3761	// Otherwise, throw an error or return tokens
3762	return parseOnly ?
3763		soFar.length :
3764		soFar ?
3765			Sizzle.error( selector ) :
3766			// Cache the tokens
3767			tokenCache( selector, groups ).slice( 0 );
3768};
3769
3770function toSelector( tokens ) {
3771	var i = 0,
3772		len = tokens.length,
3773		selector = "";
3774	for ( ; i < len; i++ ) {
3775		selector += tokens[i].value;
3776	}
3777	return selector;
3778}
3779
3780function addCombinator( matcher, combinator, base ) {
3781	var dir = combinator.dir,
3782		checkNonElements = base && dir === "parentNode",
3783		doneName = done++;
3784
3785	return combinator.first ?
3786		// Check against closest ancestor/preceding element
3787		function( elem, context, xml ) {
3788			while ( (elem = elem[ dir ]) ) {
3789				if ( elem.nodeType === 1 || checkNonElements ) {
3790					return matcher( elem, context, xml );
3791				}
3792			}
3793		} :
3794
3795		// Check against all ancestor/preceding elements
3796		function( elem, context, xml ) {
3797			var oldCache, outerCache,
3798				newCache = [ dirruns, doneName ];
3799
3800			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
3801			if ( xml ) {
3802				while ( (elem = elem[ dir ]) ) {
3803					if ( elem.nodeType === 1 || checkNonElements ) {
3804						if ( matcher( elem, context, xml ) ) {
3805							return true;
3806						}
3807					}
3808				}
3809			} else {
3810				while ( (elem = elem[ dir ]) ) {
3811					if ( elem.nodeType === 1 || checkNonElements ) {
3812						outerCache = elem[ expando ] || (elem[ expando ] = {});
3813						if ( (oldCache = outerCache[ dir ]) &&
3814							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
3815
3816							// Assign to newCache so results back-propagate to previous elements
3817							return (newCache[ 2 ] = oldCache[ 2 ]);
3818						} else {
3819							// Reuse newcache so results back-propagate to previous elements
3820							outerCache[ dir ] = newCache;
3821
3822							// A match means we're done; a fail means we have to keep checking
3823							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
3824								return true;
3825							}
3826						}
3827					}
3828				}
3829			}
3830		};
3831}
3832
3833function elementMatcher( matchers ) {
3834	return matchers.length > 1 ?
3835		function( elem, context, xml ) {
3836			var i = matchers.length;
3837			while ( i-- ) {
3838				if ( !matchers[i]( elem, context, xml ) ) {
3839					return false;
3840				}
3841			}
3842			return true;
3843		} :
3844		matchers[0];
3845}
3846
3847function multipleContexts( selector, contexts, results ) {
3848	var i = 0,
3849		len = contexts.length;
3850	for ( ; i < len; i++ ) {
3851		Sizzle( selector, contexts[i], results );
3852	}
3853	return results;
3854}
3855
3856function condense( unmatched, map, filter, context, xml ) {
3857	var elem,
3858		newUnmatched = [],
3859		i = 0,
3860		len = unmatched.length,
3861		mapped = map != null;
3862
3863	for ( ; i < len; i++ ) {
3864		if ( (elem = unmatched[i]) ) {
3865			if ( !filter || filter( elem, context, xml ) ) {
3866				newUnmatched.push( elem );
3867				if ( mapped ) {
3868					map.push( i );
3869				}
3870			}
3871		}
3872	}
3873
3874	return newUnmatched;
3875}
3876
3877function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
3878	if ( postFilter && !postFilter[ expando ] ) {
3879		postFilter = setMatcher( postFilter );
3880	}
3881	if ( postFinder && !postFinder[ expando ] ) {
3882		postFinder = setMatcher( postFinder, postSelector );
3883	}
3884	return markFunction(function( seed, results, context, xml ) {
3885		var temp, i, elem,
3886			preMap = [],
3887			postMap = [],
3888			preexisting = results.length,
3889
3890			// Get initial elements from seed or context
3891			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
3892
3893			// Prefilter to get matcher input, preserving a map for seed-results synchronization
3894			matcherIn = preFilter && ( seed || !selector ) ?
3895				condense( elems, preMap, preFilter, context, xml ) :
3896				elems,
3897
3898			matcherOut = matcher ?
3899				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
3900				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
3901
3902					// ...intermediate processing is necessary
3903					[] :
3904
3905					// ...otherwise use results directly
3906					results :
3907				matcherIn;
3908
3909		// Find primary matches
3910		if ( matcher ) {
3911			matcher( matcherIn, matcherOut, context, xml );
3912		}
3913
3914		// Apply postFilter
3915		if ( postFilter ) {
3916			temp = condense( matcherOut, postMap );
3917			postFilter( temp, [], context, xml );
3918
3919			// Un-match failing elements by moving them back to matcherIn
3920			i = temp.length;
3921			while ( i-- ) {
3922				if ( (elem = temp[i]) ) {
3923					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
3924				}
3925			}
3926		}
3927
3928		if ( seed ) {
3929			if ( postFinder || preFilter ) {
3930				if ( postFinder ) {
3931					// Get the final matcherOut by condensing this intermediate into postFinder contexts
3932					temp = [];
3933					i = matcherOut.length;
3934					while ( i-- ) {
3935						if ( (elem = matcherOut[i]) ) {
3936							// Restore matcherIn since elem is not yet a final match
3937							temp.push( (matcherIn[i] = elem) );
3938						}
3939					}
3940					postFinder( null, (matcherOut = []), temp, xml );
3941				}
3942
3943				// Move matched elements from seed to results to keep them synchronized
3944				i = matcherOut.length;
3945				while ( i-- ) {
3946					if ( (elem = matcherOut[i]) &&
3947						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
3948
3949						seed[temp] = !(results[temp] = elem);
3950					}
3951				}
3952			}
3953
3954		// Add elements to results, through postFinder if defined
3955		} else {
3956			matcherOut = condense(
3957				matcherOut === results ?
3958					matcherOut.splice( preexisting, matcherOut.length ) :
3959					matcherOut
3960			);
3961			if ( postFinder ) {
3962				postFinder( null, results, matcherOut, xml );
3963			} else {
3964				push.apply( results, matcherOut );
3965			}
3966		}
3967	});
3968}
3969
3970function matcherFromTokens( tokens ) {
3971	var checkContext, matcher, j,
3972		len = tokens.length,
3973		leadingRelative = Expr.relative[ tokens[0].type ],
3974		implicitRelative = leadingRelative || Expr.relative[" "],
3975		i = leadingRelative ? 1 : 0,
3976
3977		// The foundational matcher ensures that elements are reachable from top-level context(s)
3978		matchContext = addCombinator( function( elem ) {
3979			return elem === checkContext;
3980		}, implicitRelative, true ),
3981		matchAnyContext = addCombinator( function( elem ) {
3982			return indexOf( checkContext, elem ) > -1;
3983		}, implicitRelative, true ),
3984		matchers = [ function( elem, context, xml ) {
3985			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
3986				(checkContext = context).nodeType ?
3987					matchContext( elem, context, xml ) :
3988					matchAnyContext( elem, context, xml ) );
3989			// Avoid hanging onto element (issue #299)
3990			checkContext = null;
3991			return ret;
3992		} ];
3993
3994	for ( ; i < len; i++ ) {
3995		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
3996			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
3997		} else {
3998			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
3999
4000			// Return special upon seeing a positional matcher
4001			if ( matcher[ expando ] ) {
4002				// Find the next relative operator (if any) for proper handling
4003				j = ++i;
4004				for ( ; j < len; j++ ) {
4005					if ( Expr.relative[ tokens[j].type ] ) {
4006						break;
4007					}
4008				}
4009				return setMatcher(
4010					i > 1 && elementMatcher( matchers ),
4011					i > 1 && toSelector(
4012						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
4013						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
4014					).replace( rtrim, "$1" ),
4015					matcher,
4016					i < j && matcherFromTokens( tokens.slice( i, j ) ),
4017					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
4018					j < len && toSelector( tokens )
4019				);
4020			}
4021			matchers.push( matcher );
4022		}
4023	}
4024
4025	return elementMatcher( matchers );
4026}
4027
4028function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
4029	var bySet = setMatchers.length > 0,
4030		byElement = elementMatchers.length > 0,
4031		superMatcher = function( seed, context, xml, results, outermost ) {
4032			var elem, j, matcher,
4033				matchedCount = 0,
4034				i = "0",
4035				unmatched = seed && [],
4036				setMatched = [],
4037				contextBackup = outermostContext,
4038				// We must always have either seed elements or outermost context
4039				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
4040				// Use integer dirruns iff this is the outermost matcher
4041				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
4042				len = elems.length;
4043
4044			if ( outermost ) {
4045				outermostContext = context !== document && context;
4046			}
4047
4048			// Add elements passing elementMatchers directly to results
4049			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
4050			// Support: IE<9, Safari
4051			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
4052			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
4053				if ( byElement && elem ) {
4054					j = 0;
4055					while ( (matcher = elementMatchers[j++]) ) {
4056						if ( matcher( elem, context, xml ) ) {
4057							results.push( elem );
4058							break;
4059						}
4060					}
4061					if ( outermost ) {
4062						dirruns = dirrunsUnique;
4063					}
4064				}
4065
4066				// Track unmatched elements for set filters
4067				if ( bySet ) {
4068					// They will have gone through all possible matchers
4069					if ( (elem = !matcher && elem) ) {
4070						matchedCount--;
4071					}
4072
4073					// Lengthen the array for every element, matched or not
4074					if ( seed ) {
4075						unmatched.push( elem );
4076					}
4077				}
4078			}
4079
4080			// Apply set filters to unmatched elements
4081			matchedCount += i;
4082			if ( bySet && i !== matchedCount ) {
4083				j = 0;
4084				while ( (matcher = setMatchers[j++]) ) {
4085					matcher( unmatched, setMatched, context, xml );
4086				}
4087
4088				if ( seed ) {
4089					// Reintegrate element matches to eliminate the need for sorting
4090					if ( matchedCount > 0 ) {
4091						while ( i-- ) {
4092							if ( !(unmatched[i] || setMatched[i]) ) {
4093								setMatched[i] = pop.call( results );
4094							}
4095						}
4096					}
4097
4098					// Discard index placeholder values to get only actual matches
4099					setMatched = condense( setMatched );
4100				}
4101
4102				// Add matches to results
4103				push.apply( results, setMatched );
4104
4105				// Seedless set matches succeeding multiple successful matchers stipulate sorting
4106				if ( outermost && !seed && setMatched.length > 0 &&
4107					( matchedCount + setMatchers.length ) > 1 ) {
4108
4109					Sizzle.uniqueSort( results );
4110				}
4111			}
4112
4113			// Override manipulation of globals by nested matchers
4114			if ( outermost ) {
4115				dirruns = dirrunsUnique;
4116				outermostContext = contextBackup;
4117			}
4118
4119			return unmatched;
4120		};
4121
4122	return bySet ?
4123		markFunction( superMatcher ) :
4124		superMatcher;
4125}
4126
4127compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
4128	var i,
4129		setMatchers = [],
4130		elementMatchers = [],
4131		cached = compilerCache[ selector + " " ];
4132
4133	if ( !cached ) {
4134		// Generate a function of recursive functions that can be used to check each element
4135		if ( !match ) {
4136			match = tokenize( selector );
4137		}
4138		i = match.length;
4139		while ( i-- ) {
4140			cached = matcherFromTokens( match[i] );
4141			if ( cached[ expando ] ) {
4142				setMatchers.push( cached );
4143			} else {
4144				elementMatchers.push( cached );
4145			}
4146		}
4147
4148		// Cache the compiled function
4149		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
4150
4151		// Save selector and tokenization
4152		cached.selector = selector;
4153	}
4154	return cached;
4155};
4156
4157/**
4158 * A low-level selection function that works with Sizzle's compiled
4159 *  selector functions
4160 * @param {String|Function} selector A selector or a pre-compiled
4161 *  selector function built with Sizzle.compile
4162 * @param {Element} context
4163 * @param {Array} [results]
4164 * @param {Array} [seed] A set of elements to match against
4165 */
4166select = Sizzle.select = function( selector, context, results, seed ) {
4167	var i, tokens, token, type, find,
4168		compiled = typeof selector === "function" && selector,
4169		match = !seed && tokenize( (selector = compiled.selector || selector) );
4170
4171	results = results || [];
4172
4173	// Try to minimize operations if there is no seed and only one group
4174	if ( match.length === 1 ) {
4175
4176		// Take a shortcut and set the context if the root selector is an ID
4177		tokens = match[0] = match[0].slice( 0 );
4178		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
4179				support.getById && context.nodeType === 9 && documentIsHTML &&
4180				Expr.relative[ tokens[1].type ] ) {
4181
4182			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
4183			if ( !context ) {
4184				return results;
4185
4186			// Precompiled matchers will still verify ancestry, so step up a level
4187			} else if ( compiled ) {
4188				context = context.parentNode;
4189			}
4190
4191			selector = selector.slice( tokens.shift().value.length );
4192		}
4193
4194		// Fetch a seed set for right-to-left matching
4195		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
4196		while ( i-- ) {
4197			token = tokens[i];
4198
4199			// Abort if we hit a combinator
4200			if ( Expr.relative[ (type = token.type) ] ) {
4201				break;
4202			}
4203			if ( (find = Expr.find[ type ]) ) {
4204				// Search, expanding context for leading sibling combinators
4205				if ( (seed = find(
4206					token.matches[0].replace( runescape, funescape ),
4207					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
4208				)) ) {
4209
4210					// If seed is empty or no tokens remain, we can return early
4211					tokens.splice( i, 1 );
4212					selector = seed.length && toSelector( tokens );
4213					if ( !selector ) {
4214						push.apply( results, seed );
4215						return results;
4216					}
4217
4218					break;
4219				}
4220			}
4221		}
4222	}
4223
4224	// Compile and execute a filtering function if one is not provided
4225	// Provide `match` to avoid retokenization if we modified the selector above
4226	( compiled || compile( selector, match ) )(
4227		seed,
4228		context,
4229		!documentIsHTML,
4230		results,
4231		rsibling.test( selector ) && testContext( context.parentNode ) || context
4232	);
4233	return results;
4234};
4235
4236// One-time assignments
4237
4238// Sort stability
4239support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
4240
4241// Support: Chrome 14-35+
4242// Always assume duplicates if they aren't passed to the comparison function
4243support.detectDuplicates = !!hasDuplicate;
4244
4245// Initialize against the default document
4246setDocument();
4247
4248// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
4249// Detached nodes confoundingly follow *each other*
4250support.sortDetached = assert(function( div1 ) {
4251	// Should return 1, but returns 4 (following)
4252	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
4253});
4254
4255// Support: IE<8
4256// Prevent attribute/property "interpolation"
4257// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
4258if ( !assert(function( div ) {
4259	div.innerHTML = "<a href='#'></a>";
4260	return div.firstChild.getAttribute("href") === "#" ;
4261}) ) {
4262	addHandle( "type|href|height|width", function( elem, name, isXML ) {
4263		if ( !isXML ) {
4264			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
4265		}
4266	});
4267}
4268
4269// Support: IE<9
4270// Use defaultValue in place of getAttribute("value")
4271if ( !support.attributes || !assert(function( div ) {
4272	div.innerHTML = "<input/>";
4273	div.firstChild.setAttribute( "value", "" );
4274	return div.firstChild.getAttribute( "value" ) === "";
4275}) ) {
4276	addHandle( "value", function( elem, name, isXML ) {
4277		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
4278			return elem.defaultValue;
4279		}
4280	});
4281}
4282
4283// Support: IE<9
4284// Use getAttributeNode to fetch booleans when getAttribute lies
4285if ( !assert(function( div ) {
4286	return div.getAttribute("disabled") == null;
4287}) ) {
4288	addHandle( booleans, function( elem, name, isXML ) {
4289		var val;
4290		if ( !isXML ) {
4291			return elem[ name ] === true ? name.toLowerCase() :
4292					(val = elem.getAttributeNode( name )) && val.specified ?
4293					val.value :
4294				null;
4295		}
4296	});
4297}
4298
4299return Sizzle;
4300
4301})( window );
4302
4303
4304
4305jQuery.find = Sizzle;
4306jQuery.expr = Sizzle.selectors;
4307jQuery.expr[":"] = jQuery.expr.pseudos;
4308jQuery.unique = Sizzle.uniqueSort;
4309jQuery.text = Sizzle.getText;
4310jQuery.isXMLDoc = Sizzle.isXML;
4311jQuery.contains = Sizzle.contains;
4312
4313
4314
4315var rneedsContext = jQuery.expr.match.needsContext;
4316
4317var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
4318
4319
4320
4321var risSimple = /^.[^:#\[\.,]*$/;
4322
4323// Implement the identical functionality for filter and not
4324function winnow( elements, qualifier, not ) {
4325	if ( jQuery.isFunction( qualifier ) ) {
4326		return jQuery.grep( elements, function( elem, i ) {
4327			/* jshint -W018 */
4328			return !!qualifier.call( elem, i, elem ) !== not;
4329		});
4330
4331	}
4332
4333	if ( qualifier.nodeType ) {
4334		return jQuery.grep( elements, function( elem ) {
4335			return ( elem === qualifier ) !== not;
4336		});
4337
4338	}
4339
4340	if ( typeof qualifier === "string" ) {
4341		if ( risSimple.test( qualifier ) ) {
4342			return jQuery.filter( qualifier, elements, not );
4343		}
4344
4345		qualifier = jQuery.filter( qualifier, elements );
4346	}
4347
4348	return jQuery.grep( elements, function( elem ) {
4349		return ( 
vendor: 92,830 bytes, lines 4349-7721
4349jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
4350	});
4351}
4352
4353jQuery.filter = function( expr, elems, not ) {
4354	var elem = elems[ 0 ];
4355
4356	if ( not ) {
4357		expr = ":not(" + expr + ")";
4358	}
4359
4360	return elems.length === 1 && elem.nodeType === 1 ?
4361		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
4362		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
4363			return elem.nodeType === 1;
4364		}));
4365};
4366
4367jQuery.fn.extend({
4368	find: function( selector ) {
4369		var i,
4370			ret = [],
4371			self = this,
4372			len = self.length;
4373
4374		if ( typeof selector !== "string" ) {
4375			return this.pushStack( jQuery( selector ).filter(function() {
4376				for ( i = 0; i < len; i++ ) {
4377					if ( jQuery.contains( self[ i ], this ) ) {
4378						return true;
4379					}
4380				}
4381			}) );
4382		}
4383
4384		for ( i = 0; i < len; i++ ) {
4385			jQuery.find( selector, self[ i ], ret );
4386		}
4387
4388		// Needed because $( selector, context ) becomes $( context ).find( selector )
4389		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
4390		ret.selector = this.selector ? this.selector + " " + selector : selector;
4391		return ret;
4392	},
4393	filter: function( selector ) {
4394		return this.pushStack( winnow(this, selector || [], false) );
4395	},
4396	not: function( selector ) {
4397		return this.pushStack( winnow(this, selector || [], true) );
4398	},
4399	is: function( selector ) {
4400		return !!winnow(
4401			this,
4402
4403			// If this is a positional/relative selector, check membership in the returned set
4404			// so $("p:first").is("p:last") won't return true for a doc with two "p".
4405			typeof selector === "string" && rneedsContext.test( selector ) ?
4406				jQuery( selector ) :
4407				selector || [],
4408			false
4409		).length;
4410	}
4411});
4412
4413
4414// Initialize a jQuery object
4415
4416
4417// A central reference to the root jQuery(document)
4418var rootjQuery,
4419
4420	// Use the correct document accordingly with window argument (sandbox)
4421	document = window.document,
4422
4423	// A simple way to check for HTML strings
4424	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
4425	// Strict HTML recognition (#11290: must start with <)
4426	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
4427
4428	init = jQuery.fn.init = function( selector, context ) {
4429		var match, elem;
4430
4431		// HANDLE: $(""), $(null), $(undefined), $(false)
4432		if ( !selector ) {
4433			return this;
4434		}
4435
4436		// Handle HTML strings
4437		if ( typeof selector === "string" ) {
4438			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
4439				// Assume that strings that start and end with <> are HTML and skip the regex check
4440				match = [ null, selector, null ];
4441
4442			} else {
4443				match = rquickExpr.exec( selector );
4444			}
4445
4446			// Match html or make sure no context is specified for #id
4447			if ( match && (match[1] || !context) ) {
4448
4449				// HANDLE: $(html) -> $(array)
4450				if ( match[1] ) {
4451					context = context instanceof jQuery ? context[0] : context;
4452
4453					// scripts is true for back-compat
4454					// Intentionally let the error be thrown if parseHTML is not present
4455					jQuery.merge( this, jQuery.parseHTML(
4456						match[1],
4457						context && context.nodeType ? context.ownerDocument || context : document,
4458						true
4459					) );
4460
4461					// HANDLE: $(html, props)
4462					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
4463						for ( match in context ) {
4464							// Properties of context are called as methods if possible
4465							if ( jQuery.isFunction( this[ match ] ) ) {
4466								this[ match ]( context[ match ] );
4467
4468							// ...and otherwise set as attributes
4469							} else {
4470								this.attr( match, context[ match ] );
4471							}
4472						}
4473					}
4474
4475					return this;
4476
4477				// HANDLE: $(#id)
4478				} else {
4479					elem = document.getElementById( match[2] );
4480
4481					// Check parentNode to catch when Blackberry 4.6 returns
4482					// nodes that are no longer in the document #6963
4483					if ( elem && elem.parentNode ) {
4484						// Handle the case where IE and Opera return items
4485						// by name instead of ID
4486						if ( elem.id !== match[2] ) {
4487							return rootjQuery.find( selector );
4488						}
4489
4490						// Otherwise, we inject the element directly into the jQuery object
4491						this.length = 1;
4492						this[0] = elem;
4493					}
4494
4495					this.context = document;
4496					this.selector = selector;
4497					return this;
4498				}
4499
4500			// HANDLE: $(expr, $(...))
4501			} else if ( !context || context.jquery ) {
4502				return ( context || rootjQuery ).find( selector );
4503
4504			// HANDLE: $(expr, context)
4505			// (which is just equivalent to: $(context).find(expr)
4506			} else {
4507				return this.constructor( context ).find( selector );
4508			}
4509
4510		// HANDLE: $(DOMElement)
4511		} else if ( selector.nodeType ) {
4512			this.context = this[0] = selector;
4513			this.length = 1;
4514			return this;
4515
4516		// HANDLE: $(function)
4517		// Shortcut for document ready
4518		} else if ( jQuery.isFunction( selector ) ) {
4519			return typeof rootjQuery.ready !== "undefined" ?
4520				rootjQuery.ready( selector ) :
4521				// Execute immediately if ready is not present
4522				selector( jQuery );
4523		}
4524
4525		if ( selector.selector !== undefined ) {
4526			this.selector = selector.selector;
4527			this.context = selector.context;
4528		}
4529
4530		return jQuery.makeArray( selector, this );
4531	};
4532
4533// Give the init function the jQuery prototype for later instantiation
4534init.prototype = jQuery.fn;
4535
4536// Initialize central reference
4537rootjQuery = jQuery( document );
4538
4539
4540var rparentsprev = /^(?:parents|prev(?:Until|All))/,
4541	// methods guaranteed to produce a unique set when starting from a unique set
4542	guaranteedUnique = {
4543		children: true,
4544		contents: true,
4545		next: true,
4546		prev: true
4547	};
4548
4549jQuery.extend({
4550	dir: function( elem, dir, until ) {
4551		var matched = [],
4552			cur = elem[ dir ];
4553
4554		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
4555			if ( cur.nodeType === 1 ) {
4556				matched.push( cur );
4557			}
4558			cur = cur[dir];
4559		}
4560		return matched;
4561	},
4562
4563	sibling: function( n, elem ) {
4564		var r = [];
4565
4566		for ( ; n; n = n.nextSibling ) {
4567			if ( n.nodeType === 1 && n !== elem ) {
4568				r.push( n );
4569			}
4570		}
4571
4572		return r;
4573	}
4574});
4575
4576jQuery.fn.extend({
4577	has: function( target ) {
4578		var i,
4579			targets = jQuery( target, this ),
4580			len = targets.length;
4581
4582		return this.filter(function() {
4583			for ( i = 0; i < len; i++ ) {
4584				if ( jQuery.contains( this, targets[i] ) ) {
4585					return true;
4586				}
4587			}
4588		});
4589	},
4590
4591	closest: function( selectors, context ) {
4592		var cur,
4593			i = 0,
4594			l = this.length,
4595			matched = [],
4596			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
4597				jQuery( selectors, context || this.context ) :
4598				0;
4599
4600		for ( ; i < l; i++ ) {
4601			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
4602				// Always skip document fragments
4603				if ( cur.nodeType < 11 && (pos ?
4604					pos.index(cur) > -1 :
4605
4606					// Don't pass non-elements to Sizzle
4607					cur.nodeType === 1 &&
4608						jQuery.find.matchesSelector(cur, selectors)) ) {
4609
4610					matched.push( cur );
4611					break;
4612				}
4613			}
4614		}
4615
4616		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
4617	},
4618
4619	// Determine the position of an element within
4620	// the matched set of elements
4621	index: function( elem ) {
4622
4623		// No argument, return index in parent
4624		if ( !elem ) {
4625			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
4626		}
4627
4628		// index in selector
4629		if ( typeof elem === "string" ) {
4630			return jQuery.inArray( this[0], jQuery( elem ) );
4631		}
4632
4633		// Locate the position of the desired element
4634		return jQuery.inArray(
4635			// If it receives a jQuery object, the first element is used
4636			elem.jquery ? elem[0] : elem, this );
4637	},
4638
4639	add: function( selector, context ) {
4640		return this.pushStack(
4641			jQuery.unique(
4642				jQuery.merge( this.get(), jQuery( selector, context ) )
4643			)
4644		);
4645	},
4646
4647	addBack: function( selector ) {
4648		return this.add( selector == null ?
4649			this.prevObject : this.prevObject.filter(selector)
4650		);
4651	}
4652});
4653
4654function sibling( cur, dir ) {
4655	do {
4656		cur = cur[ dir ];
4657	} while ( cur && cur.nodeType !== 1 );
4658
4659	return cur;
4660}
4661
4662jQuery.each({
4663	parent: function( elem ) {
4664		var parent = elem.parentNode;
4665		return parent && parent.nodeType !== 11 ? parent : null;
4666	},
4667	parents: function( elem ) {
4668		return jQuery.dir( elem, "parentNode" );
4669	},
4670	parentsUntil: function( elem, i, until ) {
4671		return jQuery.dir( elem, "parentNode", until );
4672	},
4673	next: function( elem ) {
4674		return sibling( elem, "nextSibling" );
4675	},
4676	prev: function( elem ) {
4677		return sibling( elem, "previousSibling" );
4678	},
4679	nextAll: function( elem ) {
4680		return jQuery.dir( elem, "nextSibling" );
4681	},
4682	prevAll: function( elem ) {
4683		return jQuery.dir( elem, "previousSibling" );
4684	},
4685	nextUntil: function( elem, i, until ) {
4686		return jQuery.dir( elem, "nextSibling", until );
4687	},
4688	prevUntil: function( elem, i, until ) {
4689		return jQuery.dir( elem, "previousSibling", until );
4690	},
4691	siblings: function( elem ) {
4692		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
4693	},
4694	children: function( elem ) {
4695		return jQuery.sibling( elem.firstChild );
4696	},
4697	contents: function( elem ) {
4698		return jQuery.nodeName( elem, "iframe" ) ?
4699			elem.contentDocument || elem.contentWindow.document :
4700			jQuery.merge( [], elem.childNodes );
4701	}
4702}, function( name, fn ) {
4703	jQuery.fn[ name ] = function( until, selector ) {
4704		var ret = jQuery.map( this, fn, until );
4705
4706		if ( name.slice( -5 ) !== "Until" ) {
4707			selector = until;
4708		}
4709
4710		if ( selector && typeof selector === "string" ) {
4711			ret = jQuery.filter( selector, ret );
4712		}
4713
4714		if ( this.length > 1 ) {
4715			// Remove duplicates
4716			if ( !guaranteedUnique[ name ] ) {
4717				ret = jQuery.unique( ret );
4718			}
4719
4720			// Reverse order for parents* and prev-derivatives
4721			if ( rparentsprev.test( name ) ) {
4722				ret = ret.reverse();
4723			}
4724		}
4725
4726		return this.pushStack( ret );
4727	};
4728});
4729var rnotwhite = (/\S+/g);
4730
4731
4732
4733// String to Object options format cache
4734var optionsCache = {};
4735
4736// Convert String-formatted options into Object-formatted ones and store in cache
4737function createOptions( options ) {
4738	var object = optionsCache[ options ] = {};
4739	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
4740		object[ flag ] = true;
4741	});
4742	return object;
4743}
4744
4745/*
4746 * Create a callback list using the following parameters:
4747 *
4748 *	options: an optional list of space-separated options that will change how
4749 *			the callback list behaves or a more traditional option object
4750 *
4751 * By default a callback list will act like an event callback list and can be
4752 * "fired" multiple times.
4753 *
4754 * Possible options:
4755 *
4756 *	once:			will ensure the callback list can only be fired once (like a Deferred)
4757 *
4758 *	memory:			will keep track of previous values and will call any callback added
4759 *					after the list has been fired right away with the latest "memorized"
4760 *					values (like a Deferred)
4761 *
4762 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
4763 *
4764 *	stopOnFalse:	interrupt callings when a callback returns false
4765 *
4766 */
4767jQuery.Callbacks = function( options ) {
4768
4769	// Convert options from String-formatted to Object-formatted if needed
4770	// (we check in cache first)
4771	options = typeof options === "string" ?
4772		( optionsCache[ options ] || createOptions( options ) ) :
4773		jQuery.extend( {}, options );
4774
4775	var // Flag to know if list is currently firing
4776		firing,
4777		// Last fire value (for non-forgettable lists)
4778		memory,
4779		// Flag to know if list was already fired
4780		fired,
4781		// End of the loop when firing
4782		firingLength,
4783		// Index of currently firing callback (modified by remove if needed)
4784		firingIndex,
4785		// First callback to fire (used internally by add and fireWith)
4786		firingStart,
4787		// Actual callback list
4788		list = [],
4789		// Stack of fire calls for repeatable lists
4790		stack = !options.once && [],
4791		// Fire callbacks
4792		fire = function( data ) {
4793			memory = options.memory && data;
4794			fired = true;
4795			firingIndex = firingStart || 0;
4796			firingStart = 0;
4797			firingLength = list.length;
4798			firing = true;
4799			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
4800				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
4801					memory = false; // To prevent further calls using add
4802					break;
4803				}
4804			}
4805			firing = false;
4806			if ( list ) {
4807				if ( stack ) {
4808					if ( stack.length ) {
4809						fire( stack.shift() );
4810					}
4811				} else if ( memory ) {
4812					list = [];
4813				} else {
4814					self.disable();
4815				}
4816			}
4817		},
4818		// Actual Callbacks object
4819		self = {
4820			// Add a callback or a collection of callbacks to the list
4821			add: function() {
4822				if ( list ) {
4823					// First, we save the current length
4824					var start = list.length;
4825					(function add( args ) {
4826						jQuery.each( args, function( _, arg ) {
4827							var type = jQuery.type( arg );
4828							if ( type === "function" ) {
4829								if ( !options.unique || !self.has( arg ) ) {
4830									list.push( arg );
4831								}
4832							} else if ( arg && arg.length && type !== "string" ) {
4833								// Inspect recursively
4834								add( arg );
4835							}
4836						});
4837					})( arguments );
4838					// Do we need to add the callbacks to the
4839					// current firing batch?
4840					if ( firing ) {
4841						firingLength = list.length;
4842					// With memory, if we're not firing then
4843					// we should call right away
4844					} else if ( memory ) {
4845						firingStart = start;
4846						fire( memory );
4847					}
4848				}
4849				return this;
4850			},
4851			// Remove a callback from the list
4852			remove: function() {
4853				if ( list ) {
4854					jQuery.each( arguments, function( _, arg ) {
4855						var index;
4856						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
4857							list.splice( index, 1 );
4858							// Handle firing indexes
4859							if ( firing ) {
4860								if ( index <= firingLength ) {
4861									firingLength--;
4862								}
4863								if ( index <= firingIndex ) {
4864									firingIndex--;
4865								}
4866							}
4867						}
4868					});
4869				}
4870				return this;
4871			},
4872			// Check if a given callback is in the list.
4873			// If no argument is given, return whether or not list has callbacks attached.
4874			has: function( fn ) {
4875				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
4876			},
4877			// Remove all callbacks from the list
4878			empty: function() {
4879				list = [];
4880				firingLength = 0;
4881				return this;
4882			},
4883			// Have the list do nothing anymore
4884			disable: function() {
4885				list = stack = memory = undefined;
4886				return this;
4887			},
4888			// Is it disabled?
4889			disabled: function() {
4890				return !list;
4891			},
4892			// Lock the list in its current state
4893			lock: function() {
4894				stack = undefined;
4895				if ( !memory ) {
4896					self.disable();
4897				}
4898				return this;
4899			},
4900			// Is it locked?
4901			locked: function() {
4902				return !stack;
4903			},
4904			// Call all callbacks with the given context and arguments
4905			fireWith: function( context, args ) {
4906				if ( list && ( !fired || stack ) ) {
4907					args = args || [];
4908					args = [ context, args.slice ? args.slice() : args ];
4909					if ( firing ) {
4910						stack.push( args );
4911					} else {
4912						fire( args );
4913					}
4914				}
4915				return this;
4916			},
4917			// Call all the callbacks with the given arguments
4918			fire: function() {
4919				self.fireWith( this, arguments );
4920				return this;
4921			},
4922			// To know if the callbacks have already been called at least once
4923			fired: function() {
4924				return !!fired;
4925			}
4926		};
4927
4928	return self;
4929};
4930
4931
4932jQuery.extend({
4933
4934	Deferred: function( func ) {
4935		var tuples = [
4936				// action, add listener, listener list, final state
4937				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
4938				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
4939				[ "notify", "progress", jQuery.Callbacks("memory") ]
4940			],
4941			state = "pending",
4942			promise = {
4943				state: function() {
4944					return state;
4945				},
4946				always: function() {
4947					deferred.done( arguments ).fail( arguments );
4948					return this;
4949				},
4950				then: function( /* fnDone, fnFail, fnProgress */ ) {
4951					var fns = arguments;
4952					return jQuery.Deferred(function( newDefer ) {
4953						jQuery.each( tuples, function( i, tuple ) {
4954							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
4955							// deferred[ done | fail | progress ] for forwarding actions to newDefer
4956							deferred[ tuple[1] ](function() {
4957								var returned = fn && fn.apply( this, arguments );
4958								if ( returned && jQuery.isFunction( returned.promise ) ) {
4959									returned.promise()
4960										.done( newDefer.resolve )
4961										.fail( newDefer.reject )
4962										.progress( newDefer.notify );
4963								} else {
4964									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
4965								}
4966							});
4967						});
4968						fns = null;
4969					}).promise();
4970				},
4971				// Get a promise for this deferred
4972				// If obj is provided, the promise aspect is added to the object
4973				promise: function( obj ) {
4974					return obj != null ? jQuery.extend( obj, promise ) : promise;
4975				}
4976			},
4977			deferred = {};
4978
4979		// Keep pipe for back-compat
4980		promise.pipe = promise.then;
4981
4982		// Add list-specific methods
4983		jQuery.each( tuples, function( i, tuple ) {
4984			var list = tuple[ 2 ],
4985				stateString = tuple[ 3 ];
4986
4987			// promise[ done | fail | progress ] = list.add
4988			promise[ tuple[1] ] = list.add;
4989
4990			// Handle state
4991			if ( stateString ) {
4992				list.add(function() {
4993					// state = [ resolved | rejected ]
4994					state = stateString;
4995
4996				// [ reject_list | resolve_list ].disable; progress_list.lock
4997				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
4998			}
4999
5000			// deferred[ resolve | reject | notify ]
5001			deferred[ tuple[0] ] = function() {
5002				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
5003				return this;
5004			};
5005			deferred[ tuple[0] + "With" ] = list.fireWith;
5006		});
5007
5008		// Make the deferred a promise
5009		promise.promise( deferred );
5010
5011		// Call given func if any
5012		if ( func ) {
5013			func.call( deferred, deferred );
5014		}
5015
5016		// All done!
5017		return deferred;
5018	},
5019
5020	// Deferred helper
5021	when: function( subordinate /* , ..., subordinateN */ ) {
5022		var i = 0,
5023			resolveValues = slice.call( arguments ),
5024			length = resolveValues.length,
5025
5026			// the count of uncompleted subordinates
5027			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
5028
5029			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
5030			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
5031
5032			// Update function for both resolve and progress values
5033			updateFunc = function( i, contexts, values ) {
5034				return function( value ) {
5035					contexts[ i ] = this;
5036					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
5037					if ( values === progressValues ) {
5038						deferred.notifyWith( contexts, values );
5039
5040					} else if ( !(--remaining) ) {
5041						deferred.resolveWith( contexts, values );
5042					}
5043				};
5044			},
5045
5046			progressValues, progressContexts, resolveContexts;
5047
5048		// add listeners to Deferred subordinates; treat others as resolved
5049		if ( length > 1 ) {
5050			progressValues = new Array( length );
5051			progressContexts = new Array( length );
5052			resolveContexts = new Array( length );
5053			for ( ; i < length; i++ ) {
5054				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
5055					resolveValues[ i ].promise()
5056						.done( updateFunc( i, resolveContexts, resolveValues ) )
5057						.fail( deferred.reject )
5058						.progress( updateFunc( i, progressContexts, progressValues ) );
5059				} else {
5060					--remaining;
5061				}
5062			}
5063		}
5064
5065		// if we're not waiting on anything, resolve the master
5066		if ( !remaining ) {
5067			deferred.resolveWith( resolveContexts, resolveValues );
5068		}
5069
5070		return deferred.promise();
5071	}
5072});
5073
5074
5075// The deferred used on DOM ready
5076var readyList;
5077
5078jQuery.fn.ready = function( fn ) {
5079	// Add the callback
5080	jQuery.ready.promise().done( fn );
5081
5082	return this;
5083};
5084
5085jQuery.extend({
5086	// Is the DOM ready to be used? Set to true once it occurs.
5087	isReady: false,
5088
5089	// A counter to track how many items to wait for before
5090	// the ready event fires. See #6781
5091	readyWait: 1,
5092
5093	// Hold (or release) the ready event
5094	holdReady: function( hold ) {
5095		if ( hold ) {
5096			jQuery.readyWait++;
5097		} else {
5098			jQuery.ready( true );
5099		}
5100	},
5101
5102	// Handle when the DOM is ready
5103	ready: function( wait ) {
5104
5105		// Abort if there are pending holds or we're already ready
5106		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
5107			return;
5108		}
5109
5110		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
5111		if ( !document.body ) {
5112			return setTimeout( jQuery.ready );
5113		}
5114
5115		// Remember that the DOM is ready
5116		jQuery.isReady = true;
5117
5118		// If a normal DOM Ready event fired, decrement, and wait if need be
5119		if ( wait !== true && --jQuery.readyWait > 0 ) {
5120			return;
5121		}
5122
5123		// If there are functions bound, to execute
5124		readyList.resolveWith( document, [ jQuery ] );
5125
5126		// Trigger any bound ready events
5127		if ( jQuery.fn.triggerHandler ) {
5128			jQuery( document ).triggerHandler( "ready" );
5129			jQuery( document ).off( "ready" );
5130		}
5131	}
5132});
5133
5134/**
5135 * Clean-up method for dom ready events
5136 */
5137function detach() {
5138	if ( document.addEventListener ) {
5139		document.removeEventListener( "DOMContentLoaded", completed, false );
5140		window.removeEventListener( "load", completed, false );
5141
5142	} else {
5143		document.detachEvent( "onreadystatechange", completed );
5144		window.detachEvent( "onload", completed );
5145	}
5146}
5147
5148/**
5149 * The ready event handler and self cleanup method
5150 */
5151function completed() {
5152	// readyState === "complete" is good enough for us to call the dom ready in oldIE
5153	if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
5154		detach();
5155		jQuery.ready();
5156	}
5157}
5158
5159jQuery.ready.promise = function( obj ) {
5160	if ( !readyList ) {
5161
5162		readyList = jQuery.Deferred();
5163
5164		// Catch cases where $(document).ready() is called after the browser event has already occurred.
5165		// we once tried to use readyState "interactive" here, but it caused issues like the one
5166		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
5167		if ( document.readyState === "complete" ) {
5168			// Handle it asynchronously to allow scripts the opportunity to delay ready
5169			setTimeout( jQuery.ready );
5170
5171		// Standards-based browsers support DOMContentLoaded
5172		} else if ( document.addEventListener ) {
5173			// Use the handy event callback
5174			document.addEventListener( "DOMContentLoaded", completed, false );
5175
5176			// A fallback to window.onload, that will always work
5177			window.addEventListener( "load", completed, false );
5178
5179		// If IE event model is used
5180		} else {
5181			// Ensure firing before onload, maybe late but safe also for iframes
5182			document.attachEvent( "onreadystatechange", completed );
5183
5184			// A fallback to window.onload, that will always work
5185			window.attachEvent( "onload", completed );
5186
5187			// If IE and not a frame
5188			// continually check to see if the document is ready
5189			var top = false;
5190
5191			try {
5192				top = window.frameElement == null && document.documentElement;
5193			} catch(e) {}
5194
5195			if ( top && top.doScroll ) {
5196				(function doScrollCheck() {
5197					if ( !jQuery.isReady ) {
5198
5199						try {
5200							// Use the trick by Diego Perini
5201							// http://javascript.nwbox.com/IEContentLoaded/
5202							top.doScroll("left");
5203						} catch(e) {
5204							return setTimeout( doScrollCheck, 50 );
5205						}
5206
5207						// detach all dom ready events
5208						detach();
5209
5210						// and execute any waiting functions
5211						jQuery.ready();
5212					}
5213				})();
5214			}
5215		}
5216	}
5217	return readyList.promise( obj );
5218};
5219
5220
5221var strundefined = typeof undefined;
5222
5223
5224
5225// Support: IE<9
5226// Iteration over object's inherited properties before its own
5227var i;
5228for ( i in jQuery( support ) ) {
5229	break;
5230}
5231support.ownLast = i !== "0";
5232
5233// Note: most support tests are defined in their respective modules.
5234// false until the test is run
5235support.inlineBlockNeedsLayout = false;
5236
5237// Execute ASAP in case we need to set body.style.zoom
5238jQuery(function() {
5239	// Minified: var a,b,c,d
5240	var val, div, body, container;
5241
5242	body = document.getElementsByTagName( "body" )[ 0 ];
5243	if ( !body || !body.style ) {
5244		// Return for frameset docs that don't have a body
5245		return;
5246	}
5247
5248	// Setup
5249	div = document.createElement( "div" );
5250	container = document.createElement( "div" );
5251	container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
5252	body.appendChild( container ).appendChild( div );
5253
5254	if ( typeof div.style.zoom !== strundefined ) {
5255		// Support: IE<8
5256		// Check if natively block-level elements act like inline-block
5257		// elements when setting their display to 'inline' and giving
5258		// them layout
5259		div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
5260
5261		support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
5262		if ( val ) {
5263			// Prevent IE 6 from affecting layout for positioned elements #11048
5264			// Prevent IE from shrinking the body in IE 7 mode #12869
5265			// Support: IE<8
5266			body.style.zoom = 1;
5267		}
5268	}
5269
5270	body.removeChild( container );
5271});
5272
5273
5274
5275
5276(function() {
5277	var div = document.createElement( "div" );
5278
5279	// Execute the test only if not already executed in another module.
5280	if (support.deleteExpando == null) {
5281		// Support: IE<9
5282		support.deleteExpando = true;
5283		try {
5284			delete div.test;
5285		} catch( e ) {
5286			support.deleteExpando = false;
5287		}
5288	}
5289
5290	// Null elements to avoid leaks in IE.
5291	div = null;
5292})();
5293
5294
5295/**
5296 * Determines whether an object can have data
5297 */
5298jQuery.acceptData = function( elem ) {
5299	var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
5300		nodeType = +elem.nodeType || 1;
5301
5302	// Do not set data on non-element DOM nodes because it will not be cleared (#8335).
5303	return nodeType !== 1 && nodeType !== 9 ?
5304		false :
5305
5306		// Nodes accept data unless otherwise specified; rejection can be conditional
5307		!noData || noData !== true && elem.getAttribute("classid") === noData;
5308};
5309
5310
5311var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
5312	rmultiDash = /([A-Z])/g;
5313
5314function dataAttr( elem, key, data ) {
5315	// If nothing was found internally, try to fetch any
5316	// data from the HTML5 data-* attribute
5317	if ( data === undefined && elem.nodeType === 1 ) {
5318
5319		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
5320
5321		data = elem.getAttribute( name );
5322
5323		if ( typeof data === "string" ) {
5324			try {
5325				data = data === "true" ? true :
5326					data === "false" ? false :
5327					data === "null" ? null :
5328					// Only convert to a number if it doesn't change the string
5329					+data + "" === data ? +data :
5330					rbrace.test( data ) ? jQuery.parseJSON( data ) :
5331					data;
5332			} catch( e ) {}
5333
5334			// Make sure we set the data so it isn't changed later
5335			jQuery.data( elem, key, data );
5336
5337		} else {
5338			data = undefined;
5339		}
5340	}
5341
5342	return data;
5343}
5344
5345// checks a cache object for emptiness
5346function isEmptyDataObject( obj ) {
5347	var name;
5348	for ( name in obj ) {
5349
5350		// if the public data object is empty, the private is still empty
5351		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
5352			continue;
5353		}
5354		if ( name !== "toJSON" ) {
5355			return false;
5356		}
5357	}
5358
5359	return true;
5360}
5361
5362function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
5363	if ( !jQuery.acceptData( elem ) ) {
5364		return;
5365	}
5366
5367	var ret, thisCache,
5368		internalKey = jQuery.expando,
5369
5370		// We have to handle DOM nodes and JS objects differently because IE6-7
5371		// can't GC object references properly across the DOM-JS boundary
5372		isNode = elem.nodeType,
5373
5374		// Only DOM nodes need the global jQuery cache; JS object data is
5375		// attached directly to the object so GC can occur automatically
5376		cache = isNode ? jQuery.cache : elem,
5377
5378		// Only defining an ID for JS objects if its cache already exists allows
5379		// the code to shortcut on the same path as a DOM node with no cache
5380		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
5381
5382	// Avoid doing any more work than we need to when trying to get data on an
5383	// object that has no data at all
5384	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
5385		return;
5386	}
5387
5388	if ( !id ) {
5389		// Only DOM nodes need a new unique ID for each element since their data
5390		// ends up in the global cache
5391		if ( isNode ) {
5392			id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
5393		} else {
5394			id = internalKey;
5395		}
5396	}
5397
5398	if ( !cache[ id ] ) {
5399		// Avoid exposing jQuery metadata on plain JS objects when the object
5400		// is serialized using JSON.stringify
5401		cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
5402	}
5403
5404	// An object can be passed to jQuery.data instead of a key/value pair; this gets
5405	// shallow copied over onto the existing cache
5406	if ( typeof name === "object" || typeof name === "function" ) {
5407		if ( pvt ) {
5408			cache[ id ] = jQuery.extend( cache[ id ], name );
5409		} else {
5410			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
5411		}
5412	}
5413
5414	thisCache = cache[ id ];
5415
5416	// jQuery data() is stored in a separate object inside the object's internal data
5417	// cache in order to avoid key collisions between internal data and user-defined
5418	// data.
5419	if ( !pvt ) {
5420		if ( !thisCache.data ) {
5421			thisCache.data = {};
5422		}
5423
5424		thisCache = thisCache.data;
5425	}
5426
5427	if ( data !== undefined ) {
5428		thisCache[ jQuery.camelCase( name ) ] = data;
5429	}
5430
5431	// Check for both converted-to-camel and non-converted data property names
5432	// If a data property was specified
5433	if ( typeof name === "string" ) {
5434
5435		// First Try to find as-is property data
5436		ret = thisCache[ name ];
5437
5438		// Test for null|undefined property data
5439		if ( ret == null ) {
5440
5441			// Try to find the camelCased property
5442			ret = thisCache[ jQuery.camelCase( name ) ];
5443		}
5444	} else {
5445		ret = thisCache;
5446	}
5447
5448	return ret;
5449}
5450
5451function internalRemoveData( elem, name, pvt ) {
5452	if ( !jQuery.acceptData( elem ) ) {
5453		return;
5454	}
5455
5456	var thisCache, i,
5457		isNode = elem.nodeType,
5458
5459		// See jQuery.data for more information
5460		cache = isNode ? jQuery.cache : elem,
5461		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
5462
5463	// If there is already no cache entry for this object, there is no
5464	// purpose in continuing
5465	if ( !cache[ id ] ) {
5466		return;
5467	}
5468
5469	if ( name ) {
5470
5471		thisCache = pvt ? cache[ id ] : cache[ id ].data;
5472
5473		if ( thisCache ) {
5474
5475			// Support array or space separated string names for data keys
5476			if ( !jQuery.isArray( name ) ) {
5477
5478				// try the string as a key before any manipulation
5479				if ( name in thisCache ) {
5480					name = [ name ];
5481				} else {
5482
5483					// split the camel cased version by spaces unless a key with the spaces exists
5484					name = jQuery.camelCase( name );
5485					if ( name in thisCache ) {
5486						name = [ name ];
5487					} else {
5488						name = name.split(" ");
5489					}
5490				}
5491			} else {
5492				// If "name" is an array of keys...
5493				// When data is initially created, via ("key", "val") signature,
5494				// keys will be converted to camelCase.
5495				// Since there is no way to tell _how_ a key was added, remove
5496				// both plain key and camelCase key. #12786
5497				// This will only penalize the array argument path.
5498				name = name.concat( jQuery.map( name, jQuery.camelCase ) );
5499			}
5500
5501			i = name.length;
5502			while ( i-- ) {
5503				delete thisCache[ name[i] ];
5504			}
5505
5506			// If there is no data left in the cache, we want to continue
5507			// and let the cache object itself get destroyed
5508			if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
5509				return;
5510			}
5511		}
5512	}
5513
5514	// See jQuery.data for more information
5515	if ( !pvt ) {
5516		delete cache[ id ].data;
5517
5518		// Don't destroy the parent cache unless the internal data object
5519		// had been the only thing left in it
5520		if ( !isEmptyDataObject( cache[ id ] ) ) {
5521			return;
5522		}
5523	}
5524
5525	// Destroy the cache
5526	if ( isNode ) {
5527		jQuery.cleanData( [ elem ], true );
5528
5529	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
5530	/* jshint eqeqeq: false */
5531	} else if ( support.deleteExpando || cache != cache.window ) {
5532		/* jshint eqeqeq: true */
5533		delete cache[ id ];
5534
5535	// When all else fails, null
5536	} else {
5537		cache[ id ] = null;
5538	}
5539}
5540
5541jQuery.extend({
5542	cache: {},
5543
5544	// The following elements (space-suffixed to avoid Object.prototype collisions)
5545	// throw uncatchable exceptions if you attempt to set expando properties
5546	noData: {
5547		"applet ": true,
5548		"embed ": true,
5549		// ...but Flash objects (which have this classid) *can* handle expandos
5550		"object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
5551	},
5552
5553	hasData: function( elem ) {
5554		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
5555		return !!elem && !isEmptyDataObject( elem );
5556	},
5557
5558	data: function( elem, name, data ) {
5559		return internalData( elem, name, data );
5560	},
5561
5562	removeData: function( elem, name ) {
5563		return internalRemoveData( elem, name );
5564	},
5565
5566	// For internal use only.
5567	_data: function( elem, name, data ) {
5568		return internalData( elem, name, data, true );
5569	},
5570
5571	_removeData: function( elem, name ) {
5572		return internalRemoveData( elem, name, true );
5573	}
5574});
5575
5576jQuery.fn.extend({
5577	data: function( key, value ) {
5578		var i, name, data,
5579			elem = this[0],
5580			attrs = elem && elem.attributes;
5581
5582		// Special expections of .data basically thwart jQuery.access,
5583		// so implement the relevant behavior ourselves
5584
5585		// Gets all values
5586		if ( key === undefined ) {
5587			if ( this.length ) {
5588				data = jQuery.data( elem );
5589
5590				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
5591					i = attrs.length;
5592					while ( i-- ) {
5593
5594						// Support: IE11+
5595						// The attrs elements can be null (#14894)
5596						if ( attrs[ i ] ) {
5597							name = attrs[ i ].name;
5598							if ( name.indexOf( "data-" ) === 0 ) {
5599								name = jQuery.camelCase( name.slice(5) );
5600								dataAttr( elem, name, data[ name ] );
5601							}
5602						}
5603					}
5604					jQuery._data( elem, "parsedAttrs", true );
5605				}
5606			}
5607
5608			return data;
5609		}
5610
5611		// Sets multiple values
5612		if ( typeof key === "object" ) {
5613			return this.each(function() {
5614				jQuery.data( this, key );
5615			});
5616		}
5617
5618		return arguments.length > 1 ?
5619
5620			// Sets one value
5621			this.each(function() {
5622				jQuery.data( this, key, value );
5623			}) :
5624
5625			// Gets one value
5626			// Try to fetch any internally stored data first
5627			elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
5628	},
5629
5630	removeData: function( key ) {
5631		return this.each(function() {
5632			jQuery.removeData( this, key );
5633		});
5634	}
5635});
5636
5637
5638jQuery.extend({
5639	queue: function( elem, type, data ) {
5640		var queue;
5641
5642		if ( elem ) {
5643			type = ( type || "fx" ) + "queue";
5644			queue = jQuery._data( elem, type );
5645
5646			// Speed up dequeue by getting out quickly if this is just a lookup
5647			if ( data ) {
5648				if ( !queue || jQuery.isArray(data) ) {
5649					queue = jQuery._data( elem, type, jQuery.makeArray(data) );
5650				} else {
5651					queue.push( data );
5652				}
5653			}
5654			return queue || [];
5655		}
5656	},
5657
5658	dequeue: function( elem, type ) {
5659		type = type || "fx";
5660
5661		var queue = jQuery.queue( elem, type ),
5662			startLength = queue.length,
5663			fn = queue.shift(),
5664			hooks = jQuery._queueHooks( elem, type ),
5665			next = function() {
5666				jQuery.dequeue( elem, type );
5667			};
5668
5669		// If the fx queue is dequeued, always remove the progress sentinel
5670		if ( fn === "inprogress" ) {
5671			fn = queue.shift();
5672			startLength--;
5673		}
5674
5675		if ( fn ) {
5676
5677			// Add a progress sentinel to prevent the fx queue from being
5678			// automatically dequeued
5679			if ( type === "fx" ) {
5680				queue.unshift( "inprogress" );
5681			}
5682
5683			// clear up the last queue stop function
5684			delete hooks.stop;
5685			fn.call( elem, next, hooks );
5686		}
5687
5688		if ( !startLength && hooks ) {
5689			hooks.empty.fire();
5690		}
5691	},
5692
5693	// not intended for public consumption - generates a queueHooks object, or returns the current one
5694	_queueHooks: function( elem, type ) {
5695		var key = type + "queueHooks";
5696		return jQuery._data( elem, key ) || jQuery._data( elem, key, {
5697			empty: jQuery.Callbacks("once memory").add(function() {
5698				jQuery._removeData( elem, type + "queue" );
5699				jQuery._removeData( elem, key );
5700			})
5701		});
5702	}
5703});
5704
5705jQuery.fn.extend({
5706	queue: function( type, data ) {
5707		var setter = 2;
5708
5709		if ( typeof type !== "string" ) {
5710			data = type;
5711			type = "fx";
5712			setter--;
5713		}
5714
5715		if ( arguments.length < setter ) {
5716			return jQuery.queue( this[0], type );
5717		}
5718
5719		return data === undefined ?
5720			this :
5721			this.each(function() {
5722				var queue = jQuery.queue( this, type, data );
5723
5724				// ensure a hooks for this queue
5725				jQuery._queueHooks( this, type );
5726
5727				if ( type === "fx" && queue[0] !== "inprogress" ) {
5728					jQuery.dequeue( this, type );
5729				}
5730			});
5731	},
5732	dequeue: function( type ) {
5733		return this.each(function() {
5734			jQuery.dequeue( this, type );
5735		});
5736	},
5737	clearQueue: function( type ) {
5738		return this.queue( type || "fx", [] );
5739	},
5740	// Get a promise resolved when queues of a certain type
5741	// are emptied (fx is the type by default)
5742	promise: function( type, obj ) {
5743		var tmp,
5744			count = 1,
5745			defer = jQuery.Deferred(),
5746			elements = this,
5747			i = this.length,
5748			resolve = function() {
5749				if ( !( --count ) ) {
5750					defer.resolveWith( elements, [ elements ] );
5751				}
5752			};
5753
5754		if ( typeof type !== "string" ) {
5755			obj = type;
5756			type = undefined;
5757		}
5758		type = type || "fx";
5759
5760		while ( i-- ) {
5761			tmp = jQuery._data( elements[ i ], type + "queueHooks" );
5762			if ( tmp && tmp.empty ) {
5763				count++;
5764				tmp.empty.add( resolve );
5765			}
5766		}
5767		resolve();
5768		return defer.promise( obj );
5769	}
5770});
5771var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
5772
5773var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
5774
5775var isHidden = function( elem, el ) {
5776		// isHidden might be called from jQuery#filter function;
5777		// in that case, element will be second argument
5778		elem = el || elem;
5779		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
5780	};
5781
5782
5783
5784// Multifunctional method to get and set values of a collection
5785// The value/s can optionally be executed if it's a function
5786var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
5787	var i = 0,
5788		length = elems.length,
5789		bulk = key == null;
5790
5791	// Sets many values
5792	if ( jQuery.type( key ) === "object" ) {
5793		chainable = true;
5794		for ( i in key ) {
5795			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
5796		}
5797
5798	// Sets one value
5799	} else if ( value !== undefined ) {
5800		chainable = true;
5801
5802		if ( !jQuery.isFunction( value ) ) {
5803			raw = true;
5804		}
5805
5806		if ( bulk ) {
5807			// Bulk operations run against the entire set
5808			if ( raw ) {
5809				fn.call( elems, value );
5810				fn = null;
5811
5812			// ...except when executing function values
5813			} else {
5814				bulk = fn;
5815				fn = function( elem, key, value ) {
5816					return bulk.call( jQuery( elem ), value );
5817				};
5818			}
5819		}
5820
5821		if ( fn ) {
5822			for ( ; i < length; i++ ) {
5823				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
5824			}
5825		}
5826	}
5827
5828	return chainable ?
5829		elems :
5830
5831		// Gets
5832		bulk ?
5833			fn.call( elems ) :
5834			length ? fn( elems[0], key ) : emptyGet;
5835};
5836var rcheckableType = (/^(?:checkbox|radio)$/i);
5837
5838
5839
5840(function() {
5841	// Minified: var a,b,c
5842	var input = document.createElement( "input" ),
5843		div = document.createElement( "div" ),
5844		fragment = document.createDocumentFragment();
5845
5846	// Setup
5847	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
5848
5849	// IE strips leading whitespace when .innerHTML is used
5850	support.leadingWhitespace = div.firstChild.nodeType === 3;
5851
5852	// Make sure that tbody elements aren't automatically inserted
5853	// IE will insert them into empty tables
5854	support.tbody = !div.getElementsByTagName( "tbody" ).length;
5855
5856	// Make sure that link elements get serialized correctly by innerHTML
5857	// This requires a wrapper element in IE
5858	support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
5859
5860	// Makes sure cloning an html5 element does not cause problems
5861	// Where outerHTML is undefined, this still works
5862	support.html5Clone =
5863		document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
5864
5865	// Check if a disconnected checkbox will retain its checked
5866	// value of true after appended to the DOM (IE6/7)
5867	input.type = "checkbox";
5868	input.checked = true;
5869	fragment.appendChild( input );
5870	support.appendChecked = input.checked;
5871
5872	// Make sure textarea (and checkbox) defaultValue is properly cloned
5873	// Support: IE6-IE11+
5874	div.innerHTML = "<textarea>x</textarea>";
5875	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
5876
5877	// #11217 - WebKit loses check when the name is after the checked attribute
5878	fragment.appendChild( div );
5879	div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
5880
5881	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
5882	// old WebKit doesn't clone checked state correctly in fragments
5883	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
5884
5885	// Support: IE<9
5886	// Opera does not clone events (and typeof div.attachEvent === undefined).
5887	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
5888	support.noCloneEvent = true;
5889	if ( div.attachEvent ) {
5890		div.attachEvent( "onclick", function() {
5891			support.noCloneEvent = false;
5892		});
5893
5894		div.cloneNode( true ).click();
5895	}
5896
5897	// Execute the test only if not already executed in another module.
5898	if (support.deleteExpando == null) {
5899		// Support: IE<9
5900		support.deleteExpando = true;
5901		try {
5902			delete div.test;
5903		} catch( e ) {
5904			support.deleteExpando = false;
5905		}
5906	}
5907})();
5908
5909
5910(function() {
5911	var i, eventName,
5912		div = document.createElement( "div" );
5913
5914	// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
5915	for ( i in { submit: true, change: true, focusin: true }) {
5916		eventName = "on" + i;
5917
5918		if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
5919			// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
5920			div.setAttribute( eventName, "t" );
5921			support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
5922		}
5923	}
5924
5925	// Null elements to avoid leaks in IE.
5926	div = null;
5927})();
5928
5929
5930var rformElems = /^(?:input|select|textarea)$/i,
5931	rkeyEvent = /^key/,
5932	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
5933	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
5934	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
5935
5936function returnTrue() {
5937	return true;
5938}
5939
5940function returnFalse() {
5941	return false;
5942}
5943
5944function safeActiveElement() {
5945	try {
5946		return document.activeElement;
5947	} catch ( err ) { }
5948}
5949
5950/*
5951 * Helper functions for managing events -- not part of the public interface.
5952 * Props to Dean Edwards' addEvent library for many of the ideas.
5953 */
5954jQuery.event = {
5955
5956	global: {},
5957
5958	add: function( elem, types, handler, data, selector ) {
5959		var tmp, events, t, handleObjIn,
5960			special, eventHandle, handleObj,
5961			handlers, type, namespaces, origType,
5962			elemData = jQuery._data( elem );
5963
5964		// Don't attach events to noData or text/comment nodes (but allow plain objects)
5965		if ( !elemData ) {
5966			return;
5967		}
5968
5969		// Caller can pass in an object of custom data in lieu of the handler
5970		if ( handler.handler ) {
5971			handleObjIn = handler;
5972			handler = handleObjIn.handler;
5973			selector = handleObjIn.selector;
5974		}
5975
5976		// Make sure that the handler has a unique ID, used to find/remove it later
5977		if ( !handler.guid ) {
5978			handler.guid = jQuery.guid++;
5979		}
5980
5981		// Init the element's event structure and main handler, if this is the first
5982		if ( !(events = elemData.events) ) {
5983			events = elemData.events = {};
5984		}
5985		if ( !(eventHandle = elemData.handle) ) {
5986			eventHandle = elemData.handle = function( e ) {
5987				// Discard the second event of a jQuery.event.trigger() and
5988				// when an event is called after a page has unloaded
5989				return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
5990					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
5991					undefined;
5992			};
5993			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
5994			eventHandle.elem = elem;
5995		}
5996
5997		// Handle multiple events separated by a space
5998		types = ( types || "" ).match( rnotwhite ) || [ "" ];
5999		t = types.length;
6000		while ( t-- ) {
6001			tmp = rtypenamespace.exec( types[t] ) || [];
6002			type = origType = tmp[1];
6003			namespaces = ( tmp[2] || "" ).split( "." ).sort();
6004
6005			// There *must* be a type, no attaching namespace-only handlers
6006			if ( !type ) {
6007				continue;
6008			}
6009
6010			// If event changes its type, use the special event handlers for the changed type
6011			special = jQuery.event.special[ type ] || {};
6012
6013			// If selector defined, determine special event api type, otherwise given type
6014			type = ( selector ? special.delegateType : special.bindType ) || type;
6015
6016			// Update special based on newly reset type
6017			special = jQuery.event.special[ type ] || {};
6018
6019			// handleObj is passed to all event handlers
6020			handleObj = jQuery.extend({
6021				type: type,
6022				origType: origType,
6023				data: data,
6024				handler: handler,
6025				guid: handler.guid,
6026				selector: selector,
6027				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
6028				namespace: namespaces.join(".")
6029			}, handleObjIn );
6030
6031			// Init the event handler queue if we're the first
6032			if ( !(handlers = events[ type ]) ) {
6033				handlers = events[ type ] = [];
6034				handlers.delegateCount = 0;
6035
6036				// Only use addEventListener/attachEvent if the special events handler returns false
6037				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
6038					// Bind the global event handler to the element
6039					if ( elem.addEventListener ) {
6040						elem.addEventListener( type, eventHandle, false );
6041
6042					} else if ( elem.attachEvent ) {
6043						elem.attachEvent( "on" + type, eventHandle );
6044					}
6045				}
6046			}
6047
6048			if ( special.add ) {
6049				special.add.call( elem, handleObj );
6050
6051				if ( !handleObj.handler.guid ) {
6052					handleObj.handler.guid = handler.guid;
6053				}
6054			}
6055
6056			// Add to the element's handler list, delegates in front
6057			if ( selector ) {
6058				handlers.splice( handlers.delegateCount++, 0, handleObj );
6059			} else {
6060				handlers.push( handleObj );
6061			}
6062
6063			// Keep track of which events have ever been used, for event optimization
6064			jQuery.event.global[ type ] = true;
6065		}
6066
6067		// Nullify elem to prevent memory leaks in IE
6068		elem = null;
6069	},
6070
6071	// Detach an event or set of events from an element
6072	remove: function( elem, types, handler, selector, mappedTypes ) {
6073		var j, handleObj, tmp,
6074			origCount, t, events,
6075			special, handlers, type,
6076			namespaces, origType,
6077			elemData = jQuery.hasData( elem ) && jQuery._data( elem );
6078
6079		if ( !elemData || !(events = elemData.events) ) {
6080			return;
6081		}
6082
6083		// Once for each type.namespace in types; type may be omitted
6084		types = ( types || "" ).match( rnotwhite ) || [ "" ];
6085		t = types.length;
6086		while ( t-- ) {
6087			tmp = rtypenamespace.exec( types[t] ) || [];
6088			type = origType = tmp[1];
6089			namespaces = ( tmp[2] || "" ).split( "." ).sort();
6090
6091			// Unbind all events (on this namespace, if provided) for the element
6092			if ( !type ) {
6093				for ( type in events ) {
6094					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
6095				}
6096				continue;
6097			}
6098
6099			special = jQuery.event.special[ type ] || {};
6100			type = ( selector ? special.delegateType : special.bindType ) || type;
6101			handlers = events[ type ] || [];
6102			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
6103
6104			// Remove matching events
6105			origCount = j = handlers.length;
6106			while ( j-- ) {
6107				handleObj = handlers[ j ];
6108
6109				if ( ( mappedTypes || origType === handleObj.origType ) &&
6110					( !handler || handler.guid === handleObj.guid ) &&
6111					( !tmp || tmp.test( handleObj.namespace ) ) &&
6112					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
6113					handlers.splice( j, 1 );
6114
6115					if ( handleObj.selector ) {
6116						handlers.delegateCount--;
6117					}
6118					if ( special.remove ) {
6119						special.remove.call( elem, handleObj );
6120					}
6121				}
6122			}
6123
6124			// Remove generic event handler if we removed something and no more handlers exist
6125			// (avoids potential for endless recursion during removal of special event handlers)
6126			if ( origCount && !handlers.length ) {
6127				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
6128					jQuery.removeEvent( elem, type, elemData.handle );
6129				}
6130
6131				delete events[ type ];
6132			}
6133		}
6134
6135		// Remove the expando if it's no longer used
6136		if ( jQuery.isEmptyObject( events ) ) {
6137			delete elemData.handle;
6138
6139			// removeData also checks for emptiness and clears the expando if empty
6140			// so use it instead of delete
6141			jQuery._removeData( elem, "events" );
6142		}
6143	},
6144
6145	trigger: function( event, data, elem, onlyHandlers ) {
6146		var handle, ontype, cur,
6147			bubbleType, special, tmp, i,
6148			eventPath = [ elem || document ],
6149			type = hasOwn.call( event, "type" ) ? event.type : event,
6150			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
6151
6152		cur = tmp = elem = elem || document;
6153
6154		// Don't do events on text and comment nodes
6155		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
6156			return;
6157		}
6158
6159		// focus/blur morphs to focusin/out; ensure we're not firing them right now
6160		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
6161			return;
6162		}
6163
6164		if ( type.indexOf(".") >= 0 ) {
6165			// Namespaced trigger; create a regexp to match event type in handle()
6166			namespaces = type.split(".");
6167			type = namespaces.shift();
6168			namespaces.sort();
6169		}
6170		ontype = type.indexOf(":") < 0 && "on" + type;
6171
6172		// Caller can pass in a jQuery.Event object, Object, or just an event type string
6173		event = event[ jQuery.expando ] ?
6174			event :
6175			new jQuery.Event( type, typeof event === "object" && event );
6176
6177		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
6178		event.isTrigger = onlyHandlers ? 2 : 3;
6179		event.namespace = namespaces.join(".");
6180		event.namespace_re = event.namespace ?
6181			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
6182			null;
6183
6184		// Clean up the event in case it is being reused
6185		event.result = undefined;
6186		if ( !event.target ) {
6187			event.target = elem;
6188		}
6189
6190		// Clone any incoming data and prepend the event, creating the handler arg list
6191		data = data == null ?
6192			[ event ] :
6193			jQuery.makeArray( data, [ event ] );
6194
6195		// Allow special events to draw outside the lines
6196		special = jQuery.event.special[ type ] || {};
6197		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
6198			return;
6199		}
6200
6201		// Determine event propagation path in advance, per W3C events spec (#9951)
6202		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
6203		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
6204
6205			bubbleType = special.delegateType || type;
6206			if ( !rfocusMorph.test( bubbleType + type ) ) {
6207				cur = cur.parentNode;
6208			}
6209			for ( ; cur; cur = cur.parentNode ) {
6210				eventPath.push( cur );
6211				tmp = cur;
6212			}
6213
6214			// Only add window if we got to document (e.g., not plain obj or detached DOM)
6215			if ( tmp === (elem.ownerDocument || document) ) {
6216				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
6217			}
6218		}
6219
6220		// Fire handlers on the event path
6221		i = 0;
6222		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
6223
6224			event.type = i > 1 ?
6225				bubbleType :
6226				special.bindType || type;
6227
6228			// jQuery handler
6229			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
6230			if ( handle ) {
6231				handle.apply( cur, data );
6232			}
6233
6234			// Native handler
6235			handle = ontype && cur[ ontype ];
6236			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
6237				event.result = handle.apply( cur, data );
6238				if ( event.result === false ) {
6239					event.preventDefault();
6240				}
6241			}
6242		}
6243		event.type = type;
6244
6245		// If nobody prevented the default action, do it now
6246		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
6247
6248			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
6249				jQuery.acceptData( elem ) ) {
6250
6251				// Call a native DOM method on the target with the same name name as the event.
6252				// Can't use an .isFunction() check here because IE6/7 fails that test.
6253				// Don't do default actions on window, that's where global variables be (#6170)
6254				if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
6255
6256					// Don't re-trigger an onFOO event when we call its FOO() method
6257					tmp = elem[ ontype ];
6258
6259					if ( tmp ) {
6260						elem[ ontype ] = null;
6261					}
6262
6263					// Prevent re-triggering of the same event, since we already bubbled it above
6264					jQuery.event.triggered = type;
6265					try {
6266						elem[ type ]();
6267					} catch ( e ) {
6268						// IE<9 dies on focus/blur to hidden element (#1486,#12518)
6269						// only reproducible on winXP IE8 native, not IE9 in IE8 mode
6270					}
6271					jQuery.event.triggered = undefined;
6272
6273					if ( tmp ) {
6274						elem[ ontype ] = tmp;
6275					}
6276				}
6277			}
6278		}
6279
6280		return event.result;
6281	},
6282
6283	dispatch: function( event ) {
6284
6285		// Make a writable jQuery.Event from the native event object
6286		event = jQuery.event.fix( event );
6287
6288		var i, ret, handleObj, matched, j,
6289			handlerQueue = [],
6290			args = slice.call( arguments ),
6291			handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
6292			special = jQuery.event.special[ event.type ] || {};
6293
6294		// Use the fix-ed jQuery.Event rather than the (read-only) native event
6295		args[0] = event;
6296		event.delegateTarget = this;
6297
6298		// Call the preDispatch hook for the mapped type, and let it bail if desired
6299		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
6300			return;
6301		}
6302
6303		// Determine handlers
6304		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
6305
6306		// Run delegates first; they may want to stop propagation beneath us
6307		i = 0;
6308		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
6309			event.currentTarget = matched.elem;
6310
6311			j = 0;
6312			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
6313
6314				// Triggered event must either 1) have no namespace, or
6315				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
6316				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
6317
6318					event.handleObj = handleObj;
6319					event.data = handleObj.data;
6320
6321					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
6322							.apply( matched.elem, args );
6323
6324					if ( ret !== undefined ) {
6325						if ( (event.result = ret) === false ) {
6326							event.preventDefault();
6327							event.stopPropagation();
6328						}
6329					}
6330				}
6331			}
6332		}
6333
6334		// Call the postDispatch hook for the mapped type
6335		if ( special.postDispatch ) {
6336			special.postDispatch.call( this, event );
6337		}
6338
6339		return event.result;
6340	},
6341
6342	handlers: function( event, handlers ) {
6343		var sel, handleObj, matches, i,
6344			handlerQueue = [],
6345			delegateCount = handlers.delegateCount,
6346			cur = event.target;
6347
6348		// Find delegate handlers
6349		// Black-hole SVG <use> instance trees (#13180)
6350		// Avoid non-left-click bubbling in Firefox (#3861)
6351		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
6352
6353			/* jshint eqeqeq: false */
6354			for ( ; cur != this; cur = cur.parentNode || this ) {
6355				/* jshint eqeqeq: true */
6356
6357				// Don't check non-elements (#13208)
6358				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
6359				if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
6360					matches = [];
6361					for ( i = 0; i < delegateCount; i++ ) {
6362						handleObj = handlers[ i ];
6363
6364						// Don't conflict with Object.prototype properties (#13203)
6365						sel = handleObj.selector + " ";
6366
6367						if ( matches[ sel ] === undefined ) {
6368							matches[ sel ] = handleObj.needsContext ?
6369								jQuery( sel, this ).index( cur ) >= 0 :
6370								jQuery.find( sel, this, null, [ cur ] ).length;
6371						}
6372						if ( matches[ sel ] ) {
6373							matches.push( handleObj );
6374						}
6375					}
6376					if ( matches.length ) {
6377						handlerQueue.push({ elem: cur, handlers: matches });
6378					}
6379				}
6380			}
6381		}
6382
6383		// Add the remaining (directly-bound) handlers
6384		if ( delegateCount < handlers.length ) {
6385			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
6386		}
6387
6388		return handlerQueue;
6389	},
6390
6391	fix: function( event ) {
6392		if ( event[ jQuery.expando ] ) {
6393			return event;
6394		}
6395
6396		// Create a writable copy of the event object and normalize some properties
6397		var i, prop, copy,
6398			type = event.type,
6399			originalEvent = event,
6400			fixHook = this.fixHooks[ type ];
6401
6402		if ( !fixHook ) {
6403			this.fixHooks[ type ] = fixHook =
6404				rmouseEvent.test( type ) ? this.mouseHooks :
6405				rkeyEvent.test( type ) ? this.keyHooks :
6406				{};
6407		}
6408		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
6409
6410		event = new jQuery.Event( originalEvent );
6411
6412		i = copy.length;
6413		while ( i-- ) {
6414			prop = copy[ i ];
6415			event[ prop ] = originalEvent[ prop ];
6416		}
6417
6418		// Support: IE<9
6419		// Fix target property (#1925)
6420		if ( !event.target ) {
6421			event.target = originalEvent.srcElement || document;
6422		}
6423
6424		// Support: Chrome 23+, Safari?
6425		// Target should not be a text node (#504, #13143)
6426		if ( event.target.nodeType === 3 ) {
6427			event.target = event.target.parentNode;
6428		}
6429
6430		// Support: IE<9
6431		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
6432		event.metaKey = !!event.metaKey;
6433
6434		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
6435	},
6436
6437	// Includes some event props shared by KeyEvent and MouseEvent
6438	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
6439
6440	fixHooks: {},
6441
6442	keyHooks: {
6443		props: "char charCode key keyCode".split(" "),
6444		filter: function( event, original ) {
6445
6446			// Add which for key events
6447			if ( event.which == null ) {
6448				event.which = original.charCode != null ? original.charCode : original.keyCode;
6449			}
6450
6451			return event;
6452		}
6453	},
6454
6455	mouseHooks: {
6456		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
6457		filter: function( event, original ) {
6458			var body, eventDoc, doc,
6459				button = original.button,
6460				fromElement = original.fromElement;
6461
6462			// Calculate pageX/Y if missing and clientX/Y available
6463			if ( event.pageX == null && original.clientX != null ) {
6464				eventDoc = event.target.ownerDocument || document;
6465				doc = eventDoc.documentElement;
6466				body = eventDoc.body;
6467
6468				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
6469				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
6470			}
6471
6472			// Add relatedTarget, if necessary
6473			if ( !event.relatedTarget && fromElement ) {
6474				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
6475			}
6476
6477			// Add which for click: 1 === left; 2 === middle; 3 === right
6478			// Note: button is not normalized, so don't use it
6479			if ( !event.which && button !== undefined ) {
6480				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
6481			}
6482
6483			return event;
6484		}
6485	},
6486
6487	special: {
6488		load: {
6489			// Prevent triggered image.load events from bubbling to window.load
6490			noBubble: true
6491		},
6492		focus: {
6493			// Fire native event if possible so blur/focus sequence is correct
6494			trigger: function() {
6495				if ( this !== safeActiveElement() && this.focus ) {
6496					try {
6497						this.focus();
6498						return false;
6499					} catch ( e ) {
6500						// Support: IE<9
6501						// If we error on focus to hidden element (#1486, #12518),
6502						// let .trigger() run the handlers
6503					}
6504				}
6505			},
6506			delegateType: "focusin"
6507		},
6508		blur: {
6509			trigger: function() {
6510				if ( this === safeActiveElement() && this.blur ) {
6511					this.blur();
6512					return false;
6513				}
6514			},
6515			delegateType: "focusout"
6516		},
6517		click: {
6518			// For checkbox, fire native event so checked state will be right
6519			trigger: function() {
6520				if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
6521					this.click();
6522					return false;
6523				}
6524			},
6525
6526			// For cross-browser consistency, don't fire native .click() on links
6527			_default: function( event ) {
6528				return jQuery.nodeName( event.target, "a" );
6529			}
6530		},
6531
6532		beforeunload: {
6533			postDispatch: function( event ) {
6534
6535				// Support: Firefox 20+
6536				// Firefox doesn't alert if the returnValue field is not set.
6537				if ( event.result !== undefined && event.originalEvent ) {
6538					event.originalEvent.returnValue = event.result;
6539				}
6540			}
6541		}
6542	},
6543
6544	simulate: function( type, elem, event, bubble ) {
6545		// Piggyback on a donor event to simulate a different one.
6546		// Fake originalEvent to avoid donor's stopPropagation, but if the
6547		// simulated event prevents default then we do the same on the donor.
6548		var e = jQuery.extend(
6549			new jQuery.Event(),
6550			event,
6551			{
6552				type: type,
6553				isSimulated: true,
6554				originalEvent: {}
6555			}
6556		);
6557		if ( bubble ) {
6558			jQuery.event.trigger( e, null, elem );
6559		} else {
6560			jQuery.event.dispatch.call( elem, e );
6561		}
6562		if ( e.isDefaultPrevented() ) {
6563			event.preventDefault();
6564		}
6565	}
6566};
6567
6568jQuery.removeEvent = document.removeEventListener ?
6569	function( elem, type, handle ) {
6570		if ( elem.removeEventListener ) {
6571			elem.removeEventListener( type, handle, false );
6572		}
6573	} :
6574	function( elem, type, handle ) {
6575		var name = "on" + type;
6576
6577		if ( elem.detachEvent ) {
6578
6579			// #8545, #7054, preventing memory leaks for custom events in IE6-8
6580			// detachEvent needed property on element, by name of that event, to properly expose it to GC
6581			if ( typeof elem[ name ] === strundefined ) {
6582				elem[ name ] = null;
6583			}
6584
6585			elem.detachEvent( name, handle );
6586		}
6587	};
6588
6589jQuery.Event = function( src, props ) {
6590	// Allow instantiation without the 'new' keyword
6591	if ( !(this instanceof jQuery.Event) ) {
6592		return new jQuery.Event( src, props );
6593	}
6594
6595	// Event object
6596	if ( src && src.type ) {
6597		this.originalEvent = src;
6598		this.type = src.type;
6599
6600		// Events bubbling up the document may have been marked as prevented
6601		// by a handler lower down the tree; reflect the correct value.
6602		this.isDefaultPrevented = src.defaultPrevented ||
6603				src.defaultPrevented === undefined &&
6604				// Support: IE < 9, Android < 4.0
6605				src.returnValue === false ?
6606			returnTrue :
6607			returnFalse;
6608
6609	// Event type
6610	} else {
6611		this.type = src;
6612	}
6613
6614	// Put explicitly provided properties onto the event object
6615	if ( props ) {
6616		jQuery.extend( this, props );
6617	}
6618
6619	// Create a timestamp if incoming event doesn't have one
6620	this.timeStamp = src && src.timeStamp || jQuery.now();
6621
6622	// Mark it as fixed
6623	this[ jQuery.expando ] = true;
6624};
6625
6626// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
6627// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
6628jQuery.Event.prototype = {
6629	isDefaultPrevented: returnFalse,
6630	isPropagationStopped: returnFalse,
6631	isImmediatePropagationStopped: returnFalse,
6632
6633	preventDefault: function() {
6634		var e = this.originalEvent;
6635
6636		this.isDefaultPrevented = returnTrue;
6637		if ( !e ) {
6638			return;
6639		}
6640
6641		// If preventDefault exists, run it on the original event
6642		if ( e.preventDefault ) {
6643			e.preventDefault();
6644
6645		// Support: IE
6646		// Otherwise set the returnValue property of the original event to false
6647		} else {
6648			e.returnValue = false;
6649		}
6650	},
6651	stopPropagation: function() {
6652		var e = this.originalEvent;
6653
6654		this.isPropagationStopped = returnTrue;
6655		if ( !e ) {
6656			return;
6657		}
6658		// If stopPropagation exists, run it on the original event
6659		if ( e.stopPropagation ) {
6660			e.stopPropagation();
6661		}
6662
6663		// Support: IE
6664		// Set the cancelBubble property of the original event to true
6665		e.cancelBubble = true;
6666	},
6667	stopImmediatePropagation: function() {
6668		var e = this.originalEvent;
6669
6670		this.isImmediatePropagationStopped = returnTrue;
6671
6672		if ( e && e.stopImmediatePropagation ) {
6673			e.stopImmediatePropagation();
6674		}
6675
6676		this.stopPropagation();
6677	}
6678};
6679
6680// Create mouseenter/leave events using mouseover/out and event-time checks
6681jQuery.each({
6682	mouseenter: "mouseover",
6683	mouseleave: "mouseout",
6684	pointerenter: "pointerover",
6685	pointerleave: "pointerout"
6686}, function( orig, fix ) {
6687	jQuery.event.special[ orig ] = {
6688		delegateType: fix,
6689		bindType: fix,
6690
6691		handle: function( event ) {
6692			var ret,
6693				target = this,
6694				related = event.relatedTarget,
6695				handleObj = event.handleObj;
6696
6697			// For mousenter/leave call the handler if related is outside the target.
6698			// NB: No relatedTarget if the mouse left/entered the browser window
6699			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
6700				event.type = handleObj.origType;
6701				ret = handleObj.handler.apply( this, arguments );
6702				event.type = fix;
6703			}
6704			return ret;
6705		}
6706	};
6707});
6708
6709// IE submit delegation
6710if ( !support.submitBubbles ) {
6711
6712	jQuery.event.special.submit = {
6713		setup: function() {
6714			// Only need this for delegated form submit events
6715			if ( jQuery.nodeName( this, "form" ) ) {
6716				return false;
6717			}
6718
6719			// Lazy-add a submit handler when a descendant form may potentially be submitted
6720			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
6721				// Node name check avoids a VML-related crash in IE (#9807)
6722				var elem = e.target,
6723					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
6724				if ( form && !jQuery._data( form, "submitBubbles" ) ) {
6725					jQuery.event.add( form, "submit._submit", function( event ) {
6726						event._submit_bubble = true;
6727					});
6728					jQuery._data( form, "submitBubbles", true );
6729				}
6730			});
6731			// return undefined since we don't need an event listener
6732		},
6733
6734		postDispatch: function( event ) {
6735			// If form was submitted by the user, bubble the event up the tree
6736			if ( event._submit_bubble ) {
6737				delete event._submit_bubble;
6738				if ( this.parentNode && !event.isTrigger ) {
6739					jQuery.event.simulate( "submit", this.parentNode, event, true );
6740				}
6741			}
6742		},
6743
6744		teardown: function() {
6745			// Only need this for delegated form submit events
6746			if ( jQuery.nodeName( this, "form" ) ) {
6747				return false;
6748			}
6749
6750			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
6751			jQuery.event.remove( this, "._submit" );
6752		}
6753	};
6754}
6755
6756// IE change delegation and checkbox/radio fix
6757if ( !support.changeBubbles ) {
6758
6759	jQuery.event.special.change = {
6760
6761		setup: function() {
6762
6763			if ( rformElems.test( this.nodeName ) ) {
6764				// IE doesn't fire change on a check/radio until blur; trigger it on click
6765				// after a propertychange. Eat the blur-change in special.change.handle.
6766				// This still fires onchange a second time for check/radio after blur.
6767				if ( this.type === "checkbox" || this.type === "radio" ) {
6768					jQuery.event.add( this, "propertychange._change", function( event ) {
6769						if ( event.originalEvent.propertyName === "checked" ) {
6770							this._just_changed = true;
6771						}
6772					});
6773					jQuery.event.add( this, "click._change", function( event ) {
6774						if ( this._just_changed && !event.isTrigger ) {
6775							this._just_changed = false;
6776						}
6777						// Allow triggered, simulated change events (#11500)
6778						jQuery.event.simulate( "change", this, event, true );
6779					});
6780				}
6781				return false;
6782			}
6783			// Delegated event; lazy-add a change handler on descendant inputs
6784			jQuery.event.add( this, "beforeactivate._change", function( e ) {
6785				var elem = e.target;
6786
6787				if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
6788					jQuery.event.add( elem, "change._change", function( event ) {
6789						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
6790							jQuery.event.simulate( "change", this.parentNode, event, true );
6791						}
6792					});
6793					jQuery._data( elem, "changeBubbles", true );
6794				}
6795			});
6796		},
6797
6798		handle: function( event ) {
6799			var elem = event.target;
6800
6801			// Swallow native change events from checkbox/radio, we already triggered them above
6802			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
6803				return event.handleObj.handler.apply( this, arguments );
6804			}
6805		},
6806
6807		teardown: function() {
6808			jQuery.event.remove( this, "._change" );
6809
6810			return !rformElems.test( this.nodeName );
6811		}
6812	};
6813}
6814
6815// Create "bubbling" focus and blur events
6816if ( !support.focusinBubbles ) {
6817	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
6818
6819		// Attach a single capturing handler on the document while someone wants focusin/focusout
6820		var handler = function( event ) {
6821				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
6822			};
6823
6824		jQuery.event.special[ fix ] = {
6825			setup: function() {
6826				var doc = this.ownerDocument || this,
6827					attaches = jQuery._data( doc, fix );
6828
6829				if ( !attaches ) {
6830					doc.addEventListener( orig, handler, true );
6831				}
6832				jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
6833			},
6834			teardown: function() {
6835				var doc = this.ownerDocument || this,
6836					attaches = jQuery._data( doc, fix ) - 1;
6837
6838				if ( !attaches ) {
6839					doc.removeEventListener( orig, handler, true );
6840					jQuery._removeData( doc, fix );
6841				} else {
6842					jQuery._data( doc, fix, attaches );
6843				}
6844			}
6845		};
6846	});
6847}
6848
6849jQuery.fn.extend({
6850
6851	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
6852		var type, origFn;
6853
6854		// Types can be a map of types/handlers
6855		if ( typeof types === "object" ) {
6856			// ( types-Object, selector, data )
6857			if ( typeof selector !== "string" ) {
6858				// ( types-Object, data )
6859				data = data || selector;
6860				selector = undefined;
6861			}
6862			for ( type in types ) {
6863				this.on( type, selector, data, types[ type ], one );
6864			}
6865			return this;
6866		}
6867
6868		if ( data == null && fn == null ) {
6869			// ( types, fn )
6870			fn = selector;
6871			data = selector = undefined;
6872		} else if ( fn == null ) {
6873			if ( typeof selector === "string" ) {
6874				// ( types, selector, fn )
6875				fn = data;
6876				data = undefined;
6877			} else {
6878				// ( types, data, fn )
6879				fn = data;
6880				data = selector;
6881				selector = undefined;
6882			}
6883		}
6884		if ( fn === false ) {
6885			fn = returnFalse;
6886		} else if ( !fn ) {
6887			return this;
6888		}
6889
6890		if ( one === 1 ) {
6891			origFn = fn;
6892			fn = function( event ) {
6893				// Can use an empty set, since event contains the info
6894				jQuery().off( event );
6895				return origFn.apply( this, arguments );
6896			};
6897			// Use same guid so caller can remove using origFn
6898			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
6899		}
6900		return this.each( function() {
6901			jQuery.event.add( this, types, fn, data, selector );
6902		});
6903	},
6904	one: function( types, selector, data, fn ) {
6905		return this.on( types, selector, data, fn, 1 );
6906	},
6907	off: function( types, selector, fn ) {
6908		var handleObj, type;
6909		if ( types && types.preventDefault && types.handleObj ) {
6910			// ( event )  dispatched jQuery.Event
6911			handleObj = types.handleObj;
6912			jQuery( types.delegateTarget ).off(
6913				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
6914				handleObj.selector,
6915				handleObj.handler
6916			);
6917			return this;
6918		}
6919		if ( typeof types === "object" ) {
6920			// ( types-object [, selector] )
6921			for ( type in types ) {
6922				this.off( type, selector, types[ type ] );
6923			}
6924			return this;
6925		}
6926		if ( selector === false || typeof selector === "function" ) {
6927			// ( types [, fn] )
6928			fn = selector;
6929			selector = undefined;
6930		}
6931		if ( fn === false ) {
6932			fn = returnFalse;
6933		}
6934		return this.each(function() {
6935			jQuery.event.remove( this, types, fn, selector );
6936		});
6937	},
6938
6939	trigger: function( type, data ) {
6940		return this.each(function() {
6941			jQuery.event.trigger( type, data, this );
6942		});
6943	},
6944	triggerHandler: function( type, data ) {
6945		var elem = this[0];
6946		if ( elem ) {
6947			return jQuery.event.trigger( type, data, elem, true );
6948		}
6949	}
6950});
6951
6952
6953function createSafeFragment( document ) {
6954	var list = nodeNames.split( "|" ),
6955		safeFrag = document.createDocumentFragment();
6956
6957	if ( safeFrag.createElement ) {
6958		while ( list.length ) {
6959			safeFrag.createElement(
6960				list.pop()
6961			);
6962		}
6963	}
6964	return safeFrag;
6965}
6966
6967var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
6968		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
6969	rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
6970	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
6971	rleadingWhitespace = /^\s+/,
6972	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
6973	rtagName = /<([\w:]+)/,
6974	rtbody = /<tbody/i,
6975	rhtml = /<|&#?\w+;/,
6976	rnoInnerhtml = /<(?:script|style|link)/i,
6977	// checked="checked" or checked
6978	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
6979	rscriptType = /^$|\/(?:java|ecma)script/i,
6980	rscriptTypeMasked = /^true\/(.*)/,
6981	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
6982
6983	// We have to close these tags to support XHTML (#13200)
6984	wrapMap = {
6985		option: [ 1, "<select multiple='multiple'>", "</select>" ],
6986		legend: [ 1, "<fieldset>", "</fieldset>" ],
6987		area: [ 1, "<map>", "</map>" ],
6988		param: [ 1, "<object>", "</object>" ],
6989		thead: [ 1, "<table>", "</table>" ],
6990		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
6991		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
6992		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
6993
6994		// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
6995		// unless wrapped in a div with non-breaking characters in front of it.
6996		_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
6997	},
6998	safeFragment = createSafeFragment( document ),
6999	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
7000
7001wrapMap.optgroup = wrapMap.option;
7002wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
7003wrapMap.th = wrapMap.td;
7004
7005function getAll( context, tag ) {
7006	var elems, elem,
7007		i = 0,
7008		found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
7009			typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
7010			undefined;
7011
7012	if ( !found ) {
7013		for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
7014			if ( !tag || jQuery.nodeName( elem, tag ) ) {
7015				found.push( elem );
7016			} else {
7017				jQuery.merge( found, getAll( elem, tag ) );
7018			}
7019		}
7020	}
7021
7022	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
7023		jQuery.merge( [ context ], found ) :
7024		found;
7025}
7026
7027// Used in buildFragment, fixes the defaultChecked property
7028function fixDefaultChecked( elem ) {
7029	if ( rcheckableType.test( elem.type ) ) {
7030		elem.defaultChecked = elem.checked;
7031	}
7032}
7033
7034// Support: IE<8
7035// Manipulating tables requires a tbody
7036function manipulationTarget( elem, content ) {
7037	return jQuery.nodeName( elem, "table" ) &&
7038		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
7039
7040		elem.getElementsByTagName("tbody")[0] ||
7041			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
7042		elem;
7043}
7044
7045// Replace/restore the type attribute of script elements for safe DOM manipulation
7046function disableScript( elem ) {
7047	elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
7048	return elem;
7049}
7050function restoreScript( elem ) {
7051	var match = rscriptTypeMasked.exec( elem.type );
7052	if ( match ) {
7053		elem.type = match[1];
7054	} else {
7055		elem.removeAttribute("type");
7056	}
7057	return elem;
7058}
7059
7060// Mark scripts as having already been evaluated
7061function setGlobalEval( elems, refElements ) {
7062	var elem,
7063		i = 0;
7064	for ( ; (elem = elems[i]) != null; i++ ) {
7065		jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
7066	}
7067}
7068
7069function cloneCopyEvent( src, dest ) {
7070
7071	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
7072		return;
7073	}
7074
7075	var type, i, l,
7076		oldData = jQuery._data( src ),
7077		curData = jQuery._data( dest, oldData ),
7078		events = oldData.events;
7079
7080	if ( events ) {
7081		delete curData.handle;
7082		curData.events = {};
7083
7084		for ( type in events ) {
7085			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
7086				jQuery.event.add( dest, type, events[ type ][ i ] );
7087			}
7088		}
7089	}
7090
7091	// make the cloned public data object a copy from the original
7092	if ( curData.data ) {
7093		curData.data = jQuery.extend( {}, curData.data );
7094	}
7095}
7096
7097function fixCloneNodeIssues( src, dest ) {
7098	var nodeName, e, data;
7099
7100	// We do not need to do anything for non-Elements
7101	if ( dest.nodeType !== 1 ) {
7102		return;
7103	}
7104
7105	nodeName = dest.nodeName.toLowerCase();
7106
7107	// IE6-8 copies events bound via attachEvent when using cloneNode.
7108	if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
7109		data = jQuery._data( dest );
7110
7111		for ( e in data.events ) {
7112			jQuery.removeEvent( dest, e, data.handle );
7113		}
7114
7115		// Event data gets referenced instead of copied if the expando gets copied too
7116		dest.removeAttribute( jQuery.expando );
7117	}
7118
7119	// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
7120	if ( nodeName === "script" && dest.text !== src.text ) {
7121		disableScript( dest ).text = src.text;
7122		restoreScript( dest );
7123
7124	// IE6-10 improperly clones children of object elements using classid.
7125	// IE10 throws NoModificationAllowedError if parent is null, #12132.
7126	} else if ( nodeName === "object" ) {
7127		if ( dest.parentNode ) {
7128			dest.outerHTML = src.outerHTML;
7129		}
7130
7131		// This path appears unavoidable for IE9. When cloning an object
7132		// element in IE9, the outerHTML strategy above is not sufficient.
7133		// If the src has innerHTML and the destination does not,
7134		// copy the src.innerHTML into the dest.innerHTML. #10324
7135		if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
7136			dest.innerHTML = src.innerHTML;
7137		}
7138
7139	} else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
7140		// IE6-8 fails to persist the checked state of a cloned checkbox
7141		// or radio button. Worse, IE6-7 fail to give the cloned element
7142		// a checked appearance if the defaultChecked value isn't also set
7143
7144		dest.defaultChecked = dest.checked = src.checked;
7145
7146		// IE6-7 get confused and end up setting the value of a cloned
7147		// checkbox/radio button to an empty string instead of "on"
7148		if ( dest.value !== src.value ) {
7149			dest.value = src.value;
7150		}
7151
7152	// IE6-8 fails to return the selected option to the default selected
7153	// state when cloning options
7154	} else if ( nodeName === "option" ) {
7155		dest.defaultSelected = dest.selected = src.defaultSelected;
7156
7157	// IE6-8 fails to set the defaultValue to the correct value when
7158	// cloning other types of input fields
7159	} else if ( nodeName === "input" || nodeName === "textarea" ) {
7160		dest.defaultValue = src.defaultValue;
7161	}
7162}
7163
7164jQuery.extend({
7165	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
7166		var destElements, node, clone, i, srcElements,
7167			inPage = jQuery.contains( elem.ownerDocument, elem );
7168
7169		if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
7170			clone = elem.cloneNode( true );
7171
7172		// IE<=8 does not properly clone detached, unknown element nodes
7173		} else {
7174			fragmentDiv.innerHTML = elem.outerHTML;
7175			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
7176		}
7177
7178		if ( (!support.noCloneEvent || !support.noCloneChecked) &&
7179				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
7180
7181			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
7182			destElements = getAll( clone );
7183			srcElements = getAll( elem );
7184
7185			// Fix all IE cloning issues
7186			for ( i = 0; (node = srcElements[i]) != null; ++i ) {
7187				// Ensure that the destination node is not null; Fixes #9587
7188				if ( destElements[i] ) {
7189					fixCloneNodeIssues( node, destElements[i] );
7190				}
7191			}
7192		}
7193
7194		// Copy the events from the original to the clone
7195		if ( dataAndEvents ) {
7196			if ( deepDataAndEvents ) {
7197				srcElements = srcElements || getAll( elem );
7198				destElements = destElements || getAll( clone );
7199
7200				for ( i = 0; (node = srcElements[i]) != null; i++ ) {
7201					cloneCopyEvent( node, destElements[i] );
7202				}
7203			} else {
7204				cloneCopyEvent( elem, clone );
7205			}
7206		}
7207
7208		// Preserve script evaluation history
7209		destElements = getAll( clone, "script" );
7210		if ( destElements.length > 0 ) {
7211			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
7212		}
7213
7214		destElements = srcElements = node = null;
7215
7216		// Return the cloned set
7217		return clone;
7218	},
7219
7220	buildFragment: function( elems, context, scripts, selection ) {
7221		var j, elem, contains,
7222			tmp, tag, tbody, wrap,
7223			l = elems.length,
7224
7225			// Ensure a safe fragment
7226			safe = createSafeFragment( context ),
7227
7228			nodes = [],
7229			i = 0;
7230
7231		for ( ; i < l; i++ ) {
7232			elem = elems[ i ];
7233
7234			if ( elem || elem === 0 ) {
7235
7236				// Add nodes directly
7237				if ( jQuery.type( elem ) === "object" ) {
7238					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
7239
7240				// Convert non-html into a text node
7241				} else if ( !rhtml.test( elem ) ) {
7242					nodes.push( context.createTextNode( elem ) );
7243
7244				// Convert html into DOM nodes
7245				} else {
7246					tmp = tmp || safe.appendChild( context.createElement("div") );
7247
7248					// Deserialize a standard representation
7249					tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
7250					wrap = wrapMap[ tag ] || wrapMap._default;
7251
7252					tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
7253
7254					// Descend through wrappers to the right content
7255					j = wrap[0];
7256					while ( j-- ) {
7257						tmp = tmp.lastChild;
7258					}
7259
7260					// Manually add leading whitespace removed by IE
7261					if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
7262						nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
7263					}
7264
7265					// Remove IE's autoinserted <tbody> from table fragments
7266					if ( !support.tbody ) {
7267
7268						// String was a <table>, *may* have spurious <tbody>
7269						elem = tag === "table" && !rtbody.test( elem ) ?
7270							tmp.firstChild :
7271
7272							// String was a bare <thead> or <tfoot>
7273							wrap[1] === "<table>" && !rtbody.test( elem ) ?
7274								tmp :
7275								0;
7276
7277						j = elem && elem.childNodes.length;
7278						while ( j-- ) {
7279							if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
7280								elem.removeChild( tbody );
7281							}
7282						}
7283					}
7284
7285					jQuery.merge( nodes, tmp.childNodes );
7286
7287					// Fix #12392 for WebKit and IE > 9
7288					tmp.textContent = "";
7289
7290					// Fix #12392 for oldIE
7291					while ( tmp.firstChild ) {
7292						tmp.removeChild( tmp.firstChild );
7293					}
7294
7295					// Remember the top-level container for proper cleanup
7296					tmp = safe.lastChild;
7297				}
7298			}
7299		}
7300
7301		// Fix #11356: Clear elements from fragment
7302		if ( tmp ) {
7303			safe.removeChild( tmp );
7304		}
7305
7306		// Reset defaultChecked for any radios and checkboxes
7307		// about to be appended to the DOM in IE 6/7 (#8060)
7308		if ( !support.appendChecked ) {
7309			jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
7310		}
7311
7312		i = 0;
7313		while ( (elem = nodes[ i++ ]) ) {
7314
7315			// #4087 - If origin and destination elements are the same, and this is
7316			// that element, do not do anything
7317			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
7318				continue;
7319			}
7320
7321			contains = jQuery.contains( elem.ownerDocument, elem );
7322
7323			// Append to fragment
7324			tmp = getAll( safe.appendChild( elem ), "script" );
7325
7326			// Preserve script evaluation history
7327			if ( contains ) {
7328				setGlobalEval( tmp );
7329			}
7330
7331			// Capture executables
7332			if ( scripts ) {
7333				j = 0;
7334				while ( (elem = tmp[ j++ ]) ) {
7335					if ( rscriptType.test( elem.type || "" ) ) {
7336						scripts.push( elem );
7337					}
7338				}
7339			}
7340		}
7341
7342		tmp = null;
7343
7344		return safe;
7345	},
7346
7347	cleanData: function( elems, /* internal */ acceptData ) {
7348		var elem, type, id, data,
7349			i = 0,
7350			internalKey = jQuery.expando,
7351			cache = jQuery.cache,
7352			deleteExpando = support.deleteExpando,
7353			special = jQuery.event.special;
7354
7355		for ( ; (elem = elems[i]) != null; i++ ) {
7356			if ( acceptData || jQuery.acceptData( elem ) ) {
7357
7358				id = elem[ internalKey ];
7359				data = id && cache[ id ];
7360
7361				if ( data ) {
7362					if ( data.events ) {
7363						for ( type in data.events ) {
7364							if ( special[ type ] ) {
7365								jQuery.event.remove( elem, type );
7366
7367							// This is a shortcut to avoid jQuery.event.remove's overhead
7368							} else {
7369								jQuery.removeEvent( elem, type, data.handle );
7370							}
7371						}
7372					}
7373
7374					// Remove cache only if it was not already removed by jQuery.event.remove
7375					if ( cache[ id ] ) {
7376
7377						delete cache[ id ];
7378
7379						// IE does not allow us to delete expando properties from nodes,
7380						// nor does it have a removeAttribute function on Document nodes;
7381						// we must handle all of these cases
7382						if ( deleteExpando ) {
7383							delete elem[ internalKey ];
7384
7385						} else if ( typeof elem.removeAttribute !== strundefined ) {
7386							elem.removeAttribute( internalKey );
7387
7388						} else {
7389							elem[ internalKey ] = null;
7390						}
7391
7392						deletedIds.push( id );
7393					}
7394				}
7395			}
7396		}
7397	}
7398});
7399
7400jQuery.fn.extend({
7401	text: function( value ) {
7402		return access( this, function( value ) {
7403			return value === undefined ?
7404				jQuery.text( this ) :
7405				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
7406		}, null, value, arguments.length );
7407	},
7408
7409	append: function() {
7410		return this.domManip( arguments, function( elem ) {
7411			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
7412				var target = manipulationTarget( this, elem );
7413				target.appendChild( elem );
7414			}
7415		});
7416	},
7417
7418	prepend: function() {
7419		return this.domManip( arguments, function( elem ) {
7420			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
7421				var target = manipulationTarget( this, elem );
7422				target.insertBefore( elem, target.firstChild );
7423			}
7424		});
7425	},
7426
7427	before: function() {
7428		return this.domManip( arguments, function( elem ) {
7429			if ( this.parentNode ) {
7430				this.parentNode.insertBefore( elem, this );
7431			}
7432		});
7433	},
7434
7435	after: function() {
7436		return this.domManip( arguments, function( elem ) {
7437			if ( this.parentNode ) {
7438				this.parentNode.insertBefore( elem, this.nextSibling );
7439			}
7440		});
7441	},
7442
7443	remove: function( selector, keepData /* Internal Use Only */ ) {
7444		var elem,
7445			elems = selector ? jQuery.filter( selector, this ) : this,
7446			i = 0;
7447
7448		for ( ; (elem = elems[i]) != null; i++ ) {
7449
7450			if ( !keepData && elem.nodeType === 1 ) {
7451				jQuery.cleanData( getAll( elem ) );
7452			}
7453
7454			if ( elem.parentNode ) {
7455				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
7456					setGlobalEval( getAll( elem, "script" ) );
7457				}
7458				elem.parentNode.removeChild( elem );
7459			}
7460		}
7461
7462		return this;
7463	},
7464
7465	empty: function() {
7466		var elem,
7467			i = 0;
7468
7469		for ( ; (elem = this[i]) != null; i++ ) {
7470			// Remove element nodes and prevent memory leaks
7471			if ( elem.nodeType === 1 ) {
7472				jQuery.cleanData( getAll( elem, false ) );
7473			}
7474
7475			// Remove any remaining nodes
7476			while ( elem.firstChild ) {
7477				elem.removeChild( elem.firstChild );
7478			}
7479
7480			// If this is a select, ensure that it displays empty (#12336)
7481			// Support: IE<9
7482			if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
7483				elem.options.length = 0;
7484			}
7485		}
7486
7487		return this;
7488	},
7489
7490	clone: function( dataAndEvents, deepDataAndEvents ) {
7491		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
7492		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
7493
7494		return this.map(function() {
7495			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
7496		});
7497	},
7498
7499	html: function( value ) {
7500		return access( this, function( value ) {
7501			var elem = this[ 0 ] || {},
7502				i = 0,
7503				l = this.length;
7504
7505			if ( value === undefined ) {
7506				return elem.nodeType === 1 ?
7507					elem.innerHTML.replace( rinlinejQuery, "" ) :
7508					undefined;
7509			}
7510
7511			// See if we can take a shortcut and just use innerHTML
7512			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
7513				( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
7514				( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
7515				!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
7516
7517				value = value.replace( rxhtmlTag, "<$1></$2>" );
7518
7519				try {
7520					for (; i < l; i++ ) {
7521						// Remove element nodes and prevent memory leaks
7522						elem = this[i] || {};
7523						if ( elem.nodeType === 1 ) {
7524							jQuery.cleanData( getAll( elem, false ) );
7525							elem.innerHTML = value;
7526						}
7527					}
7528
7529					elem = 0;
7530
7531				// If using innerHTML throws an exception, use the fallback method
7532				} catch(e) {}
7533			}
7534
7535			if ( elem ) {
7536				this.empty().append( value );
7537			}
7538		}, null, value, arguments.length );
7539	},
7540
7541	replaceWith: function() {
7542		var arg = arguments[ 0 ];
7543
7544		// Make the changes, replacing each context element with the new content
7545		this.domManip( arguments, function( elem ) {
7546			arg = this.parentNode;
7547
7548			jQuery.cleanData( getAll( this ) );
7549
7550			if ( arg ) {
7551				arg.replaceChild( elem, this );
7552			}
7553		});
7554
7555		// Force removal if there was no new content (e.g., from empty arguments)
7556		return arg && (arg.length || arg.nodeType) ? this : this.remove();
7557	},
7558
7559	detach: function( selector ) {
7560		return this.remove( selector, true );
7561	},
7562
7563	domManip: function( args, callback ) {
7564
7565		// Flatten any nested arrays
7566		args = concat.apply( [], args );
7567
7568		var first, node, hasScripts,
7569			scripts, doc, fragment,
7570			i = 0,
7571			l = this.length,
7572			set = this,
7573			iNoClone = l - 1,
7574			value = args[0],
7575			isFunction = jQuery.isFunction( value );
7576
7577		// We can't cloneNode fragments that contain checked, in WebKit
7578		if ( isFunction ||
7579				( l > 1 && typeof value === "string" &&
7580					!support.checkClone && rchecked.test( value ) ) ) {
7581			return this.each(function( index ) {
7582				var self = set.eq( index );
7583				if ( isFunction ) {
7584					args[0] = value.call( this, index, self.html() );
7585				}
7586				self.domManip( args, callback );
7587			});
7588		}
7589
7590		if ( l ) {
7591			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
7592			first = fragment.firstChild;
7593
7594			if ( fragment.childNodes.length === 1 ) {
7595				fragment = first;
7596			}
7597
7598			if ( first ) {
7599				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
7600				hasScripts = scripts.length;
7601
7602				// Use the original fragment for the last item instead of the first because it can end up
7603				// being emptied incorrectly in certain situations (#8070).
7604				for ( ; i < l; i++ ) {
7605					node = fragment;
7606
7607					if ( i !== iNoClone ) {
7608						node = jQuery.clone( node, true, true );
7609
7610						// Keep references to cloned scripts for later restoration
7611						if ( hasScripts ) {
7612							jQuery.merge( scripts, getAll( node, "script" ) );
7613						}
7614					}
7615
7616					callback.call( this[i], node, i );
7617				}
7618
7619				if ( hasScripts ) {
7620					doc = scripts[ scripts.length - 1 ].ownerDocument;
7621
7622					// Reenable scripts
7623					jQuery.map( scripts, restoreScript );
7624
7625					// Evaluate executable scripts on first document insertion
7626					for ( i = 0; i < hasScripts; i++ ) {
7627						node = scripts[ i ];
7628						if ( rscriptType.test( node.type || "" ) &&
7629							!jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
7630
7631							if ( node.src ) {
7632								// Optional AJAX dependency, but won't run scripts if not present
7633								if ( jQuery._evalUrl ) {
7634									jQuery._evalUrl( node.src );
7635								}
7636							} else {
7637								jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
7638							}
7639						}
7640					}
7641				}
7642
7643				// Fix #11809: Avoid leaking memory
7644				fragment = first = null;
7645			}
7646		}
7647
7648		return this;
7649	}
7650});
7651
7652jQuery.each({
7653	appendTo: "append",
7654	prependTo: "prepend",
7655	insertBefore: "before",
7656	insertAfter: "after",
7657	replaceAll: "replaceWith"
7658}, function( name, original ) {
7659	jQuery.fn[ name ] = function( selector ) {
7660		var elems,
7661			i = 0,
7662			ret = [],
7663			insert = jQuery( selector ),
7664			last = insert.length - 1;
7665
7666		for ( ; i <= last; i++ ) {
7667			elems = i === last ? this : this.clone(true);
7668			jQuery( insert[i] )[ original ]( elems );
7669
7670			// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
7671			push.apply( ret, elems.get() );
7672		}
7673
7674		return this.pushStack( ret );
7675	};
7676});
7677
7678
7679var iframe,
7680	elemdisplay = {};
7681
7682/**
7683 * Retrieve the actual display of a element
7684 * @param {String} name nodeName of the element
7685 * @param {Object} doc Document object
7686 */
7687// Called only from within defaultDisplay
7688function actualDisplay( name, doc ) {
7689	var style,
7690		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
7691
7692		// getDefaultComputedStyle might be reliably used only on attached element
7693		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
7694
7695			// Use of this method is a temporary fix (more like optmization) until something better comes along,
7696			// since it was removed from specification and supported only in FF
7697			style.display : jQuery.css( elem[ 0 ], "display" );
7698
7699	// We don't have any data stored on the element,
7700	// so use "detach" method as fast way to get rid of the element
7701	elem.detach();
7702
7703	return display;
7704}
7705
7706/**
7707 * Try to determine the default display value of an element
7708 * @param {String} nodeName
7709 */
7710function defaultDisplay( nodeName ) {
7711	var doc = document,
7712		display = elemdisplay[ nodeName ];
7713
7714	if ( !display ) {
7715		display = actualDisplay( nodeName, doc );
7716
7717		// If the simple way fails, read from inside an iframe
7718		if ( display === "none" || !display ) {
7719
7720			// Use the already-created iframe if possible
7721			iframe = (iframe || jQuery( "<iframe 
7721style='border: none;' width='0' height='0'/>" )).appendTo( doc.documentElement );
7722
7723			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
7724			doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
7725
7726			// Support: IE
7727			doc.write();
7728			doc.close();
7729
7730			display = actualDisplay( nodeName, doc );
7731			iframe.detach();
7732		}
7733
7734		// Store the correct default display
7735		elemdisplay[ nodeName ] = display;
7736	}
7737
7738	return display;
7739}
7740
7741
7742(function() {
7743	var shrinkWrapBlocksVal;
7744
7745	support.shrinkWrapBlocks = function() {
7746		if ( shrinkWrapBlocksVal != null ) {
7747			return shrinkWrapBlocksVal;
7748		}
7749
7750		// Will be changed later if needed.
7751		shrinkWrapBlocksVal = false;
vendor: 1,671 bytes, lines 7752-7806
7752
7753		// Minified: var b,c,d
7754		var div, body, container;
7755
7756		body = document.getElementsByTagName( "body" )[ 0 ];
7757		if ( !body || !body.style ) {
7758			// Test fired too early or in an unsupported environment, exit.
7759			return;
7760		}
7761
7762		// Setup
7763		div = document.createElement( "div" );
7764		container = document.createElement( "div" );
7765		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
7766		body.appendChild( container ).appendChild( div );
7767
7768		// Support: IE6
7769		// Check if elements with layout shrink-wrap their children
7770		if ( typeof div.style.zoom !== strundefined ) {
7771			// Reset CSS: box-sizing; display; margin; border
7772			div.style.cssText =
7773				// Support: Firefox<29, Android 2.3
7774				// Vendor-prefix box-sizing
7775				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
7776				"box-sizing:content-box;display:block;margin:0;border:0;" +
7777				"padding:1px;width:1px;zoom:1";
7778			div.appendChild( document.createElement( "div" ) ).style.width = "5px";
7779			shrinkWrapBlocksVal = div.offsetWidth !== 3;
7780		}
7781
7782		body.removeChild( container );
7783
7784		return shrinkWrapBlocksVal;
7785	};
7786
7787})();
7788var rmargin = (/^margin/);
7789
7790var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
7791
7792
7793
7794var getStyles, curCSS,
7795	rposition = /^(top|right|bottom|left)$/;
7796
7797if ( window.getComputedStyle ) {
7798	getStyles = function( elem ) {
7799		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
7800		// IE throws on elements created in popups
7801		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
7802		if ( elem.ownerDocument.defaultView.opener ) {
7803			return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
7804		}
7805
7806		return windo
vendor: 7,468 bytes, lines 7806-8053
7806w.getComputedStyle( elem, null );
7807	};
7808
7809	curCSS = function( elem, name, computed ) {
7810		var width, minWidth, maxWidth, ret,
7811			style = elem.style;
7812
7813		computed = computed || getStyles( elem );
7814
7815		// getPropertyValue is only needed for .css('filter') in IE9, see #12537
7816		ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
7817
7818		if ( computed ) {
7819
7820			if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
7821				ret = jQuery.style( elem, name );
7822			}
7823
7824			// A tribute to the "awesome hack by Dean Edwards"
7825			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
7826			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
7827			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
7828			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
7829
7830				// Remember the original values
7831				width = style.width;
7832				minWidth = style.minWidth;
7833				maxWidth = style.maxWidth;
7834
7835				// Put in the new values to get a computed value out
7836				style.minWidth = style.maxWidth = style.width = ret;
7837				ret = computed.width;
7838
7839				// Revert the changed values
7840				style.width = width;
7841				style.minWidth = minWidth;
7842				style.maxWidth = maxWidth;
7843			}
7844		}
7845
7846		// Support: IE
7847		// IE returns zIndex value as an integer.
7848		return ret === undefined ?
7849			ret :
7850			ret + "";
7851	};
7852} else if ( document.documentElement.currentStyle ) {
7853	getStyles = function( elem ) {
7854		return elem.currentStyle;
7855	};
7856
7857	curCSS = function( elem, name, computed ) {
7858		var left, rs, rsLeft, ret,
7859			style = elem.style;
7860
7861		computed = computed || getStyles( elem );
7862		ret = computed ? computed[ name ] : undefined;
7863
7864		// Avoid setting ret to empty string here
7865		// so we don't default to auto
7866		if ( ret == null && style && style[ name ] ) {
7867			ret = style[ name ];
7868		}
7869
7870		// From the awesome hack by Dean Edwards
7871		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
7872
7873		// If we're not dealing with a regular pixel number
7874		// but a number that has a weird ending, we need to convert it to pixels
7875		// but not position css attributes, as those are proportional to the parent element instead
7876		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
7877		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
7878
7879			// Remember the original values
7880			left = style.left;
7881			rs = elem.runtimeStyle;
7882			rsLeft = rs && rs.left;
7883
7884			// Put in the new values to get a computed value out
7885			if ( rsLeft ) {
7886				rs.left = elem.currentStyle.left;
7887			}
7888			style.left = name === "fontSize" ? "1em" : ret;
7889			ret = style.pixelLeft + "px";
7890
7891			// Revert the changed values
7892			style.left = left;
7893			if ( rsLeft ) {
7894				rs.left = rsLeft;
7895			}
7896		}
7897
7898		// Support: IE
7899		// IE returns zIndex value as an integer.
7900		return ret === undefined ?
7901			ret :
7902			ret + "" || "auto";
7903	};
7904}
7905
7906
7907
7908
7909function addGetHookIf( conditionFn, hookFn ) {
7910	// Define the hook, we'll check on the first run if it's really needed.
7911	return {
7912		get: function() {
7913			var condition = conditionFn();
7914
7915			if ( condition == null ) {
7916				// The test was not ready at this point; screw the hook this time
7917				// but check again when needed next time.
7918				return;
7919			}
7920
7921			if ( condition ) {
7922				// Hook not needed (or it's not possible to use it due to missing dependency),
7923				// remove it.
7924				// Since there are no other hooks for marginRight, remove the whole object.
7925				delete this.get;
7926				return;
7927			}
7928
7929			// Hook needed; redefine it so that the support test is not executed again.
7930
7931			return (this.get = hookFn).apply( this, arguments );
7932		}
7933	};
7934}
7935
7936
7937(function() {
7938	// Minified: var b,c,d,e,f,g, h,i
7939	var div, style, a, pixelPositionVal, boxSizingReliableVal,
7940		reliableHiddenOffsetsVal, reliableMarginRightVal;
7941
7942	// Setup
7943	div = document.createElement( "div" );
7944	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
7945	a = div.getElementsByTagName( "a" )[ 0 ];
7946	style = a && a.style;
7947
7948	// Finish early in limited (non-browser) environments
7949	if ( !style ) {
7950		return;
7951	}
7952
7953	style.cssText = "float:left;opacity:.5";
7954
7955	// Support: IE<9
7956	// Make sure that element opacity exists (as opposed to filter)
7957	support.opacity = style.opacity === "0.5";
7958
7959	// Verify style float existence
7960	// (IE uses styleFloat instead of cssFloat)
7961	support.cssFloat = !!style.cssFloat;
7962
7963	div.style.backgroundClip = "content-box";
7964	div.cloneNode( true ).style.backgroundClip = "";
7965	support.clearCloneStyle = div.style.backgroundClip === "content-box";
7966
7967	// Support: Firefox<29, Android 2.3
7968	// Vendor-prefix box-sizing
7969	support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
7970		style.WebkitBoxSizing === "";
7971
7972	jQuery.extend(support, {
7973		reliableHiddenOffsets: function() {
7974			if ( reliableHiddenOffsetsVal == null ) {
7975				computeStyleTests();
7976			}
7977			return reliableHiddenOffsetsVal;
7978		},
7979
7980		boxSizingReliable: function() {
7981			if ( boxSizingReliableVal == null ) {
7982				computeStyleTests();
7983			}
7984			return boxSizingReliableVal;
7985		},
7986
7987		pixelPosition: function() {
7988			if ( pixelPositionVal == null ) {
7989				computeStyleTests();
7990			}
7991			return pixelPositionVal;
7992		},
7993
7994		// Support: Android 2.3
7995		reliableMarginRight: function() {
7996			if ( reliableMarginRightVal == null ) {
7997				computeStyleTests();
7998			}
7999			return reliableMarginRightVal;
8000		}
8001	});
8002
8003	function computeStyleTests() {
8004		// Minified: var b,c,d,j
8005		var div, body, container, contents;
8006
8007		body = document.getElementsByTagName( "body" )[ 0 ];
8008		if ( !body || !body.style ) {
8009			// Test fired too early or in an unsupported environment, exit.
8010			return;
8011		}
8012
8013		// Setup
8014		div = document.createElement( "div" );
8015		container = document.createElement( "div" );
8016		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
8017		body.appendChild( container ).appendChild( div );
8018
8019		div.style.cssText =
8020			// Support: Firefox<29, Android 2.3
8021			// Vendor-prefix box-sizing
8022			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
8023			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
8024			"border:1px;padding:1px;width:4px;position:absolute";
8025
8026		// Support: IE<9
8027		// Assume reasonable values in the absence of getComputedStyle
8028		pixelPositionVal = boxSizingReliableVal = false;
8029		reliableMarginRightVal = true;
8030
8031		// Check for getComputedStyle so that this code is not run in IE<9.
8032		if ( window.getComputedStyle ) {
8033			pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
8034			boxSizingReliableVal =
8035				( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
8036
8037			// Support: Android 2.3
8038			// Div with explicit width and no margin-right incorrectly
8039			// gets computed margin-right based on width of container (#3333)
8040			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
8041			contents = div.appendChild( document.createElement( "div" ) );
8042
8043			// Reset CSS: box-sizing; display; margin; border; padding
8044			contents.style.cssText = div.style.cssText =
8045				// Support: Firefox<29, Android 2.3
8046				// Vendor-prefix box-sizing
8047				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
8048				"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
8049			contents.style.marginRight = contents.style.width = "0";
8050			div.style.width = "1px";
8051
8052			reliableMarginRightVal =
8053				!parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
8054
8055			div.removeChild( contents
vendor: 73,689 bytes, lines 8055-10763
8055 );
8056		}
8057
8058		// Support: IE8
8059		// Check if table cells still have offsetWidth/Height when they are set
8060		// to display:none and there are still other visible table cells in a
8061		// table row; if so, offsetWidth/Height are not reliable for use when
8062		// determining if an element has been hidden directly using
8063		// display:none (it is still safe to use offsets if a parent element is
8064		// hidden; don safety goggles and see bug #4512 for more information).
8065		div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
8066		contents = div.getElementsByTagName( "td" );
8067		contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
8068		reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
8069		if ( reliableHiddenOffsetsVal ) {
8070			contents[ 0 ].style.display = "";
8071			contents[ 1 ].style.display = "none";
8072			reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
8073		}
8074
8075		body.removeChild( container );
8076	}
8077
8078})();
8079
8080
8081// A method for quickly swapping in/out CSS properties to get correct calculations.
8082jQuery.swap = function( elem, options, callback, args ) {
8083	var ret, name,
8084		old = {};
8085
8086	// Remember the old values, and insert the new ones
8087	for ( name in options ) {
8088		old[ name ] = elem.style[ name ];
8089		elem.style[ name ] = options[ name ];
8090	}
8091
8092	ret = callback.apply( elem, args || [] );
8093
8094	// Revert the old values
8095	for ( name in options ) {
8096		elem.style[ name ] = old[ name ];
8097	}
8098
8099	return ret;
8100};
8101
8102
8103var
8104		ralpha = /alpha\([^)]*\)/i,
8105	ropacity = /opacity\s*=\s*([^)]*)/,
8106
8107	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
8108	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
8109	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
8110	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
8111	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
8112
8113	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
8114	cssNormalTransform = {
8115		letterSpacing: "0",
8116		fontWeight: "400"
8117	},
8118
8119	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
8120
8121
8122// return a css property mapped to a potentially vendor prefixed property
8123function vendorPropName( style, name ) {
8124
8125	// shortcut for names that are not vendor prefixed
8126	if ( name in style ) {
8127		return name;
8128	}
8129
8130	// check for vendor prefixed names
8131	var capName = name.charAt(0).toUpperCase() + name.slice(1),
8132		origName = name,
8133		i = cssPrefixes.length;
8134
8135	while ( i-- ) {
8136		name = cssPrefixes[ i ] + capName;
8137		if ( name in style ) {
8138			return name;
8139		}
8140	}
8141
8142	return origName;
8143}
8144
8145function showHide( elements, show ) {
8146	var display, elem, hidden,
8147		values = [],
8148		index = 0,
8149		length = elements.length;
8150
8151	for ( ; index < length; index++ ) {
8152		elem = elements[ index ];
8153		if ( !elem.style ) {
8154			continue;
8155		}
8156
8157		values[ index ] = jQuery._data( elem, "olddisplay" );
8158		display = elem.style.display;
8159		if ( show ) {
8160			// Reset the inline display of this element to learn if it is
8161			// being hidden by cascaded rules or not
8162			if ( !values[ index ] && display === "none" ) {
8163				elem.style.display = "";
8164			}
8165
8166			// Set elements which have been overridden with display: none
8167			// in a stylesheet to whatever the default browser style is
8168			// for such an element
8169			if ( elem.style.display === "" && isHidden( elem ) ) {
8170				values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
8171			}
8172		} else {
8173			hidden = isHidden( elem );
8174
8175			if ( display && display !== "none" || !hidden ) {
8176				jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
8177			}
8178		}
8179	}
8180
8181	// Set the display of most of the elements in a second loop
8182	// to avoid the constant reflow
8183	for ( index = 0; index < length; index++ ) {
8184		elem = elements[ index ];
8185		if ( !elem.style ) {
8186			continue;
8187		}
8188		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
8189			elem.style.display = show ? values[ index ] || "" : "none";
8190		}
8191	}
8192
8193	return elements;
8194}
8195
8196function setPositiveNumber( elem, value, subtract ) {
8197	var matches = rnumsplit.exec( value );
8198	return matches ?
8199		// Guard against undefined "subtract", e.g., when used as in cssHooks
8200		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
8201		value;
8202}
8203
8204function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
8205	var i = extra === ( isBorderBox ? "border" : "content" ) ?
8206		// If we already have the right measurement, avoid augmentation
8207		4 :
8208		// Otherwise initialize for horizontal or vertical properties
8209		name === "width" ? 1 : 0,
8210
8211		val = 0;
8212
8213	for ( ; i < 4; i += 2 ) {
8214		// both box models exclude margin, so add it if we want it
8215		if ( extra === "margin" ) {
8216			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
8217		}
8218
8219		if ( isBorderBox ) {
8220			// border-box includes padding, so remove it if we want content
8221			if ( extra === "content" ) {
8222				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
8223			}
8224
8225			// at this point, extra isn't border nor margin, so remove border
8226			if ( extra !== "margin" ) {
8227				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
8228			}
8229		} else {
8230			// at this point, extra isn't content, so add padding
8231			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
8232
8233			// at this point, extra isn't content nor padding, so add border
8234			if ( extra !== "padding" ) {
8235				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
8236			}
8237		}
8238	}
8239
8240	return val;
8241}
8242
8243function getWidthOrHeight( elem, name, extra ) {
8244
8245	// Start with offset property, which is equivalent to the border-box value
8246	var valueIsBorderBox = true,
8247		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
8248		styles = getStyles( elem ),
8249		isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
8250
8251	// some non-html elements return undefined for offsetWidth, so check for null/undefined
8252	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
8253	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
8254	if ( val <= 0 || val == null ) {
8255		// Fall back to computed then uncomputed css if necessary
8256		val = curCSS( elem, name, styles );
8257		if ( val < 0 || val == null ) {
8258			val = elem.style[ name ];
8259		}
8260
8261		// Computed unit is not pixels. Stop here and return.
8262		if ( rnumnonpx.test(val) ) {
8263			return val;
8264		}
8265
8266		// we need the check for style in case a browser which returns unreliable values
8267		// for getComputedStyle silently falls back to the reliable elem.style
8268		valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
8269
8270		// Normalize "", auto, and prepare for extra
8271		val = parseFloat( val ) || 0;
8272	}
8273
8274	// use the active box-sizing model to add/subtract irrelevant styles
8275	return ( val +
8276		augmentWidthOrHeight(
8277			elem,
8278			name,
8279			extra || ( isBorderBox ? "border" : "content" ),
8280			valueIsBorderBox,
8281			styles
8282		)
8283	) + "px";
8284}
8285
8286jQuery.extend({
8287	// Add in style property hooks for overriding the default
8288	// behavior of getting and setting a style property
8289	cssHooks: {
8290		opacity: {
8291			get: function( elem, computed ) {
8292				if ( computed ) {
8293					// We should always get a number back from opacity
8294					var ret = curCSS( elem, "opacity" );
8295					return ret === "" ? "1" : ret;
8296				}
8297			}
8298		}
8299	},
8300
8301	// Don't automatically add "px" to these possibly-unitless properties
8302	cssNumber: {
8303		"columnCount": true,
8304		"fillOpacity": true,
8305		"flexGrow": true,
8306		"flexShrink": true,
8307		"fontWeight": true,
8308		"lineHeight": true,
8309		"opacity": true,
8310		"order": true,
8311		"orphans": true,
8312		"widows": true,
8313		"zIndex": true,
8314		"zoom": true
8315	},
8316
8317	// Add in properties whose names you wish to fix before
8318	// setting or getting the value
8319	cssProps: {
8320		// normalize float css property
8321		"float": support.cssFloat ? "cssFloat" : "styleFloat"
8322	},
8323
8324	// Get and set the style property on a DOM Node
8325	style: function( elem, name, value, extra ) {
8326		// Don't set styles on text and comment nodes
8327		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
8328			return;
8329		}
8330
8331		// Make sure that we're working with the right name
8332		var ret, type, hooks,
8333			origName = jQuery.camelCase( name ),
8334			style = elem.style;
8335
8336		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
8337
8338		// gets hook for the prefixed version
8339		// followed by the unprefixed version
8340		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
8341
8342		// Check if we're setting a value
8343		if ( value !== undefined ) {
8344			type = typeof value;
8345
8346			// convert relative number strings (+= or -=) to relative numbers. #7345
8347			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
8348				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
8349				// Fixes bug #9237
8350				type = "number";
8351			}
8352
8353			// Make sure that null and NaN values aren't set. See: #7116
8354			if ( value == null || value !== value ) {
8355				return;
8356			}
8357
8358			// If a number was passed in, add 'px' to the (except for certain CSS properties)
8359			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
8360				value += "px";
8361			}
8362
8363			// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
8364			// but it would mean to define eight (for every problematic property) identical functions
8365			if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
8366				style[ name ] = "inherit";
8367			}
8368
8369			// If a hook was provided, use that value, otherwise just set the specified value
8370			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
8371
8372				// Support: IE
8373				// Swallow errors from 'invalid' CSS values (#5509)
8374				try {
8375					style[ name ] = value;
8376				} catch(e) {}
8377			}
8378
8379		} else {
8380			// If a hook was provided get the non-computed value from there
8381			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
8382				return ret;
8383			}
8384
8385			// Otherwise just get the value from the style object
8386			return style[ name ];
8387		}
8388	},
8389
8390	css: function( elem, name, extra, styles ) {
8391		var num, val, hooks,
8392			origName = jQuery.camelCase( name );
8393
8394		// Make sure that we're working with the right name
8395		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
8396
8397		// gets hook for the prefixed version
8398		// followed by the unprefixed version
8399		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
8400
8401		// If a hook was provided get the computed value from there
8402		if ( hooks && "get" in hooks ) {
8403			val = hooks.get( elem, true, extra );
8404		}
8405
8406		// Otherwise, if a way to get the computed value exists, use that
8407		if ( val === undefined ) {
8408			val = curCSS( elem, name, styles );
8409		}
8410
8411		//convert "normal" to computed value
8412		if ( val === "normal" && name in cssNormalTransform ) {
8413			val = cssNormalTransform[ name ];
8414		}
8415
8416		// Return, converting to number if forced or a qualifier was provided and val looks numeric
8417		if ( extra === "" || extra ) {
8418			num = parseFloat( val );
8419			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
8420		}
8421		return val;
8422	}
8423});
8424
8425jQuery.each([ "height", "width" ], function( i, name ) {
8426	jQuery.cssHooks[ name ] = {
8427		get: function( elem, computed, extra ) {
8428			if ( computed ) {
8429				// certain elements can have dimension info if we invisibly show them
8430				// however, it must have a current display style that would benefit from this
8431				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
8432					jQuery.swap( elem, cssShow, function() {
8433						return getWidthOrHeight( elem, name, extra );
8434					}) :
8435					getWidthOrHeight( elem, name, extra );
8436			}
8437		},
8438
8439		set: function( elem, value, extra ) {
8440			var styles = extra && getStyles( elem );
8441			return setPositiveNumber( elem, value, extra ?
8442				augmentWidthOrHeight(
8443					elem,
8444					name,
8445					extra,
8446					support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
8447					styles
8448				) : 0
8449			);
8450		}
8451	};
8452});
8453
8454if ( !support.opacity ) {
8455	jQuery.cssHooks.opacity = {
8456		get: function( elem, computed ) {
8457			// IE uses filters for opacity
8458			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
8459				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
8460				computed ? "1" : "";
8461		},
8462
8463		set: function( elem, value ) {
8464			var style = elem.style,
8465				currentStyle = elem.currentStyle,
8466				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
8467				filter = currentStyle && currentStyle.filter || style.filter || "";
8468
8469			// IE has trouble with opacity if it does not have layout
8470			// Force it by setting the zoom level
8471			style.zoom = 1;
8472
8473			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
8474			// if value === "", then remove inline opacity #12685
8475			if ( ( value >= 1 || value === "" ) &&
8476					jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
8477					style.removeAttribute ) {
8478
8479				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
8480				// if "filter:" is present at all, clearType is disabled, we want to avoid this
8481				// style.removeAttribute is IE Only, but so apparently is this code path...
8482				style.removeAttribute( "filter" );
8483
8484				// if there is no filter style applied in a css rule or unset inline opacity, we are done
8485				if ( value === "" || currentStyle && !currentStyle.filter ) {
8486					return;
8487				}
8488			}
8489
8490			// otherwise, set new filter values
8491			style.filter = ralpha.test( filter ) ?
8492				filter.replace( ralpha, opacity ) :
8493				filter + " " + opacity;
8494		}
8495	};
8496}
8497
8498jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
8499	function( elem, computed ) {
8500		if ( computed ) {
8501			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
8502			// Work around by temporarily setting element display to inline-block
8503			return jQuery.swap( elem, { "display": "inline-block" },
8504				curCSS, [ elem, "marginRight" ] );
8505		}
8506	}
8507);
8508
8509// These hooks are used by animate to expand properties
8510jQuery.each({
8511	margin: "",
8512	padding: "",
8513	border: "Width"
8514}, function( prefix, suffix ) {
8515	jQuery.cssHooks[ prefix + suffix ] = {
8516		expand: function( value ) {
8517			var i = 0,
8518				expanded = {},
8519
8520				// assumes a single number if not a string
8521				parts = typeof value === "string" ? value.split(" ") : [ value ];
8522
8523			for ( ; i < 4; i++ ) {
8524				expanded[ prefix + cssExpand[ i ] + suffix ] =
8525					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
8526			}
8527
8528			return expanded;
8529		}
8530	};
8531
8532	if ( !rmargin.test( prefix ) ) {
8533		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
8534	}
8535});
8536
8537jQuery.fn.extend({
8538	css: function( name, value ) {
8539		return access( this, function( elem, name, value ) {
8540			var styles, len,
8541				map = {},
8542				i = 0;
8543
8544			if ( jQuery.isArray( name ) ) {
8545				styles = getStyles( elem );
8546				len = name.length;
8547
8548				for ( ; i < len; i++ ) {
8549					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
8550				}
8551
8552				return map;
8553			}
8554
8555			return value !== undefined ?
8556				jQuery.style( elem, name, value ) :
8557				jQuery.css( elem, name );
8558		}, name, value, arguments.length > 1 );
8559	},
8560	show: function() {
8561		return showHide( this, true );
8562	},
8563	hide: function() {
8564		return showHide( this );
8565	},
8566	toggle: function( state ) {
8567		if ( typeof state === "boolean" ) {
8568			return state ? this.show() : this.hide();
8569		}
8570
8571		return this.each(function() {
8572			if ( isHidden( this ) ) {
8573				jQuery( this ).show();
8574			} else {
8575				jQuery( this ).hide();
8576			}
8577		});
8578	}
8579});
8580
8581
8582function Tween( elem, options, prop, end, easing ) {
8583	return new Tween.prototype.init( elem, options, prop, end, easing );
8584}
8585jQuery.Tween = Tween;
8586
8587Tween.prototype = {
8588	constructor: Tween,
8589	init: function( elem, options, prop, end, easing, unit ) {
8590		this.elem = elem;
8591		this.prop = prop;
8592		this.easing = easing || "swing";
8593		this.options = options;
8594		this.start = this.now = this.cur();
8595		this.end = end;
8596		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8597	},
8598	cur: function() {
8599		var hooks = Tween.propHooks[ this.prop ];
8600
8601		return hooks && hooks.get ?
8602			hooks.get( this ) :
8603			Tween.propHooks._default.get( this );
8604	},
8605	run: function( percent ) {
8606		var eased,
8607			hooks = Tween.propHooks[ this.prop ];
8608
8609		if ( this.options.duration ) {
8610			this.pos = eased = jQuery.easing[ this.easing ](
8611				percent, this.options.duration * percent, 0, 1, this.options.duration
8612			);
8613		} else {
8614			this.pos = eased = percent;
8615		}
8616		this.now = ( this.end - this.start ) * eased + this.start;
8617
8618		if ( this.options.step ) {
8619			this.options.step.call( this.elem, this.now, this );
8620		}
8621
8622		if ( hooks && hooks.set ) {
8623			hooks.set( this );
8624		} else {
8625			Tween.propHooks._default.set( this );
8626		}
8627		return this;
8628	}
8629};
8630
8631Tween.prototype.init.prototype = Tween.prototype;
8632
8633Tween.propHooks = {
8634	_default: {
8635		get: function( tween ) {
8636			var result;
8637
8638			if ( tween.elem[ tween.prop ] != null &&
8639				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
8640				return tween.elem[ tween.prop ];
8641			}
8642
8643			// passing an empty string as a 3rd parameter to .css will automatically
8644			// attempt a parseFloat and fallback to a string if the parse fails
8645			// so, simple values such as "10px" are parsed to Float.
8646			// complex values such as "rotate(1rad)" are returned as is.
8647			result = jQuery.css( tween.elem, tween.prop, "" );
8648			// Empty strings, null, undefined and "auto" are converted to 0.
8649			return !result || result === "auto" ? 0 : result;
8650		},
8651		set: function( tween ) {
8652			// use step hook for back compat - use cssHook if its there - use .style if its
8653			// available and use plain properties where available
8654			if ( jQuery.fx.step[ tween.prop ] ) {
8655				jQuery.fx.step[ tween.prop ]( tween );
8656			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
8657				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
8658			} else {
8659				tween.elem[ tween.prop ] = tween.now;
8660			}
8661		}
8662	}
8663};
8664
8665// Support: IE <=9
8666// Panic based approach to setting things on disconnected nodes
8667
8668Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
8669	set: function( tween ) {
8670		if ( tween.elem.nodeType && tween.elem.parentNode ) {
8671			tween.elem[ tween.prop ] = tween.now;
8672		}
8673	}
8674};
8675
8676jQuery.easing = {
8677	linear: function( p ) {
8678		return p;
8679	},
8680	swing: function( p ) {
8681		return 0.5 - Math.cos( p * Math.PI ) / 2;
8682	}
8683};
8684
8685jQuery.fx = Tween.prototype.init;
8686
8687// Back Compat <1.8 extension point
8688jQuery.fx.step = {};
8689
8690
8691
8692
8693var
8694	fxNow, timerId,
8695	rfxtypes = /^(?:toggle|show|hide)$/,
8696	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
8697	rrun = /queueHooks$/,
8698	animationPrefilters = [ defaultPrefilter ],
8699	tweeners = {
8700		"*": [ function( prop, value ) {
8701			var tween = this.createTween( prop, value ),
8702				target = tween.cur(),
8703				parts = rfxnum.exec( value ),
8704				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
8705
8706				// Starting value computation is required for potential unit mismatches
8707				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
8708					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
8709				scale = 1,
8710				maxIterations = 20;
8711
8712			if ( start && start[ 3 ] !== unit ) {
8713				// Trust units reported by jQuery.css
8714				unit = unit || start[ 3 ];
8715
8716				// Make sure we update the tween properties later on
8717				parts = parts || [];
8718
8719				// Iteratively approximate from a nonzero starting point
8720				start = +target || 1;
8721
8722				do {
8723					// If previous iteration zeroed out, double until we get *something*
8724					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
8725					scale = scale || ".5";
8726
8727					// Adjust and apply
8728					start = start / scale;
8729					jQuery.style( tween.elem, prop, start + unit );
8730
8731				// Update scale, tolerating zero or NaN from tween.cur()
8732				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8733				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8734			}
8735
8736			// Update tween properties
8737			if ( parts ) {
8738				start = tween.start = +start || +target || 0;
8739				tween.unit = unit;
8740				// If a +=/-= token was provided, we're doing a relative animation
8741				tween.end = parts[ 1 ] ?
8742					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
8743					+parts[ 2 ];
8744			}
8745
8746			return tween;
8747		} ]
8748	};
8749
8750// Animations created synchronously will run synchronously
8751function createFxNow() {
8752	setTimeout(function() {
8753		fxNow = undefined;
8754	});
8755	return ( fxNow = jQuery.now() );
8756}
8757
8758// Generate parameters to create a standard animation
8759function genFx( type, includeWidth ) {
8760	var which,
8761		attrs = { height: type },
8762		i = 0;
8763
8764	// if we include width, step value is 1 to do all cssExpand values,
8765	// if we don't include width, step value is 2 to skip over Left and Right
8766	includeWidth = includeWidth ? 1 : 0;
8767	for ( ; i < 4 ; i += 2 - includeWidth ) {
8768		which = cssExpand[ i ];
8769		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
8770	}
8771
8772	if ( includeWidth ) {
8773		attrs.opacity = attrs.width = type;
8774	}
8775
8776	return attrs;
8777}
8778
8779function createTween( value, prop, animation ) {
8780	var tween,
8781		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8782		index = 0,
8783		length = collection.length;
8784	for ( ; index < length; index++ ) {
8785		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
8786
8787			// we're done with this property
8788			return tween;
8789		}
8790	}
8791}
8792
8793function defaultPrefilter( elem, props, opts ) {
8794	/* jshint validthis: true */
8795	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
8796		anim = this,
8797		orig = {},
8798		style = elem.style,
8799		hidden = elem.nodeType && isHidden( elem ),
8800		dataShow = jQuery._data( elem, "fxshow" );
8801
8802	// handle queue: false promises
8803	if ( !opts.queue ) {
8804		hooks = jQuery._queueHooks( elem, "fx" );
8805		if ( hooks.unqueued == null ) {
8806			hooks.unqueued = 0;
8807			oldfire = hooks.empty.fire;
8808			hooks.empty.fire = function() {
8809				if ( !hooks.unqueued ) {
8810					oldfire();
8811				}
8812			};
8813		}
8814		hooks.unqueued++;
8815
8816		anim.always(function() {
8817			// doing this makes sure that the complete handler will be called
8818			// before this completes
8819			anim.always(function() {
8820				hooks.unqueued--;
8821				if ( !jQuery.queue( elem, "fx" ).length ) {
8822					hooks.empty.fire();
8823				}
8824			});
8825		});
8826	}
8827
8828	// height/width overflow pass
8829	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
8830		// Make sure that nothing sneaks out
8831		// Record all 3 overflow attributes because IE does not
8832		// change the overflow attribute when overflowX and
8833		// overflowY are set to the same value
8834		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
8835
8836		// Set display property to inline-block for height/width
8837		// animations on inline elements that are having width/height animated
8838		display = jQuery.css( elem, "display" );
8839
8840		// Test default display if display is currently "none"
8841		checkDisplay = display === "none" ?
8842			jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
8843
8844		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
8845
8846			// inline-level elements accept inline-block;
8847			// block-level elements need to be inline with layout
8848			if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
8849				style.display = "inline-block";
8850			} else {
8851				style.zoom = 1;
8852			}
8853		}
8854	}
8855
8856	if ( opts.overflow ) {
8857		style.overflow = "hidden";
8858		if ( !support.shrinkWrapBlocks() ) {
8859			anim.always(function() {
8860				style.overflow = opts.overflow[ 0 ];
8861				style.overflowX = opts.overflow[ 1 ];
8862				style.overflowY = opts.overflow[ 2 ];
8863			});
8864		}
8865	}
8866
8867	// show/hide pass
8868	for ( prop in props ) {
8869		value = props[ prop ];
8870		if ( rfxtypes.exec( value ) ) {
8871			delete props[ prop ];
8872			toggle = toggle || value === "toggle";
8873			if ( value === ( hidden ? "hide" : "show" ) ) {
8874
8875				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
8876				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
8877					hidden = true;
8878				} else {
8879					continue;
8880				}
8881			}
8882			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
8883
8884		// Any non-fx value stops us from restoring the original display value
8885		} else {
8886			display = undefined;
8887		}
8888	}
8889
8890	if ( !jQuery.isEmptyObject( orig ) ) {
8891		if ( dataShow ) {
8892			if ( "hidden" in dataShow ) {
8893				hidden = dataShow.hidden;
8894			}
8895		} else {
8896			dataShow = jQuery._data( elem, "fxshow", {} );
8897		}
8898
8899		// store state if its toggle - enables .stop().toggle() to "reverse"
8900		if ( toggle ) {
8901			dataShow.hidden = !hidden;
8902		}
8903		if ( hidden ) {
8904			jQuery( elem ).show();
8905		} else {
8906			anim.done(function() {
8907				jQuery( elem ).hide();
8908			});
8909		}
8910		anim.done(function() {
8911			var prop;
8912			jQuery._removeData( elem, "fxshow" );
8913			for ( prop in orig ) {
8914				jQuery.style( elem, prop, orig[ prop ] );
8915			}
8916		});
8917		for ( prop in orig ) {
8918			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
8919
8920			if ( !( prop in dataShow ) ) {
8921				dataShow[ prop ] = tween.start;
8922				if ( hidden ) {
8923					tween.end = tween.start;
8924					tween.start = prop === "width" || prop === "height" ? 1 : 0;
8925				}
8926			}
8927		}
8928
8929	// If this is a noop like .hide().hide(), restore an overwritten display value
8930	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
8931		style.display = display;
8932	}
8933}
8934
8935function propFilter( props, specialEasing ) {
8936	var index, name, easing, value, hooks;
8937
8938	// camelCase, specialEasing and expand cssHook pass
8939	for ( index in props ) {
8940		name = jQuery.camelCase( index );
8941		easing = specialEasing[ name ];
8942		value = props[ index ];
8943		if ( jQuery.isArray( value ) ) {
8944			easing = value[ 1 ];
8945			value = props[ index ] = value[ 0 ];
8946		}
8947
8948		if ( index !== name ) {
8949			props[ name ] = value;
8950			delete props[ index ];
8951		}
8952
8953		hooks = jQuery.cssHooks[ name ];
8954		if ( hooks && "expand" in hooks ) {
8955			value = hooks.expand( value );
8956			delete props[ name ];
8957
8958			// not quite $.extend, this wont overwrite keys already present.
8959			// also - reusing 'index' from above because we have the correct "name"
8960			for ( index in value ) {
8961				if ( !( index in props ) ) {
8962					props[ index ] = value[ index ];
8963					specialEasing[ index ] = easing;
8964				}
8965			}
8966		} else {
8967			specialEasing[ name ] = easing;
8968		}
8969	}
8970}
8971
8972function Animation( elem, properties, options ) {
8973	var result,
8974		stopped,
8975		index = 0,
8976		length = animationPrefilters.length,
8977		deferred = jQuery.Deferred().always( function() {
8978			// don't match elem in the :animated selector
8979			delete tick.elem;
8980		}),
8981		tick = function() {
8982			if ( stopped ) {
8983				return false;
8984			}
8985			var currentTime = fxNow || createFxNow(),
8986				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8987				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8988				temp = remaining / animation.duration || 0,
8989				percent = 1 - temp,
8990				index = 0,
8991				length = animation.tweens.length;
8992
8993			for ( ; index < length ; index++ ) {
8994				animation.tweens[ index ].run( percent );
8995			}
8996
8997			deferred.notifyWith( elem, [ animation, percent, remaining ]);
8998
8999			if ( percent < 1 && length ) {
9000				return remaining;
9001			} else {
9002				deferred.resolveWith( elem, [ animation ] );
9003				return false;
9004			}
9005		},
9006		animation = deferred.promise({
9007			elem: elem,
9008			props: jQuery.extend( {}, properties ),
9009			opts: jQuery.extend( true, { specialEasing: {} }, options ),
9010			originalProperties: properties,
9011			originalOptions: options,
9012			startTime: fxNow || createFxNow(),
9013			duration: options.duration,
9014			tweens: [],
9015			createTween: function( prop, end ) {
9016				var tween = jQuery.Tween( elem, animation.opts, prop, end,
9017						animation.opts.specialEasing[ prop ] || animation.opts.easing );
9018				animation.tweens.push( tween );
9019				return tween;
9020			},
9021			stop: function( gotoEnd ) {
9022				var index = 0,
9023					// if we are going to the end, we want to run all the tweens
9024					// otherwise we skip this part
9025					length = gotoEnd ? animation.tweens.length : 0;
9026				if ( stopped ) {
9027					return this;
9028				}
9029				stopped = true;
9030				for ( ; index < length ; index++ ) {
9031					animation.tweens[ index ].run( 1 );
9032				}
9033
9034				// resolve when we played the last frame
9035				// otherwise, reject
9036				if ( gotoEnd ) {
9037					deferred.resolveWith( elem, [ animation, gotoEnd ] );
9038				} else {
9039					deferred.rejectWith( elem, [ animation, gotoEnd ] );
9040				}
9041				return this;
9042			}
9043		}),
9044		props = animation.props;
9045
9046	propFilter( props, animation.opts.specialEasing );
9047
9048	for ( ; index < length ; index++ ) {
9049		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
9050		if ( result ) {
9051			return result;
9052		}
9053	}
9054
9055	jQuery.map( props, createTween, animation );
9056
9057	if ( jQuery.isFunction( animation.opts.start ) ) {
9058		animation.opts.start.call( elem, animation );
9059	}
9060
9061	jQuery.fx.timer(
9062		jQuery.extend( tick, {
9063			elem: elem,
9064			anim: animation,
9065			queue: animation.opts.queue
9066		})
9067	);
9068
9069	// attach callbacks from options
9070	return animation.progress( animation.opts.progress )
9071		.done( animation.opts.done, animation.opts.complete )
9072		.fail( animation.opts.fail )
9073		.always( animation.opts.always );
9074}
9075
9076jQuery.Animation = jQuery.extend( Animation, {
9077	tweener: function( props, callback ) {
9078		if ( jQuery.isFunction( props ) ) {
9079			callback = props;
9080			props = [ "*" ];
9081		} else {
9082			props = props.split(" ");
9083		}
9084
9085		var prop,
9086			index = 0,
9087			length = props.length;
9088
9089		for ( ; index < length ; index++ ) {
9090			prop = props[ index ];
9091			tweeners[ prop ] = tweeners[ prop ] || [];
9092			tweeners[ prop ].unshift( callback );
9093		}
9094	},
9095
9096	prefilter: function( callback, prepend ) {
9097		if ( prepend ) {
9098			animationPrefilters.unshift( callback );
9099		} else {
9100			animationPrefilters.push( callback );
9101		}
9102	}
9103});
9104
9105jQuery.speed = function( speed, easing, fn ) {
9106	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9107		complete: fn || !fn && easing ||
9108			jQuery.isFunction( speed ) && speed,
9109		duration: speed,
9110		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9111	};
9112
9113	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9114		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9115
9116	// normalize opt.queue - true/undefined/null -> "fx"
9117	if ( opt.queue == null || opt.queue === true ) {
9118		opt.queue = "fx";
9119	}
9120
9121	// Queueing
9122	opt.old = opt.complete;
9123
9124	opt.complete = function() {
9125		if ( jQuery.isFunction( opt.old ) ) {
9126			opt.old.call( this );
9127		}
9128
9129		if ( opt.queue ) {
9130			jQuery.dequeue( this, opt.queue );
9131		}
9132	};
9133
9134	return opt;
9135};
9136
9137jQuery.fn.extend({
9138	fadeTo: function( speed, to, easing, callback ) {
9139
9140		// show any hidden elements after setting opacity to 0
9141		return this.filter( isHidden ).css( "opacity", 0 ).show()
9142
9143			// animate to the value specified
9144			.end().animate({ opacity: to }, speed, easing, callback );
9145	},
9146	animate: function( prop, speed, easing, callback ) {
9147		var empty = jQuery.isEmptyObject( prop ),
9148			optall = jQuery.speed( speed, easing, callback ),
9149			doAnimation = function() {
9150				// Operate on a copy of prop so per-property easing won't be lost
9151				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9152
9153				// Empty animations, or finishing resolves immediately
9154				if ( empty || jQuery._data( this, "finish" ) ) {
9155					anim.stop( true );
9156				}
9157			};
9158			doAnimation.finish = doAnimation;
9159
9160		return empty || optall.queue === false ?
9161			this.each( doAnimation ) :
9162			this.queue( optall.queue, doAnimation );
9163	},
9164	stop: function( type, clearQueue, gotoEnd ) {
9165		var stopQueue = function( hooks ) {
9166			var stop = hooks.stop;
9167			delete hooks.stop;
9168			stop( gotoEnd );
9169		};
9170
9171		if ( typeof type !== "string" ) {
9172			gotoEnd = clearQueue;
9173			clearQueue = type;
9174			type = undefined;
9175		}
9176		if ( clearQueue && type !== false ) {
9177			this.queue( type || "fx", [] );
9178		}
9179
9180		return this.each(function() {
9181			var dequeue = true,
9182				index = type != null && type + "queueHooks",
9183				timers = jQuery.timers,
9184				data = jQuery._data( this );
9185
9186			if ( index ) {
9187				if ( data[ index ] && data[ index ].stop ) {
9188					stopQueue( data[ index ] );
9189				}
9190			} else {
9191				for ( index in data ) {
9192					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9193						stopQueue( data[ index ] );
9194					}
9195				}
9196			}
9197
9198			for ( index = timers.length; index--; ) {
9199				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9200					timers[ index ].anim.stop( gotoEnd );
9201					dequeue = false;
9202					timers.splice( index, 1 );
9203				}
9204			}
9205
9206			// start the next in the queue if the last step wasn't forced
9207			// timers currently will call their complete callbacks, which will dequeue
9208			// but only if they were gotoEnd
9209			if ( dequeue || !gotoEnd ) {
9210				jQuery.dequeue( this, type );
9211			}
9212		});
9213	},
9214	finish: function( type ) {
9215		if ( type !== false ) {
9216			type = type || "fx";
9217		}
9218		return this.each(function() {
9219			var index,
9220				data = jQuery._data( this ),
9221				queue = data[ type + "queue" ],
9222				hooks = data[ type + "queueHooks" ],
9223				timers = jQuery.timers,
9224				length = queue ? queue.length : 0;
9225
9226			// enable finishing flag on private data
9227			data.finish = true;
9228
9229			// empty the queue first
9230			jQuery.queue( this, type, [] );
9231
9232			if ( hooks && hooks.stop ) {
9233				hooks.stop.call( this, true );
9234			}
9235
9236			// look for any active animations, and finish them
9237			for ( index = timers.length; index--; ) {
9238				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
9239					timers[ index ].anim.stop( true );
9240					timers.splice( index, 1 );
9241				}
9242			}
9243
9244			// look for any animations in the old queue and finish them
9245			for ( index = 0; index < length; index++ ) {
9246				if ( queue[ index ] && queue[ index ].finish ) {
9247					queue[ index ].finish.call( this );
9248				}
9249			}
9250
9251			// turn off finishing flag
9252			delete data.finish;
9253		});
9254	}
9255});
9256
9257jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9258	var cssFn = jQuery.fn[ name ];
9259	jQuery.fn[ name ] = function( speed, easing, callback ) {
9260		return speed == null || typeof speed === "boolean" ?
9261			cssFn.apply( this, arguments ) :
9262			this.animate( genFx( name, true ), speed, easing, callback );
9263	};
9264});
9265
9266// Generate shortcuts for custom animations
9267jQuery.each({
9268	slideDown: genFx("show"),
9269	slideUp: genFx("hide"),
9270	slideToggle: genFx("toggle"),
9271	fadeIn: { opacity: "show" },
9272	fadeOut: { opacity: "hide" },
9273	fadeToggle: { opacity: "toggle" }
9274}, function( name, props ) {
9275	jQuery.fn[ name ] = function( speed, easing, callback ) {
9276		return this.animate( props, speed, easing, callback );
9277	};
9278});
9279
9280jQuery.timers = [];
9281jQuery.fx.tick = function() {
9282	var timer,
9283		timers = jQuery.timers,
9284		i = 0;
9285
9286	fxNow = jQuery.now();
9287
9288	for ( ; i < timers.length; i++ ) {
9289		timer = timers[ i ];
9290		// Checks the timer has not already been removed
9291		if ( !timer() && timers[ i ] === timer ) {
9292			timers.splice( i--, 1 );
9293		}
9294	}
9295
9296	if ( !timers.length ) {
9297		jQuery.fx.stop();
9298	}
9299	fxNow = undefined;
9300};
9301
9302jQuery.fx.timer = function( timer ) {
9303	jQuery.timers.push( timer );
9304	if ( timer() ) {
9305		jQuery.fx.start();
9306	} else {
9307		jQuery.timers.pop();
9308	}
9309};
9310
9311jQuery.fx.interval = 13;
9312
9313jQuery.fx.start = function() {
9314	if ( !timerId ) {
9315		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9316	}
9317};
9318
9319jQuery.fx.stop = function() {
9320	clearInterval( timerId );
9321	timerId = null;
9322};
9323
9324jQuery.fx.speeds = {
9325	slow: 600,
9326	fast: 200,
9327	// Default speed
9328	_default: 400
9329};
9330
9331
9332// Based off of the plugin by Clint Helfers, with permission.
9333// http://blindsignals.com/index.php/2009/07/jquery-delay/
9334jQuery.fn.delay = function( time, type ) {
9335	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
9336	type = type || "fx";
9337
9338	return this.queue( type, function( next, hooks ) {
9339		var timeout = setTimeout( next, time );
9340		hooks.stop = function() {
9341			clearTimeout( timeout );
9342		};
9343	});
9344};
9345
9346
9347(function() {
9348	// Minified: var a,b,c,d,e
9349	var input, div, select, a, opt;
9350
9351	// Setup
9352	div = document.createElement( "div" );
9353	div.setAttribute( "className", "t" );
9354	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
9355	a = div.getElementsByTagName("a")[ 0 ];
9356
9357	// First batch of tests.
9358	select = document.createElement("select");
9359	opt = select.appendChild( document.createElement("option") );
9360	input = div.getElementsByTagName("input")[ 0 ];
9361
9362	a.style.cssText = "top:1px";
9363
9364	// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
9365	support.getSetAttribute = div.className !== "t";
9366
9367	// Get the style information from getAttribute
9368	// (IE uses .cssText instead)
9369	support.style = /top/.test( a.getAttribute("style") );
9370
9371	// Make sure that URLs aren't manipulated
9372	// (IE normalizes it by default)
9373	support.hrefNormalized = a.getAttribute("href") === "/a";
9374
9375	// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
9376	support.checkOn = !!input.value;
9377
9378	// Make sure that a selected-by-default option has a working selected property.
9379	// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
9380	support.optSelected = opt.selected;
9381
9382	// Tests for enctype support on a form (#6743)
9383	support.enctype = !!document.createElement("form").enctype;
9384
9385	// Make sure that the options inside disabled selects aren't marked as disabled
9386	// (WebKit marks them as disabled)
9387	select.disabled = true;
9388	support.optDisabled = !opt.disabled;
9389
9390	// Support: IE8 only
9391	// Check if we can trust getAttribute("value")
9392	input = document.createElement( "input" );
9393	input.setAttribute( "value", "" );
9394	support.input = input.getAttribute( "value" ) === "";
9395
9396	// Check if an input maintains its value after becoming a radio
9397	input.value = "t";
9398	input.setAttribute( "type", "radio" );
9399	support.radioValue = input.value === "t";
9400})();
9401
9402
9403var rreturn = /\r/g;
9404
9405jQuery.fn.extend({
9406	val: function( value ) {
9407		var hooks, ret, isFunction,
9408			elem = this[0];
9409
9410		if ( !arguments.length ) {
9411			if ( elem ) {
9412				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
9413
9414				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
9415					return ret;
9416				}
9417
9418				ret = elem.value;
9419
9420				return typeof ret === "string" ?
9421					// handle most common string cases
9422					ret.replace(rreturn, "") :
9423					// handle cases where value is null/undef or number
9424					ret == null ? "" : ret;
9425			}
9426
9427			return;
9428		}
9429
9430		isFunction = jQuery.isFunction( value );
9431
9432		return this.each(function( i ) {
9433			var val;
9434
9435			if ( this.nodeType !== 1 ) {
9436				return;
9437			}
9438
9439			if ( isFunction ) {
9440				val = value.call( this, i, jQuery( this ).val() );
9441			} else {
9442				val = value;
9443			}
9444
9445			// Treat null/undefined as ""; convert numbers to string
9446			if ( val == null ) {
9447				val = "";
9448			} else if ( typeof val === "number" ) {
9449				val += "";
9450			} else if ( jQuery.isArray( val ) ) {
9451				val = jQuery.map( val, function( value ) {
9452					return value == null ? "" : value + "";
9453				});
9454			}
9455
9456			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
9457
9458			// If set returns undefined, fall back to normal setting
9459			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
9460				this.value = val;
9461			}
9462		});
9463	}
9464});
9465
9466jQuery.extend({
9467	valHooks: {
9468		option: {
9469			get: function( elem ) {
9470				var val = jQuery.find.attr( elem, "value" );
9471				return val != null ?
9472					val :
9473					// Support: IE10-11+
9474					// option.text throws exceptions (#14686, #14858)
9475					jQuery.trim( jQuery.text( elem ) );
9476			}
9477		},
9478		select: {
9479			get: function( elem ) {
9480				var value, option,
9481					options = elem.options,
9482					index = elem.selectedIndex,
9483					one = elem.type === "select-one" || index < 0,
9484					values = one ? null : [],
9485					max = one ? index + 1 : options.length,
9486					i = index < 0 ?
9487						max :
9488						one ? index : 0;
9489
9490				// Loop through all the selected options
9491				for ( ; i < max; i++ ) {
9492					option = options[ i ];
9493
9494					// oldIE doesn't update selected after form reset (#2551)
9495					if ( ( option.selected || i === index ) &&
9496							// Don't return options that are disabled or in a disabled optgroup
9497							( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
9498							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
9499
9500						// Get the specific value for the option
9501						value = jQuery( option ).val();
9502
9503						// We don't need an array for one selects
9504						if ( one ) {
9505							return value;
9506						}
9507
9508						// Multi-Selects return an array
9509						values.push( value );
9510					}
9511				}
9512
9513				return values;
9514			},
9515
9516			set: function( elem, value ) {
9517				var optionSet, option,
9518					options = elem.options,
9519					values = jQuery.makeArray( value ),
9520					i = options.length;
9521
9522				while ( i-- ) {
9523					option = options[ i ];
9524
9525					if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
9526
9527						// Support: IE6
9528						// When new option element is added to select box we need to
9529						// force reflow of newly added node in order to workaround delay
9530						// of initialization properties
9531						try {
9532							option.selected = optionSet = true;
9533
9534						} catch ( _ ) {
9535
9536							// Will be executed only in IE6
9537							option.scrollHeight;
9538						}
9539
9540					} else {
9541						option.selected = false;
9542					}
9543				}
9544
9545				// Force browsers to behave consistently when non-matching value is set
9546				if ( !optionSet ) {
9547					elem.selectedIndex = -1;
9548				}
9549
9550				return options;
9551			}
9552		}
9553	}
9554});
9555
9556// Radios and checkboxes getter/setter
9557jQuery.each([ "radio", "checkbox" ], function() {
9558	jQuery.valHooks[ this ] = {
9559		set: function( elem, value ) {
9560			if ( jQuery.isArray( value ) ) {
9561				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
9562			}
9563		}
9564	};
9565	if ( !support.checkOn ) {
9566		jQuery.valHooks[ this ].get = function( elem ) {
9567			// Support: Webkit
9568			// "" is returned instead of "on" if a value isn't specified
9569			return elem.getAttribute("value") === null ? "on" : elem.value;
9570		};
9571	}
9572});
9573
9574
9575
9576
9577var nodeHook, boolHook,
9578	attrHandle = jQuery.expr.attrHandle,
9579	ruseDefault = /^(?:checked|selected)$/i,
9580	getSetAttribute = support.getSetAttribute,
9581	getSetInput = support.input;
9582
9583jQuery.fn.extend({
9584	attr: function( name, value ) {
9585		return access( this, jQuery.attr, name, value, arguments.length > 1 );
9586	},
9587
9588	removeAttr: function( name ) {
9589		return this.each(function() {
9590			jQuery.removeAttr( this, name );
9591		});
9592	}
9593});
9594
9595jQuery.extend({
9596	attr: function( elem, name, value ) {
9597		var hooks, ret,
9598			nType = elem.nodeType;
9599
9600		// don't get/set attributes on text, comment and attribute nodes
9601		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
9602			return;
9603		}
9604
9605		// Fallback to prop when attributes are not supported
9606		if ( typeof elem.getAttribute === strundefined ) {
9607			return jQuery.prop( elem, name, value );
9608		}
9609
9610		// All attributes are lowercase
9611		// Grab necessary hook if one is defined
9612		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
9613			name = name.toLowerCase();
9614			hooks = jQuery.attrHooks[ name ] ||
9615				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
9616		}
9617
9618		if ( value !== undefined ) {
9619
9620			if ( value === null ) {
9621				jQuery.removeAttr( elem, name );
9622
9623			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
9624				return ret;
9625
9626			} else {
9627				elem.setAttribute( name, value + "" );
9628				return value;
9629			}
9630
9631		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
9632			return ret;
9633
9634		} else {
9635			ret = jQuery.find.attr( elem, name );
9636
9637			// Non-existent attributes return null, we normalize to undefined
9638			return ret == null ?
9639				undefined :
9640				ret;
9641		}
9642	},
9643
9644	removeAttr: function( elem, value ) {
9645		var name, propName,
9646			i = 0,
9647			attrNames = value && value.match( rnotwhite );
9648
9649		if ( attrNames && elem.nodeType === 1 ) {
9650			while ( (name = attrNames[i++]) ) {
9651				propName = jQuery.propFix[ name ] || name;
9652
9653				// Boolean attributes get special treatment (#10870)
9654				if ( jQuery.expr.match.bool.test( name ) ) {
9655					// Set corresponding property to false
9656					if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
9657						elem[ propName ] = false;
9658					// Support: IE<9
9659					// Also clear defaultChecked/defaultSelected (if appropriate)
9660					} else {
9661						elem[ jQuery.camelCase( "default-" + name ) ] =
9662							elem[ propName ] = false;
9663					}
9664
9665				// See #9699 for explanation of this approach (setting first, then removal)
9666				} else {
9667					jQuery.attr( elem, name, "" );
9668				}
9669
9670				elem.removeAttribute( getSetAttribute ? name : propName );
9671			}
9672		}
9673	},
9674
9675	attrHooks: {
9676		type: {
9677			set: function( elem, value ) {
9678				if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
9679					// Setting the type on a radio button after the value resets the value in IE6-9
9680					// Reset value to default in case type is set after value during creation
9681					var val = elem.value;
9682					elem.setAttribute( "type", value );
9683					if ( val ) {
9684						elem.value = val;
9685					}
9686					return value;
9687				}
9688			}
9689		}
9690	}
9691});
9692
9693// Hook for boolean attributes
9694boolHook = {
9695	set: function( elem, value, name ) {
9696		if ( value === false ) {
9697			// Remove boolean attributes when set to false
9698			jQuery.removeAttr( elem, name );
9699		} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
9700			// IE<8 needs the *property* name
9701			elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
9702
9703		// Use defaultChecked and defaultSelected for oldIE
9704		} else {
9705			elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
9706		}
9707
9708		return name;
9709	}
9710};
9711
9712// Retrieve booleans specially
9713jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
9714
9715	var getter = attrHandle[ name ] || jQuery.find.attr;
9716
9717	attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
9718		function( elem, name, isXML ) {
9719			var ret, handle;
9720			if ( !isXML ) {
9721				// Avoid an infinite loop by temporarily removing this function from the getter
9722				handle = attrHandle[ name ];
9723				attrHandle[ name ] = ret;
9724				ret = getter( elem, name, isXML ) != null ?
9725					name.toLowerCase() :
9726					null;
9727				attrHandle[ name ] = handle;
9728			}
9729			return ret;
9730		} :
9731		function( elem, name, isXML ) {
9732			if ( !isXML ) {
9733				return elem[ jQuery.camelCase( "default-" + name ) ] ?
9734					name.toLowerCase() :
9735					null;
9736			}
9737		};
9738});
9739
9740// fix oldIE attroperties
9741if ( !getSetInput || !getSetAttribute ) {
9742	jQuery.attrHooks.value = {
9743		set: function( elem, value, name ) {
9744			if ( jQuery.nodeName( elem, "input" ) ) {
9745				// Does not return so that setAttribute is also used
9746				elem.defaultValue = value;
9747			} else {
9748				// Use nodeHook if defined (#1954); otherwise setAttribute is fine
9749				return nodeHook && nodeHook.set( elem, value, name );
9750			}
9751		}
9752	};
9753}
9754
9755// IE6/7 do not support getting/setting some attributes with get/setAttribute
9756if ( !getSetAttribute ) {
9757
9758	// Use this for any attribute in IE6/7
9759	// This fixes almost every IE6/7 issue
9760	nodeHook = {
9761		set: function( elem, value, name ) {
9762			// Set the existing or create a new attribute node
9763			var ret = elem.getAttributeNode( name );
9764			if ( !ret ) {
9765				elem.setAttributeNode(
9766					(ret = elem.ownerDocument.createAttribute( name ))
9767				);
9768			}
9769
9770			ret.value = value += "";
9771
9772			// Break association with cloned elements by also using setAttribute (#9646)
9773			if ( name === "value" || value === elem.getAttribute( name ) ) {
9774				return value;
9775			}
9776		}
9777	};
9778
9779	// Some attributes are constructed with empty-string values when not defined
9780	attrHandle.id = attrHandle.name = attrHandle.coords =
9781		function( elem, name, isXML ) {
9782			var ret;
9783			if ( !isXML ) {
9784				return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
9785					ret.value :
9786					null;
9787			}
9788		};
9789
9790	// Fixing value retrieval on a button requires this module
9791	jQuery.valHooks.button = {
9792		get: function( elem, name ) {
9793			var ret = elem.getAttributeNode( name );
9794			if ( ret && ret.specified ) {
9795				return ret.value;
9796			}
9797		},
9798		set: nodeHook.set
9799	};
9800
9801	// Set contenteditable to false on removals(#10429)
9802	// Setting to empty string throws an error as an invalid value
9803	jQuery.attrHooks.contenteditable = {
9804		set: function( elem, value, name ) {
9805			nodeHook.set( elem, value === "" ? false : value, name );
9806		}
9807	};
9808
9809	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
9810	// This is for removals
9811	jQuery.each([ "width", "height" ], function( i, name ) {
9812		jQuery.attrHooks[ name ] = {
9813			set: function( elem, value ) {
9814				if ( value === "" ) {
9815					elem.setAttribute( name, "auto" );
9816					return value;
9817				}
9818			}
9819		};
9820	});
9821}
9822
9823if ( !support.style ) {
9824	jQuery.attrHooks.style = {
9825		get: function( elem ) {
9826			// Return undefined in the case of empty string
9827			// Note: IE uppercases css property names, but if we were to .toLowerCase()
9828			// .cssText, that would destroy case senstitivity in URL's, like in "background"
9829			return elem.style.cssText || undefined;
9830		},
9831		set: function( elem, value ) {
9832			return ( elem.style.cssText = value + "" );
9833		}
9834	};
9835}
9836
9837
9838
9839
9840var rfocusable = /^(?:input|select|textarea|button|object)$/i,
9841	rclickable = /^(?:a|area)$/i;
9842
9843jQuery.fn.extend({
9844	prop: function( name, value ) {
9845		return access( this, jQuery.prop, name, value, arguments.length > 1 );
9846	},
9847
9848	removeProp: function( name ) {
9849		name = jQuery.propFix[ name ] || name;
9850		return this.each(function() {
9851			// try/catch handles cases where IE balks (such as removing a property on window)
9852			try {
9853				this[ name ] = undefined;
9854				delete this[ name ];
9855			} catch( e ) {}
9856		});
9857	}
9858});
9859
9860jQuery.extend({
9861	propFix: {
9862		"for": "htmlFor",
9863		"class": "className"
9864	},
9865
9866	prop: function( elem, name, value ) {
9867		var ret, hooks, notxml,
9868			nType = elem.nodeType;
9869
9870		// don't get/set properties on text, comment and attribute nodes
9871		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
9872			return;
9873		}
9874
9875		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
9876
9877		if ( notxml ) {
9878			// Fix name and attach hooks
9879			name = jQuery.propFix[ name ] || name;
9880			hooks = jQuery.propHooks[ name ];
9881		}
9882
9883		if ( value !== undefined ) {
9884			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
9885				ret :
9886				( elem[ name ] = value );
9887
9888		} else {
9889			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
9890				ret :
9891				elem[ name ];
9892		}
9893	},
9894
9895	propHooks: {
9896		tabIndex: {
9897			get: function( elem ) {
9898				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
9899				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
9900				// Use proper attribute retrieval(#12072)
9901				var tabindex = jQuery.find.attr( elem, "tabindex" );
9902
9903				return tabindex ?
9904					parseInt( tabindex, 10 ) :
9905					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
9906						0 :
9907						-1;
9908			}
9909		}
9910	}
9911});
9912
9913// Some attributes require a special call on IE
9914// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
9915if ( !support.hrefNormalized ) {
9916	// href/src property should get the full normalized URL (#10299/#12915)
9917	jQuery.each([ "href", "src" ], function( i, name ) {
9918		jQuery.propHooks[ name ] = {
9919			get: function( elem ) {
9920				return elem.getAttribute( name, 4 );
9921			}
9922		};
9923	});
9924}
9925
9926// Support: Safari, IE9+
9927// mis-reports the default selected property of an option
9928// Accessing the parent's selectedIndex property fixes it
9929if ( !support.optSelected ) {
9930	jQuery.propHooks.selected = {
9931		get: function( elem ) {
9932			var parent = elem.parentNode;
9933
9934			if ( parent ) {
9935				parent.selectedIndex;
9936
9937				// Make sure that it also works with optgroups, see #5701
9938				if ( parent.parentNode ) {
9939					parent.parentNode.selectedIndex;
9940				}
9941			}
9942			return null;
9943		}
9944	};
9945}
9946
9947jQuery.each([
9948	"tabIndex",
9949	"readOnly",
9950	"maxLength",
9951	"cellSpacing",
9952	"cellPadding",
9953	"rowSpan",
9954	"colSpan",
9955	"useMap",
9956	"frameBorder",
9957	"contentEditable"
9958], function() {
9959	jQuery.propFix[ this.toLowerCase() ] = this;
9960});
9961
9962// IE6/7 call enctype encoding
9963if ( !support.enctype ) {
9964	jQuery.propFix.enctype = "encoding";
9965}
9966
9967
9968
9969
9970var rclass = /[\t\r\n\f]/g;
9971
9972jQuery.fn.extend({
9973	addClass: function( value ) {
9974		var classes, elem, cur, clazz, j, finalValue,
9975			i = 0,
9976			len = this.length,
9977			proceed = typeof value === "string" && value;
9978
9979		if ( jQuery.isFunction( value ) ) {
9980			return this.each(function( j ) {
9981				jQuery( this ).addClass( value.call( this, j, this.className ) );
9982			});
9983		}
9984
9985		if ( proceed ) {
9986			// The disjunction here is for better compressibility (see removeClass)
9987			classes = ( value || "" ).match( rnotwhite ) || [];
9988
9989			for ( ; i < len; i++ ) {
9990				elem = this[ i ];
9991				cur = elem.nodeType === 1 && ( elem.className ?
9992					( " " + elem.className + " " ).replace( rclass, " " ) :
9993					" "
9994				);
9995
9996				if ( cur ) {
9997					j = 0;
9998					while ( (clazz = classes[j++]) ) {
9999						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
10000							cur += clazz + " ";
10001						}
10002					}
10003
10004					// only assign if different to avoid unneeded rendering.
10005					finalValue = jQuery.trim( cur );
10006					if ( elem.className !== finalValue ) {
10007						elem.className = finalValue;
10008					}
10009				}
10010			}
10011		}
10012
10013		return this;
10014	},
10015
10016	removeClass: function( value ) {
10017		var classes, elem, cur, clazz, j, finalValue,
10018			i = 0,
10019			len = this.length,
10020			proceed = arguments.length === 0 || typeof value === "string" && value;
10021
10022		if ( jQuery.isFunction( value ) ) {
10023			return this.each(function( j ) {
10024				jQuery( this ).removeClass( value.call( this, j, this.className ) );
10025			});
10026		}
10027		if ( proceed ) {
10028			classes = ( value || "" ).match( rnotwhite ) || [];
10029
10030			for ( ; i < len; i++ ) {
10031				elem = this[ i ];
10032				// This expression is here for better compressibility (see addClass)
10033				cur = elem.nodeType === 1 && ( elem.className ?
10034					( " " + elem.className + " " ).replace( rclass, " " ) :
10035					""
10036				);
10037
10038				if ( cur ) {
10039					j = 0;
10040					while ( (clazz = classes[j++]) ) {
10041						// Remove *all* instances
10042						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
10043							cur = cur.replace( " " + clazz + " ", " " );
10044						}
10045					}
10046
10047					// only assign if different to avoid unneeded rendering.
10048					finalValue = value ? jQuery.trim( cur ) : "";
10049					if ( elem.className !== finalValue ) {
10050						elem.className = finalValue;
10051					}
10052				}
10053			}
10054		}
10055
10056		return this;
10057	},
10058
10059	toggleClass: function( value, stateVal ) {
10060		var type = typeof value;
10061
10062		if ( typeof stateVal === "boolean" && type === "string" ) {
10063			return stateVal ? this.addClass( value ) : this.removeClass( value );
10064		}
10065
10066		if ( jQuery.isFunction( value ) ) {
10067			return this.each(function( i ) {
10068				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
10069			});
10070		}
10071
10072		return this.each(function() {
10073			if ( type === "string" ) {
10074				// toggle individual class names
10075				var className,
10076					i = 0,
10077					self = jQuery( this ),
10078					classNames = value.match( rnotwhite ) || [];
10079
10080				while ( (className = classNames[ i++ ]) ) {
10081					// check each className given, space separated list
10082					if ( self.hasClass( className ) ) {
10083						self.removeClass( className );
10084					} else {
10085						self.addClass( className );
10086					}
10087				}
10088
10089			// Toggle whole class name
10090			} else if ( type === strundefined || type === "boolean" ) {
10091				if ( this.className ) {
10092					// store className if set
10093					jQuery._data( this, "__className__", this.className );
10094				}
10095
10096				// If the element has a class name or if we're passed "false",
10097				// then remove the whole classname (if there was one, the above saved it).
10098				// Otherwise bring back whatever was previously saved (if anything),
10099				// falling back to the empty string if nothing was stored.
10100				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
10101			}
10102		});
10103	},
10104
10105	hasClass: function( selector ) {
10106		var className = " " + selector + " ",
10107			i = 0,
10108			l = this.length;
10109		for ( ; i < l; i++ ) {
10110			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
10111				return true;
10112			}
10113		}
10114
10115		return false;
10116	}
10117});
10118
10119
10120
10121
10122// Return jQuery for attributes-only inclusion
10123
10124
10125jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
10126	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
10127	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
10128
10129	// Handle event binding
10130	jQuery.fn[ name ] = function( data, fn ) {
10131		return arguments.length > 0 ?
10132			this.on( name, null, data, fn ) :
10133			this.trigger( name );
10134	};
10135});
10136
10137jQuery.fn.extend({
10138	hover: function( fnOver, fnOut ) {
10139		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
10140	},
10141
10142	bind: function( types, data, fn ) {
10143		return this.on( types, null, data, fn );
10144	},
10145	unbind: function( types, fn ) {
10146		return this.off( types, null, fn );
10147	},
10148
10149	delegate: function( selector, types, data, fn ) {
10150		return this.on( types, selector, data, fn );
10151	},
10152	undelegate: function( selector, types, fn ) {
10153		// ( namespace ) or ( selector, types [, fn] )
10154		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
10155	}
10156});
10157
10158
10159var nonce = jQuery.now();
10160
10161var rquery = (/\?/);
10162
10163
10164
10165var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
10166
10167jQuery.parseJSON = function( data ) {
10168	// Attempt to parse using the native JSON parser first
10169	if ( window.JSON && window.JSON.parse ) {
10170		// Support: Android 2.3
10171		// Workaround failure to string-cast null input
10172		return window.JSON.parse( data + "" );
10173	}
10174
10175	var requireNonComma,
10176		depth = null,
10177		str = jQuery.trim( data + "" );
10178
10179	// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
10180	// after removing valid tokens
10181	return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
10182
10183		// Force termination if we see a misplaced comma
10184		if ( requireNonComma && comma ) {
10185			depth = 0;
10186		}
10187
10188		// Perform no more replacements after returning to outermost depth
10189		if ( depth === 0 ) {
10190			return token;
10191		}
10192
10193		// Commas must not follow "[", "{", or ","
10194		requireNonComma = open || comma;
10195
10196		// Determine new depth
10197		// array/object open ("[" or "{"): depth += true - false (increment)
10198		// array/object close ("]" or "}"): depth += false - true (decrement)
10199		// other cases ("," or primitive): depth += true - true (numeric cast)
10200		depth += !close - !open;
10201
10202		// Remove this token
10203		return "";
10204	}) ) ?
10205		( Function( "return " + str ) )() :
10206		jQuery.error( "Invalid JSON: " + data );
10207};
10208
10209
10210// Cross-browser xml parsing
10211jQuery.parseXML = function( data ) {
10212	var xml, tmp;
10213	if ( !data || typeof data !== "string" ) {
10214		return null;
10215	}
10216	try {
10217		if ( window.DOMParser ) { // Standard
10218			tmp = new DOMParser();
10219			xml = tmp.parseFromString( data, "text/xml" );
10220		} else { // IE
10221			xml = new ActiveXObject( "Microsoft.XMLDOM" );
10222			xml.async = "false";
10223			xml.loadXML( data );
10224		}
10225	} catch( e ) {
10226		xml = undefined;
10227	}
10228	if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
10229		jQuery.error( "Invalid XML: " + data );
10230	}
10231	return xml;
10232};
10233
10234
10235var
10236	// Document location
10237	ajaxLocParts,
10238	ajaxLocation,
10239
10240	rhash = /#.*$/,
10241	rts = /([?&])_=[^&]*/,
10242	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
10243	// #7653, #8125, #8152: local protocol detection
10244	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
10245	rnoContent = /^(?:GET|HEAD)$/,
10246	rprotocol = /^\/\//,
10247	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
10248
10249	/* Prefilters
10250	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
10251	 * 2) These are called:
10252	 *    - BEFORE asking for a transport
10253	 *    - AFTER param serialization (s.data is a string if s.processData is true)
10254	 * 3) key is the dataType
10255	 * 4) the catchall symbol "*" can be used
10256	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
10257	 */
10258	prefilters = {},
10259
10260	/* Transports bindings
10261	 * 1) key is the dataType
10262	 * 2) the catchall symbol "*" can be used
10263	 * 3) selection will start with transport dataType and THEN go to "*" if needed
10264	 */
10265	transports = {},
10266
10267	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
10268	allTypes = "*/".concat("*");
10269
10270// #8138, IE may throw an exception when accessing
10271// a field from window.location if document.domain has been set
10272try {
10273	ajaxLocation = location.href;
10274} catch( e ) {
10275	// Use the href attribute of an A element
10276	// since IE will modify it given document.location
10277	ajaxLocation = document.createElement( "a" );
10278	ajaxLocation.href = "";
10279	ajaxLocation = ajaxLocation.href;
10280}
10281
10282// Segment location into parts
10283ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
10284
10285// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
10286function addToPrefiltersOrTransports( structure ) {
10287
10288	// dataTypeExpression is optional and defaults to "*"
10289	return function( dataTypeExpression, func ) {
10290
10291		if ( typeof dataTypeExpression !== "string" ) {
10292			func = dataTypeExpression;
10293			dataTypeExpression = "*";
10294		}
10295
10296		var dataType,
10297			i = 0,
10298			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
10299
10300		if ( jQuery.isFunction( func ) ) {
10301			// For each dataType in the dataTypeExpression
10302			while ( (dataType = dataTypes[i++]) ) {
10303				// Prepend if requested
10304				if ( dataType.charAt( 0 ) === "+" ) {
10305					dataType = dataType.slice( 1 ) || "*";
10306					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
10307
10308				// Otherwise append
10309				} else {
10310					(structure[ dataType ] = structure[ dataType ] || []).push( func );
10311				}
10312			}
10313		}
10314	};
10315}
10316
10317// Base inspection function for prefilters and transports
10318function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
10319
10320	var inspected = {},
10321		seekingTransport = ( structure === transports );
10322
10323	function inspect( dataType ) {
10324		var selected;
10325		inspected[ dataType ] = true;
10326		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
10327			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
10328			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
10329				options.dataTypes.unshift( dataTypeOrTransport );
10330				inspect( dataTypeOrTransport );
10331				return false;
10332			} else if ( seekingTransport ) {
10333				return !( selected = dataTypeOrTransport );
10334			}
10335		});
10336		return selected;
10337	}
10338
10339	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
10340}
10341
10342// A special extend for ajax options
10343// that takes "flat" options (not to be deep extended)
10344// Fixes #9887
10345function ajaxExtend( target, src ) {
10346	var deep, key,
10347		flatOptions = jQuery.ajaxSettings.flatOptions || {};
10348
10349	for ( key in src ) {
10350		if ( src[ key ] !== undefined ) {
10351			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
10352		}
10353	}
10354	if ( deep ) {
10355		jQuery.extend( true, target, deep );
10356	}
10357
10358	return target;
10359}
10360
10361/* Handles responses to an ajax request:
10362 * - finds the right dataType (mediates between content-type and expected dataType)
10363 * - returns the corresponding response
10364 */
10365function ajaxHandleResponses( s, jqXHR, responses ) {
10366	var firstDataType, ct, finalDataType, type,
10367		contents = s.contents,
10368		dataTypes = s.dataTypes;
10369
10370	// Remove auto dataType and get content-type in the process
10371	while ( dataTypes[ 0 ] === "*" ) {
10372		dataTypes.shift();
10373		if ( ct === undefined ) {
10374			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
10375		}
10376	}
10377
10378	// Check if we're dealing with a known content-type
10379	if ( ct ) {
10380		for ( type in contents ) {
10381			if ( contents[ type ] && contents[ type ].test( ct ) ) {
10382				dataTypes.unshift( type );
10383				break;
10384			}
10385		}
10386	}
10387
10388	// Check to see if we have a response for the expected dataType
10389	if ( dataTypes[ 0 ] in responses ) {
10390		finalDataType = dataTypes[ 0 ];
10391	} else {
10392		// Try convertible dataTypes
10393		for ( type in responses ) {
10394			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
10395				finalDataType = type;
10396				break;
10397			}
10398			if ( !firstDataType ) {
10399				firstDataType = type;
10400			}
10401		}
10402		// Or just use first one
10403		finalDataType = finalDataType || firstDataType;
10404	}
10405
10406	// If we found a dataType
10407	// We add the dataType to the list if needed
10408	// and return the corresponding response
10409	if ( finalDataType ) {
10410		if ( finalDataType !== dataTypes[ 0 ] ) {
10411			dataTypes.unshift( finalDataType );
10412		}
10413		return responses[ finalDataType ];
10414	}
10415}
10416
10417/* Chain conversions given the request and the original response
10418 * Also sets the responseXXX fields on the jqXHR instance
10419 */
10420function ajaxConvert( s, response, jqXHR, isSuccess ) {
10421	var conv2, current, conv, tmp, prev,
10422		converters = {},
10423		// Work with a copy of dataTypes in case we need to modify it for conversion
10424		dataTypes = s.dataTypes.slice();
10425
10426	// Create converters map with lowercased keys
10427	if ( dataTypes[ 1 ] ) {
10428		for ( conv in s.converters ) {
10429			converters[ conv.toLowerCase() ] = s.converters[ conv ];
10430		}
10431	}
10432
10433	current = dataTypes.shift();
10434
10435	// Convert to each sequential dataType
10436	while ( current ) {
10437
10438		if ( s.responseFields[ current ] ) {
10439			jqXHR[ s.responseFields[ current ] ] = response;
10440		}
10441
10442		// Apply the dataFilter if provided
10443		if ( !prev && isSuccess && s.dataFilter ) {
10444			response = s.dataFilter( response, s.dataType );
10445		}
10446
10447		prev = current;
10448		current = dataTypes.shift();
10449
10450		if ( current ) {
10451
10452			// There's only work to do if current dataType is non-auto
10453			if ( current === "*" ) {
10454
10455				current = prev;
10456
10457			// Convert response if prev dataType is non-auto and differs from current
10458			} else if ( prev !== "*" && prev !== current ) {
10459
10460				// Seek a direct converter
10461				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
10462
10463				// If none found, seek a pair
10464				if ( !conv ) {
10465					for ( conv2 in converters ) {
10466
10467						// If conv2 outputs current
10468						tmp = conv2.split( " " );
10469						if ( tmp[ 1 ] === current ) {
10470
10471							// If prev can be converted to accepted input
10472							conv = converters[ prev + " " + tmp[ 0 ] ] ||
10473								converters[ "* " + tmp[ 0 ] ];
10474							if ( conv ) {
10475								// Condense equivalence converters
10476								if ( conv === true ) {
10477									conv = converters[ conv2 ];
10478
10479								// Otherwise, insert the intermediate dataType
10480								} else if ( converters[ conv2 ] !== true ) {
10481									current = tmp[ 0 ];
10482									dataTypes.unshift( tmp[ 1 ] );
10483								}
10484								break;
10485							}
10486						}
10487					}
10488				}
10489
10490				// Apply converter (if not an equivalence)
10491				if ( conv !== true ) {
10492
10493					// Unless errors are allowed to bubble, catch and return them
10494					if ( conv && s[ "throws" ] ) {
10495						response = conv( response );
10496					} else {
10497						try {
10498							response = conv( response );
10499						} catch ( e ) {
10500							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
10501						}
10502					}
10503				}
10504			}
10505		}
10506	}
10507
10508	return { state: "success", data: response };
10509}
10510
10511jQuery.extend({
10512
10513	// Counter for holding the number of active queries
10514	active: 0,
10515
10516	// Last-Modified header cache for next request
10517	lastModified: {},
10518	etag: {},
10519
10520	ajaxSettings: {
10521		url: ajaxLocation,
10522		type: "GET",
10523		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
10524		global: true,
10525		processData: true,
10526		async: true,
10527		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
10528		/*
10529		timeout: 0,
10530		data: null,
10531		dataType: null,
10532		username: null,
10533		password: null,
10534		cache: null,
10535		throws: false,
10536		traditional: false,
10537		headers: {},
10538		*/
10539
10540		accepts: {
10541			"*": allTypes,
10542			text: "text/plain",
10543			html: "text/html",
10544			xml: "application/xml, text/xml",
10545			json: "application/json, text/javascript"
10546		},
10547
10548		contents: {
10549			xml: /xml/,
10550			html: /html/,
10551			json: /json/
10552		},
10553
10554		responseFields: {
10555			xml: "responseXML",
10556			text: "responseText",
10557			json: "responseJSON"
10558		},
10559
10560		// Data converters
10561		// Keys separate source (or catchall "*") and destination types with a single space
10562		converters: {
10563
10564			// Convert anything to text
10565			"* text": String,
10566
10567			// Text to html (true = no transformation)
10568			"text html": true,
10569
10570			// Evaluate text as a json expression
10571			"text json": jQuery.parseJSON,
10572
10573			// Parse text as xml
10574			"text xml": jQuery.parseXML
10575		},
10576
10577		// For options that shouldn't be deep extended:
10578		// you can add your own custom options here if
10579		// and when you create one that shouldn't be
10580		// deep extended (see ajaxExtend)
10581		flatOptions: {
10582			url: true,
10583			context: true
10584		}
10585	},
10586
10587	// Creates a full fledged settings object into target
10588	// with both ajaxSettings and settings fields.
10589	// If target is omitted, writes into ajaxSettings.
10590	ajaxSetup: function( target, settings ) {
10591		return settings ?
10592
10593			// Building a settings object
10594			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
10595
10596			// Extending ajaxSettings
10597			ajaxExtend( jQuery.ajaxSettings, target );
10598	},
10599
10600	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
10601	ajaxTransport: addToPrefiltersOrTransports( transports ),
10602
10603	// Main method
10604	ajax: function( url, options ) {
10605
10606		// If url is an object, simulate pre-1.5 signature
10607		if ( typeof url === "object" ) {
10608			options = url;
10609			url = undefined;
10610		}
10611
10612		// Force options to be an object
10613		options = options || {};
10614
10615		var // Cross-domain detection vars
10616			parts,
10617			// Loop variable
10618			i,
10619			// URL without anti-cache param
10620			cacheURL,
10621			// Response headers as string
10622			responseHeadersString,
10623			// timeout handle
10624			timeoutTimer,
10625
10626			// To know if global events are to be dispatched
10627			fireGlobals,
10628
10629			transport,
10630			// Response headers
10631			responseHeaders,
10632			// Create the final options object
10633			s = jQuery.ajaxSetup( {}, options ),
10634			// Callbacks context
10635			callbackContext = s.context || s,
10636			// Context for global events is callbackContext if it is a DOM node or jQuery collection
10637			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
10638				jQuery( callbackContext ) :
10639				jQuery.event,
10640			// Deferreds
10641			deferred = jQuery.Deferred(),
10642			completeDeferred = jQuery.Callbacks("once memory"),
10643			// Status-dependent callbacks
10644			statusCode = s.statusCode || {},
10645			// Headers (they are sent all at once)
10646			requestHeaders = {},
10647			requestHeadersNames = {},
10648			// The jqXHR state
10649			state = 0,
10650			// Default abort message
10651			strAbort = "canceled",
10652			// Fake xhr
10653			jqXHR = {
10654				readyState: 0,
10655
10656				// Builds headers hashtable if needed
10657				getResponseHeader: function( key ) {
10658					var match;
10659					if ( state === 2 ) {
10660						if ( !responseHeaders ) {
10661							responseHeaders = {};
10662							while ( (match = rheaders.exec( responseHeadersString )) ) {
10663								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
10664							}
10665						}
10666						match = responseHeaders[ key.toLowerCase() ];
10667					}
10668					return match == null ? null : match;
10669				},
10670
10671				// Raw string
10672				getAllResponseHeaders: function() {
10673					return state === 2 ? responseHeadersString : null;
10674				},
10675
10676				// Caches the header
10677				setRequestHeader: function( name, value ) {
10678					var lname = name.toLowerCase();
10679					if ( !state ) {
10680						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
10681						requestHeaders[ name ] = value;
10682					}
10683					return this;
10684				},
10685
10686				// Overrides response content-type header
10687				overrideMimeType: function( type ) {
10688					if ( !state ) {
10689						s.mimeType = type;
10690					}
10691					return this;
10692				},
10693
10694				// Status-dependent callbacks
10695				statusCode: function( map ) {
10696					var code;
10697					if ( map ) {
10698						if ( state < 2 ) {
10699							for ( code in map ) {
10700								// Lazy-add the new callback in a way that preserves old ones
10701								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
10702							}
10703						} else {
10704							// Execute the appropriate callbacks
10705							jqXHR.always( map[ jqXHR.status ] );
10706						}
10707					}
10708					return this;
10709				},
10710
10711				// Cancel the request
10712				abort: function( statusText ) {
10713					var finalText = statusText || strAbort;
10714					if ( transport ) {
10715						transport.abort( finalText );
10716					}
10717					done( 0, finalText );
10718					return this;
10719				}
10720			};
10721
10722		// Attach deferreds
10723		deferred.promise( jqXHR ).complete = completeDeferred.add;
10724		jqXHR.success = jqXHR.done;
10725		jqXHR.error = jqXHR.fail;
10726
10727		// Remove hash character (#7531: and string promotion)
10728		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
10729		// Handle falsy url in the settings object (#10093: consistency with old signature)
10730		// We also use the url parameter if available
10731		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
10732
10733		// Alias method option to type as per ticket #12004
10734		s.type = options.method || options.type || s.method || s.type;
10735
10736		// Extract dataTypes list
10737		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
10738
10739		// A cross-domain request is in order when we have a protocol:host:port mismatch
10740		if ( s.crossDomain == null ) {
10741			parts = rurl.exec( s.url.toLowerCase() );
10742			s.crossDomain = !!( parts &&
10743				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
10744					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
10745						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
10746			);
10747		}
10748
10749		// Convert data if not already a string
10750		if ( s.data && s.processData && typeof s.data !== "string" ) {
10751			s.data = jQuery.param( s.data, s.traditional );
10752		}
10753
10754		// Apply prefilters
10755		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
10756
10757		// If request was aborted inside a prefilter, stop there
10758		if ( state === 2 ) {
10759			return jqXHR;
10760		}
10761
10762		// We can fire global events as of now if asked to
10763		
10763// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
10764		fireGlobals = jQuery.event && s.global;
10765
10766		// Watch for a new set of requests
10767		if ( fireGlobals && jQuery.active++ === 0 ) {
10768			jQuery.event.trigger("ajaxStart");
10769		}
10770
10771		// Uppercase the type
10772		s.type = s.type.toUpperCase();
10773
10774		// Determine if request has content
10775		s.hasContent = !rnoContent.test( s.type );
10776
10777		// Save the URL in case we're toying with the If-Modified-Since
10778		// and/or If-None-Match header later on
10779		cacheURL = s.url;
10780
10781		// More options handling for requests with no content
10782		if ( !s.hasContent ) {
10783
10784			// If data is available, append data to url
10785			if ( s.data ) {
vendor: 12,323 bytes, lines 10786-11250
10786				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
10787				// #9682: remove data so that it's not used in an eventual retry
10788				delete s.data;
10789			}
10790
10791			// Add anti-cache in url if needed
10792			if ( s.cache === false ) {
10793				s.url = rts.test( cacheURL ) ?
10794
10795					// If there is already a '_' parameter, set its value
10796					cacheURL.replace( rts, "$1_=" + nonce++ ) :
10797
10798					// Otherwise add one to the end
10799					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
10800			}
10801		}
10802
10803		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
10804		if ( s.ifModified ) {
10805			if ( jQuery.lastModified[ cacheURL ] ) {
10806				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
10807			}
10808			if ( jQuery.etag[ cacheURL ] ) {
10809				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
10810			}
10811		}
10812
10813		// Set the correct header, if data is being sent
10814		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
10815			jqXHR.setRequestHeader( "Content-Type", s.contentType );
10816		}
10817
10818		// Set the Accepts header for the server, depending on the dataType
10819		jqXHR.setRequestHeader(
10820			"Accept",
10821			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
10822				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
10823				s.accepts[ "*" ]
10824		);
10825
10826		// Check for headers option
10827		for ( i in s.headers ) {
10828			jqXHR.setRequestHeader( i, s.headers[ i ] );
10829		}
10830
10831		// Allow custom headers/mimetypes and early abort
10832		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
10833			// Abort if not done already and return
10834			return jqXHR.abort();
10835		}
10836
10837		// aborting is no longer a cancellation
10838		strAbort = "abort";
10839
10840		// Install callbacks on deferreds
10841		for ( i in { success: 1, error: 1, complete: 1 } ) {
10842			jqXHR[ i ]( s[ i ] );
10843		}
10844
10845		// Get transport
10846		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
10847
10848		// If no transport, we auto-abort
10849		if ( !transport ) {
10850			done( -1, "No Transport" );
10851		} else {
10852			jqXHR.readyState = 1;
10853
10854			// Send global event
10855			if ( fireGlobals ) {
10856				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
10857			}
10858			// Timeout
10859			if ( s.async && s.timeout > 0 ) {
10860				timeoutTimer = setTimeout(function() {
10861					jqXHR.abort("timeout");
10862				}, s.timeout );
10863			}
10864
10865			try {
10866				state = 1;
10867				transport.send( requestHeaders, done );
10868			} catch ( e ) {
10869				// Propagate exception as error if not done
10870				if ( state < 2 ) {
10871					done( -1, e );
10872				// Simply rethrow otherwise
10873				} else {
10874					throw e;
10875				}
10876			}
10877		}
10878
10879		// Callback for when everything is done
10880		function done( status, nativeStatusText, responses, headers ) {
10881			var isSuccess, success, error, response, modified,
10882				statusText = nativeStatusText;
10883
10884			// Called once
10885			if ( state === 2 ) {
10886				return;
10887			}
10888
10889			// State is "done" now
10890			state = 2;
10891
10892			// Clear timeout if it exists
10893			if ( timeoutTimer ) {
10894				clearTimeout( timeoutTimer );
10895			}
10896
10897			// Dereference transport for early garbage collection
10898			// (no matter how long the jqXHR object will be used)
10899			transport = undefined;
10900
10901			// Cache response headers
10902			responseHeadersString = headers || "";
10903
10904			// Set readyState
10905			jqXHR.readyState = status > 0 ? 4 : 0;
10906
10907			// Determine if successful
10908			isSuccess = status >= 200 && status < 300 || status === 304;
10909
10910			// Get response data
10911			if ( responses ) {
10912				response = ajaxHandleResponses( s, jqXHR, responses );
10913			}
10914
10915			// Convert no matter what (that way responseXXX fields are always set)
10916			response = ajaxConvert( s, response, jqXHR, isSuccess );
10917
10918			// If successful, handle type chaining
10919			if ( isSuccess ) {
10920
10921				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
10922				if ( s.ifModified ) {
10923					modified = jqXHR.getResponseHeader("Last-Modified");
10924					if ( modified ) {
10925						jQuery.lastModified[ cacheURL ] = modified;
10926					}
10927					modified = jqXHR.getResponseHeader("etag");
10928					if ( modified ) {
10929						jQuery.etag[ cacheURL ] = modified;
10930					}
10931				}
10932
10933				// if no content
10934				if ( status === 204 || s.type === "HEAD" ) {
10935					statusText = "nocontent";
10936
10937				// if not modified
10938				} else if ( status === 304 ) {
10939					statusText = "notmodified";
10940
10941				// If we have data, let's convert it
10942				} else {
10943					statusText = response.state;
10944					success = response.data;
10945					error = response.error;
10946					isSuccess = !error;
10947				}
10948			} else {
10949				// We extract error from statusText
10950				// then normalize statusText and status for non-aborts
10951				error = statusText;
10952				if ( status || !statusText ) {
10953					statusText = "error";
10954					if ( status < 0 ) {
10955						status = 0;
10956					}
10957				}
10958			}
10959
10960			// Set data for the fake xhr object
10961			jqXHR.status = status;
10962			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
10963
10964			// Success/Error
10965			if ( isSuccess ) {
10966				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
10967			} else {
10968				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
10969			}
10970
10971			// Status-dependent callbacks
10972			jqXHR.statusCode( statusCode );
10973			statusCode = undefined;
10974
10975			if ( fireGlobals ) {
10976				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
10977					[ jqXHR, s, isSuccess ? success : error ] );
10978			}
10979
10980			// Complete
10981			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
10982
10983			if ( fireGlobals ) {
10984				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
10985				// Handle the global AJAX counter
10986				if ( !( --jQuery.active ) ) {
10987					jQuery.event.trigger("ajaxStop");
10988				}
10989			}
10990		}
10991
10992		return jqXHR;
10993	},
10994
10995	getJSON: function( url, data, callback ) {
10996		return jQuery.get( url, data, callback, "json" );
10997	},
10998
10999	getScript: function( url, callback ) {
11000		return jQuery.get( url, undefined, callback, "script" );
11001	}
11002});
11003
11004jQuery.each( [ "get", "post" ], function( i, method ) {
11005	jQuery[ method ] = function( url, data, callback, type ) {
11006		// shift arguments if data argument was omitted
11007		if ( jQuery.isFunction( data ) ) {
11008			type = type || callback;
11009			callback = data;
11010			data = undefined;
11011		}
11012
11013		return jQuery.ajax({
11014			url: url,
11015			type: method,
11016			dataType: type,
11017			data: data,
11018			success: callback
11019		});
11020	};
11021});
11022
11023
11024jQuery._evalUrl = function( url ) {
11025	return jQuery.ajax({
11026		url: url,
11027		type: "GET",
11028		dataType: "script",
11029		async: false,
11030		global: false,
11031		"throws": true
11032	});
11033};
11034
11035
11036jQuery.fn.extend({
11037	wrapAll: function( html ) {
11038		if ( jQuery.isFunction( html ) ) {
11039			return this.each(function(i) {
11040				jQuery(this).wrapAll( html.call(this, i) );
11041			});
11042		}
11043
11044		if ( this[0] ) {
11045			// The elements to wrap the target around
11046			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
11047
11048			if ( this[0].parentNode ) {
11049				wrap.insertBefore( this[0] );
11050			}
11051
11052			wrap.map(function() {
11053				var elem = this;
11054
11055				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
11056					elem = elem.firstChild;
11057				}
11058
11059				return elem;
11060			}).append( this );
11061		}
11062
11063		return this;
11064	},
11065
11066	wrapInner: function( html ) {
11067		if ( jQuery.isFunction( html ) ) {
11068			return this.each(function(i) {
11069				jQuery(this).wrapInner( html.call(this, i) );
11070			});
11071		}
11072
11073		return this.each(function() {
11074			var self = jQuery( this ),
11075				contents = self.contents();
11076
11077			if ( contents.length ) {
11078				contents.wrapAll( html );
11079
11080			} else {
11081				self.append( html );
11082			}
11083		});
11084	},
11085
11086	wrap: function( html ) {
11087		var isFunction = jQuery.isFunction( html );
11088
11089		return this.each(function(i) {
11090			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
11091		});
11092	},
11093
11094	unwrap: function() {
11095		return this.parent().each(function() {
11096			if ( !jQuery.nodeName( this, "body" ) ) {
11097				jQuery( this ).replaceWith( this.childNodes );
11098			}
11099		}).end();
11100	}
11101});
11102
11103
11104jQuery.expr.filters.hidden = function( elem ) {
11105	// Support: Opera <= 12.12
11106	// Opera reports offsetWidths and offsetHeights less than zero on some elements
11107	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
11108		(!support.reliableHiddenOffsets() &&
11109			((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
11110};
11111
11112jQuery.expr.filters.visible = function( elem ) {
11113	return !jQuery.expr.filters.hidden( elem );
11114};
11115
11116
11117
11118
11119var r20 = /%20/g,
11120	rbracket = /\[\]$/,
11121	rCRLF = /\r?\n/g,
11122	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
11123	rsubmittable = /^(?:input|select|textarea|keygen)/i;
11124
11125function buildParams( prefix, obj, traditional, add ) {
11126	var name;
11127
11128	if ( jQuery.isArray( obj ) ) {
11129		// Serialize array item.
11130		jQuery.each( obj, function( i, v ) {
11131			if ( traditional || rbracket.test( prefix ) ) {
11132				// Treat each array item as a scalar.
11133				add( prefix, v );
11134
11135			} else {
11136				// Item is non-scalar (array or object), encode its numeric index.
11137				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
11138			}
11139		});
11140
11141	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
11142		// Serialize object item.
11143		for ( name in obj ) {
11144			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
11145		}
11146
11147	} else {
11148		// Serialize scalar item.
11149		add( prefix, obj );
11150	}
11151}
11152
11153// Serialize an array of form elements or a set of
11154// key/values into a query string
11155jQuery.param = function( a, traditional ) {
11156	var prefix,
11157		s = [],
11158		add = function( key, value ) {
11159			// If value is a function, invoke it and return its value
11160			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
11161			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
11162		};
11163
11164	// Set traditional to true for jQuery <= 1.3.2 behavior.
11165	if ( traditional === undefined ) {
11166		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
11167	}
11168
11169	// If an array was passed in, assume that it is an array of form elements.
11170	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
11171		// Serialize the form elements
11172		jQuery.each( a, function() {
11173			add( this.name, this.value );
11174		});
11175
11176	} else {
11177		// If traditional, encode the "old" way (the way 1.3.2 or older
11178		// did it), otherwise encode params recursively.
11179		for ( prefix in a ) {
11180			buildParams( prefix, a[ prefix ], traditional, add );
11181		}
11182	}
11183
11184	// Return the resulting serialization
11185	return s.join( "&" ).replace( r20, "+" );
11186};
11187
11188jQuery.fn.extend({
11189	serialize: function() {
11190		return jQuery.param( this.serializeArray() );
11191	},
11192	serializeArray: function() {
11193		return this.map(function() {
11194			// Can add propHook for "elements" to filter or add form elements
11195			var elements = jQuery.prop( this, "elements" );
11196			return elements ? jQuery.makeArray( elements ) : this;
11197		})
11198		.filter(function() {
11199			var type = this.type;
11200			// Use .is(":disabled") so that fieldset[disabled] works
11201			return this.name && !jQuery( this ).is( ":disabled" ) &&
11202				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
11203				( this.checked || !rcheckableType.test( type ) );
11204		})
11205		.map(function( i, elem ) {
11206			var val = jQuery( this ).val();
11207
11208			return val == null ?
11209				null :
11210				jQuery.isArray( val ) ?
11211					jQuery.map( val, function( val ) {
11212						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
11213					}) :
11214					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
11215		}).get();
11216	}
11217});
11218
11219
11220// Create the request object
11221// (This is still attached to ajaxSettings for backward compatibility)
11222jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
11223	// Support: IE6+
11224	function() {
11225
11226		// XHR cannot access local files, always use ActiveX for that case
11227		return !this.isLocal &&
11228
11229			// Support: IE7-8
11230			// oldIE XHR does not support non-RFC2616 methods (#13240)
11231			// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
11232			// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
11233			// Although this check for six methods instead of eight
11234			// since IE also does not support "trace" and "connect"
11235			/^(get|post|head|put|delete|options)$/i.test( this.type ) &&
11236
11237			createStandardXHR() || createActiveXHR();
11238	} :
11239	// For all other browsers, use the standard XMLHttpRequest object
11240	createStandardXHR;
11241
11242var xhrId = 0,
11243	xhrCallbacks = {},
11244	xhrSupported = jQuery.ajaxSettings.xhr();
11245
11246// Support: IE<10
11247// Open requests must be manually aborted on unload (#5280)
11248// See https://support.microsoft.com/kb/2856746 for more info
11249if ( window.attachEvent ) {
11250	window.attachEvent( "on
vendor: 11,251 bytes, lines 11250-11683
11250unload", function() {
11251		for ( var key in xhrCallbacks ) {
11252			xhrCallbacks[ key ]( undefined, true );
11253		}
11254	});
11255}
11256
11257// Determine support properties
11258support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
11259xhrSupported = support.ajax = !!xhrSupported;
11260
11261// Create transport if the browser can provide an xhr
11262if ( xhrSupported ) {
11263
11264	jQuery.ajaxTransport(function( options ) {
11265		// Cross domain only allowed if supported through XMLHttpRequest
11266		if ( !options.crossDomain || support.cors ) {
11267
11268			var callback;
11269
11270			return {
11271				send: function( headers, complete ) {
11272					var i,
11273						xhr = options.xhr(),
11274						id = ++xhrId;
11275
11276					// Open the socket
11277					xhr.open( options.type, options.url, options.async, options.username, options.password );
11278
11279					// Apply custom fields if provided
11280					if ( options.xhrFields ) {
11281						for ( i in options.xhrFields ) {
11282							xhr[ i ] = options.xhrFields[ i ];
11283						}
11284					}
11285
11286					// Override mime type if needed
11287					if ( options.mimeType && xhr.overrideMimeType ) {
11288						xhr.overrideMimeType( options.mimeType );
11289					}
11290
11291					// X-Requested-With header
11292					// For cross-domain requests, seeing as conditions for a preflight are
11293					// akin to a jigsaw puzzle, we simply never set it to be sure.
11294					// (it can always be set on a per-request basis or even using ajaxSetup)
11295					// For same-domain requests, won't change header if already provided.
11296					if ( !options.crossDomain && !headers["X-Requested-With"] ) {
11297						headers["X-Requested-With"] = "XMLHttpRequest";
11298					}
11299
11300					// Set headers
11301					for ( i in headers ) {
11302						// Support: IE<9
11303						// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
11304						// request header to a null-value.
11305						//
11306						// To keep consistent with other XHR implementations, cast the value
11307						// to string and ignore `undefined`.
11308						if ( headers[ i ] !== undefined ) {
11309							xhr.setRequestHeader( i, headers[ i ] + "" );
11310						}
11311					}
11312
11313					// Do send the request
11314					// This may raise an exception which is actually
11315					// handled in jQuery.ajax (so no try/catch here)
11316					xhr.send( ( options.hasContent && options.data ) || null );
11317
11318					// Listener
11319					callback = function( _, isAbort ) {
11320						var status, statusText, responses;
11321
11322						// Was never called and is aborted or complete
11323						if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
11324							// Clean up
11325							delete xhrCallbacks[ id ];
11326							callback = undefined;
11327							xhr.onreadystatechange = jQuery.noop;
11328
11329							// Abort manually if needed
11330							if ( isAbort ) {
11331								if ( xhr.readyState !== 4 ) {
11332									xhr.abort();
11333								}
11334							} else {
11335								responses = {};
11336								status = xhr.status;
11337
11338								// Support: IE<10
11339								// Accessing binary-data responseText throws an exception
11340								// (#11426)
11341								if ( typeof xhr.responseText === "string" ) {
11342									responses.text = xhr.responseText;
11343								}
11344
11345								// Firefox throws an exception when accessing
11346								// statusText for faulty cross-domain requests
11347								try {
11348									statusText = xhr.statusText;
11349								} catch( e ) {
11350									// We normalize with Webkit giving an empty statusText
11351									statusText = "";
11352								}
11353
11354								// Filter status for non standard behaviors
11355
11356								// If the request is local and we have data: assume a success
11357								// (success with no data won't get notified, that's the best we
11358								// can do given current implementations)
11359								if ( !status && options.isLocal && !options.crossDomain ) {
11360									status = responses.text ? 200 : 404;
11361								// IE - #1450: sometimes returns 1223 when it should be 204
11362								} else if ( status === 1223 ) {
11363									status = 204;
11364								}
11365							}
11366						}
11367
11368						// Call complete if needed
11369						if ( responses ) {
11370							complete( status, statusText, responses, xhr.getAllResponseHeaders() );
11371						}
11372					};
11373
11374					if ( !options.async ) {
11375						// if we're in sync mode we fire the callback
11376						callback();
11377					} else if ( xhr.readyState === 4 ) {
11378						// (IE6 & IE7) if it's in cache and has been
11379						// retrieved directly we need to fire the callback
11380						setTimeout( callback );
11381					} else {
11382						// Add to the list of active xhr callbacks
11383						xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
11384					}
11385				},
11386
11387				abort: function() {
11388					if ( callback ) {
11389						callback( undefined, true );
11390					}
11391				}
11392			};
11393		}
11394	});
11395}
11396
11397// Functions to create xhrs
11398function createStandardXHR() {
11399	try {
11400		return new window.XMLHttpRequest();
11401	} catch( e ) {}
11402}
11403
11404function createActiveXHR() {
11405	try {
11406		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
11407	} catch( e ) {}
11408}
11409
11410
11411
11412
11413// Install script dataType
11414jQuery.ajaxSetup({
11415	accepts: {
11416		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
11417	},
11418	contents: {
11419		script: /(?:java|ecma)script/
11420	},
11421	converters: {
11422		"text script": function( text ) {
11423			jQuery.globalEval( text );
11424			return text;
11425		}
11426	}
11427});
11428
11429// Handle cache's special case and global
11430jQuery.ajaxPrefilter( "script", function( s ) {
11431	if ( s.cache === undefined ) {
11432		s.cache = false;
11433	}
11434	if ( s.crossDomain ) {
11435		s.type = "GET";
11436		s.global = false;
11437	}
11438});
11439
11440// Bind script tag hack transport
11441jQuery.ajaxTransport( "script", function(s) {
11442
11443	// This transport only deals with cross domain requests
11444	if ( s.crossDomain ) {
11445
11446		var script,
11447			head = document.head || jQuery("head")[0] || document.documentElement;
11448
11449		return {
11450
11451			send: function( _, callback ) {
11452
11453				script = document.createElement("script");
11454
11455				script.async = true;
11456
11457				if ( s.scriptCharset ) {
11458					script.charset = s.scriptCharset;
11459				}
11460
11461				script.src = s.url;
11462
11463				// Attach handlers for all browsers
11464				script.onload = script.onreadystatechange = function( _, isAbort ) {
11465
11466					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
11467
11468						// Handle memory leak in IE
11469						script.onload = script.onreadystatechange = null;
11470
11471						// Remove the script
11472						if ( script.parentNode ) {
11473							script.parentNode.removeChild( script );
11474						}
11475
11476						// Dereference the script
11477						script = null;
11478
11479						// Callback if not abort
11480						if ( !isAbort ) {
11481							callback( 200, "success" );
11482						}
11483					}
11484				};
11485
11486				// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
11487				// Use native DOM manipulation to avoid our domManip AJAX trickery
11488				head.insertBefore( script, head.firstChild );
11489			},
11490
11491			abort: function() {
11492				if ( script ) {
11493					script.onload( undefined, true );
11494				}
11495			}
11496		};
11497	}
11498});
11499
11500
11501
11502
11503var oldCallbacks = [],
11504	rjsonp = /(=)\?(?=&|$)|\?\?/;
11505
11506// Default jsonp settings
11507jQuery.ajaxSetup({
11508	jsonp: "callback",
11509	jsonpCallback: function() {
11510		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
11511		this[ callback ] = true;
11512		return callback;
11513	}
11514});
11515
11516// Detect, normalize options and install callbacks for jsonp requests
11517jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
11518
11519	var callbackName, overwritten, responseContainer,
11520		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
11521			"url" :
11522			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
11523		);
11524
11525	// Handle iff the expected data type is "jsonp" or we have a parameter to set
11526	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
11527
11528		// Get callback name, remembering preexisting value associated with it
11529		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
11530			s.jsonpCallback() :
11531			s.jsonpCallback;
11532
11533		// Insert callback into url or form data
11534		if ( jsonProp ) {
11535			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
11536		} else if ( s.jsonp !== false ) {
11537			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
11538		}
11539
11540		// Use data converter to retrieve json after script execution
11541		s.converters["script json"] = function() {
11542			if ( !responseContainer ) {
11543				jQuery.error( callbackName + " was not called" );
11544			}
11545			return responseContainer[ 0 ];
11546		};
11547
11548		// force json dataType
11549		s.dataTypes[ 0 ] = "json";
11550
11551		// Install callback
11552		overwritten = window[ callbackName ];
11553		window[ callbackName ] = function() {
11554			responseContainer = arguments;
11555		};
11556
11557		// Clean-up function (fires after converters)
11558		jqXHR.always(function() {
11559			// Restore preexisting value
11560			window[ callbackName ] = overwritten;
11561
11562			// Save back as free
11563			if ( s[ callbackName ] ) {
11564				// make sure that re-using the options doesn't screw things around
11565				s.jsonpCallback = originalSettings.jsonpCallback;
11566
11567				// save the callback name for future use
11568				oldCallbacks.push( callbackName );
11569			}
11570
11571			// Call if it was a function and we have a response
11572			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
11573				overwritten( responseContainer[ 0 ] );
11574			}
11575
11576			responseContainer = overwritten = undefined;
11577		});
11578
11579		// Delegate to script
11580		return "script";
11581	}
11582});
11583
11584
11585
11586
11587// data: string of html
11588// context (optional): If specified, the fragment will be created in this context, defaults to document
11589// keepScripts (optional): If true, will include scripts passed in the html string
11590jQuery.parseHTML = function( data, context, keepScripts ) {
11591	if ( !data || typeof data !== "string" ) {
11592		return null;
11593	}
11594	if ( typeof context === "boolean" ) {
11595		keepScripts = context;
11596		context = false;
11597	}
11598	context = context || document;
11599
11600	var parsed = rsingleTag.exec( data ),
11601		scripts = !keepScripts && [];
11602
11603	// Single tag
11604	if ( parsed ) {
11605		return [ context.createElement( parsed[1] ) ];
11606	}
11607
11608	parsed = jQuery.buildFragment( [ data ], context, scripts );
11609
11610	if ( scripts && scripts.length ) {
11611		jQuery( scripts ).remove();
11612	}
11613
11614	return jQuery.merge( [], parsed.childNodes );
11615};
11616
11617
11618// Keep a copy of the old load method
11619var _load = jQuery.fn.load;
11620
11621/**
11622 * Load a url into a page
11623 */
11624jQuery.fn.load = function( url, params, callback ) {
11625	if ( typeof url !== "string" && _load ) {
11626		return _load.apply( this, arguments );
11627	}
11628
11629	var selector, response, type,
11630		self = this,
11631		off = url.indexOf(" ");
11632
11633	if ( off >= 0 ) {
11634		selector = jQuery.trim( url.slice( off, url.length ) );
11635		url = url.slice( 0, off );
11636	}
11637
11638	// If it's a function
11639	if ( jQuery.isFunction( params ) ) {
11640
11641		// We assume that it's the callback
11642		callback = params;
11643		params = undefined;
11644
11645	// Otherwise, build a param string
11646	} else if ( params && typeof params === "object" ) {
11647		type = "POST";
11648	}
11649
11650	// If we have elements to modify, make the request
11651	if ( self.length > 0 ) {
11652		jQuery.ajax({
11653			url: url,
11654
11655			// if "type" variable is undefined, then "GET" method will be used
11656			type: type,
11657			dataType: "html",
11658			data: params
11659		}).done(function( responseText ) {
11660
11661			// Save response for use in complete callback
11662			response = arguments;
11663
11664			self.html( selector ?
11665
11666				// If a selector was specified, locate the right elements in a dummy div
11667				// Exclude scripts to avoid IE 'Permission Denied' errors
11668				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
11669
11670				// Otherwise use the full result
11671				responseText );
11672
11673		}).complete( callback && function( jqXHR, status ) {
11674			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
11675		});
11676	}
11677
11678	return this;
11679};
11680
11681
11682
11683
11684// Attach a bunch of functions for handling common AJAX events
11685jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
11686	jQuery.fn[ type ] = function( fn ) {
11687		return this.on( type, fn );
11688	};
11689})
vendor: 9,149 bytes, lines 11689-12003
11689;
11690
11691
11692
11693
11694jQuery.expr.filters.animated = function( elem ) {
11695	return jQuery.grep(jQuery.timers, function( fn ) {
11696		return elem === fn.elem;
11697	}).length;
11698};
11699
11700
11701
11702
11703
11704var docElem = window.document.documentElement;
11705
11706/**
11707 * Gets a window from an element
11708 */
11709function getWindow( elem ) {
11710	return jQuery.isWindow( elem ) ?
11711		elem :
11712		elem.nodeType === 9 ?
11713			elem.defaultView || elem.parentWindow :
11714			false;
11715}
11716
11717jQuery.offset = {
11718	setOffset: function( elem, options, i ) {
11719		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
11720			position = jQuery.css( elem, "position" ),
11721			curElem = jQuery( elem ),
11722			props = {};
11723
11724		// set position first, in-case top/left are set even on static elem
11725		if ( position === "static" ) {
11726			elem.style.position = "relative";
11727		}
11728
11729		curOffset = curElem.offset();
11730		curCSSTop = jQuery.css( elem, "top" );
11731		curCSSLeft = jQuery.css( elem, "left" );
11732		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
11733			jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
11734
11735		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
11736		if ( calculatePosition ) {
11737			curPosition = curElem.position();
11738			curTop = curPosition.top;
11739			curLeft = curPosition.left;
11740		} else {
11741			curTop = parseFloat( curCSSTop ) || 0;
11742			curLeft = parseFloat( curCSSLeft ) || 0;
11743		}
11744
11745		if ( jQuery.isFunction( options ) ) {
11746			options = options.call( elem, i, curOffset );
11747		}
11748
11749		if ( options.top != null ) {
11750			props.top = ( options.top - curOffset.top ) + curTop;
11751		}
11752		if ( options.left != null ) {
11753			props.left = ( options.left - curOffset.left ) + curLeft;
11754		}
11755
11756		if ( "using" in options ) {
11757			options.using.call( elem, props );
11758		} else {
11759			curElem.css( props );
11760		}
11761	}
11762};
11763
11764jQuery.fn.extend({
11765	offset: function( options ) {
11766		if ( arguments.length ) {
11767			return options === undefined ?
11768				this :
11769				this.each(function( i ) {
11770					jQuery.offset.setOffset( this, options, i );
11771				});
11772		}
11773
11774		var docElem, win,
11775			box = { top: 0, left: 0 },
11776			elem = this[ 0 ],
11777			doc = elem && elem.ownerDocument;
11778
11779		if ( !doc ) {
11780			return;
11781		}
11782
11783		docElem = doc.documentElement;
11784
11785		// Make sure it's not a disconnected DOM node
11786		if ( !jQuery.contains( docElem, elem ) ) {
11787			return box;
11788		}
11789
11790		// If we don't have gBCR, just use 0,0 rather than error
11791		// BlackBerry 5, iOS 3 (original iPhone)
11792		if ( typeof elem.getBoundingClientRect !== strundefined ) {
11793			box = elem.getBoundingClientRect();
11794		}
11795		win = getWindow( doc );
11796		return {
11797			top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
11798			left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
11799		};
11800	},
11801
11802	position: function() {
11803		if ( !this[ 0 ] ) {
11804			return;
11805		}
11806
11807		var offsetParent, offset,
11808			parentOffset = { top: 0, left: 0 },
11809			elem = this[ 0 ];
11810
11811		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
11812		if ( jQuery.css( elem, "position" ) === "fixed" ) {
11813			// we assume that getBoundingClientRect is available when computed position is fixed
11814			offset = elem.getBoundingClientRect();
11815		} else {
11816			// Get *real* offsetParent
11817			offsetParent = this.offsetParent();
11818
11819			// Get correct offsets
11820			offset = this.offset();
11821			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
11822				parentOffset = offsetParent.offset();
11823			}
11824
11825			// Add offsetParent borders
11826			parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
11827			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
11828		}
11829
11830		// Subtract parent offsets and element margins
11831		// note: when an element has margin: auto the offsetLeft and marginLeft
11832		// are the same in Safari causing offset.left to incorrectly be 0
11833		return {
11834			top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
11835			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
11836		};
11837	},
11838
11839	offsetParent: function() {
11840		return this.map(function() {
11841			var offsetParent = this.offsetParent || docElem;
11842
11843			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
11844				offsetParent = offsetParent.offsetParent;
11845			}
11846			return offsetParent || docElem;
11847		});
11848	}
11849});
11850
11851// Create scrollLeft and scrollTop methods
11852jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
11853	var top = /Y/.test( prop );
11854
11855	jQuery.fn[ method ] = function( val ) {
11856		return access( this, function( elem, method, val ) {
11857			var win = getWindow( elem );
11858
11859			if ( val === undefined ) {
11860				return win ? (prop in win) ? win[ prop ] :
11861					win.document.documentElement[ method ] :
11862					elem[ method ];
11863			}
11864
11865			if ( win ) {
11866				win.scrollTo(
11867					!top ? val : jQuery( win ).scrollLeft(),
11868					top ? val : jQuery( win ).scrollTop()
11869				);
11870
11871			} else {
11872				elem[ method ] = val;
11873			}
11874		}, method, val, arguments.length, null );
11875	};
11876});
11877
11878// Add the top/left cssHooks using jQuery.fn.position
11879// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
11880// getComputedStyle returns percent when specified for top/left/bottom/right
11881// rather than make the css module depend on the offset module, we just check for it here
11882jQuery.each( [ "top", "left" ], function( i, prop ) {
11883	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
11884		function( elem, computed ) {
11885			if ( computed ) {
11886				computed = curCSS( elem, prop );
11887				// if curCSS returns percentage, fallback to offset
11888				return rnumnonpx.test( computed ) ?
11889					jQuery( elem ).position()[ prop ] + "px" :
11890					computed;
11891			}
11892		}
11893	);
11894});
11895
11896
11897// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
11898jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
11899	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
11900		// margin is only for outerHeight, outerWidth
11901		jQuery.fn[ funcName ] = function( margin, value ) {
11902			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
11903				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
11904
11905			return access( this, function( elem, type, value ) {
11906				var doc;
11907
11908				if ( jQuery.isWindow( elem ) ) {
11909					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
11910					// isn't a whole lot we can do. See pull request at this URL for discussion:
11911					// https://github.com/jquery/jquery/pull/764
11912					return elem.document.documentElement[ "client" + name ];
11913				}
11914
11915				// Get document width or height
11916				if ( elem.nodeType === 9 ) {
11917					doc = elem.documentElement;
11918
11919					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
11920					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
11921					return Math.max(
11922						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
11923						elem.body[ "offset" + name ], doc[ "offset" + name ],
11924						doc[ "client" + name ]
11925					);
11926				}
11927
11928				return value === undefined ?
11929					// Get width or height on the element, requesting but not forcing parseFloat
11930					jQuery.css( elem, type, extra ) :
11931
11932					// Set width or height on the element
11933					jQuery.style( elem, type, value, extra );
11934			}, type, chainable ? margin : undefined, chainable, null );
11935		};
11936	});
11937});
11938
11939
11940// The number of elements contained in the matched element set
11941jQuery.fn.size = function() {
11942	return this.length;
11943};
11944
11945jQuery.fn.andSelf = jQuery.fn.addBack;
11946
11947
11948
11949
11950// Register as a named AMD module, since jQuery can be concatenated with other
11951// files that may use define, but not via a proper concatenation script that
11952// understands anonymous AMD modules. A named AMD is safest and most robust
11953// way to register. Lowercase jquery is used because AMD module names are
11954// derived from file names, and jQuery is normally delivered in a lowercase
11955// file name. Do this after creating the global so that if an AMD module wants
11956// to call noConflict to hide this version of jQuery, it will work.
11957
11958// Note that for maximum portability, libraries that are not jQuery should
11959// declare themselves as anonymous modules, and avoid setting a global if an
11960// AMD loader is present. jQuery is a special case. For more information, see
11961// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
11962
11963if ( typeof define === "function" && define.amd ) {
11964	define( "jquery", [], function() {
11965		return jQuery;
11966	});
11967}
11968
11969
11970
11971
11972var
11973	// Map over jQuery in case of overwrite
11974	_jQuery = window.jQuery,
11975
11976	// Map over the $ in case of overwrite
11977	_$ = window.$;
11978
11979jQuery.noConflict = function( deep ) {
11980	if ( window.$ === jQuery ) {
11981		window.$ = _$;
11982	}
11983
11984	if ( deep && window.jQuery === jQuery ) {
11985		window.jQuery = _jQuery;
11986	}
11987
11988	return jQuery;
11989};
11990
11991// Expose jQuery and $ identifiers, even in
11992// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
11993// and CommonJS for browser emulators (#13566)
11994if ( typeof noGlobal === strundefined ) {
11995	window.jQuery = window.$ = jQuery;
11996}
11997
11998
11999
12000
12001return jQuery;
12002
12003}));
vendor: 5,321 bytes, lines 12004-12194
12004
12005/*!
12006 * Bootstrap v3.3.7 (http://getbootstrap.com)
12007 * Copyright 2011-2018 Twitter, Inc.
12008 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12009 */
12010
12011/*!
12012 * Generated using the Bootstrap Customizer (<none>)
12013 * Config saved to config.json and <none>
12014 */
12015if (typeof jQuery === 'undefined') {
12016  throw new Error('Bootstrap\'s JavaScript requires jQuery')
12017}
12018+function ($) {
12019  'use strict';
12020  var version = $.fn.jquery.split(' ')[0].split('.')
12021  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
12022    throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
12023  }
12024}(jQuery);
12025
12026/* ========================================================================
12027 * Bootstrap: alert.js v3.3.7
12028 * http://getbootstrap.com/javascript/#alerts
12029 * ========================================================================
12030 * Copyright 2011-2016 Twitter, Inc.
12031 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12032 * ======================================================================== */
12033
12034
12035+function ($) {
12036  'use strict';
12037
12038  // ALERT CLASS DEFINITION
12039  // ======================
12040
12041  var dismiss = '[data-dismiss="alert"]'
12042  var Alert   = function (el) {
12043    $(el).on('click', dismiss, this.close)
12044  }
12045
12046  Alert.VERSION = '3.3.7'
12047
12048  Alert.TRANSITION_DURATION = 150
12049
12050  Alert.prototype.close = function (e) {
12051    var $this    = $(this)
12052    var selector = $this.attr('data-target')
12053
12054    if (!selector) {
12055      selector = $this.attr('href')
12056      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
12057    }
12058
12059    var $parent = $(selector === '#' ? [] : selector)
12060
12061    if (e) e.preventDefault()
12062
12063    if (!$parent.length) {
12064      $parent = $this.closest('.alert')
12065    }
12066
12067    $parent.trigger(e = $.Event('close.bs.alert'))
12068
12069    if (e.isDefaultPrevented()) return
12070
12071    $parent.removeClass('in')
12072
12073    function removeElement() {
12074      // detach from parent, fire event then clean up data
12075      $parent.detach().trigger('closed.bs.alert').remove()
12076    }
12077
12078    $.support.transition && $parent.hasClass('fade') ?
12079      $parent
12080        .one('bsTransitionEnd', removeElement)
12081        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
12082      removeElement()
12083  }
12084
12085
12086  // ALERT PLUGIN DEFINITION
12087  // =======================
12088
12089  function Plugin(option) {
12090    return this.each(function () {
12091      var $this = $(this)
12092      var data  = $this.data('bs.alert')
12093
12094      if (!data) $this.data('bs.alert', (data = new Alert(this)))
12095      if (typeof option == 'string') data[option].call($this)
12096    })
12097  }
12098
12099  var old = $.fn.alert
12100
12101  $.fn.alert             = Plugin
12102  $.fn.alert.Constructor = Alert
12103
12104
12105  // ALERT NO CONFLICT
12106  // =================
12107
12108  $.fn.alert.noConflict = function () {
12109    $.fn.alert = old
12110    return this
12111  }
12112
12113
12114  // ALERT DATA-API
12115  // ==============
12116
12117  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
12118
12119}(jQuery);
12120
12121/* ========================================================================
12122 * Bootstrap: button.js v3.3.7
12123 * http://getbootstrap.com/javascript/#buttons
12124 * ========================================================================
12125 * Copyright 2011-2016 Twitter, Inc.
12126 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12127 * ======================================================================== */
12128
12129
12130+function ($) {
12131  'use strict';
12132
12133  // BUTTON PUBLIC CLASS DEFINITION
12134  // ==============================
12135
12136  var Button = function (element, options) {
12137    this.$element  = $(element)
12138    this.options   = $.extend({}, Button.DEFAULTS, options)
12139    this.isLoading = false
12140  }
12141
12142  Button.VERSION  = '3.3.7'
12143
12144  Button.DEFAULTS = {
12145    loadingText: 'loading...'
12146  }
12147
12148  Button.prototype.setState = function (state) {
12149    var d    = 'disabled'
12150    var $el  = this.$element
12151    var val  = $el.is('input') ? 'val' : 'html'
12152    var data = $el.data()
12153
12154    state += 'Text'
12155
12156    if (data.resetText == null) $el.data('resetText', $el[val]())
12157
12158    // push to event loop to allow forms to submit
12159    setTimeout($.proxy(function () {
12160      $el[val](data[state] == null ? this.options[state] : data[state])
12161
12162      if (state == 'loadingText') {
12163        this.isLoading = true
12164        $el.addClass(d).attr(d, d).prop(d, true)
12165      } else if (this.isLoading) {
12166        this.isLoading = false
12167        $el.removeClass(d).removeAttr(d).prop(d, false)
12168      }
12169    }, this), 0)
12170  }
12171
12172  Button.prototype.toggle = function () {
12173    var changed = true
12174    var $parent = this.$element.closest('[data-toggle="buttons"]')
12175
12176    if ($parent.length) {
12177      var $input = this.$element.find('input')
12178      if ($input.prop('type') == 'radio') {
12179        if ($input.prop('checked')) changed = false
12180        $parent.find('.active').removeClass('active')
12181        this.$element.addClass('active')
12182      } else if ($input.prop('type') == 'checkbox') {
12183        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
12184        this.$element.toggleClass('active')
12185      }
12186      $input.prop('checked', this.$element.hasClass('active'))
12187      if (changed) $input.trigger('change')
12188    } else {
12189      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
12190      this.$element.toggleClass('active')
12191    }
12192  }
12193
12194
vendor: 6,031 bytes, lines 12195-12390
12195  // BUTTON PLUGIN DEFINITION
12196  // ========================
12197
12198  function Plugin(option) {
12199    return this.each(function () {
12200      var $this   = $(this)
12201      var data    = $this.data('bs.button')
12202      var options = typeof option == 'object' && option
12203
12204      if (!data) $this.data('bs.button', (data = new Button(this, options)))
12205
12206      if (option == 'toggle') data.toggle()
12207      else if (option) data.setState(option)
12208    })
12209  }
12210
12211  var old = $.fn.button
12212
12213  $.fn.button             = Plugin
12214  $.fn.button.Constructor = Button
12215
12216
12217  // BUTTON NO CONFLICT
12218  // ==================
12219
12220  $.fn.button.noConflict = function () {
12221    $.fn.button = old
12222    return this
12223  }
12224
12225
12226  // BUTTON DATA-API
12227  // ===============
12228
12229  $(document)
12230    .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
12231      var $btn = $(e.target).closest('.btn')
12232      Plugin.call($btn, 'toggle')
12233      if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
12234        // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
12235        e.preventDefault()
12236        // The target component still receive the focus
12237        if ($btn.is('input,button')) $btn.trigger('focus')
12238        else $btn.find('input:visible,button:visible').first().trigger('focus')
12239      }
12240    })
12241    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
12242      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
12243    })
12244
12245}(jQuery);
12246
12247/* ========================================================================
12248 * Bootstrap: carousel.js v3.3.7
12249 * http://getbootstrap.com/javascript/#carousel
12250 * ========================================================================
12251 * Copyright 2011-2016 Twitter, Inc.
12252 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12253 * ======================================================================== */
12254
12255
12256+function ($) {
12257  'use strict';
12258
12259  // CAROUSEL CLASS DEFINITION
12260  // =========================
12261
12262  var Carousel = function (element, options) {
12263    this.$element    = $(element)
12264    this.$indicators = this.$element.find('.carousel-indicators')
12265    this.options     = options
12266    this.paused      = null
12267    this.sliding     = null
12268    this.interval    = null
12269    this.$active     = null
12270    this.$items      = null
12271
12272    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
12273
12274    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
12275      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
12276      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
12277  }
12278
12279  Carousel.VERSION  = '3.3.7'
12280
12281  Carousel.TRANSITION_DURATION = 600
12282
12283  Carousel.DEFAULTS = {
12284    interval: 5000,
12285    pause: 'hover',
12286    wrap: true,
12287    keyboard: true
12288  }
12289
12290  Carousel.prototype.keydown = function (e) {
12291    if (/input|textarea/i.test(e.target.tagName)) return
12292    switch (e.which) {
12293      case 37: this.prev(); break
12294      case 39: this.next(); break
12295      default: return
12296    }
12297
12298    e.preventDefault()
12299  }
12300
12301  Carousel.prototype.cycle = function (e) {
12302    e || (this.paused = false)
12303
12304    this.interval && clearInterval(this.interval)
12305
12306    this.options.interval
12307      && !this.paused
12308      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
12309
12310    return this
12311  }
12312
12313  Carousel.prototype.getItemIndex = function (item) {
12314    this.$items = item.parent().children('.item')
12315    return this.$items.index(item || this.$active)
12316  }
12317
12318  Carousel.prototype.getItemForDirection = function (direction, active) {
12319    var activeIndex = this.getItemIndex(active)
12320    var willWrap = (direction == 'prev' && activeIndex === 0)
12321                || (direction == 'next' && activeIndex == (this.$items.length - 1))
12322    if (willWrap && !this.options.wrap) return active
12323    var delta = direction == 'prev' ? -1 : 1
12324    var itemIndex = (activeIndex + delta) % this.$items.length
12325    return this.$items.eq(itemIndex)
12326  }
12327
12328  Carousel.prototype.to = function (pos) {
12329    var that        = this
12330    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
12331
12332    if (pos > (this.$items.length - 1) || pos < 0) return
12333
12334    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
12335    if (activeIndex == pos) return this.pause().cycle()
12336
12337    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
12338  }
12339
12340  Carousel.prototype.pause = function (e) {
12341    e || (this.paused = true)
12342
12343    if (this.$element.find('.next, .prev').length && $.support.transition) {
12344      this.$element.trigger($.support.transition.end)
12345      this.cycle(true)
12346    }
12347
12348    this.interval = clearInterval(this.interval)
12349
12350    return this
12351  }
12352
12353  Carousel.prototype.next = function () {
12354    if (this.sliding) return
12355    return this.slide('next')
12356  }
12357
12358  Carousel.prototype.prev = function () {
12359    if (this.sliding) return
12360    return this.slide('prev')
12361  }
12362
12363  Carousel.prototype.slide = function (type, next) {
12364    var $active   = this.$element.find('.item.active')
12365    var $next     = next || this.getItemForDirection(type, $active)
12366    var isCycling = this.interval
12367    var direction = type == 'next' ? 'left' : 'right'
12368    var that      = this
12369
12370    if ($next.hasClass('active')) return (this.sliding = false)
12371
12372    var relatedTarget = $next[0]
12373    var slideEvent = $.Event('slide.bs.carousel', {
12374      relatedTarget: relatedTarget,
12375      direction: direction
12376    })
12377    this.$element.trigger(slideEvent)
12378    if (slideEvent.isDefaultPrevented()) return
12379
12380    this.sliding = true
12381
12382    isCycling && this.pause()
12383
12384    if (this.$indicators.length) {
12385      this.$indicators.find('.active').removeClass('active')
12386      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
12387      $nextIndicator && $nextIndicator.addClass('active')
12388    }
12389
12390    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
vendor: 2,590 bytes, lines 12391-12480
12391    if ($.support.transition && this.$element.hasClass('slide')) {
12392      $next.addClass(type)
12393      $next[0].offsetWidth // force reflow
12394      $active.addClass(direction)
12395      $next.addClass(direction)
12396      $active
12397        .one('bsTransitionEnd', function () {
12398          $next.removeClass([type, direction].join(' ')).addClass('active')
12399          $active.removeClass(['active', direction].join(' '))
12400          that.sliding = false
12401          setTimeout(function () {
12402            that.$element.trigger(slidEvent)
12403          }, 0)
12404        })
12405        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
12406    } else {
12407      $active.removeClass('active')
12408      $next.addClass('active')
12409      this.sliding = false
12410      this.$element.trigger(slidEvent)
12411    }
12412
12413    isCycling && this.cycle()
12414
12415    return this
12416  }
12417
12418
12419  // CAROUSEL PLUGIN DEFINITION
12420  // ==========================
12421
12422  function Plugin(option) {
12423    return this.each(function () {
12424      var $this   = $(this)
12425      var data    = $this.data('bs.carousel')
12426      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
12427      var action  = typeof option == 'string' ? option : options.slide
12428
12429      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
12430      if (typeof option == 'number') data.to(option)
12431      else if (action) data[action]()
12432      else if (options.interval) data.pause().cycle()
12433    })
12434  }
12435
12436  var old = $.fn.carousel
12437
12438  $.fn.carousel             = Plugin
12439  $.fn.carousel.Constructor = Carousel
12440
12441
12442  // CAROUSEL NO CONFLICT
12443  // ====================
12444
12445  $.fn.carousel.noConflict = function () {
12446    $.fn.carousel = old
12447    return this
12448  }
12449
12450
12451  // CAROUSEL DATA-API
12452  // =================
12453
12454  var clickHandler = function (e) {
12455    var href
12456    var $this   = $(this)
12457    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
12458    if (!$target.hasClass('carousel')) return
12459    var options = $.extend({}, $target.data(), $this.data())
12460    var slideIndex = $this.attr('data-slide-to')
12461    if (slideIndex) options.interval = false
12462
12463    Plugin.call($target, options)
12464
12465    if (slideIndex) {
12466      $target.data('bs.carousel').to(slideIndex)
12467    }
12468
12469    e.preventDefault()
12470  }
12471
12472  $(document)
12473    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
12474    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
12475
12476  $(window).on('load', function () {
12477    $('[data-ride="carousel"]').each(function () {
12478      var $carousel = $(this)
12479      Plugin.call($carousel, $carousel.data())
12480    }
vendor: 18,562 bytes, lines 12480-13109
12480)
12481  })
12482
12483}(jQuery);
12484
12485/* ========================================================================
12486 * Bootstrap: dropdown.js v3.3.7
12487 * http://getbootstrap.com/javascript/#dropdowns
12488 * ========================================================================
12489 * Copyright 2011-2016 Twitter, Inc.
12490 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12491 * ======================================================================== */
12492
12493
12494+function ($) {
12495  'use strict';
12496
12497  // DROPDOWN CLASS DEFINITION
12498  // =========================
12499
12500  var backdrop = '.dropdown-backdrop'
12501  var toggle   = '[data-toggle="dropdown"]'
12502  var Dropdown = function (element) {
12503    $(element).on('click.bs.dropdown', this.toggle)
12504  }
12505
12506  Dropdown.VERSION = '3.3.7'
12507
12508  function getParent($this) {
12509    var selector = $this.attr('data-target')
12510
12511    if (!selector) {
12512      selector = $this.attr('href')
12513      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
12514    }
12515
12516    var $parent = selector && $(selector)
12517
12518    return $parent && $parent.length ? $parent : $this.parent()
12519  }
12520
12521  function clearMenus(e) {
12522    if (e && e.which === 3) return
12523    $(backdrop).remove()
12524    $(toggle).each(function () {
12525      var $this         = $(this)
12526      var $parent       = getParent($this)
12527      var relatedTarget = { relatedTarget: this }
12528
12529      if (!$parent.hasClass('open')) return
12530
12531      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
12532
12533      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
12534
12535      if (e.isDefaultPrevented()) return
12536
12537      $this.attr('aria-expanded', 'false')
12538      $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
12539    })
12540  }
12541
12542  Dropdown.prototype.toggle = function (e) {
12543    var $this = $(this)
12544
12545    if ($this.is('.disabled, :disabled')) return
12546
12547    var $parent  = getParent($this)
12548    var isActive = $parent.hasClass('open')
12549
12550    clearMenus()
12551
12552    if (!isActive) {
12553      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
12554        // if mobile we use a backdrop because click events don't delegate
12555        $(document.createElement('div'))
12556          .addClass('dropdown-backdrop')
12557          .insertAfter($(this))
12558          .on('click', clearMenus)
12559      }
12560
12561      var relatedTarget = { relatedTarget: this }
12562      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
12563
12564      if (e.isDefaultPrevented()) return
12565
12566      $this
12567        .trigger('focus')
12568        .attr('aria-expanded', 'true')
12569
12570      $parent
12571        .toggleClass('open')
12572        .trigger($.Event('shown.bs.dropdown', relatedTarget))
12573    }
12574
12575    return false
12576  }
12577
12578  Dropdown.prototype.keydown = function (e) {
12579    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
12580
12581    var $this = $(this)
12582
12583    e.preventDefault()
12584    e.stopPropagation()
12585
12586    if ($this.is('.disabled, :disabled')) return
12587
12588    var $parent  = getParent($this)
12589    var isActive = $parent.hasClass('open')
12590
12591    if (!isActive && e.which != 27 || isActive && e.which == 27) {
12592      if (e.which == 27) $parent.find(toggle).trigger('focus')
12593      return $this.trigger('click')
12594    }
12595
12596    var desc = ' li:not(.disabled):visible a'
12597    var $items = $parent.find('.dropdown-menu' + desc)
12598
12599    if (!$items.length) return
12600
12601    var index = $items.index(e.target)
12602
12603    if (e.which == 38 && index > 0)                 index--         // up
12604    if (e.which == 40 && index < $items.length - 1) index++         // down
12605    if (!~index)                                    index = 0
12606
12607    $items.eq(index).trigger('focus')
12608  }
12609
12610
12611  // DROPDOWN PLUGIN DEFINITION
12612  // ==========================
12613
12614  function Plugin(option) {
12615    return this.each(function () {
12616      var $this = $(this)
12617      var data  = $this.data('bs.dropdown')
12618
12619      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
12620      if (typeof option == 'string') data[option].call($this)
12621    })
12622  }
12623
12624  var old = $.fn.dropdown
12625
12626  $.fn.dropdown             = Plugin
12627  $.fn.dropdown.Constructor = Dropdown
12628
12629
12630  // DROPDOWN NO CONFLICT
12631  // ====================
12632
12633  $.fn.dropdown.noConflict = function () {
12634    $.fn.dropdown = old
12635    return this
12636  }
12637
12638
12639  // APPLY TO STANDARD DROPDOWN ELEMENTS
12640  // ===================================
12641
12642  $(document)
12643    .on('click.bs.dropdown.data-api', clearMenus)
12644    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
12645    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
12646    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
12647    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
12648
12649}(jQuery);
12650
12651/* ========================================================================
12652 * Bootstrap: modal.js v3.3.7
12653 * http://getbootstrap.com/javascript/#modals
12654 * ========================================================================
12655 * Copyright 2011-2016 Twitter, Inc.
12656 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12657 * ======================================================================== */
12658
12659
12660+function ($) {
12661  'use strict';
12662
12663  // MODAL CLASS DEFINITION
12664  // ======================
12665
12666  var Modal = function (element, options) {
12667    this.options             = options
12668    this.$body               = $(document.body)
12669    this.$element            = $(element)
12670    this.$dialog             = this.$element.find('.modal-dialog')
12671    this.$backdrop           = null
12672    this.isShown             = null
12673    this.originalBodyPad     = null
12674    this.scrollbarWidth      = 0
12675    this.ignoreBackdropClick = false
12676
12677    if (this.options.remote) {
12678      this.$element
12679        .find('.modal-content')
12680        .load(this.options.remote, $.proxy(function () {
12681          this.$element.trigger('loaded.bs.modal')
12682        }, this))
12683    }
12684  }
12685
12686  Modal.VERSION  = '3.3.7'
12687
12688  Modal.TRANSITION_DURATION = 300
12689  Modal.BACKDROP_TRANSITION_DURATION = 150
12690
12691  Modal.DEFAULTS = {
12692    backdrop: true,
12693    keyboard: true,
12694    show: true
12695  }
12696
12697  Modal.prototype.toggle = function (_relatedTarget) {
12698    return this.isShown ? this.hide() : this.show(_relatedTarget)
12699  }
12700
12701  Modal.prototype.show = function (_relatedTarget) {
12702    var that = this
12703    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
12704
12705    this.$element.trigger(e)
12706
12707    if (this.isShown || e.isDefaultPrevented()) return
12708
12709    this.isShown = true
12710
12711    this.checkScrollbar()
12712    this.setScrollbar()
12713    this.$body.addClass('modal-open')
12714
12715    this.escape()
12716    this.resize()
12717
12718    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
12719
12720    this.$dialog.on('mousedown.dismiss.bs.modal', function () {
12721      that.$element.one('mouseup.dismiss.bs.modal', function (e) {
12722        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
12723      })
12724    })
12725
12726    this.backdrop(function () {
12727      var transition = $.support.transition && that.$element.hasClass('fade')
12728
12729      if (!that.$element.parent().length) {
12730        that.$element.appendTo(that.$body) // don't move modals dom position
12731      }
12732
12733      that.$element
12734        .show()
12735        .scrollTop(0)
12736
12737      that.adjustDialog()
12738
12739      if (transition) {
12740        that.$element[0].offsetWidth // force reflow
12741      }
12742
12743      that.$element.addClass('in')
12744
12745      that.enforceFocus()
12746
12747      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
12748
12749      transition ?
12750        that.$dialog // wait for modal to slide in
12751          .one('bsTransitionEnd', function () {
12752            that.$element.trigger('focus').trigger(e)
12753          })
12754          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
12755        that.$element.trigger('focus').trigger(e)
12756    })
12757  }
12758
12759  Modal.prototype.hide = function (e) {
12760    if (e) e.preventDefault()
12761
12762    e = $.Event('hide.bs.modal')
12763
12764    this.$element.trigger(e)
12765
12766    if (!this.isShown || e.isDefaultPrevented()) return
12767
12768    this.isShown = false
12769
12770    this.escape()
12771    this.resize()
12772
12773    $(document).off('focusin.bs.modal')
12774
12775    this.$element
12776      .removeClass('in')
12777      .off('click.dismiss.bs.modal')
12778      .off('mouseup.dismiss.bs.modal')
12779
12780    this.$dialog.off('mousedown.dismiss.bs.modal')
12781
12782    $.support.transition && this.$element.hasClass('fade') ?
12783      this.$element
12784        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
12785        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
12786      this.hideModal()
12787  }
12788
12789  Modal.prototype.enforceFocus = function () {
12790    $(document)
12791      .off('focusin.bs.modal') // guard against infinite focus loop
12792      .on('focusin.bs.modal', $.proxy(function (e) {
12793        if (document !== e.target &&
12794            this.$element[0] !== e.target &&
12795            !this.$element.has(e.target).length) {
12796          this.$element.trigger('focus')
12797        }
12798      }, this))
12799  }
12800
12801  Modal.prototype.escape = function () {
12802    if (this.isShown && this.options.keyboard) {
12803      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
12804        e.which == 27 && this.hide()
12805      }, this))
12806    } else if (!this.isShown) {
12807      this.$element.off('keydown.dismiss.bs.modal')
12808    }
12809  }
12810
12811  Modal.prototype.resize = function () {
12812    if (this.isShown) {
12813      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
12814    } else {
12815      $(window).off('resize.bs.modal')
12816    }
12817  }
12818
12819  Modal.prototype.hideModal = function () {
12820    var that = this
12821    this.$element.hide()
12822    this.backdrop(function () {
12823      that.$body.removeClass('modal-open')
12824      that.resetAdjustments()
12825      that.resetScrollbar()
12826      that.$element.trigger('hidden.bs.modal')
12827    })
12828  }
12829
12830  Modal.prototype.removeBackdrop = function () {
12831    this.$backdrop && this.$backdrop.remove()
12832    this.$backdrop = null
12833  }
12834
12835  Modal.prototype.backdrop = function (callback) {
12836    var that = this
12837    var animate = this.$element.hasClass('fade') ? 'fade' : ''
12838
12839    if (this.isShown && this.options.backdrop) {
12840      var doAnimate = $.support.transition && animate
12841
12842      this.$backdrop = $(document.createElement('div'))
12843        .addClass('modal-backdrop ' + animate)
12844        .appendTo(this.$body)
12845
12846      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
12847        if (this.ignoreBackdropClick) {
12848          this.ignoreBackdropClick = false
12849          return
12850        }
12851        if (e.target !== e.currentTarget) return
12852        this.options.backdrop == 'static'
12853          ? this.$element[0].focus()
12854          : this.hide()
12855      }, this))
12856
12857      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
12858
12859      this.$backdrop.addClass('in')
12860
12861      if (!callback) return
12862
12863      doAnimate ?
12864        this.$backdrop
12865          .one('bsTransitionEnd', callback)
12866          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
12867        callback()
12868
12869    } else if (!this.isShown && this.$backdrop) {
12870      this.$backdrop.removeClass('in')
12871
12872      var callbackRemove = function () {
12873        that.removeBackdrop()
12874        callback && callback()
12875      }
12876      $.support.transition && this.$element.hasClass('fade') ?
12877        this.$backdrop
12878          .one('bsTransitionEnd', callbackRemove)
12879          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
12880        callbackRemove()
12881
12882    } else if (callback) {
12883      callback()
12884    }
12885  }
12886
12887  // these following methods are used to handle overflowing modals
12888
12889  Modal.prototype.handleUpdate = function () {
12890    this.adjustDialog()
12891  }
12892
12893  Modal.prototype.adjustDialog = function () {
12894    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
12895
12896    this.$element.css({
12897      paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
12898      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
12899    })
12900  }
12901
12902  Modal.prototype.resetAdjustments = function () {
12903    this.$element.css({
12904      paddingLeft: '',
12905      paddingRight: ''
12906    })
12907  }
12908
12909  Modal.prototype.checkScrollbar = function () {
12910    var fullWindowWidth = window.innerWidth
12911    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
12912      var documentElementRect = document.documentElement.getBoundingClientRect()
12913      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
12914    }
12915    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
12916    this.scrollbarWidth = this.measureScrollbar()
12917  }
12918
12919  Modal.prototype.setScrollbar = function () {
12920    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
12921    this.originalBodyPad = document.body.style.paddingRight || ''
12922    if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
12923  }
12924
12925  Modal.prototype.resetScrollbar = function () {
12926    this.$body.css('padding-right', this.originalBodyPad)
12927  }
12928
12929  Modal.prototype.measureScrollbar = function () { // thx walsh
12930    var scrollDiv = document.createElement('div')
12931    scrollDiv.className = 'modal-scrollbar-measure'
12932    this.$body.append(scrollDiv)
12933    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
12934    this.$body[0].removeChild(scrollDiv)
12935    return scrollbarWidth
12936  }
12937
12938
12939  // MODAL PLUGIN DEFINITION
12940  // =======================
12941
12942  function Plugin(option, _relatedTarget) {
12943    return this.each(function () {
12944      var $this   = $(this)
12945      var data    = $this.data('bs.modal')
12946      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
12947
12948      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
12949      if (typeof option == 'string') data[option](_relatedTarget)
12950      else if (options.show) data.show(_relatedTarget)
12951    })
12952  }
12953
12954  var old = $.fn.modal
12955
12956  $.fn.modal             = Plugin
12957  $.fn.modal.Constructor = Modal
12958
12959
12960  // MODAL NO CONFLICT
12961  // =================
12962
12963  $.fn.modal.noConflict = function () {
12964    $.fn.modal = old
12965    return this
12966  }
12967
12968
12969  // MODAL DATA-API
12970  // ==============
12971
12972  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
12973    var $this   = $(this)
12974    var href    = $this.attr('href')
12975    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
12976    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
12977
12978    if ($this.is('a')) e.preventDefault()
12979
12980    $target.one('show.bs.modal', function (showEvent) {
12981      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
12982      $target.one('hidden.bs.modal', function () {
12983        $this.is(':visible') && $this.trigger('focus')
12984      })
12985    })
12986    Plugin.call($target, option, this)
12987  })
12988
12989}(jQuery);
12990
12991/* ========================================================================
12992 * Bootstrap: tooltip.js v3.3.7
12993 * http://getbootstrap.com/javascript/#tooltip
12994 * Inspired by the original jQuery.tipsy by Jason Frame
12995 * ========================================================================
12996 * Copyright 2011-2016 Twitter, Inc.
12997 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12998 * ======================================================================== */
12999
13000
13001+function ($) {
13002  'use strict';
13003
13004  // TOOLTIP PUBLIC CLASS DEFINITION
13005  // ===============================
13006
13007  var Tooltip = function (element, options) {
13008    this.type       = null
13009    this.options    = null
13010    this.enabled    = null
13011    this.timeout    = null
13012    this.hoverState = null
13013    this.$element   = null
13014    this.inState    = null
13015
13016    this.init('tooltip', element, options)
13017  }
13018
13019  Tooltip.VERSION  = '3.3.7'
13020
13021  Tooltip.TRANSITION_DURATION = 150
13022
13023  Tooltip.DEFAULTS = {
13024    animation: true,
13025    placement: 'top',
13026    selector: false,
13027    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
13028    trigger: 'hover focus',
13029    title: '',
13030    delay: 0,
13031    html: false,
13032    container: false,
13033    viewport: {
13034      selector: 'body',
13035      padding: 0
13036    }
13037  }
13038
13039  Tooltip.prototype.init = function (type, element, options) {
13040    this.enabled   = true
13041    this.type      = type
13042    this.$element  = $(element)
13043    this.options   = this.getOptions(options)
13044    this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
13045    this.inState   = { click: false, hover: false, focus: false }
13046
13047    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
13048      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
13049    }
13050
13051    var triggers = this.options.trigger.split(' ')
13052
13053    for (var i = triggers.length; i--;) {
13054      var trigger = triggers[i]
13055
13056      if (trigger == 'click') {
13057        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
13058      } else if (trigger != 'manual') {
13059        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
13060        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
13061
13062        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
13063        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
13064      }
13065    }
13066
13067    this.options.selector ?
13068      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
13069      this.fixTitle()
13070  }
13071
13072  Tooltip.prototype.getDefaults = function () {
13073    return Tooltip.DEFAULTS
13074  }
13075
13076  Tooltip.prototype.getOptions = function (options) {
13077    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
13078
13079    if (options.delay && typeof options.delay == 'number') {
13080      options.delay = {
13081        show: options.delay,
13082        hide: options.delay
13083      }
13084    }
13085
13086    return options
13087  }
13088
13089  Tooltip.prototype.getDelegateOptions = function () {
13090    var options  = {}
13091    var defaults = this.getDefaults()
13092
13093    this._options && $.each(this._options, function (key, value) {
13094      if (defaults[key] != value) options[key] = value
13095    })
13096
13097    return options
13098  }
13099
13100  Tooltip.prototype.enter = function (obj) {
13101    var self = obj instanceof this.constructor ?
13102      obj : $(obj.currentTarget).data('bs.' + this.type)
13103
13104    if (!self) {
13105      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
13106      $(obj.currentTarget).data('bs.' + this.type, self)
13107    }
13108
13109    if (obj instanceof $.Event) {
vendor: 16,074 bytes, lines 13110-13620
13110      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
13111    }
13112
13113    if (self.tip().hasClass('in') || self.hoverState == 'in') {
13114      self.hoverState = 'in'
13115      return
13116    }
13117
13118    clearTimeout(self.timeout)
13119
13120    self.hoverState = 'in'
13121
13122    if (!self.options.delay || !self.options.delay.show) return self.show()
13123
13124    self.timeout = setTimeout(function () {
13125      if (self.hoverState == 'in') self.show()
13126    }, self.options.delay.show)
13127  }
13128
13129  Tooltip.prototype.isInStateTrue = function () {
13130    for (var key in this.inState) {
13131      if (this.inState[key]) return true
13132    }
13133
13134    return false
13135  }
13136
13137  Tooltip.prototype.leave = function (obj) {
13138    var self = obj instanceof this.constructor ?
13139      obj : $(obj.currentTarget).data('bs.' + this.type)
13140
13141    if (!self) {
13142      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
13143      $(obj.currentTarget).data('bs.' + this.type, self)
13144    }
13145
13146    if (obj instanceof $.Event) {
13147      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
13148    }
13149
13150    if (self.isInStateTrue()) return
13151
13152    clearTimeout(self.timeout)
13153
13154    self.hoverState = 'out'
13155
13156    if (!self.options.delay || !self.options.delay.hide) return self.hide()
13157
13158    self.timeout = setTimeout(function () {
13159      if (self.hoverState == 'out') self.hide()
13160    }, self.options.delay.hide)
13161  }
13162
13163  Tooltip.prototype.show = function () {
13164    var e = $.Event('show.bs.' + this.type)
13165
13166    if (this.hasContent() && this.enabled) {
13167      this.$element.trigger(e)
13168
13169      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
13170      if (e.isDefaultPrevented() || !inDom) return
13171      var that = this
13172
13173      var $tip = this.tip()
13174
13175      var tipId = this.getUID(this.type)
13176
13177      this.setContent()
13178      $tip.attr('id', tipId)
13179      this.$element.attr('aria-describedby', tipId)
13180
13181      if (this.options.animation) $tip.addClass('fade')
13182
13183      var placement = typeof this.options.placement == 'function' ?
13184        this.options.placement.call(this, $tip[0], this.$element[0]) :
13185        this.options.placement
13186
13187      var autoToken = /\s?auto?\s?/i
13188      var autoPlace = autoToken.test(placement)
13189      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
13190
13191      $tip
13192        .detach()
13193        .css({ top: 0, left: 0, display: 'block' })
13194        .addClass(placement)
13195        .data('bs.' + this.type, this)
13196
13197      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
13198      this.$element.trigger('inserted.bs.' + this.type)
13199
13200      var pos          = this.getPosition()
13201      var actualWidth  = $tip[0].offsetWidth
13202      var actualHeight = $tip[0].offsetHeight
13203
13204      if (autoPlace) {
13205        var orgPlacement = placement
13206        var viewportDim = this.getPosition(this.$viewport)
13207
13208        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :
13209                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :
13210                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :
13211                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :
13212                    placement
13213
13214        $tip
13215          .removeClass(orgPlacement)
13216          .addClass(placement)
13217      }
13218
13219      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
13220
13221      this.applyPlacement(calculatedOffset, placement)
13222
13223      var complete = function () {
13224        var prevHoverState = that.hoverState
13225        that.$element.trigger('shown.bs.' + that.type)
13226        that.hoverState = null
13227
13228        if (prevHoverState == 'out') that.leave(that)
13229      }
13230
13231      $.support.transition && this.$tip.hasClass('fade') ?
13232        $tip
13233          .one('bsTransitionEnd', complete)
13234          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
13235        complete()
13236    }
13237  }
13238
13239  Tooltip.prototype.applyPlacement = function (offset, placement) {
13240    var $tip   = this.tip()
13241    var width  = $tip[0].offsetWidth
13242    var height = $tip[0].offsetHeight
13243
13244    // manually read margins because getBoundingClientRect includes difference
13245    var marginTop = parseInt($tip.css('margin-top'), 10)
13246    var marginLeft = parseInt($tip.css('margin-left'), 10)
13247
13248    // we must check for NaN for ie 8/9
13249    if (isNaN(marginTop))  marginTop  = 0
13250    if (isNaN(marginLeft)) marginLeft = 0
13251
13252    offset.top  += marginTop
13253    offset.left += marginLeft
13254
13255    // $.fn.offset doesn't round pixel values
13256    // so we use setOffset directly with our own function B-0
13257    $.offset.setOffset($tip[0], $.extend({
13258      using: function (props) {
13259        $tip.css({
13260          top: Math.round(props.top),
13261          left: Math.round(props.left)
13262        })
13263      }
13264    }, offset), 0)
13265
13266    $tip.addClass('in')
13267
13268    // check to see if placing tip in new offset caused the tip to resize itself
13269    var actualWidth  = $tip[0].offsetWidth
13270    var actualHeight = $tip[0].offsetHeight
13271
13272    if (placement == 'top' && actualHeight != height) {
13273      offset.top = offset.top + height - actualHeight
13274    }
13275
13276    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
13277
13278    if (delta.left) offset.left += delta.left
13279    else offset.top += delta.top
13280
13281    var isVertical          = /top|bottom/.test(placement)
13282    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
13283    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
13284
13285    $tip.offset(offset)
13286    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
13287  }
13288
13289  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
13290    this.arrow()
13291      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
13292      .css(isVertical ? 'top' : 'left', '')
13293  }
13294
13295  Tooltip.prototype.setContent = function () {
13296    var $tip  = this.tip()
13297    var title = this.getTitle()
13298
13299    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
13300    $tip.removeClass('fade in top bottom left right')
13301  }
13302
13303  Tooltip.prototype.hide = function (callback) {
13304    var that = this
13305    var $tip = $(this.$tip)
13306    var e    = $.Event('hide.bs.' + this.type)
13307
13308    function complete() {
13309      if (that.hoverState != 'in') $tip.detach()
13310      if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
13311        that.$element
13312          .removeAttr('aria-describedby')
13313          .trigger('hidden.bs.' + that.type)
13314      }
13315      callback && callback()
13316    }
13317
13318    this.$element.trigger(e)
13319
13320    if (e.isDefaultPrevented()) return
13321
13322    $tip.removeClass('in')
13323
13324    $.support.transition && $tip.hasClass('fade') ?
13325      $tip
13326        .one('bsTransitionEnd', complete)
13327        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
13328      complete()
13329
13330    this.hoverState = null
13331
13332    return this
13333  }
13334
13335  Tooltip.prototype.fixTitle = function () {
13336    var $e = this.$element
13337    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
13338      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
13339    }
13340  }
13341
13342  Tooltip.prototype.hasContent = function () {
13343    return this.getTitle()
13344  }
13345
13346  Tooltip.prototype.getPosition = function ($element) {
13347    $element   = $element || this.$element
13348
13349    var el     = $element[0]
13350    var isBody = el.tagName == 'BODY'
13351
13352    var elRect    = el.getBoundingClientRect()
13353    if (elRect.width == null) {
13354      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
13355      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
13356    }
13357    var isSvg = window.SVGElement && el instanceof window.SVGElement
13358    // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
13359    // See https://github.com/twbs/bootstrap/issues/20280
13360    var elOffset  = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
13361    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
13362    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
13363
13364    return $.extend({}, elRect, scroll, outerDims, elOffset)
13365  }
13366
13367  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
13368    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
13369           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
13370           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
13371        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
13372
13373  }
13374
13375  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
13376    var delta = { top: 0, left: 0 }
13377    if (!this.$viewport) return delta
13378
13379    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
13380    var viewportDimensions = this.getPosition(this.$viewport)
13381
13382    if (/right|left/.test(placement)) {
13383      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
13384      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
13385      if (topEdgeOffset < viewportDimensions.top) { // top overflow
13386        delta.top = viewportDimensions.top - topEdgeOffset
13387      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
13388        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
13389      }
13390    } else {
13391      var leftEdgeOffset  = pos.left - viewportPadding
13392      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
13393      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
13394        delta.left = viewportDimensions.left - leftEdgeOffset
13395      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
13396        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
13397      }
13398    }
13399
13400    return delta
13401  }
13402
13403  Tooltip.prototype.getTitle = function () {
13404    var title
13405    var $e = this.$element
13406    var o  = this.options
13407
13408    title = $e.attr('data-original-title')
13409      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
13410
13411    return title
13412  }
13413
13414  Tooltip.prototype.getUID = function (prefix) {
13415    do prefix += ~~(Math.random() * 1000000)
13416    while (document.getElementById(prefix))
13417    return prefix
13418  }
13419
13420  Tooltip.prototype.tip = function () {
13421    if (!this.$tip) {
13422      this.$tip = $(this.options.template)
13423      if (this.$tip.length != 1) {
13424        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
13425      }
13426    }
13427    return this.$tip
13428  }
13429
13430  Tooltip.prototype.arrow = function () {
13431    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
13432  }
13433
13434  Tooltip.prototype.enable = function () {
13435    this.enabled = true
13436  }
13437
13438  Tooltip.prototype.disable = function () {
13439    this.enabled = false
13440  }
13441
13442  Tooltip.prototype.toggleEnabled = function () {
13443    this.enabled = !this.enabled
13444  }
13445
13446  Tooltip.prototype.toggle = function (e) {
13447    var self = this
13448    if (e) {
13449      self = $(e.currentTarget).data('bs.' + this.type)
13450      if (!self) {
13451        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
13452        $(e.currentTarget).data('bs.' + this.type, self)
13453      }
13454    }
13455
13456    if (e) {
13457      self.inState.click = !self.inState.click
13458      if (self.isInStateTrue()) self.enter(self)
13459      else self.leave(self)
13460    } else {
13461      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
13462    }
13463  }
13464
13465  Tooltip.prototype.destroy = function () {
13466    var that = this
13467    clearTimeout(this.timeout)
13468    this.hide(function () {
13469      that.$element.off('.' + that.type).removeData('bs.' + that.type)
13470      if (that.$tip) {
13471        that.$tip.detach()
13472      }
13473      that.$tip = null
13474      that.$arrow = null
13475      that.$viewport = null
13476      that.$element = null
13477    })
13478  }
13479
13480
13481  // TOOLTIP PLUGIN DEFINITION
13482  // =========================
13483
13484  function Plugin(option) {
13485    return this.each(function () {
13486      var $this   = $(this)
13487      var data    = $this.data('bs.tooltip')
13488      var options = typeof option == 'object' && option
13489
13490      if (!data && /destroy|hide/.test(option)) return
13491      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
13492      if (typeof option == 'string') data[option]()
13493    })
13494  }
13495
13496  var old = $.fn.tooltip
13497
13498  $.fn.tooltip             = Plugin
13499  $.fn.tooltip.Constructor = Tooltip
13500
13501
13502  // TOOLTIP NO CONFLICT
13503  // ===================
13504
13505  $.fn.tooltip.noConflict = function () {
13506    $.fn.tooltip = old
13507    return this
13508  }
13509
13510}(jQuery);
13511
13512/* ========================================================================
13513 * Bootstrap: popover.js v3.3.7
13514 * http://getbootstrap.com/javascript/#popovers
13515 * ========================================================================
13516 * Copyright 2011-2016 Twitter, Inc.
13517 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13518 * ======================================================================== */
13519
13520
13521+function ($) {
13522  'use strict';
13523
13524  // POPOVER PUBLIC CLASS DEFINITION
13525  // ===============================
13526
13527  var Popover = function (element, options) {
13528    this.init('popover', element, options)
13529  }
13530
13531  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
13532
13533  Popover.VERSION  = '3.3.7'
13534
13535  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
13536    placement: 'right',
13537    trigger: 'click',
13538    content: '',
13539    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
13540  })
13541
13542
13543  // NOTE: POPOVER EXTENDS tooltip.js
13544  // ================================
13545
13546  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
13547
13548  Popover.prototype.constructor = Popover
13549
13550  Popover.prototype.getDefaults = function () {
13551    return Popover.DEFAULTS
13552  }
13553
13554  Popover.prototype.setContent = function () {
13555    var $tip    = this.tip()
13556    var title   = this.getTitle()
13557    var content = this.getContent()
13558
13559    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
13560    $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
13561      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
13562    ](content)
13563
13564    $tip.removeClass('fade top bottom left right in')
13565
13566    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
13567    // this manually by checking the contents.
13568    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
13569  }
13570
13571  Popover.prototype.hasContent = function () {
13572    return this.getTitle() || this.getContent()
13573  }
13574
13575  Popover.prototype.getContent = function () {
13576    var $e = this.$element
13577    var o  = this.options
13578
13579    return $e.attr('data-content')
13580      || (typeof o.content == 'function' ?
13581            o.content.call($e[0]) :
13582            o.content)
13583  }
13584
13585  Popover.prototype.arrow = function () {
13586    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
13587  }
13588
13589
13590  // POPOVER PLUGIN DEFINITION
13591  // =========================
13592
13593  function Plugin(option) {
13594    return this.each(function () {
13595      var $this   = $(this)
13596      var data    = $this.data('bs.popover')
13597      var options = typeof option == 'object' && option
13598
13599      if (!data && /destroy|hide/.test(option)) return
13600      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
13601      if (typeof option == 'string') data[option]()
13602    })
13603  }
13604
13605  var old = $.fn.popover
13606
13607  $.fn.popover             = Plugin
13608  $.fn.popover.Constructor = Popover
13609
13610
13611  // POPOVER NO CONFLICT
13612  // ===================
13613
13614  $.fn.popover.noConflict = function () {
13615    $.fn.popover = old
13616    return this
13617  }
13618
13619}(jQuery);
13620
vendor: 24,275 bytes, lines 13621-14492
13621/* ========================================================================
13622 * Bootstrap: tab.js v3.3.7
13623 * http://getbootstrap.com/javascript/#tabs
13624 * ========================================================================
13625 * Copyright 2011-2016 Twitter, Inc.
13626 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13627 * ======================================================================== */
13628
13629
13630+function ($) {
13631  'use strict';
13632
13633  // TAB CLASS DEFINITION
13634  // ====================
13635
13636  var Tab = function (element) {
13637    // jscs:disable requireDollarBeforejQueryAssignment
13638    this.element = $(element)
13639    // jscs:enable requireDollarBeforejQueryAssignment
13640  }
13641
13642  Tab.VERSION = '3.3.7'
13643
13644  Tab.TRANSITION_DURATION = 150
13645
13646  Tab.prototype.show = function () {
13647    var $this    = this.element
13648    var $ul      = $this.closest('ul:not(.dropdown-menu)')
13649    var selector = $this.data('target')
13650
13651    if (!selector) {
13652      selector = $this.attr('href')
13653      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
13654    }
13655
13656    if ($this.parent('li').hasClass('active')) return
13657
13658    var $previous = $ul.find('.active:last a')
13659    var hideEvent = $.Event('hide.bs.tab', {
13660      relatedTarget: $this[0]
13661    })
13662    var showEvent = $.Event('show.bs.tab', {
13663      relatedTarget: $previous[0]
13664    })
13665
13666    $previous.trigger(hideEvent)
13667    $this.trigger(showEvent)
13668
13669    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
13670
13671    var $target = $(selector)
13672
13673    this.activate($this.closest('li'), $ul)
13674    this.activate($target, $target.parent(), function () {
13675      $previous.trigger({
13676        type: 'hidden.bs.tab',
13677        relatedTarget: $this[0]
13678      })
13679      $this.trigger({
13680        type: 'shown.bs.tab',
13681        relatedTarget: $previous[0]
13682      })
13683    })
13684  }
13685
13686  Tab.prototype.activate = function (element, container, callback) {
13687    var $active    = container.find('> .active')
13688    var transition = callback
13689      && $.support.transition
13690      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
13691
13692    function next() {
13693      $active
13694        .removeClass('active')
13695        .find('> .dropdown-menu > .active')
13696          .removeClass('active')
13697        .end()
13698        .find('[data-toggle="tab"]')
13699          .attr('aria-expanded', false)
13700
13701      element
13702        .addClass('active')
13703        .find('[data-toggle="tab"]')
13704          .attr('aria-expanded', true)
13705
13706      if (transition) {
13707        element[0].offsetWidth // reflow for transition
13708        element.addClass('in')
13709      } else {
13710        element.removeClass('fade')
13711      }
13712
13713      if (element.parent('.dropdown-menu').length) {
13714        element
13715          .closest('li.dropdown')
13716            .addClass('active')
13717          .end()
13718          .find('[data-toggle="tab"]')
13719            .attr('aria-expanded', true)
13720      }
13721
13722      callback && callback()
13723    }
13724
13725    $active.length && transition ?
13726      $active
13727        .one('bsTransitionEnd', next)
13728        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
13729      next()
13730
13731    $active.removeClass('in')
13732  }
13733
13734
13735  // TAB PLUGIN DEFINITION
13736  // =====================
13737
13738  function Plugin(option) {
13739    return this.each(function () {
13740      var $this = $(this)
13741      var data  = $this.data('bs.tab')
13742
13743      if (!data) $this.data('bs.tab', (data = new Tab(this)))
13744      if (typeof option == 'string') data[option]()
13745    })
13746  }
13747
13748  var old = $.fn.tab
13749
13750  $.fn.tab             = Plugin
13751  $.fn.tab.Constructor = Tab
13752
13753
13754  // TAB NO CONFLICT
13755  // ===============
13756
13757  $.fn.tab.noConflict = function () {
13758    $.fn.tab = old
13759    return this
13760  }
13761
13762
13763  // TAB DATA-API
13764  // ============
13765
13766  var clickHandler = function (e) {
13767    e.preventDefault()
13768    Plugin.call($(this), 'show')
13769  }
13770
13771  $(document)
13772    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
13773    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
13774
13775}(jQuery);
13776
13777/* ========================================================================
13778 * Bootstrap: affix.js v3.3.7
13779 * http://getbootstrap.com/javascript/#affix
13780 * ========================================================================
13781 * Copyright 2011-2016 Twitter, Inc.
13782 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13783 * ======================================================================== */
13784
13785
13786+function ($) {
13787  'use strict';
13788
13789  // AFFIX CLASS DEFINITION
13790  // ======================
13791
13792  var Affix = function (element, options) {
13793    this.options = $.extend({}, Affix.DEFAULTS, options)
13794
13795    this.$target = $(this.options.target)
13796      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
13797      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
13798
13799    this.$element     = $(element)
13800    this.affixed      = null
13801    this.unpin        = null
13802    this.pinnedOffset = null
13803
13804    this.checkPosition()
13805  }
13806
13807  Affix.VERSION  = '3.3.7'
13808
13809  Affix.RESET    = 'affix affix-top affix-bottom'
13810
13811  Affix.DEFAULTS = {
13812    offset: 0,
13813    target: window
13814  }
13815
13816  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
13817    var scrollTop    = this.$target.scrollTop()
13818    var position     = this.$element.offset()
13819    var targetHeight = this.$target.height()
13820
13821    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
13822
13823    if (this.affixed == 'bottom') {
13824      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
13825      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
13826    }
13827
13828    var initializing   = this.affixed == null
13829    var colliderTop    = initializing ? scrollTop : position.top
13830    var colliderHeight = initializing ? targetHeight : height
13831
13832    if (offsetTop != null && scrollTop <= offsetTop) return 'top'
13833    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
13834
13835    return false
13836  }
13837
13838  Affix.prototype.getPinnedOffset = function () {
13839    if (this.pinnedOffset) return this.pinnedOffset
13840    this.$element.removeClass(Affix.RESET).addClass('affix')
13841    var scrollTop = this.$target.scrollTop()
13842    var position  = this.$element.offset()
13843    return (this.pinnedOffset = position.top - scrollTop)
13844  }
13845
13846  Affix.prototype.checkPositionWithEventLoop = function () {
13847    setTimeout($.proxy(this.checkPosition, this), 1)
13848  }
13849
13850  Affix.prototype.checkPosition = function () {
13851    if (!this.$element.is(':visible')) return
13852
13853    var height       = this.$element.height()
13854    var offset       = this.options.offset
13855    var offsetTop    = offset.top
13856    var offsetBottom = offset.bottom
13857    var scrollHeight = Math.max($(document).height(), $(document.body).height())
13858
13859    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
13860    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
13861    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
13862
13863    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
13864
13865    if (this.affixed != affix) {
13866      if (this.unpin != null) this.$element.css('top', '')
13867
13868      var affixType = 'affix' + (affix ? '-' + affix : '')
13869      var e         = $.Event(affixType + '.bs.affix')
13870
13871      this.$element.trigger(e)
13872
13873      if (e.isDefaultPrevented()) return
13874
13875      this.affixed = affix
13876      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
13877
13878      this.$element
13879        .removeClass(Affix.RESET)
13880        .addClass(affixType)
13881        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
13882    }
13883
13884    if (affix == 'bottom') {
13885      this.$element.offset({
13886        top: scrollHeight - height - offsetBottom
13887      })
13888    }
13889  }
13890
13891
13892  // AFFIX PLUGIN DEFINITION
13893  // =======================
13894
13895  function Plugin(option) {
13896    return this.each(function () {
13897      var $this   = $(this)
13898      var data    = $this.data('bs.affix')
13899      var options = typeof option == 'object' && option
13900
13901      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
13902      if (typeof option == 'string') data[option]()
13903    })
13904  }
13905
13906  var old = $.fn.affix
13907
13908  $.fn.affix             = Plugin
13909  $.fn.affix.Constructor = Affix
13910
13911
13912  // AFFIX NO CONFLICT
13913  // =================
13914
13915  $.fn.affix.noConflict = function () {
13916    $.fn.affix = old
13917    return this
13918  }
13919
13920
13921  // AFFIX DATA-API
13922  // ==============
13923
13924  $(window).on('load', function () {
13925    $('[data-spy="affix"]').each(function () {
13926      var $spy = $(this)
13927      var data = $spy.data()
13928
13929      data.offset = data.offset || {}
13930
13931      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
13932      if (data.offsetTop    != null) data.offset.top    = data.offsetTop
13933
13934      Plugin.call($spy, data)
13935    })
13936  })
13937
13938}(jQuery);
13939
13940/* ========================================================================
13941 * Bootstrap: collapse.js v3.3.7
13942 * http://getbootstrap.com/javascript/#collapse
13943 * ========================================================================
13944 * Copyright 2011-2016 Twitter, Inc.
13945 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13946 * ======================================================================== */
13947
13948/* jshint latedef: false */
13949
13950+function ($) {
13951  'use strict';
13952
13953  // COLLAPSE PUBLIC CLASS DEFINITION
13954  // ================================
13955
13956  var Collapse = function (element, options) {
13957    this.$element      = $(element)
13958    this.options       = $.extend({}, Collapse.DEFAULTS, options)
13959    this.$trigger      = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
13960                           '[data-toggle="collapse"][data-target="#' + element.id + '"]')
13961    this.transitioning = null
13962
13963    if (this.options.parent) {
13964      this.$parent = this.getParent()
13965    } else {
13966      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
13967    }
13968
13969    if (this.options.toggle) this.toggle()
13970  }
13971
13972  Collapse.VERSION  = '3.3.7'
13973
13974  Collapse.TRANSITION_DURATION = 350
13975
13976  Collapse.DEFAULTS = {
13977    toggle: true
13978  }
13979
13980  Collapse.prototype.dimension = function () {
13981    var hasWidth = this.$element.hasClass('width')
13982    return hasWidth ? 'width' : 'height'
13983  }
13984
13985  Collapse.prototype.show = function () {
13986    if (this.transitioning || this.$element.hasClass('in')) return
13987
13988    var activesData
13989    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
13990
13991    if (actives && actives.length) {
13992      activesData = actives.data('bs.collapse')
13993      if (activesData && activesData.transitioning) return
13994    }
13995
13996    var startEvent = $.Event('show.bs.collapse')
13997    this.$element.trigger(startEvent)
13998    if (startEvent.isDefaultPrevented()) return
13999
14000    if (actives && actives.length) {
14001      Plugin.call(actives, 'hide')
14002      activesData || actives.data('bs.collapse', null)
14003    }
14004
14005    var dimension = this.dimension()
14006
14007    this.$element
14008      .removeClass('collapse')
14009      .addClass('collapsing')[dimension](0)
14010      .attr('aria-expanded', true)
14011
14012    this.$trigger
14013      .removeClass('collapsed')
14014      .attr('aria-expanded', true)
14015
14016    this.transitioning = 1
14017
14018    var complete = function () {
14019      this.$element
14020        .removeClass('collapsing')
14021        .addClass('collapse in')[dimension]('')
14022      this.transitioning = 0
14023      this.$element
14024        .trigger('shown.bs.collapse')
14025    }
14026
14027    if (!$.support.transition) return complete.call(this)
14028
14029    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
14030
14031    this.$element
14032      .one('bsTransitionEnd', $.proxy(complete, this))
14033      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
14034  }
14035
14036  Collapse.prototype.hide = function () {
14037    if (this.transitioning || !this.$element.hasClass('in')) return
14038
14039    var startEvent = $.Event('hide.bs.collapse')
14040    this.$element.trigger(startEvent)
14041    if (startEvent.isDefaultPrevented()) return
14042
14043    var dimension = this.dimension()
14044
14045    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
14046
14047    this.$element
14048      .addClass('collapsing')
14049      .removeClass('collapse in')
14050      .attr('aria-expanded', false)
14051
14052    this.$trigger
14053      .addClass('collapsed')
14054      .attr('aria-expanded', false)
14055
14056    this.transitioning = 1
14057
14058    var complete = function () {
14059      this.transitioning = 0
14060      this.$element
14061        .removeClass('collapsing')
14062        .addClass('collapse')
14063        .trigger('hidden.bs.collapse')
14064    }
14065
14066    if (!$.support.transition) return complete.call(this)
14067
14068    this.$element
14069      [dimension](0)
14070      .one('bsTransitionEnd', $.proxy(complete, this))
14071      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
14072  }
14073
14074  Collapse.prototype.toggle = function () {
14075    this[this.$element.hasClass('in') ? 'hide' : 'show']()
14076  }
14077
14078  Collapse.prototype.getParent = function () {
14079    return $(this.options.parent)
14080      .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
14081      .each($.proxy(function (i, element) {
14082        var $element = $(element)
14083        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
14084      }, this))
14085      .end()
14086  }
14087
14088  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
14089    var isOpen = $element.hasClass('in')
14090
14091    $element.attr('aria-expanded', isOpen)
14092    $trigger
14093      .toggleClass('collapsed', !isOpen)
14094      .attr('aria-expanded', isOpen)
14095  }
14096
14097  function getTargetFromTrigger($trigger) {
14098    var href
14099    var target = $trigger.attr('data-target')
14100      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
14101
14102    return $(target)
14103  }
14104
14105
14106  // COLLAPSE PLUGIN DEFINITION
14107  // ==========================
14108
14109  function Plugin(option) {
14110    return this.each(function () {
14111      var $this   = $(this)
14112      var data    = $this.data('bs.collapse')
14113      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
14114
14115      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
14116      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
14117      if (typeof option == 'string') data[option]()
14118    })
14119  }
14120
14121  var old = $.fn.collapse
14122
14123  $.fn.collapse             = Plugin
14124  $.fn.collapse.Constructor = Collapse
14125
14126
14127  // COLLAPSE NO CONFLICT
14128  // ====================
14129
14130  $.fn.collapse.noConflict = function () {
14131    $.fn.collapse = old
14132    return this
14133  }
14134
14135
14136  // COLLAPSE DATA-API
14137  // =================
14138
14139  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
14140    var $this   = $(this)
14141
14142    if (!$this.attr('data-target')) e.preventDefault()
14143
14144    var $target = getTargetFromTrigger($this)
14145    var data    = $target.data('bs.collapse')
14146    var option  = data ? 'toggle' : $this.data()
14147
14148    Plugin.call($target, option)
14149  })
14150
14151}(jQuery);
14152
14153/* ========================================================================
14154 * Bootstrap: scrollspy.js v3.3.7
14155 * http://getbootstrap.com/javascript/#scrollspy
14156 * ========================================================================
14157 * Copyright 2011-2016 Twitter, Inc.
14158 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
14159 * ======================================================================== */
14160
14161
14162+function ($) {
14163  'use strict';
14164
14165  // SCROLLSPY CLASS DEFINITION
14166  // ==========================
14167
14168  function ScrollSpy(element, options) {
14169    this.$body          = $(document.body)
14170    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
14171    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
14172    this.selector       = (this.options.target || '') + ' .nav li > a'
14173    this.offsets        = []
14174    this.targets        = []
14175    this.activeTarget   = null
14176    this.scrollHeight   = 0
14177
14178    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
14179    this.refresh()
14180    this.process()
14181  }
14182
14183  ScrollSpy.VERSION  = '3.3.7'
14184
14185  ScrollSpy.DEFAULTS = {
14186    offset: 10
14187  }
14188
14189  ScrollSpy.prototype.getScrollHeight = function () {
14190    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
14191  }
14192
14193  ScrollSpy.prototype.refresh = function () {
14194    var that          = this
14195    var offsetMethod  = 'offset'
14196    var offsetBase    = 0
14197
14198    this.offsets      = []
14199    this.targets      = []
14200    this.scrollHeight = this.getScrollHeight()
14201
14202    if (!$.isWindow(this.$scrollElement[0])) {
14203      offsetMethod = 'position'
14204      offsetBase   = this.$scrollElement.scrollTop()
14205    }
14206
14207    this.$body
14208      .find(this.selector)
14209      .map(function () {
14210        var $el   = $(this)
14211        var href  = $el.data('target') || $el.attr('href')
14212        var $href = /^#./.test(href) && $(href)
14213
14214        return ($href
14215          && $href.length
14216          && $href.is(':visible')
14217          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
14218      })
14219      .sort(function (a, b) { return a[0] - b[0] })
14220      .each(function () {
14221        that.offsets.push(this[0])
14222        that.targets.push(this[1])
14223      })
14224  }
14225
14226  ScrollSpy.prototype.process = function () {
14227    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
14228    var scrollHeight = this.getScrollHeight()
14229    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
14230    var offsets      = this.offsets
14231    var targets      = this.targets
14232    var activeTarget = this.activeTarget
14233    var i
14234
14235    if (this.scrollHeight != scrollHeight) {
14236      this.refresh()
14237    }
14238
14239    if (scrollTop >= maxScroll) {
14240      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
14241    }
14242
14243    if (activeTarget && scrollTop < offsets[0]) {
14244      this.activeTarget = null
14245      return this.clear()
14246    }
14247
14248    for (i = offsets.length; i--;) {
14249      activeTarget != targets[i]
14250        && scrollTop >= offsets[i]
14251        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
14252        && this.activate(targets[i])
14253    }
14254  }
14255
14256  ScrollSpy.prototype.activate = function (target) {
14257    this.activeTarget = target
14258
14259    this.clear()
14260
14261    var selector = this.selector +
14262      '[data-target="' + target + '"],' +
14263      this.selector + '[href="' + target + '"]'
14264
14265    var active = $(selector)
14266      .parents('li')
14267      .addClass('active')
14268
14269    if (active.parent('.dropdown-menu').length) {
14270      active = active
14271        .closest('li.dropdown')
14272        .addClass('active')
14273    }
14274
14275    active.trigger('activate.bs.scrollspy')
14276  }
14277
14278  ScrollSpy.prototype.clear = function () {
14279    $(this.selector)
14280      .parentsUntil(this.options.target, '.active')
14281      .removeClass('active')
14282  }
14283
14284
14285  // SCROLLSPY PLUGIN DEFINITION
14286  // ===========================
14287
14288  function Plugin(option) {
14289    return this.each(function () {
14290      var $this   = $(this)
14291      var data    = $this.data('bs.scrollspy')
14292      var options = typeof option == 'object' && option
14293
14294      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
14295      if (typeof option == 'string') data[option]()
14296    })
14297  }
14298
14299  var old = $.fn.scrollspy
14300
14301  $.fn.scrollspy             = Plugin
14302  $.fn.scrollspy.Constructor = ScrollSpy
14303
14304
14305  // SCROLLSPY NO CONFLICT
14306  // =====================
14307
14308  $.fn.scrollspy.noConflict = function () {
14309    $.fn.scrollspy = old
14310    return this
14311  }
14312
14313
14314  // SCROLLSPY DATA-API
14315  // ==================
14316
14317  $(window).on('load.bs.scrollspy.data-api', function () {
14318    $('[data-spy="scroll"]').each(function () {
14319      var $spy = $(this)
14320      Plugin.call($spy, $spy.data())
14321    })
14322  })
14323
14324}(jQuery);
14325
14326/* ========================================================================
14327 * Bootstrap: transition.js v3.3.7
14328 * http://getbootstrap.com/javascript/#transitions
14329 * ========================================================================
14330 * Copyright 2011-2016 Twitter, Inc.
14331 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
14332 * ======================================================================== */
14333
14334
14335+function ($) {
14336  'use strict';
14337
14338  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
14339  // ============================================================
14340
14341  function transitionEnd() {
14342    var el = document.createElement('bootstrap')
14343
14344    var transEndEventNames = {
14345      WebkitTransition : 'webkitTransitionEnd',
14346      MozTransition    : 'transitionend',
14347      OTransition      : 'oTransitionEnd otransitionend',
14348      transition       : 'transitionend'
14349    }
14350
14351    for (var name in transEndEventNames) {
14352      if (el.style[name] !== undefined) {
14353        return { end: transEndEventNames[name] }
14354      }
14355    }
14356
14357    return false // explicit for ie8 (  ._.)
14358  }
14359
14360  // http://blog.alexmaccaw.com/css-transitions
14361  $.fn.emulateTransitionEnd = function (duration) {
14362    var called = false
14363    var $el = this
14364    $(this).one('bsTransitionEnd', function () { called = true })
14365    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
14366    setTimeout(callback, duration)
14367    return this
14368  }
14369
14370  $(function () {
14371    $.support.transition = transitionEnd()
14372
14373    if (!$.support.transition) return
14374
14375    $.event.special.bsTransitionEnd = {
14376      bindType: $.support.transition.end,
14377      delegateType: $.support.transition.end,
14378      handle: function (e) {
14379        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
14380      }
14381    }
14382  })
14383
14384}(jQuery);
14385
14386// ==================================================
14387// fancyBox v3.1.25
14388//
14389// Licensed GPLv3 for open source use
14390// or fancyBox Commercial License for commercial use
14391//
14392// http://fancyapps.com/fancybox/
14393// Copyright 2017 fancyApps
14394//
14395// ==================================================
14396;(function (window, document, $, undefined) {
14397    'use strict';
14398
14399    // If there's no jQuery, fancyBox can't work
14400    // =========================================
14401
14402    if ( !$ ) {
14403        return;
14404    }
14405
14406    // Check if fancyBox is already initialized
14407    // ========================================
14408
14409    if ( $.fn.fancybox ) {
14410
14411        $.error('fancyBox already initialized');
14412
14413        return;
14414    }
14415
14416    // Private default settings
14417    // ========================
14418
14419    var defaults = {
14420
14421        // Enable infinite gallery navigation
14422        loop : false,
14423
14424        // Space around image, ignored if zoomed-in or viewport smaller than 800px
14425        margin : [44, 0],
14426
14427        // Horizontal space between slides
14428        gutter : 50,
14429
14430        // Enable keyboard navigation
14431        keyboard : true,
14432
14433        // Should display navigation arrows at the screen edges
14434        arrows : true,
14435
14436        // Should display infobar (counter and arrows at the top)
14437        infobar : false,
14438
14439        // Should display toolbar (buttons at the top)
14440        toolbar : true,
14441
14442        // What buttons should appear in the top right corner.
14443        // Buttons will be created using templates from `btnTpl` option
14444        // and they will be placed into toolbar (class="fancybox-toolbar"` element)
14445        buttons : [
14446            'slideShow',
14447            'fullScreen',
14448            'thumbs',
14449            'close'
14450        ],
14451
14452        // Detect "idle" time in seconds
14453        idleTime : 4,
14454
14455        // Should display buttons at top right corner of the content
14456        // If 'auto' - they will be created for content having type 'html', 'inline' or 'ajax'
14457        // Use template from `btnTpl.smallBtn` for customization
14458        smallBtn : 'auto',
14459
14460        // Disable right-click and use simple image protection for images
14461        protect : false,
14462
14463        // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
14464        modal : false,
14465
14466        image : {
14467
14468            // Wait for images to load before displaying
14469            // Requires predefined image dimensions
14470            // If 'auto' - will zoom in thumbnail if 'width' and 'height' attributes are found
14471            preload : "auto",
14472
14473        },
14474
14475        ajax : {
14476
14477            // Object containing settings for ajax request
14478            settings : {
14479
14480                // This helps to indicate that request comes from the modal
14481                // Feel free to change naming
14482                data : {
14483                    fancybox : true
14484                }
14485            }
14486
14487        },
14488
14489        iframe : {
14490
14491            // Iframe template
14492            tpl : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" style="border: none;
14492" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true" src=""></iframe>',
14493
14494            // Preload iframe before displaying it
14495            // This allows to calculate iframe content width and height
14496            // (note: Due to "Same Origin Policy", you can't get cross domain data).
14497            preload : true,
14498
14499            // Custom CSS styling for iframe wrapping element
14500            // You can use this to set custom iframe dimensions
14501            css : {},
14502
14503            // Iframe tag attributes
14504            attr : {
14505                scrolling : 'auto'
14506            }
14507
14508        },
14509
14510        // Open/close animation type
14511        // Possible values:
14512        //   false            - disable
14513        //   "zoom"           - zoom images from/to thumbnail
14514        //   "fade"
14515        //   "zoom-in-out"
14516        //
14517        animationEffect : "zoom",
14518
14519        // Duration in ms for open/close animation
14520        animationDuration : 366,
14521
14522        // Should image change opacity while zooming
14523        // If opacity is 'auto', then opacity will be changed if image and thumbnail have different aspect ratios
14524        zoomOpacity : 'auto',
14525
14526        // Transition effect between slides
14527        //
14528        // Possible values:
14529        //   false            - disable
14530        //   "fade'
14531        //   "slide'
14532        //   "circular'
14533        //   "tube'
14534        //   "zoom-in-out'
14535        //   "rotate'
14536        //
14537        transitionEffect : "fade",
14538
14539        // Duration in ms for transition animation
14540        transitionDuration : 366,
14541
14542        // Custom CSS class for slide element
14543        slideClass : '',
14544
14545        // Custom CSS class for layout
14546        baseClass : '',
14547
14548        // Base template for layout
14549        baseTpl	:
14550            '<div class="fancybox-container" role="dialog" tabindex="-1">' +
14551                '<div class="fancybox-bg"></div>' +
14552                '<div class="fancybox-inner">' +
14553                    '<div class="fancybox-infobar">' +
14554                        '<button data-fancybox-prev title="{{PREV}}" class="fancybox-button fancybox-button--left"></button>' +
14555                        '<div class="fancybox-infobar__body">' +
14556                            '<span data-fancybox-index></span>&nbsp;/&nbsp;<span data-fancybox-count></span>' +
14557                        '</div>' +
14558                        '<button data-fancybox-next title="{{NEXT}}" class="fancybox-button fancybox-button--right"></button>' +
14559                    '</div>' +
14560                    '<div class="fancybox-toolbar">' +
14561                        '{{BUTTONS}}' +
14562                    '</div>' +
14563                    '<div class="fancybox-navigation">' +
14564                        '<button data-fancybox-prev title="{{PREV}}" class="fancybox-arrow fancybox-arrow--left" />' +
14565                        '<button data-fancybox-next title="{{NEXT}}" class="fancybox-arrow fancybox-arrow--right" />' +
14566                    '</div>' +
14567                    '<div class="fancybox-stage"></div>' +
14568                    '<div class="fancybox-caption-wrap">' +
14569                        '<div class="fancybox-caption"></div>' +
14570                    '</div>' +
14571                '</div>' +
14572            '</div>',
14573
14574        // Loading indicator template
14575        spinnerTpl : '<div class="fancybox-loading"></div>',
14576
14577        // Error message template
14578        errorTpl : '<div class="fancybox-error"><p>{{ERROR}}<p></div>',
14579
14580        btnTpl : {
14581            slideShow  : '<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}"></button>',
14582            fullScreen : '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fullscreen" title="{{FULL_SCREEN}}"></button>',
14583            thumbs     : '<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}"></button>',
14584            close      : '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}"></button>',
14585
14586            // This small close button will be appended to your html/inline/ajax content by default,
14587            // if "smallBtn" option is not set to false
14588            smallBtn   : '<button data-fancybox-close class="fancybox-close-small" title="{{CLOSE}}"></button>'
14589        },
14590
14591        // Container is injected into this element
14592        parentEl : 'body',
14593
14594
14595        // Focus handling
14596        // ==============
14597
14598        // Try to focus on the first focusable element after opening
14599        autoFocus : true,
14600
14601        // Put focus back to active element after closing
14602        backFocus : true,
14603
14604        // Do not let user to focus on element outside modal content
14605        trapFocus : true,
14606
14607
14608        // Module specific options
14609        // =======================
14610
14611        fullScreen : {
14612            autoStart : false,
14613        },
14614
14615        touch : {
14616            vertical : true,  // Allow to drag content vertically
14617            momentum : true   // Continue movement after releasing mouse/touch when panning
14618        },
14619
14620        // Hash value when initializing manually,
14621        // set `false` to disable hash change
14622        hash : null,
14623
14624        // Customize or add new media types
14625        // Example:
14626        /*
14627        media : {
14628            youtube : {
14629                params : {
14630                    autoplay : 0
14631                }
14632            }
14633        }
14634        */
14635        media : {},
14636
14637        slideShow : {
14638            autoStart : false,
14639            speed     : 4000
14640        },
14641
14642        thumbs : {
14643            autoStart   : false,   // Display thumbnails on opening
14644            hideOnClose : true     // Hide thumbnail grid when closing animation starts
14645        },
14646
14647        // Callbacks
14648        //==========
14649
14650        // See Documentation/API/Events for more information
14651        // Example:
14652        /*
14653            afterShow: function( instance, current ) {
14654                 console.info( 'Clicked element:' );
14655                 console.info( current.opts.$orig );
14656            }
14657        */
14658
14659        onInit       : $.noop,  // When instance has been initialized
14660
14661        beforeLoad   : $.noop,  // Before the content of a slide is being loaded
14662        afterLoad    : $.noop,  // When the content of a slide is done loading
14663
14664        beforeShow   : $.noop,  // Before open animation starts
14665        afterShow    : $.noop,  // When content is done loading and animating
14666
14667        beforeClose  : $.noop,  // Before the instance attempts to close. Return false to cancel the close.
14668        afterClose   : $.noop,  // After instance has been closed
14669
14670        onActivate   : $.noop,  // When instance is brought to front
14671        onDeactivate : $.noop,  // When other instance has been activated
14672
14673
14674        // Interaction
14675        // ===========
14676
14677        // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
14678        // each option can be string or method that returns value.
14679        //
14680        // Possible values:
14681        //   "close"           - close instance
14682        //   "next"            - move to next gallery item
14683        //   "nextOrClose"     - move to next gallery item or close if gallery has only one item
14684        //   "toggleControls"  - show/hide controls
14685        //   "zoom"            - zoom image (if loaded)
14686        //   false             - do nothing
14687
14688        // Clicked on the content
14689        clickContent : function( current, event ) {
14690            return current.type === 'image' ? 'zoom' : false;
14691        },
14692
14693        // Clicked on the slide
14694        clickSlide : 'close',
14695
14696        // Clicked on the background (backdrop) element
14697        clickOutside : 'close',
14698
14699        // Same as previous two, but for double click
14700        dblclickContent : false,
14701        dblclickSlide   : false,
14702        dblclickOutside : false,
14703
14704
14705        // Custom options when mobile device is detected
14706        // =============================================
14707
14708        mobile : {
14709            clickContent : function( current, event ) {
14710                return current.type === 'image' ? 'toggleControls' : false;
14711            },
14712            clickSlide : function( current, event ) {
14713                return current.type === 'image' ? 'toggleControls' : "close";
14714            },
14715            dblclickContent : function( current, event ) {
14716                return current.type === 'image' ? 'zoom' : false;
14717            },
14718            dblclickSlide : function( current, event ) {
14719                return current.type === 'image' ? 'zoom' : false;
14720            }
14721        },
14722
14723
14724        // Internationalization
14725        // ============
14726
14727        lang : 'en',
14728        i18n : {
14729            'en' : {
14730                CLOSE       : 'Close',
14731                NEXT        : 'Next',
14732                PREV        : 'Previous',
14733                ERROR       : 'The requested content cannot be loaded. <br/> Please try again later.',
14734                PLAY_START  : 'Start slideshow',
14735                PLAY_STOP   : 'Pause slideshow',
14736                FULL_SCREEN : 'Full screen',
14737                THUMBS      : 'Thumbnails'
14738            },
14739            'de' : {
14740                CLOSE       : 'Schliessen',
14741                NEXT        : 'Weiter',
14742                PREV        : 'Zurück',
14743                ERROR       : 'Die angeforderten Daten konnten nicht geladen werden. <br/>
14743 Bitte versuchen Sie es später nochmal.',
14744                PLAY_START  : 'Diaschau starten',
14745                PLAY_STOP   : 'Diaschau beenden',
14746                FULL_SCREEN : 'Vollbild',
14747                THUMBS      : 'Vorschaubilder'
14748            }
14749        }
14750
14751    };
14752
14753    // Few useful variables and methods
14754    // ================================
14755
14756    var $W = $(window);
14757    var $D = $(document);
14758
14759    var called = 0;
14760
14761
14762    // Check if an object is a jQuery object and not a native JavaScript object
14763    // ========================================================================
14764
14765    var isQuery = function ( obj ) {
14766        return obj && obj.hasOwnProperty && obj instanceof $;
14767    };
14768
14769
14770    // Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame"
14771    // ===============================================================================
14772
14773    var requestAFrame = (function () {
14774        return window.requestAnimationFrame ||
14775                window.webkitRequestAnimationFrame ||
14776                window.mozRequestAnimationFrame ||
14777                window.oRequestAnimationFrame ||
14778                // if all else fails, use setTimeout
14779                function (callback) {
14780                    return window.setTimeout(callback, 1000 / 60);
14781                };
14782    })();
14783
14784
14785    // Detect the supported transition-end event property name
14786    // =======================================================
14787
14788    var transitionEnd = (function () {
14789        var t, el = document.createElement("fakeelement");
14790
14791        var transitions = {
14792            "transition"      : "transitionend",
14793            "OTransition"     : "oTransitionEnd",
14794            "MozTransition"   : "transitionend",
14795            "WebkitTransition": "webkitTransitionEnd"
14796        };
14797
14798        for (t in transitions) {
14799            if (el.style[t] !== undefined){
14800                return transitions[t];
14801            }
14802        }
14803    })();
14804
14805
14806    // Force redraw on an element.
14807    // This helps in cases where the browser doesn't redraw an updated element properly.
14808    // =================================================================================
14809
14810    var forceRedraw = function( $el ) {
14811        return ( $el && $el.length && $el[0].offsetHeight );
14812    };
14813
14814
14815    // Class definition
14816    // ================
14817
14818    var FancyBox = function( content, opts, index ) {
14819        var self = this;
14820
14821        self.opts  = $.extend( true, { index : index }, defaults, opts || {} );
14822
14823        // Exclude buttons option from deep merging
14824        if ( opts && $.isArray( opts.buttons ) ) {
14825            self.opts.buttons = opts.buttons;
14826        }
14827
14828        self.id    = self.opts.id || ++called;
14829        self.group = [];
14830
14831        self.currIndex = parseInt( self.opts.index, 10 ) || 0;
14832        self.prevIndex = null;
14833
14834        self.prevPos = null;
14835        self.currPos = 0;
14836
14837        self.firstRun = null;
14838
14839        // Create group elements from original item collection
14840        self.createGroup( content );
14841
14842        if ( !self.group.length ) {
14843            return;
14844        }
14845
14846        // Save last active element and current scroll position
14847        self.$lastFocus = $(document.activeElement).blur();
14848
14849        // Collection of gallery objects
14850        self.slides = {};
14851
14852        self.init( content );
14853
14854    };
14855
14856    $.extend(FancyBox.prototype, {
14857
14858        // Create DOM structure
14859        // ====================
14860
14861        init : function() {
14862            var self = this;
14863
14864            var testWidth, $container, buttonStr;
14865
14866            var firstItemOpts = self.group[ self.currIndex ].opts;
14867
14868            self.scrollTop  = $D.scrollTop();
14869            self.scrollLeft = $D.scrollLeft();
14870
14871
14872            // Hide scrollbars
14873            // ===============
14874
14875            if ( !$.fancybox.getInstance() && !$.fancybox.isMobile && $( 'body' ).css('overflow') !== 'hidden' ) {
14876                testWidth = $( 'body' ).width();
14877
14878                $( 'html' ).addClass( 'fancybox-enabled' );
14879
14880                // Compare body width after applying "overflow: hidden"
14881                testWidth = $( 'body' ).width() - testWidth;
14882
14883                // If width has changed - compensate missing scrollbars by adding right margin
14884                if ( testWidth > 1 ) {
14885                    $( 'head' ).append( '<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar, .fancybox-enabled body { margin-right: ' + testWidth + 'px; }</style>' );
14886                }
14887            }
14888
14889
14890            // Build html markup and set references
14891            // ====================================
14892
14893            // Build html code for buttons and insert into main template
14894            buttonStr = '';
14895
14896            $.each( firstItemOpts.buttons, function( index, value ) {
14897                buttonStr += ( firstItemOpts.btnTpl[ value ] || '' );
14898            });
14899
14900            // Create markup from base template, it will be initially hidden to
14901            // avoid unnecessary work like painting while initializing is not complete
14902            $container = $( self.translate( self, firstItemOpts.baseTpl.replace( '\{\{BUTTONS\}\}', buttonStr ) ) )
14903                .addClass( 'fancybox-is-hidden' )
14904                .attr('id', 'fancybox-container-' + self.id)
14905                .addClass( firstItemOpts.baseClass )
14906                .data( 'FancyBox', self )
14907                .prependTo( firstItemOpts.parentEl );
14908
14909            // Create object holding references to jQuery wrapped nodes
14910            self.$refs = {
14911                container : $container
14912            };
14913
14914            [ 'bg', 'inner', 'infobar', 'toolbar', 'stage', 'caption' ].forEach(function(item) {
14915                self.$refs[ item ] = $container.find( '.fancybox-' + item );
14916            });
14917
14918            // Check for redundant elements
14919            if ( !firstItemOpts.arrows || self.group.length < 2 ) {
14920                $container.find('.fancybox-navigation').remove();
14921            }
14922
14923            if ( !firstItemOpts.infobar ) {
14924                self.$refs.infobar.remove();
14925            }
14926
14927            if ( !firstItemOpts.toolbar ) {
14928                self.$refs.toolbar.remove();
14929            }
14930
14931            self.trigger( 'onInit' );
14932
14933            // Bring to front and enable events
14934            self.activate();
14935
14936            // Build slides, load and reveal content
14937            self.jumpTo( self.currIndex );
14938        },
14939
14940
14941        // Simple i18n support - replaces object keys found in template
14942        // with corresponding values
14943        // ============================================================
14944
14945        translate : function( obj, str ) {
14946            var arr = obj.opts.i18n[ obj.opts.lang ];
14947
14948            return str.replace(/\{\{(\w+)\}\}/g, function(match, n) {
14949                var value = arr[n];
14950
14951                if ( value === undefined ) {
14952                    return match;
14953                }
14954
14955                return value;
14956            });
14957        },
14958
14959        // Create array of gally item objects
14960        // Check if each object has valid type and content
14961        // ===============================================
14962
14963        createGroup : function ( content ) {
14964            var self  = this;
14965            var items = $.makeArray( content );
14966
14967            $.each(items, function( i, item ) {
14968                var obj  = {},
14969                    opts = {},
14970                    data = [],
14971                    $item,
14972                    type,
14973                    src,
14974                    srcParts;
14975
14976                // Step 1 - Make sure we have an object
14977                // ====================================
14978
14979                if ( $.isPlainObject( item ) ) {
14980
14981                    // We probably have manual usage here, something like
14982                    // $.fancybox.open( [ { src : "image.jpg", type : "image" } ] )
14983
14984                    obj  = item;
14985                    opts = item.opts || item;
14986
14987                } else if ( $.type( item ) === 'object' && $( item ).length ) {
14988
14989                    // Here we propbably have jQuery collection returned by some selector
14990
14991                    $item = $( item );
14992                    data  = $item.data();
14993
14994                    opts = 'options' in data ? data.options : {};
14995                    opts = $.type( opts ) === 'object' ? opts : {};
14996
14997                    obj.src  = 'src' in data ? data.src : ( opts.src || $item.attr( 'href' ) );
14998
14999                    [ 'width', 'height', 'thumb', 'type', 'filter' ].forEach(function(item) {
15000                        if ( item in data ) {
15001                            opts[ item ] = data[ item ];
15002                        }
15003                    });
15004
15005                    if ( 'srcset' in data ) {
15006                        opts.image = { srcset : data.srcset };
15007                    }
15008
15009                    opts.$orig = $item;
15010
15011                    if ( !obj.type && !obj.src ) {
15012                        obj.type = 'inline';
15013                        obj.src  = item;
15014                    }
15015
15016                } else {
15017
15018                    // Assume we have a simple html code, for example:
15019                    // $.fancybox.open( '<div><h1>Hi!</h1></div>' );
15020
15021                    obj = {
15022                        type : 'html',
15023                        src  : item + ''
15024                    };
15025
15026                }
15027
15028                // Each gallery object has full collection of options
15029                obj.opts = $.extend( true, {}, self.opts, opts );
15030
15031                if ( $.fancybox.isMobile ) {
15032                    obj.opts = $.extend( true, {}, obj.opts, obj.opts.mobile );
15033                }
15034
15035
15036                // Step 2 - Make sure we have content type, if not - try to guess
15037                // ==============================================================
15038
15039                type = obj.type || obj.opts.type;
15040                src  = obj.src || '';
15041
15042                if ( !type && src ) {
15043                    if ( src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i) ) {
15044                        type = 'image';
15045
15046                    } else if ( src.match(/\.(pdf)((\?|#).*)?$/i) ) {
15047                        type = 'pdf';
15048
15049                    } else if ( src.charAt(0) === '#' ) {
15050                        type = 'inline';
15051                    }
15052                }
15053
15054                obj.type = type;
15055
15056
15057                // Step 3 - Some adjustments
15058                // =========================
15059
15060                obj.index = self.group.length;
15061
15062                // Check if $orig and $thumb objects exist
15063                if ( obj.opts.$orig && !obj.opts.$orig.length ) {
15064                    delete obj.opts.$orig;
15065                }
15066
15067                if ( !obj.opts.$thumb && obj.opts.$orig ) {
15068                    obj.opts.$thumb = obj.opts.$orig.find( 'img:first' );
15069                }
15070
15071                if ( obj.opts.$thumb && !obj.opts.$thumb.length ) {
15072                    delete obj.opts.$thumb;
15073                }
15074
15075                // Caption is a "special" option, it can be passed as a method
15076                if ( $.type( obj.opts.caption ) === 'function' ) {
15077                    obj.opts.caption = obj.opts.caption.apply( item, [ self, obj ] );
15078
15079                } else if ( 'caption' in data ) {
15080                    obj.opts.caption = data.caption;
15081                }
15082
15083                // Make sure we have caption as a string
15084                obj.opts.caption = obj.opts.caption === undefined ? '' : obj.opts.caption + '';
15085
15086                // Check if url contains "filter" used to filter the content
15087                // Example: "ajax.html #something"
15088                if ( type === 'ajax' ) {
15089                    srcParts = src.split(/\s+/, 2);
15090
15091                    if ( srcParts.length > 1 ) {
15092                        obj.src = srcParts.shift();
15093
15094                        obj.opts.filter = srcParts.shift();
15095                    }
15096                }
15097
15098                if ( obj.opts.smallBtn == 'auto' ) {
15099
15100                    if ( $.inArray( type, ['html', 'inline', 'ajax'] ) > -1 ) {
15101                        obj.opts.toolbar  = false;
15102                        obj.opts.smallBtn = true;
15103
15104                    } else {
15105                        obj.opts.smallBtn = false;
15106                    }
15107
15108                }
15109
15110                // If the type is "pdf", then simply load file into iframe
15111                if ( type === 'pdf' ) {
15112                    obj.type = 'iframe';
15113
15114                    obj.opts.iframe.preload = false;
15115                }
15116
15117                // Hide all buttons and disable interactivity for modal items
15118                if ( obj.opts.modal ) {
15119
15120                    obj.opts = $.extend(true, obj.opts, {
15121                        // Remove buttons
15122                        infobar : 0,
15123                        toolbar : 0,
15124
15125                        smallBtn : 0,
15126
15127                        // Disable keyboard navigation
15128                        keyboard : 0,
15129
15130                        // Disable some modules
15131                        slideShow  : 0,
15132                        fullScreen : 0,
15133                        thumbs     : 0,
15134                        touch      : 0,
15135
15136                        // Disable click event handlers
15137                        clickContent    : false,
15138                        clickSlide      : false,
15139                        clickOutside    : false,
15140                        dblclickContent : false,
15141                        dblclickSlide   : false,
15142                        dblclickOutside : false
15143                    });
15144
15145                }
15146
15147                // Step 4 - Add processed object to group
15148                // ======================================
15149
15150                self.group.push( obj );
15151
15152            });
15153
15154        },
15155
15156
15157        // Attach an event handler functions for:
15158        //   - navigation buttons
15159        //   - browser scrolling, resizing;
15160        //   - focusing
15161        //   - keyboard
15162        //   - detect idle
15163        // ======================================
15164
15165        addEvents : function() {
15166            var self = this;
15167
15168            self.removeEvents();
15169
15170            // Make navigation elements clickable
15171            self.$refs.container.on('click.fb-close', '[data-fancybox-close]', function(e) {
15172                e.stopPropagation();
15173                e.preventDefault();
15174
15175                self.close( e );
15176
15177            }).on( 'click.fb-prev touchend.fb-prev', '[data-fancybox-prev]', function(e) {
15178                e.stopPropagation();
15179                e.preventDefault();
15180
15181                self.previous();
15182
15183            }).on( 'click.fb-next touchend.fb-next', '[data-fancybox-next]', function(e) {
15184                e.stopPropagation();
15185                e.preventDefault();
15186
15187                self.next();
15188
15189            });
15190
15191
15192            // Handle page scrolling and browser resizing
15193            $W.on('orientationchange.fb resize.fb', function(e) {
15194
15195                if ( e && e.originalEvent && e.originalEvent.type === "resize" ) {
15196
15197                    requestAFrame(function() {
15198                        self.update();
15199                    });
15200
15201                } else {
15202
15203                    self.$refs.stage.hide();
15204
15205                    setTimeout(function() {
15206                        self.$refs.stage.show();
15207
15208                        self.update();
15209                    }, 500);
15210
15211                }
15212
15213            });
15214
15215            // Trap keyboard focus inside of the modal, so the user does not accidentally tab outside of the modal
15216            // (a.k.a. "escaping the modal")
15217            $D.on('focusin.fb', function(e) {
15218                var instance = $.fancybox ? $.fancybox.getInstance() : null;
15219
15220                if ( instance.isClosing || !instance.current || !instance.current.opts.trapFocus || $( e.target ).hasClass( 'fancybox-container' ) || $( e.target ).is( document ) ) {
15221                    return;
15222                }
15223
15224                if ( instance && $( e.target ).css( 'position' ) !== 'fixed' && !instance.$refs.container.has( e.target ).length ) {
15225                    e.stopPropagation();
15226
15227                    instance.focus();
15228
15229                    // Sometimes page gets scrolled, set it back
15230                    $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
15231                }
15232            });
15233
15234
15235            // Enable keyboard navigation
15236            $D.on('keydown.fb', function (e) {
15237                var current = self.current,
15238                    keycode = e.keyCode || e.which;
15239
15240                if ( !current || !current.opts.keyboard ) {
15241                    return;
15242                }
15243
15244                if ( $(e.target).is('input') || $(e.target).is('textarea') ) {
15245                    return;
15246                }
15247
15248                // Backspace and Esc keys
15249                if ( keycode === 8 || keycode === 27 ) {
15250                    e.preventDefault();
15251
15252                    self.close( e );
15253
15254                    return;
15255                }
15256
15257                // Left arrow and Up arrow
15258                if ( keycode === 37 || keycode === 38 ) {
15259                    e.preventDefault();
15260
15261                    self.previous();
15262
15263                    return;
15264                }
15265
15266                // Righ arrow and Down arrow
15267                if ( keycode === 39 || keycode === 40 ) {
15268                    e.preventDefault();
15269
15270                    self.next();
15271
15272                    return;
15273                }
15274
15275                self.trigger('afterKeydown', e, keycode);
15276            });
15277
15278
15279            // Hide controls after some inactivity period
15280            if ( self.group[ self.currIndex ].opts.idleTime ) {
15281                self.idleSecondsCounter = 0;
15282
15283                $D.on('mousemove.fb-idle mouseenter.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle', function() {
15284                    self.idleSecondsCounter = 0;
15285
15286                    if ( self.isIdle ) {
15287                        self.showControls();
15288                    }
15289
15290                    self.isIdle = false;
15291                });
15292
15293                self.idleInterval = window.setInterval(function() {
15294
15295                    self.idleSecondsCounter++;
15296
15297                    if ( self.idleSecondsCounter >= self.group[ self.currIndex ].opts.idleTime ) {
15298                        self.isIdle = true;
15299                        self.idleSecondsCounter = 0;
15300
15301                        self.hideControls();
15302                    }
15303
15304                }, 1000);
15305            }
15306
15307        },
15308
15309
15310        // Remove events added by the core
15311        // ===============================
15312
15313        removeEvents : function () {
15314            var self = this;
15315
15316            $W.off( 'orientationchange.fb resize.fb' );
15317            $D.off( 'focusin.fb keydown.fb .fb-idle' );
15318
15319            this.$refs.container.off( '.fb-close .fb-prev .fb-next' );
15320
15321            if ( self.idleInterval ) {
15322                window.clearInterval( self.idleInterval );
15323
15324                self.idleInterval = null;
15325            }
15326        },
15327
15328
15329        // Change to previous gallery item
15330        // ===============================
15331
15332        previous : function( duration ) {
15333            return this.jumpTo( this.currPos - 1, duration );
15334        },
15335
15336
15337        // Change to next gallery item
15338        // ===========================
15339
15340        next : function( duration ) {
15341            return this.jumpTo( this.currPos + 1, duration );
15342        },
15343
15344
15345        // Switch to selected gallery item
15346        // ===============================
15347
15348        jumpTo : function ( pos, duration, slide ) {
15349            var self = this,
15350                firstRun,
15351                loop,
15352                current,
15353                previous,
15354                canvasWidth,
15355                currentPos,
15356                transitionProps;
15357
15358            var groupLen = self.group.length;
15359
15360            if ( self.isSliding || self.isClosing || ( self.isAnimating && self.firstRun ) ) {
15361                return;
15362            }
15363
15364            pos  = parseInt( pos, 10 );
15365            loop = self.current ? self.current.opts.loop : self.opts.loop;
15366
15367            if ( !loop && ( pos < 0 || pos >= groupLen ) ) {
15368                return false;
15369            }
15370
15371            firstRun = self.firstRun = ( self.firstRun === null );
15372
15373            if ( groupLen < 2 && !firstRun && !!self.isSliding ) {
15374                return;
15375            }
15376
15377            previous = self.current;
15378
15379            self.prevIndex = self.currIndex;
15380            self.prevPos   = self.currPos;
15381
15382            // Create slides
15383            current = self.createSlide( pos );
15384
15385            if ( groupLen > 1 ) {
15386                if ( loop || current.index > 0 ) {
15387                    self.createSlide( pos - 1 );
15388                }
15389
15390                if ( loop || current.index < groupLen - 1 ) {
15391                    self.createSlide( pos + 1 );
15392                }
15393            }
15394
15395            self.current   = current;
15396            self.currIndex = current.index;
15397            self.currPos   = current.pos;
15398
15399            self.trigger( 'beforeShow', firstRun );
15400
15401            self.updateControls();
15402
15403            currentPos = $.fancybox.getTranslate( current.$slide );
15404
15405            current.isMoved        = ( currentPos.left !== 0 || currentPos.top !== 0 ) && !current.$slide.hasClass( 'fancybox-animated' );
15406            current.forcedDuration = undefined;
15407
15408            if ( $.isNumeric( duration ) ) {
15409                current.forcedDuration = duration;
15410            } else {
15411                duration = current.opts[ firstRun ? 'animationDuration' : 'transitionDuration' ];
15412            }
15413
15414            duration = parseInt( duration, 10 );
15415
15416            // Fresh start - reveal container, current slide and start loading content
15417            if ( firstRun ) {
15418
15419                if ( current.opts.animationEffect && duration ) {
15420                    self.$refs.container.css( 'transition-duration', duration + 'ms' );
15421                }
15422
15423                self.$refs.container.removeClass( 'fancybox-is-hidden' );
15424
15425                forceRedraw( self.$refs.container );
15426
15427                self.$refs.container.addClass( 'fancybox-is-open' );
15428
15429                // Make first slide visible (to display loading icon, if needed)
15430                current.$slide.addClass( 'fancybox-slide--current' );
15431
15432                self.loadSlide( current );
15433
15434                self.preload();
15435
15436                return;
15437            }
15438
15439            // Clean up
15440            $.each(self.slides, function( index, slide ) {
15441                $.fancybox.stop( slide.$slide );
15442            });
15443
15444            // Make current that slide is visible even if content is still loading
15445            current.$slide.removeClass( 'fancybox-slide--next fancybox-slide--previous' ).addClass( 'fancybox-slide--current' );
15446
15447            // If slides have been dragged, animate them to correct position
15448            if ( current.isMoved ) {
15449                canvasWidth = Math.round( current.$slide.width() );
15450
15451                $.each(self.slides, function( index, slide ) {
15452                    var pos = slide.pos - current.pos;
15453
15454                    $.fancybox.animate( slide.$slide, {
15455                        top  : 0,
15456                        left : ( pos * canvasWidth ) + ( pos * slide.opts.gutter )
15457                    }, duration, function() {
15458
15459                        slide.$slide.removeAttr('style').removeClass( 'fancybox-slide--next fancybox-slide--previous' );
15460
15461                        if ( slide.pos === self.currPos ) {
15462                            current.isMoved = false;
15463
15464                            self.complete();
15465                        }
15466                    });
15467                });
15468
15469            } else {
15470                self.$refs.stage.children().removeAttr( 'style' );
15471            }
15472
15473            // Start transition that reveals current content
15474            // or wait when it will be loaded
15475
15476            if ( current.isLoaded ) {
15477                self.revealContent( current );
15478
15479            } else {
15480                self.loadSlide( current );
15481            }
15482
15483            self.preload();
15484
15485            if ( previous.pos === current.pos ) {
15486                return;
15487            }
15488
15489            // Handle previous slide
15490            // =====================
15491
15492            transitionProps = 'fancybox-slide--' + ( previous.pos > current.pos ? 'next' : 'previous' );
15493
15494            previous.$slide.removeClass( 'fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous' );
15495
15496            previous.isComplete = false;
15497
15498            if ( !duration || ( !current.isMoved && !current.opts.transitionEffect ) ) {
15499                return;
15500            }
15501
15502            if ( current.isMoved ) {
15503                previous.$slide.addClass( transitionProps );
15504
15505            } else {
15506
15507                transitionProps = 'fancybox-animated ' + transitionProps + ' fancybox-fx-' + current.opts.transitionEffect;
15508
15509                $.fancybox.animate( previous.$slide, transitionProps, duration, function() {
15510                    previous.$slide.removeClass( transitionProps ).removeAttr( 'style' );
15511                });
15512
15513            }
15514
15515        },
15516
15517
15518        // Create new "slide" element
15519        // These are gallery items  that are actually added to DOM
15520        // =======================================================
15521
15522        createSlide : function( pos ) {
15523
15524            var self = this;
15525            var $slide;
15526            var index;
15527
15528            index = pos % self.group.length;
15529            index = index < 0 ? self.group.length + index : index;
15530
15531            if ( !self.slides[ pos ] && self.group[ index ] ) {
15532                $slide = $('<div class="fancybox-slide"></div>').appendTo( self.$refs.stage );
15533
15534                self.slides[ pos ] = $.extend( true, {}, self.group[ index ], {
15535                    pos      : pos,
15536                    $slide   : $slide,
15537                    isLoaded : false,
15538                });
15539
15540                self.updateSlide( self.slides[ pos ] );
15541            }
15542
15543            return self.slides[ pos ];
15544        },
15545
15546
15547        // Scale image to the actual size of the image
15548        // ===========================================
15549
15550        scaleToActual : function( x, y, duration ) {
15551
15552            var self = this;
15553
15554            var current = self.current;
15555            var $what   = current.$content;
15556
15557            var imgPos, posX, posY, scaleX, scaleY;
15558
15559            var canvasWidth  = parseInt( current.$slide.width(), 10 );
15560            var canvasHeight = parseInt( current.$slide.height(), 10 );
15561
15562            var newImgWidth  = current.width;
15563            var newImgHeight = current.height;
15564
15565            if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating) {
15566                return;
15567            }
15568
15569            $.fancybox.stop( $what );
15570
15571            self.isAnimating = true;
15572
15573            x = x === undefined ? canvasWidth  * 0.5  : x;
15574            y = y === undefined ? canvasHeight * 0.5  : y;
15575
15576            imgPos = $.fancybox.getTranslate( $what );
15577
15578            scaleX  = newImgWidth  / imgPos.width;
15579            scaleY  = newImgHeight / imgPos.height;
15580
15581            // Get center position for original image
15582            posX = ( canvasWidth * 0.5  - newImgWidth * 0.5 );
15583            posY = ( canvasHeight * 0.5 - newImgHeight * 0.5 );
15584
15585            // Make sure image does not move away from edges
15586            if ( newImgWidth > canvasWidth ) {
15587                posX = imgPos.left * scaleX - ( ( x * scaleX ) - x );
15588
15589                if ( posX > 0 ) {
15590                    posX = 0;
15591                }
15592
15593                if ( posX <  canvasWidth - newImgWidth ) {
15594                    posX = canvasWidth - newImgWidth;
15595                }
15596            }
15597
15598            if ( newImgHeight > canvasHeight) {
15599                posY = imgPos.top  * scaleY - ( ( y * scaleY ) - y );
15600
15601                if ( posY > 0 ) {
15602                    posY = 0;
15603                }
15604
15605                if ( posY <  canvasHeight - newImgHeight ) {
15606                    posY = canvasHeight - newImgHeight;
15607                }
15608            }
15609
15610            self.updateCursor( newImgWidth, newImgHeight );
15611
15612            $.fancybox.animate( $what, {
15613                top    : posY,
15614                left   : posX,
15615                scaleX : scaleX,
15616                scaleY : scaleY
15617            }, duration || 330, function() {
15618                self.isAnimating = false;
15619            });
15620
15621            // Stop slideshow
15622            if ( self.SlideShow && self.SlideShow.isActive ) {
15623                self.SlideShow.stop();
15624            }
15625        },
15626
15627
15628        // Scale image to fit inside parent element
15629        // ========================================
15630
15631        scaleToFit : function( duration ) {
15632
15633            var self = this;
15634
15635            var current = self.current;
15636            var $what   = current.$content;
15637            var end;
15638
15639            if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating ) {
15640                return;
15641            }
15642
15643            $.fancybox.stop( $what );
15644
15645            self.isAnimating = true;
15646
15647            end = self.getFitPos( current );
15648
15649            self.updateCursor( end.width, end.height );
15650
15651            $.fancybox.animate( $what, {
15652                top    : end.top,
15653                left   : end.left,
15654                scaleX : end.width  / $what.width(),
15655                scaleY : end.height / $what.height()
15656            }, duration || 330, function() {
15657                self.isAnimating = false;
15658            });
15659
15660        },
15661
15662        // Calculate image size to fit inside viewport
15663        // ===========================================
15664
15665        getFitPos : function( slide ) {
15666            var self  = this;
15667            var $what = slide.$content;
15668
15669            var imgWidth  = slide.width;
15670            var imgHeight = slide.height;
15671
15672            var margin = slide.opts.margin;
15673
15674            var canvasWidth, canvasHeight, minRatio, width, height;
15675
15676            if ( !$what || !$what.length || ( !imgWidth && !imgHeight) ) {
15677                return false;
15678            }
15679
15680            // Convert "margin to CSS style: [ top, right, bottom, left ]
15681            if ( $.type( margin ) === "number" ) {
15682                margin = [ margin, margin ];
15683            }
15684
15685            if ( margin.length == 2 ) {
15686                margin = [ margin[0], margin[1], margin[0], margin[1] ];
15687            }
15688
15689            if ( $W.width() < 800 ) {
15690                margin = [ 0, 0, 0, 0 ];
15691            }
15692
15693            // We can not use $slide width here, because it can have different diemensions while in transiton
15694            canvasWidth  = parseInt( self.$refs.stage.width(), 10 )  - ( margin[ 1 ] + margin[ 3 ] );
15695            canvasHeight = parseInt( self.$refs.stage.height(), 10 ) - ( margin[ 0 ] + margin[ 2 ] );
15696
15697            minRatio = Math.min(1, canvasWidth / imgWidth, canvasHeight / imgHeight );
15698
15699            width  = Math.floor( minRatio * imgWidth );
15700            height = Math.floor( minRatio * imgHeight );
15701
15702            // Use floor rounding to make sure it really fits
15703            return {
15704                top    : Math.floor( ( canvasHeight - height ) * 0.5 ) + margin[ 0 ],
15705                left   : Math.floor( ( canvasWidth  - width )  * 0.5 ) + margin[ 3 ],
15706                width  : width,
15707                height : height
15708            };
15709
15710        },
15711
15712
15713        // Update position and content of all slides
15714        // =========================================
15715
15716        update : function() {
15717
15718            var self = this;
15719
15720            $.each( self.slides, function( key, slide ) {
15721                self.updateSlide( slide );
15722            });
15723
15724        },
15725
15726
15727        // Update slide position and scale content to fit
15728        // ==============================================
15729
15730        updateSlide : function( slide ) {
15731
15732            var self  = this;
15733            var $what = slide.$content;
15734
15735            if ( $what && ( slide.width || slide.height ) ) {
15736                $.fancybox.stop( $what );
15737
15738                $.fancybox.setTranslate( $what, self.getFitPos( slide ) );
15739
15740                if ( slide.pos === self.currPos ) {
15741                    self.updateCursor();
15742                }
15743            }
15744
15745            slide.$slide.trigger( 'refresh' );
15746
15747            self.trigger( 'onUpdate', slide );
15748
15749        },
15750
15751        // Update cursor style depending if content can be zoomed
15752        // ======================================================
15753
15754        updateCursor : function( nextWidth, nextHeight ) {
15755
15756            var self = this;
15757            var isScaledDown;
15758
15759            var $container = self.$refs.container.removeClass('fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-drag fancybox-can-zoomOut');
15760
15761            if ( !self.current || self.isClosing ) {
15762                return;
15763            }
15764
15765            if ( self.isZoomable() ) {
15766
15767                $container.addClass( 'fancybox-is-zoomable' );
15768
15769                if ( nextWidth !== undefined && nextHeight !== undefined ) {
15770                    isScaledDown = nextWidth < self.current.width && nextHeight < self.current.height;
15771
15772                } else {
15773                    isScaledDown = self.isScaledDown();
15774                }
15775
15776                if ( isScaledDown ) {
15777
15778                    // If image is scaled down, then, obviously, it can be zoomed to full size
15779                    $container.addClass('fancybox-can-zoomIn');
15780
15781                } else {
15782
15783                    if ( self.current.opts.touch ) {
15784
15785                        // If image size ir largen than available available and touch module is not disable,
15786                        // then user can do panning
15787                        $container.addClass('fancybox-can-drag');
15788
15789                    } else {
15790                        $container.addClass('fancybox-can-zoomOut');
15791                    }
15792
15793                }
15794
15795            } else if ( self.current.opts.touch ) {
15796                $container.addClass('fancybox-can-drag');
15797            }
15798
15799        },
15800
15801
15802        // Check if current slide is zoomable
15803        // ==================================
15804
15805        isZoomable : function() {
15806
15807            var self = this;
15808
15809            var current = self.current;
15810            var fitPos;
15811
15812            if ( !current || self.isClosing ) {
15813                return;
15814            }
15815
15816            // Assume that slide is zoomable if
15817            //   - image is loaded successfuly
15818            //   - click action is "zoom"
15819            //   - actual size of the image is smaller than available area
15820            if ( current.type === 'image' && current.isLoaded && !current.hasError &&
15821                ( current.opts.clickContent === 'zoom' || ( $.isFunction( current.opts.clickContent ) && current.opts.clickContent( current ) ===  "zoom" ) )
15822            ) {
15823
15824                fitPos = self.getFitPos( current );
15825
15826                if ( current.width > fitPos.width || current.height > fitPos.height ) {
15827                    return true;
15828                }
15829
15830            }
15831
15832            return false;
15833
15834        },
15835
15836
15837        // Check if current image dimensions are smaller than actual
15838        // =========================================================
15839
15840        isScaledDown : function() {
15841
15842            var self = this;
15843
15844            var current = self.current;
15845            var $what   = current.$content;
15846
15847            var rez = false;
15848
15849            if ( $what ) {
15850                rez = $.fancybox.getTranslate( $what );
15851                rez = rez.width < current.width || rez.height < current.height;
15852            }
15853
15854            return rez;
15855
15856        },
15857
15858
15859        // Check if image dimensions exceed parent element
15860        // ===============================================
15861
15862        canPan : function() {
15863
15864            var self = this;
15865
15866            var current = self.current;
15867            var $what   = current.$content;
15868
15869            var rez = false;
15870
15871            if ( $what ) {
15872                rez = self.getFitPos( current );
15873                rez = Math.abs( $what.width() - rez.width ) > 1  || Math.abs( $what.height() - rez.height ) > 1;
15874
15875            }
15876
15877            return rez;
15878
15879        },
15880
15881
15882        // Load content into the slide
15883        // ===========================
15884
15885        loadSlide : function( slide ) {
15886
15887            var self = this, type, $slide;
15888            var ajaxLoad;
15889
15890            if ( slide.isLoading ) {
15891                return;
15892            }
15893
15894            if ( slide.isLoaded ) {
15895                return;
15896            }
15897
15898            slide.isLoading = true;
15899
15900            self.trigger( 'beforeLoad', slide );
15901
15902            type   = slide.type;
15903            $slide = slide.$slide;
15904
15905            $slide
15906                .off( 'refresh' )
15907                .trigger( 'onReset' )
15908                .addClass( 'fancybox-slide--' + ( type || 'unknown' ) )
15909                .addClass( slide.opts.slideClass );
15910
15911            // Create content depending on the type
15912
15913            switch ( type ) {
15914
15915                case 'image':
15916
15917                    self.setImage( slide );
15918
15919                break;
15920
15921                case 'iframe':
15922
15923                    self.setIframe( slide );
15924
15925                break;
15926
15927                case 'html':
15928
15929                    self.setContent( slide, slide.src || slide.content );
15930
15931                break;
15932
15933                case 'inline':
15934
15935                    if ( $( slide.src ).length ) {
15936                        self.setContent( slide, $( slide.src ) );
15937
15938                    } else {
15939                        self.setError( slide );
15940                    }
15941
15942                break;
15943
15944                case 'ajax':
15945
15946                    self.showLoading( slide );
15947
15948                    ajaxLoad = $.ajax( $.extend( {}, slide.opts.ajax.settings, {
15949                        url : slide.src,
15950                        success : function ( data, textStatus ) {
15951
15952                            if ( textStatus === 'success' ) {
15953                                self.setContent( slide, data );
15954                            }
15955
15956                        },
15957                        error : function ( jqXHR, textStatus ) {
15958
15959                            if ( jqXHR && textStatus !== 'abort' ) {
15960                                self.setError( slide );
15961                            }
15962
15963                        }
15964                    }));
15965
15966                    $slide.one( 'onReset', function () {
15967                        ajaxLoad.abort();
15968                    });
15969
15970                break;
15971
15972                default:
15973
15974                    self.setError( slide );
15975
15976                break;
15977
15978            }
15979
15980            return true;
15981
15982        },
15983
15984
15985        // Use thumbnail image, if possible
15986        // ================================
15987
15988        setImage : function( slide ) {
15989
15990            var self   = this;
15991            var srcset = slide.opts.image.srcset;
15992
15993            var found, temp, pxRatio, windowWidth;
15994
15995            // If we have "srcset", then we need to find matching "src" value.
15996            // This is necessary, because when you set an src attribute, the browser will preload the image
15997            // before any javascript or even CSS is applied.
15998            if ( srcset ) {
15999                pxRatio     = window.devicePixelRatio || 1;
16000                windowWidth = window.innerWidth  * pxRatio;
16001
16002                temp = srcset.split(',').map(function ( el ) {
16003            		var ret = {};
16004
16005            		el.trim().split(/\s+/).forEach(function ( el, i ) {
16006                        var value = parseInt( el.substring(0, el.length - 1), 10 );
16007
16008            			if ( i === 0 ) {
16009            				return ( ret.url = el );
16010            			}
16011
16012                        if ( value ) {
16013                            ret.value   = value;
16014                            ret.postfix = el[ el.length - 1 ];
16015                        }
16016
16017            		});
16018
16019            		return ret;
16020            	});
16021
16022                // Sort by value
16023                temp.sort(function (a, b) {
16024                  return a.value - b.value;
16025                });
16026
16027                // Ok, now we have an array of all srcset values
16028                for ( var j = 0; j < temp.length; j++ ) {
16029                    var el = temp[ j ];
16030
16031                    if ( ( el.postfix === 'w' && el.value >= windowWidth ) || ( el.postfix === 'x' && el.value >= pxRatio ) ) {
16032                        found = el;
16033                        break;
16034                    }
16035                }
16036
16037                // If not found, take the last one
16038                if ( !found && temp.length ) {
16039                    found = temp[ temp.length - 1 ];
16040                }
16041
16042                if ( found ) {
16043                    slide.src = found.url;
16044
16045                    // If we have default width/height values, we can calculate height for matching source
16046                    if ( slide.width && slide.height && found.postfix == 'w' ) {
16047                        slide.height = ( slide.width / slide.height ) * found.value;
16048                        slide.width  = found.value;
16049                    }
16050                }
16051            }
16052
16053            // This will be wrapper containing both ghost and actual image
16054            slide.$content = $('<div class="fancybox-image-wrap"></div>')
16055                .addClass( 'fancybox-is-hidden' )
16056                .appendTo( slide.$slide );
16057
16058
16059            // If we have a thumbnail, we can display it while actual image is loading
16060            // Users will not stare at black screen and actual image will appear gradually
16061            if ( slide.opts.preload !== false && slide.opts.width && slide.opts.height && ( slide.opts.thumb || slide.opts.$thumb ) ) {
16062
16063                slide.width  = slide.opts.width;
16064                slide.height = slide.opts.height;
16065
16066                slide.$ghost = $('<img />')
16067                    .one('error', function() {
16068
16069                        $(this).remove();
16070
16071                        slide.$ghost = null;
16072
16073                        self.setBigImage( slide );
16074
16075                    })
16076                    .one('load', function() {
16077
16078                        self.afterLoad( slide );
16079
16080                        self.setBigImage( slide );
16081
16082                    })
16083                    .addClass( 'fancybox-image' )
16084                    .appendTo( slide.$content )
16085                    .attr( 'src', slide.opts.thumb || slide.opts.$thumb.attr( 'src' ) );
16086
16087            } else {
16088
16089                self.setBigImage( slide );
16090
16091            }
16092
16093        },
16094
16095
16096        // Create full-size image
16097        // ======================
16098
16099        setBigImage : function ( slide ) {
16100            var self = this;
16101            var $img = $('<img />');
16102
16103            slide.$image = $img
16104                .one('error', function() {
16105
16106                    self.setError( slide );
16107
16108                })
16109                .one('load', function() {
16110
16111                    // Clear timeout that checks if loading icon needs to be displayed
16112                    clearTimeout( slide.timouts );
16113
16114                    slide.timouts = null;
16115
16116                    if ( self.isClosing ) {
16117                        return;
16118                    }
16119
16120                    slide.width  = this.naturalWidth;
16121                    slide.height = this.naturalHeight;
16122
16123                    if ( slide.opts.image.srcset ) {
16124                        $img.attr( 'sizes', '100vw' ).attr( 'srcset', slide.opts.image.srcset );
16125                    }
16126
16127                    self.hideLoading( slide );
16128
16129                    if ( slide.$ghost ) {
16130
16131                        slide.timouts = setTimeout(function() {
16132                            slide.timouts = null;
16133
16134                            slide.$ghost.hide();
16135
16136                        }, Math.min( 300, Math.max( 1000, slide.height / 1600 ) ) );
16137
16138                    } else {
16139                        self.afterLoad( slide );
16140                    }
16141
16142                })
16143                .addClass( 'fancybox-image' )
16144                .attr('src', slide.src)
16145                .appendTo( slide.$content );
16146
16147            if ( $img[0].complete ) {
16148                  $img.trigger( 'load' );
16149
16150            } else if( $img[0].error ) {
16151                 $img.trigger( 'error' );
16152
16153            } else {
16154
16155                slide.timouts = setTimeout(function() {
16156                    if ( !$img[0].complete && !slide.hasError ) {
16157                        self.showLoading( slide );
16158                    }
16159
16160                }, 100);
16161
16162            }
16163
16164        },
16165
16166
16167        // Create iframe wrapper, iframe and bindings
16168        // ==========================================
16169
16170        setIframe : function( slide ) {
16171            var self	= this,
16172                opts    = slide.opts.iframe,
16173                $slide	= slide.$slide,
16174                $iframe;
16175
16176            slide.$content = $('<div class="fancybox-content' + ( opts.preload ? ' fancybox-is-hidden' : '' ) + '"></div>')
16177                .css( opts.css )
16178                .appendTo( $slide );
16179
16180            $iframe = $( opts.tpl.replace(/\{rnd\}/g, new Date().getTime()) )
16181                .attr( opts.attr )
16182                .appendTo( slide.$content );
16183
16184            if ( opts.preload ) {
16185
16186                self.showLoading( slide );
16187
16188                // Unfortunately, it is not always possible to determine if iframe is successfully loaded
16189                // (due to browser security policy)
16190
16191                $iframe.on('load.fb error.fb', function(e) {
16192                    this.isReady = 1;
16193
16194                    slide.$slide.trigger( 'refresh' );
16195
16196                    self.afterLoad( slide );
16197                });
16198
16199                // Recalculate iframe content size
16200                // ===============================
16201
16202                $slide.on('refresh.fb', function() {
16203                    var $wrap = slide.$content,
16204                        $contents,
16205                        $body,
16206                        scrollWidth,
16207                        frameWidth,
16208                        frameHeight;
16209
16210                    if ( $iframe[0].isReady !== 1 ) {
16211                        return;
16212                    }
16213
16214                    // Check if content is accessible,
16215                    // it will fail if frame is not with the same origin
16216
16217                    try {
16218                        $contents = $iframe.contents();
16219                        $body     = $contents.find('body');
16220
16221                    } catch (ignore) {}
16222
16223                    // Calculate dimensions for the wrapper
16224                    if ( $body && $body.length && !( opts.css.width !== undefined && opts.css.height !== undefined ) ) {
16225
16226                        scrollWidth = $iframe[0].contentWindow.document.documentElement.scrollWidth;
16227
16228                        frameWidth	= Math.ceil( $body.outerWidth(true) + ( $wrap.width() - scrollWidth ) );
16229                        frameHeight	= Math.ceil( $body.outerHeight(true) );
16230
16231                        // Resize wrapper to fit iframe content
16232                        $wrap.css({
16233                            'width'  : opts.css.width  === undefined ? frameWidth  + ( $wrap.outerWidth()  - $wrap.innerWidth() )  : opts.css.width,
16234                            'height' : opts.css.height === undefined ? frameHeight + ( $wrap.outerHeight() - $wrap.innerHeight() ) : opts.css.height
16235                        });
16236
16237                    }
16238
16239                    $wrap.removeClass( 'fancybox-is-hidden' );
16240
16241                });
16242
16243            } else {
16244
16245                this.afterLoad( slide );
16246
16247            }
16248
16249            $iframe.attr( 'src', slide.src );
16250
16251            if ( slide.opts.smallBtn === true ) {
16252                slide.$content.prepend( self.translate( slide, slide.opts.btnTpl.smallBtn ) );
16253            }
16254
16255            // Remove iframe if closing or changing gallery item
16256            $slide.one( 'onReset', function () {
16257
16258                // This helps IE not to throw errors when closing
16259                try {
16260
16261                    $( this ).find( 'iframe' ).hide().attr( 'src', '//about:blank' );
16262
16263                } catch ( ignore ) {}
16264
16265                $( this ).empty();
16266
16267                slide.isLoaded = false;
16268
16269            });
16270
16271        },
16272
16273
16274        // Wrap and append content to the slide
16275        // ======================================
16276
16277        setContent : function ( slide, content ) {
16278
16279            var self = this;
16280
16281            if ( self.isClosing ) {
16282                return;
16283            }
16284
16285            self.hideLoading( slide );
16286
16287            slide.$slide.empty();
16288
16289            if ( isQuery( content ) && content.parent().length ) {
16290
16291                // If content is a jQuery object, then it will be moved to the slide.
16292                // The placeholder is created so we will know where to put it back.
16293                // If user is navigating gallery fast, then the content might be already inside fancyBox
16294                // =====================================================================================
16295
16296                // Make sure content is not already moved to fancyBox
16297                content.parent( '.fancybox-slide--inline' ).trigger( 'onReset' );
16298
16299                // Create temporary element marking original place of the content
16300                slide.$placeholder = $( '<div></div>' ).hide().insertAfter( content );
16301
16302                // Make sure content is visible
16303                content.css('display', 'inline-block');
16304
16305            } else if ( !slide.hasError ) {
16306
16307                // If content is just a plain text, try to convert it to html
16308                if ( $.type( content ) === 'string' ) {
16309                    content = $('<div>').append( $.trim( content ) ).contents();
16310
16311                    // If we have text node, then add wrapping element to make vertical alignment work
16312                    if ( content[0].nodeType === 3 ) {
16313                        content = $('<div>').html( content );
16314                    }
16315                }
16316
16317                // If "filter" option is provided, then filter content
16318                if ( slide.opts.filter ) {
16319                    content = $('<div>').html( content ).find( slide.opts.filter );
16320                }
16321
16322            }
16323
16324            slide.$slide.one('onReset', function () {
16325
16326                // Put content back
16327                if ( slide.$placeholder ) {
16328                    slide.$placeholder.after( content.hide() ).remove();
16329
16330                    slide.$placeholder = null;
16331                }
16332
16333                // Remove custom close button
16334                if ( slide.$smallBtn ) {
16335                    slide.$smallBtn.remove();
16336
16337                    slide.$smallBtn = null;
16338                }
16339
16340                // Remove content and mark slide as not loaded
16341                if ( !slide.hasError ) {
16342                    $(this).empty();
16343
16344                    slide.isLoaded = false;
16345                }
16346
16347            });
16348
16349            slide.$content = $( content ).appendTo( slide.$slide );
16350
16351            if ( slide.opts.smallBtn && !slide.$smallBtn ) {
16352                slide.$smallBtn = $( self.translate( slide, slide.opts.btnTpl.smallBtn ) ).appendTo( slide.$content.filter('div').first() );
16353            }
16354
16355            this.afterLoad( slide );
16356        },
16357
16358        // Display error message
16359        // =====================
16360
16361        setError : function ( slide ) {
16362
16363            slide.hasError = true;
16364
16365            slide.$slide.removeClass( 'fancybox-slide--' + slide.type );
16366
16367            this.setContent( slide, this.translate( slide, slide.opts.errorTpl ) );
16368
16369        },
16370
16371
16372        // Show loading icon inside the slide
16373        // ==================================
16374
16375        showLoading : function( slide ) {
16376
16377            var self = this;
16378
16379            slide = slide || self.current;
16380
16381            if ( slide && !slide.$spinner ) {
16382                slide.$spinner = $( self.opts.spinnerTpl ).appendTo( slide.$slide );
16383            }
16384
16385        },
16386
16387        // Remove loading icon from the slide
16388        // ==================================
16389
16390        hideLoading : function( slide ) {
16391
16392            var self = this;
16393
16394            slide = slide || self.current;
16395
16396            if ( slide && slide.$spinner ) {
16397                slide.$spinner.remove();
16398
16399                delete slide.$spinner;
16400            }
16401
16402        },
16403
16404
16405        // Adjustments after slide content has been loaded
16406        // ===============================================
16407
16408        afterLoad : function( slide ) {
16409
16410            var self = this;
16411
16412            if ( self.isClosing ) {
16413                return;
16414            }
16415
16416            slide.isLoading = false;
16417            slide.isLoaded  = true;
16418
16419            self.trigger( 'afterLoad', slide );
16420
16421            self.hideLoading( slide );
16422
16423            if ( slide.opts.protect && slide.$content && !slide.hasError ) {
16424
16425                // Disable right click
16426                slide.$content.on( 'contextmenu.fb', function( e ) {
16427                     if ( e.button == 2 ) {
16428                         e.preventDefault();
16429                     }
16430
16431                    return true;
16432                });
16433
16434                // Add fake element on top of the image
16435                // This makes a bit harder for user to select image
16436                if ( slide.type === 'image' ) {
16437                    $( '<div class="fancybox-spaceball"></div>' ).appendTo( slide.$content );
16438                }
16439
16440            }
16441
16442            self.revealContent( slide );
16443
16444        },
16445
16446
16447        // Make content visible
16448        // This method is called right after content has been loaded or
16449        // user navigates gallery and transition should start
16450        // ============================================================
16451
16452        revealContent : function( slide ) {
16453
16454            var self   = this;
16455            var $slide = slide.$slide;
16456
16457            var effect, effectClassName, duration, opacity, end, start = false;
16458
16459            effect   = slide.opts[ self.firstRun ? 'animationEffect'   : 'transitionEffect' ];
16460            duration = slide.opts[ self.firstRun ? 'animationDuration' : 'transitionDuration' ];
16461
16462            duration = parseInt( slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10 );
16463
16464            if ( slide.isMoved || slide.pos !== self.currPos || !duration ) {
16465                effect = false;
16466            }
16467
16468            // Check if can zoom
16469            if ( effect === 'zoom' && !( slide.pos === self.currPos && duration && slide.type === 'image' && !slide.hasError && ( start = self.getThumbPos( slide ) ) ) ) {
16470                effect = 'fade';
16471            }
16472
16473
16474            // Zoom animation
16475            // ==============
16476
16477            if ( effect === 'zoom' ) {
16478                end = self.getFitPos( slide );
16479
16480                end.scaleX = end.width  / start.width;
16481                end.scaleY = end.height / start.height;
16482
16483                delete end.width;
16484                delete end.height;
16485
16486                // Check if we need to animate opacity
16487                opacity = slide.opts.zoomOpacity;
16488
16489                if ( opacity == 'auto' ) {
16490                    opacity = Math.abs( slide.width / slide.height - start.width / start.height ) > 0.1;
16491                }
16492
16493                if ( opacity ) {
16494                    start.opacity = 0.1;
16495                    end.opacity   = 1;
16496                }
16497
16498                // Draw image at start position
16499                $.fancybox.setTranslate( slide.$content.removeClass( 'fancybox-is-hidden' ), start );
16500
16501                forceRedraw( slide.$content );
16502
16503                // Start animation
16504                $.fancybox.animate( slide.$content, end, duration, function() {
16505                    self.complete();
16506                });
16507
16508                return;
16509            }
16510
16511
16512            self.updateSlide( slide );
16513
16514
16515            // Simply show content
16516            // ===================
16517
16518            if ( !effect ) {
16519                forceRedraw( $slide );
16520
16521                slide.$content.removeClass( 'fancybox-is-hidden' );
16522
16523                if ( slide.pos === self.currPos ) {
16524                    self.complete();
16525                }
16526
16527                return;
16528            }
16529
16530            $.fancybox.stop( $slide );
16531
16532            effectClassName = 'fancybox-animated fancybox-slide--' + ( slide.pos > self.prevPos ? 'next' : 'previous' ) + ' fancybox-fx-' + effect;
16533
16534            $slide.removeAttr( 'style' ).removeClass( 'fancybox-slide--current fancybox-slide--next fancybox-slide--previous' ).addClass( effectClassName );
16535
16536            slide.$content.removeClass( 'fancybox-is-hidden' );
16537
16538            //Force reflow for CSS3 transitions
16539            forceRedraw( $slide );
16540
16541            $.fancybox.animate( $slide, 'fancybox-slide--current', duration, function(e) {
16542                $slide.removeClass( effectClassName ).removeAttr( 'style' );
16543
16544                if ( slide.pos === self.currPos ) {
16545                    self.complete();
16546                }
16547
16548            }, true);
16549
16550        },
16551
16552
16553        // Check if we can and have to zoom from thumbnail
16554        //================================================
16555
16556        getThumbPos : function( slide ) {
16557
16558            var self = this;
16559            var rez  = false;
16560
16561            // Check if element is inside the viewport by at least 1 pixel
16562            var isElementVisible = function( $el ) {
16563                var element = $el[0];
16564
16565                var elementRect = element.getBoundingClientRect();
16566                var parentRects = [];
16567
16568                var visibleInAllParents;
16569
16570                while ( element.parentElement !== null ) {
16571                    if ( $(element.parentElement).css('overflow') === 'hidden'  || $(element.parentElement).css('overflow') === 'auto' ) {
16572                        parentRects.push(element.parentElement.getBoundingClientRect());
16573                    }
16574
16575                    element = element.parentElement;
16576                }
16577
16578                visibleInAllParents = parentRects.every(function(parentRect){
16579                    var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
16580                    var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
16581
16582                    return visiblePixelX > 0 && visiblePixelY > 0;
16583                });
16584
16585                return visibleInAllParents &&
16586                    elementRect.bottom > 0 && elementRect.right > 0 &&
16587                    elementRect.left < $(window).width() && elementRect.top < $(window).height();
16588            };
16589
16590            var $thumb   = slide.opts.$thumb;
16591            var thumbPos = $thumb ? $thumb.offset() : 0;
16592            var slidePos;
16593
16594            if ( thumbPos && $thumb[0].ownerDocument === document && isElementVisible( $thumb ) ) {
16595                slidePos = self.$refs.stage.offset();
16596
16597                rez = {
16598                    top    : thumbPos.top  - slidePos.top  + parseFloat( $thumb.css( "border-top-width" ) || 0 ),
16599                    left   : thumbPos.left - slidePos.left + parseFloat( $thumb.css( "border-left-width" ) || 0 ),
16600                    width  : $thumb.width(),
16601                    height : $thumb.height(),
16602                    scaleX : 1,
16603                    scaleY : 1
16604                };
16605            }
16606
16607            return rez;
16608        },
16609
16610
16611        // Final adjustments after current gallery item is moved to position
16612        // and it`s content is loaded
16613        // ==================================================================
16614
16615        complete : function() {
16616
16617            var self = this;
16618
16619            var current = self.current;
16620            var slides  = {};
16621
16622            if ( current.isMoved || !current.isLoaded || current.isComplete ) {
16623                return;
16624            }
16625
16626            current.isComplete = true;
16627
16628            current.$slide.siblings().trigger( 'onReset' );
16629
16630            // Trigger any CSS3 transiton inside the slide
16631            forceRedraw( current.$slide );
16632
16633            current.$slide.addClass( 'fancybox-slide--complete' );
16634
16635            // Remove unnecessary slides
16636            $.each( self.slides, function( key, slide ) {
16637                if ( slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1 ) {
16638                    slides[ slide.pos ] = slide;
16639
16640                } else if ( slide ) {
16641
16642                    $.fancybox.stop( slide.$slide );
16643
16644                    slide.$slide.unbind().remove();
16645                }
16646            });
16647
16648            self.slides = slides;
16649
16650            self.updateCursor();
16651
16652            self.trigger( 'afterShow' );
16653
16654            // Try to focus on the first focusable element
16655            if ( $( document.activeElement ).is( '[disabled]' ) || ( current.opts.autoFocus && !( current.type == 'image' || current.type === 'iframe' ) ) ) {
16656                self.focus();
16657            }
16658
16659        },
16660
16661
16662        // Preload next and previous slides
16663        // ================================
16664
16665        preload : function() {
16666            var self = this;
16667            var next, prev;
16668
16669            if ( self.group.length < 2 ) {
16670                return;
16671            }
16672
16673            next  = self.slides[ self.currPos + 1 ];
16674            prev  = self.slides[ self.currPos - 1 ];
16675
16676            if ( next && next.type === 'image' ) {
16677                self.loadSlide( next );
16678            }
16679
16680            if ( prev && prev.type === 'image' ) {
16681                self.loadSlide( prev );
16682            }
16683
16684        },
16685
16686
16687        // Try to find and focus on the first focusable element
16688        // ====================================================
16689
16690        focus : function() {
16691            var current = this.current;
16692            var $el;
16693
16694            if ( this.isClosing ) {
16695                return;
16696            }
16697
16698            // Skip for images and iframes
16699            $el = current && current.isComplete ? current.$slide.find('button,:input,[tabindex],a').filter(':not([disabled]):visible:first') : null;
16700            $el = $el && $el.length ? $el : this.$refs.container;
16701
16702            $el.focus();
16703        },
16704
16705
16706        // Activates current instance - brings container to the front and enables keyboard,
16707        // notifies other instances about deactivating
16708        // =================================================================================
16709
16710        activate : function () {
16711            var self = this;
16712
16713            // Deactivate all instances
16714            $( '.fancybox-container' ).each(function () {
16715                var instance = $(this).data( 'FancyBox' );
16716
16717                // Skip self and closing instances
16718                if (instance && instance.uid !== self.uid && !instance.isClosing) {
16719                    instance.trigger( 'onDeactivate' );
16720                }
16721
16722            });
16723
16724            if ( self.current ) {
16725                if ( self.$refs.container.index() > 0 ) {
16726                    self.$refs.container.prependTo( document.body );
16727                }
16728
16729                self.updateControls();
16730            }
16731
16732            self.trigger( 'onActivate' );
16733
16734            self.addEvents();
16735
16736        },
16737
16738
16739        // Start closing procedure
16740        // This will start "zoom-out" animation if needed and clean everything up afterwards
16741        // =================================================================================
16742
16743        close : function( e, d ) {
16744
16745            var self    = this;
16746            var current = self.current;
16747
16748            var effect, duration;
16749            var $what, opacity, start, end;
16750
16751            var done = function() {
16752                self.cleanUp( e );
16753            };
16754
16755            if ( self.isClosing ) {
16756                return false;
16757            }
16758
16759            self.isClosing = true;
16760
16761            // If beforeClose callback prevents closing, make sure content is centered
16762            if ( self.trigger( 'beforeClose', e ) === false ) {
16763                self.isClosing = false;
16764
16765                requestAFrame(function() {
16766                    self.update();
16767                });
16768
16769                return false;
16770            }
16771
16772            // Remove all events
16773            // If there are multiple instances, they will be set again by "activate" method
16774            self.removeEvents();
16775
16776            if ( current.timouts ) {
16777                clearTimeout( current.timouts );
16778            }
16779
16780            $what    = current.$content;
16781            effect   = current.opts.animationEffect;
16782            duration = $.isNumeric( d ) ? d : ( effect ? current.opts.animationDuration : 0 );
16783
16784            // Remove other slides
16785            current.$slide.off( transitionEnd ).removeClass( 'fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated' );
16786
16787            current.$slide.siblings().trigger( 'onReset' ).remove();
16788
16789            // Trigger animations
16790            if ( duration ) {
16791                self.$refs.container.removeClass( 'fancybox-is-open' ).addClass( 'fancybox-is-closing' );
16792            }
16793
16794            // Clean up
16795            self.hideLoading( current );
16796
16797            self.hideControls();
16798
16799            self.updateCursor();
16800
16801            // Check if possible to zoom-out
16802            if ( effect === 'zoom' && !( e !== true && $what && duration && current.type === 'image' && !current.hasError && ( end = self.getThumbPos( current ) ) ) ) {
16803                effect = 'fade';
16804            }
16805
16806            if ( effect === 'zoom' ) {
16807                $.fancybox.stop( $what );
16808
16809                start = $.fancybox.getTranslate( $what );
16810
16811                start.width  = start.width  * start.scaleX;
16812                start.height = start.height * start.scaleY;
16813
16814                // Check if we need to animate opacity
16815                opacity = current.opts.zoomOpacity;
16816
16817                if ( opacity == 'auto' ) {
16818                    opacity = Math.abs( current.width / current.height - end.width / end.height ) > 0.1;
16819                }
16820
16821                if ( opacity ) {
16822                    end.opacity = 0;
16823                }
16824
16825                start.scaleX = start.width  / end.width;
16826                start.scaleY = start.height / end.height;
16827
16828                start.width  = end.width;
16829                start.height = end.height;
16830
16831                $.fancybox.setTranslate( current.$content, start );
16832
16833                $.fancybox.animate( current.$content, end, duration, done );
16834
16835                return true;
16836            }
16837
16838            if ( effect && duration ) {
16839
16840                // If skip animation
16841                if ( e === true ) {
16842                    setTimeout( done, duration );
16843
16844                } else {
16845                    $.fancybox.animate( current.$slide.removeClass( 'fancybox-slide--current' ), 'fancybox-animated fancybox-slide--previous fancybox-fx-' + effect, duration, done );
16846                }
16847
16848            } else {
16849                done();
16850            }
16851
16852            return true;
16853        },
16854
16855
16856        // Final adjustments after removing the instance
16857        // =============================================
16858
16859        cleanUp : function( e ) {
16860            var self = this,
16861                instance;
16862
16863            self.current.$slide.trigger( 'onReset' );
16864
16865            self.$refs.container.empty().remove();
16866
16867            self.trigger( 'afterClose', e );
16868
16869            // Place back focus
16870            if ( self.$lastFocus && !!self.current.opts.backFocus ) {
16871                self.$lastFocus.focus();
16872            }
16873
16874            self.current = null;
16875
16876            // Check if there are other instances
16877            instance = $.fancybox.getInstance();
16878
16879            if ( instance ) {
16880                instance.activate();
16881
16882            } else {
16883
16884                $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
16885
16886                $( 'html' ).removeClass( 'fancybox-enabled' );
16887
16888                $( '#fancybox-style-noscroll' ).remove();
16889            }
16890
16891        },
16892
16893
16894        // Call callback and trigger an event
16895        // ==================================
16896
16897        trigger : function( name, slide ) {
16898            var args  = Array.prototype.slice.call(arguments, 1),
16899                self  = this,
16900                obj   = slide && slide.opts ? slide : self.current,
16901                rez;
16902
16903            if ( obj ) {
16904                args.unshift( obj );
16905
16906            } else {
16907                obj = self;
16908            }
16909
16910            args.unshift( self );
16911
16912            if ( $.isFunction( obj.opts[ name ] ) ) {
16913                rez = obj.opts[ name ].apply( obj, args );
16914            }
16915
16916            if ( rez === false ) {
16917                return rez;
16918            }
16919
16920            if ( name === 'afterClose' ) {
16921                $D.trigger( name + '.fb', args );
16922
16923            } else {
16924                self.$refs.container.trigger( name + '.fb', args );
16925            }
16926
16927        },
16928
16929
16930        // Update infobar values, navigation button states and reveal caption
16931        // ==================================================================
16932
16933        updateControls : function ( force ) {
16934
16935            var self = this;
16936
16937            var current  = self.current;
16938            var index    = current.index;
16939            var opts     = current.opts;
16940            var caption  = opts.caption;
16941            var $caption = self.$refs.caption;
16942
16943            // Recalculate content dimensions
16944            current.$slide.trigger( 'refresh' );
16945
16946            self.$caption = caption && caption.length ? $caption.html( caption ) : null;
16947
16948            if ( !self.isHiddenControls ) {
16949                self.showControls();
16950            }
16951
16952            // Update info and navigation elements
16953            $('[data-fancybox-count]').html( self.group.length );
16954            $('[data-fancybox-index]').html( index + 1 );
16955
16956            $('[data-fancybox-prev]').prop('disabled', ( !opts.loop && index <= 0 ) );
16957            $('[data-fancybox-next]').prop('disabled', ( !opts.loop && index >= self.group.length - 1 ) );
16958
16959        },
16960
16961        // Hide toolbar and caption
16962        // ========================
16963
16964        hideControls : function () {
16965
16966            this.isHiddenControls = true;
16967
16968            this.$refs.container.removeClass('fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav');
16969
16970        },
16971
16972        showControls : function() {
16973
16974            var self = this;
16975            var opts = self.current ? self.current.opts : self.opts;
16976            var $container = self.$refs.container;
16977
16978            self.isHiddenControls   = false;
16979            self.idleSecondsCounter = 0;
16980
16981            $container
16982                .toggleClass('fancybox-show-toolbar', !!( opts.toolbar && opts.buttons ) )
16983                .toggleClass('fancybox-show-infobar', !!( opts.infobar && self.group.length > 1 ) )
16984                .toggleClass('fancybox-show-nav',     !!( opts.arrows && self.group.length > 1 ) )
16985                .toggleClass('fancybox-is-modal',     !!opts.modal );
16986
16987            if ( self.$caption ) {
16988                $container.addClass( 'fancybox-show-caption ');
16989
16990            } else {
16991               $container.removeClass( 'fancybox-show-caption' );
16992           }
16993
16994       },
16995
16996
16997       // Toggle toolbar and caption
16998       // ==========================
16999
17000       toggleControls : function() {
17001
17002           if ( this.isHiddenControls ) {
17003               this.showControls();
17004
17005           } else {
17006               this.hideControls();
17007           }
17008
17009       },
17010
17011
17012    });
17013
17014
17015    $.fancybox = {
17016
17017        version  : "3.1.25",
17018        defaults : defaults,
17019
17020
17021        // Get current instance and execute a command.
17022        //
17023        // Examples of usage:
17024        //
17025        //   $instance = $.fancybox.getInstance();
17026        //   $.fancybox.getInstance().jumpTo( 1 );
17027        //   $.fancybox.getInstance( 'jumpTo', 1 );
17028        //   $.fancybox.getInstance( function() {
17029        //       console.info( this.currIndex );
17030        //   });
17031        // ======================================================
17032
17033        getInstance : function ( command ) {
17034            var instance = $('.fancybox-container:not(".fancybox-is-closing"):first').data( 'FancyBox' );
17035            var args     = Array.prototype.slice.call(arguments, 1);
17036
17037            if ( instance instanceof FancyBox ) {
17038
17039                if ( $.type( command ) === 'string' ) {
17040                    instance[ command ].apply( instance, args );
17041
17042                } else if ( $.type( command ) === 'function' ) {
17043                    command.apply( instance, args );
17044
17045                }
17046
17047                return instance;
17048            }
17049
17050            return false;
17051
17052        },
17053
17054
17055        // Create new instance
17056        // ===================
17057
17058        open : function ( items, opts, index ) {
17059            return new FancyBox( items, opts, index );
17060        },
17061
17062
17063        // Close current or all instances
17064        // ==============================
17065
17066        close : function ( all ) {
17067            var instance = this.getInstance();
17068
17069            if ( instance ) {
17070                instance.close();
17071
17072                // Try to find and close next instance
17073
17074                if ( all === true ) {
17075                    this.close();
17076                }
17077            }
17078
17079        },
17080
17081        // Close instances and unbind all events
17082        // ==============================
17083
17084        destroy : function() {
17085
17086            this.close( true );
17087
17088            $D.off( 'click.fb-start' );
17089
17090        },
17091
17092
17093        // Try to detect mobile devices
17094        // ============================
17095
17096        isMobile : document.createTouch !== undefined && /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent),
17097
17098
17099        // Detect if 'translate3d' support is available
17100        // ============================================
17101
17102        use3d : (function() {
17103            var div = document.createElement('div');
17104
17105            return window.getComputedStyle && window.getComputedStyle( div ).getPropertyValue('transform') && !(document.documentMode && document.documentMode < 11);
17106        }()),
17107
17108
17109        // Helper function to get current visual state of an element
17110        // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
17111        // =====================================================================
17112
17113        getTranslate : function( $el ) {
17114            var matrix;
17115
17116            if ( !$el || !$el.length ) {
17117                return false;
17118            }
17119
17120            matrix  = $el.eq( 0 ).css('transform');
17121
17122            if ( matrix && matrix.indexOf( 'matrix' ) !== -1 ) {
17123                matrix = matrix.split('(')[1];
17124                matrix = matrix.split(')')[0];
17125                matrix = matrix.split(',');
17126            } else {
17127                matrix = [];
17128            }
17129
17130            if ( matrix.length ) {
17131
17132                // If IE
17133                if ( matrix.length > 10 ) {
17134                    matrix = [ matrix[13], matrix[12], matrix[0], matrix[5] ];
17135
17136                } else {
17137                    matrix = [ matrix[5], matrix[4], matrix[0], matrix[3]];
17138                }
17139
17140                matrix = matrix.map(parseFloat);
17141
17142            } else {
17143                matrix = [ 0, 0, 1, 1 ];
17144
17145                var transRegex = /\.*translate\((.*)px,(.*)px\)/i;
17146                var transRez = transRegex.exec( $el.eq( 0 ).attr('style') );
17147
17148                if ( transRez ) {
17149                    matrix[ 0 ] = parseFloat( transRez[2] );
17150                    matrix[ 1 ] = parseFloat( transRez[1] );
17151                }
17152            }
17153
17154            return {
17155                top     : matrix[ 0 ],
17156                left    : matrix[ 1 ],
17157                scaleX  : matrix[ 2 ],
17158                scaleY  : matrix[ 3 ],
17159                opacity : parseFloat( $el.css('opacity') ),
17160                width   : $el.width(),
17161                height  : $el.height()
17162            };
17163
17164        },
17165
17166
17167        // Shortcut for setting "translate3d" properties for element
17168        // Can set be used to set opacity, too
17169        // ========================================================
17170
17171        setTranslate : function( $el, props ) {
17172            var str  = '';
17173            var css  = {};
17174
17175            if ( !$el || !props ) {
17176                return;
17177            }
17178
17179            if ( props.left !== undefined || props.top !== undefined ) {
17180                str = ( props.left === undefined ? $el.position().left : props.left )  + 'px, ' + ( props.top === undefined ? $el.position().top : props.top ) + 'px';
17181
17182                if ( this.use3d ) {
17183                    str = 'translate3d(' + str + ', 0px)';
17184
17185                } else {
17186                    str = 'translate(' + str + ')';
17187                }
17188            }
17189
17190            if ( props.scaleX !== undefined && props.scaleY !== undefined ) {
17191                str = (str.length ? str + ' ' : '') + 'scale(' + props.scaleX + ', ' + props.scaleY + ')';
17192            }
17193
17194            if ( str.length ) {
17195                css.transform = str;
17196            }
17197
17198            if ( props.opacity !== undefined ) {
17199                css.opacity = props.opacity;
17200            }
17201
17202            if ( props.width !== undefined ) {
17203                css.width = props.width;
17204            }
17205
17206            if ( props.height !== undefined ) {
17207                css.height = props.height;
17208            }
17209
17210            return $el.css( css );
17211        },
17212
17213
17214        // Simple CSS transition handler
17215        // =============================
17216
17217        animate : function ( $el, to, duration, callback, leaveAnimationName ) {
17218            var event = transitionEnd || 'transitionend';
17219
17220            if ( $.isFunction( duration ) ) {
17221                callback = duration;
17222                duration = null;
17223            }
17224
17225            if ( !$.isPlainObject( to ) ) {
17226                $el.removeAttr('style');
17227            }
17228
17229            $el.on( event, function(e) {
17230
17231                // Skip events from child elements and z-index change
17232                if ( e && e.originalEvent && ( !$el.is( e.originalEvent.target ) || e.originalEvent.propertyName == 'z-index' ) ) {
17233                    return;
17234                }
17235
17236                $el.off( event );
17237
17238                if ( $.isPlainObject( to ) ) {
17239
17240                    if ( to.scaleX !== undefined && to.scaleY !== undefined ) {
17241                        $el.css( 'transition-duration', '0ms' );
17242
17243                        to.width  = Math.round( $el.width()  * to.scaleX );
17244                        to.height = Math.round( $el.height() * to.scaleY );
17245
17246                        to.scaleX = 1;
17247                        to.scaleY = 1;
17248
17249                        $.fancybox.setTranslate( $el, to );
17250                    }
17251
17252                } else if ( leaveAnimationName !== true ) {
17253                    $el.removeClass( to );
17254                }
17255
17256                if ( $.isFunction( callback ) ) {
17257                    callback( e );
17258                }
17259
17260            });
17261
17262            if ( $.isNumeric( duration ) ) {
17263                $el.css( 'transition-duration', duration + 'ms' );
17264            }
17265
17266            if ( $.isPlainObject( to ) ) {
17267                $.fancybox.setTranslate( $el, to );
17268
17269            } else {
17270                $el.addClass( to );
17271            }
17272
17273            $el.data("timer", setTimeout(function() {
17274                $el.trigger( 'transitionend' );
17275            }, duration + 16));
17276
17277        },
17278
17279        stop : function( $el ) {
17280            clearTimeout( $el.data("timer") );
17281
17282            $el.off( transitionEnd );
17283        }
17284
17285    };
17286
17287
17288    // Default click handler for "fancyboxed" links
17289    // ============================================
17290
17291    function _run( e ) {
17292        var target	= e.currentTarget,
17293            opts	= e.data ? e.data.options : {},
17294            items	= opts.selector ? $( opts.selector ) : ( e.data ? e.data.items : [] ),
17295            value	= $(target).attr( 'data-fancybox' ) || '',
17296            index	= 0,
17297            active  = $.fancybox.getInstance();
17298
17299        e.preventDefault();
17300        e.stopPropagation();
17301
17302        // Avoid opening multiple times
17303        if ( active && active.current.opts.$orig.is( target ) ) {
17304            return;
17305        }
17306
17307        // Get all related items and find index for clicked one
17308        if ( value ) {
17309            items = items.length ? items.filter( '[data-fancybox="' + value + '"]' ) : $( '[data-fancybox="' + value + '"]' );
17310            index = items.index( target );
17311
17312            // Sometimes current item can not be found
17313            // (for example, when slider clones items)
17314            if ( index < 0 ) {
17315                index = 0;
17316            }
17317
17318        } else {
17319            items = [ target ];
17320        }
17321
17322        $.fancybox.open( items, opts, index );
17323    }
17324
17325
17326    // Create a jQuery plugin
17327    // ======================
17328
17329    $.fn.fancybox = function (options) {
17330        var selector;
17331
17332        options  = options || {};
17333        selector = options.selector || false;
17334
17335        if ( selector ) {
17336
17337            $( 'body' ).off( 'click.fb-start', selector ).on( 'click.fb-start', selector, {
17338                options : options
17339            }, _run );
17340
17341        } else {
17342
17343            this.off( 'click.fb-start' ).on( 'click.fb-start', {
17344                items   : this,
17345                options : options
17346            }, _run);
17347
17348        }
17349
17350        return this;
17351    };
17352
17353
17354    // Self initializing plugin
17355    // ========================
17356
17357    $D.on( 'click.fb-start', '[data-fancybox]', _run );
17358
17359}( window, document, window.jQuery || jQuery ));
17360
17361// ==========================================================================
17362//
17363// Media
17364// Adds additional media type support
17365//
17366// ==========================================================================
17367;(function ($) {
17368
17369	'use strict';
17370
17371	// Formats matching url to final form
17372
17373	var format = function (url, rez, params) {
17374		if ( !url ) {
17375			return;
17376		}
17377
17378		params = params || '';
17379
17380		if ( $.type(params) === "object" ) {
17381			params = $.param(params, true);
17382		}
17383
17384		$.each(rez, function (key, value) {
17385			url = url.replace('$' + key, value || '');
17386		});
17387
17388		if (params.length) {
17389			url += (url.indexOf('?') > 0 ? '&' : '?') + params;
17390		}
17391
17392		return url;
17393	};
17394
17395	// Object containing properties for each media type
17396
17397	var defaults = {
17398		youtube : {
17399			matcher : /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
17400			params  : {
17401				autoplay : 1,
17402				autohide : 1,
17403				fs  : 1,
17404				rel : 0,
17405				hd  : 1,
17406				wmode : 'transparent',
17407				enablejsapi : 1,
17408				html5 : 1
17409			},
17410			paramPlace : 8,
17411			type  : 'iframe',
17412			url   : '//www.youtube.com/embed/$4',
17413			thumb : '//img.youtube.com/vi/$4/hqdefault.jpg'
17414		},
17415
17416		vimeo : {
17417			matcher : /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
17418			params  : {
17419				autoplay : 1,
17420				hd : 1,
17421				show_title    : 1,
17422				show_byline   : 1,
17423				show_portrait : 0,
17424				fullscreen    : 1,
17425				api : 1
17426			},
17427			paramPlace : 3,
17428			type : 'iframe',
17429			url : '//player.vimeo.com/video/$2'
17430		},
17431
17432		metacafe : {
17433			matcher : /metacafe.com\/watch\/(\d+)\/(.*)?/,
17434			type    : 'iframe',
17435			url     : '//www.metacafe.com/embed/$1/?ap=1'
17436		},
17437
17438		dailymotion : {
17439			matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
17440			params : {
17441				additionalInfos : 0,
17442				autoStart : 1
17443			},
17444			type : 'iframe',
17445			url  : '//www.dailymotion.com/embed/video/$1'
17446		},
17447
17448		vine : {
17449			matcher : /vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,
17450			type    : 'iframe',
17451			url     : '//vine.co/v/$1/embed/simple'
17452		},
17453
17454		instagram : {
17455			matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
17456			type    : 'image',
17457			url     : '//$1/p/$2/media/?size=l'
17458		},
17459
17460		// Examples:
17461		// http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
17462		// https://www.google.com/maps/@37.7852006,-122.4146355,14.65z
17463		// https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
17464		gmap_place : {
17465			matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
17466			type    : 'iframe',
17467			url     : function (rez) {
17468				return '//maps.google.' + rez[2] + '/?ll=' + ( rez[9] ? rez[9] + '&z=' + Math.floor(  rez[10]  ) + ( rez[12] ? rez[12].replace(/^\//, "&") : '' )  : rez[12] ) + '&output=' + ( rez[12] && rez[12].indexOf('layer=c') > 0 ? 'svembed' : 'embed' );
17469			}
17470		},
17471
17472		// Examples:
17473		// https://www.google.com/maps/search/Empire+State+Building/
17474		// https://www.google.com/maps/search/?api=1&query=centurylink+field
17475		// https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393
17476		gmap_search : {
17477			matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,
17478			type    : 'iframe',
17479			url     : function (rez) {
17480				return '//maps.google.' + rez[2] + '/maps?q=' + rez[5].replace('query=', 'q=').replace('api=1', '') + '&output=embed';
17481			}
17482		}
17483	};
17484
17485	$(document).on('onInit.fb', function (e, instance) {
17486
17487		$.each(instance.group, function( i, item ) {
17488
17489			var url	 = item.src || '',
17490				type = false,
17491				media,
17492				thumb,
17493				rez,
17494				params,
17495				urlParams,
17496				o,
17497				provider;
17498
17499			// Skip items that already have content type
17500			if ( item.type ) {
17501				return;
17502			}
17503
17504			media = $.extend( true, {}, defaults, item.opts.media );
17505
17506			// Look for any matching media type
17507			$.each(media, function ( n, el ) {
17508				rez = url.match(el.matcher);
17509				o   = {};
17510				provider = n;
17511
17512				if (!rez) {
17513					return;
17514				}
17515
17516				type = el.type;
17517
17518				if ( el.paramPlace && rez[ el.paramPlace ] ) {
17519					urlParams = rez[ el.paramPlace ];
17520
17521					if ( urlParams[ 0 ] == '?' ) {
17522						urlParams = urlParams.substring(1);
17523					}
17524
17525					urlParams = urlParams.split('&');
17526
17527					for ( var m = 0; m < urlParams.length; ++m ) {
17528						var p = urlParams[ m ].split('=', 2);
17529
17530						if ( p.length == 2 ) {
17531							o[ p[0] ] = decodeURIComponent( p[1].replace(/\+/g, " ") );
17532						}
17533					}
17534				}
17535
17536				params = $.extend( true, {}, el.params, item.opts[ n ], o );
17537
17538				url   = $.type(el.url) === "function" ? el.url.call(this, rez, params, item) : format(el.url, rez, params);
17539				thumb = $.type(el.thumb) === "function" ? el.thumb.call(this, rez, params, item) : format(el.thumb, rez);
17540
17541				if ( provider === 'vimeo' ) {
17542					url = url.replace('&%23', '#');
17543				}
17544
17545				return false;
17546			});
17547
17548			// If it is found, then change content type and update the url
17549
17550			if ( type ) {
17551				item.src  = url;
17552				item.type = type;
17553
17554				if ( !item.opts.thumb && !( item.opts.$thumb && item.opts.$thumb.length ) ) {
17555					item.opts.thumb = thumb;
17556				}
17557
17558				if ( type === 'iframe' ) {
17559					$.extend(true, item.opts, {
17560						iframe : {
17561							preload : false,
17562							attr : {
17563								scrolling : "no"
17564							}
17565						}
17566					});
17567
17568					item.contentProvider = provider;
17569
17570					item.opts.slideClass += ' fancybox-slide--' + ( provider == 'gmap_place' || provider == 'gmap_search' ? 'map' : 'video' );
17571				}
17572
17573			} else {
17574
17575				// If no content type is found, then set it to `image` as fallback
17576				item.type = 'image';
17577			}
17578
17579		});
17580
17581	});
17582
17583}(window.jQuery));
17584
17585// ==========================================================================
17586//
17587// Guestures
17588// Adds touch guestures, handles click and tap events
17589//
17590// ==========================================================================
17591;(function (window, document, $) {
17592	'use strict';
17593
17594	var requestAFrame = (function () {
17595        return window.requestAnimationFrame ||
17596                window.webkitRequestAnimationFrame ||
17597                window.mozRequestAnimationFrame ||
17598                window.oRequestAnimationFrame ||
17599                // if all else fails, use setTimeout
17600                function (callback) {
17601                    return window.setTimeout(callback, 1000 / 60);
17602                };
17603    })();
17604
17605
17606    var cancelAFrame = (function () {
17607        return window.cancelAnimationFrame ||
17608                window.webkitCancelAnimationFrame ||
17609                window.mozCancelAnimationFrame ||
17610                window.oCancelAnimationFrame ||
17611                function (id) {
17612                    window.clearTimeout(id);
17613                };
17614    })();
17615
17616
17617	var pointers = function( e ) {
17618		var result = [];
17619
17620		e = e.originalEvent || e || window.e;
17621		e = e.touches && e.touches.length ? e.touches : ( e.changedTouches && e.changedTouches.length ? e.changedTouches : [ e ] );
17622
17623		for ( var key in e ) {
17624
17625			if ( e[ key ].pageX ) {
17626				result.push( { x : e[ key ].pageX, y : e[ key ].pageY } );
17627
17628			} else if ( e[ key ].clientX ) {
17629				result.push( { x : e[ key ].clientX, y : e[ key ].clientY } );
17630			}
17631		}
17632
17633		return result;
17634	};
17635
17636	var distance = function( point2, point1, what ) {
17637		if ( !point1 || !point2 ) {
17638			return 0;
17639		}
17640
17641		if ( what === 'x' ) {
17642			return point2.x - point1.x;
17643
17644		} else if ( what === 'y' ) {
17645			return point2.y - point1.y;
17646		}
17647
17648		return Math.sqrt( Math.pow( point2.x - point1.x, 2 ) + Math.pow( point2.y - point1.y, 2 ) );
17649	};
17650
17651	var isClickable = function( $el ) {
17652
17653		if ( $el.is('a,button,input,select,textarea') || $.isFunction( $el.get(0).onclick ) || $el.data('selectable') ) {
17654			return true;
17655		}
17656
17657		// Check for attributes like data-fancybox-next or data-fancybox-close
17658		for ( var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++ ) {
17659            if ( atts[i].nodeName.substr(0, 14) === 'data-fancybox-' ) {
17660                return true;
17661            }
17662        }
17663
17664	 	return false;
17665	};
17666
17667	var hasScrollbars = function( el ) {
17668		var overflowY = window.getComputedStyle( el )['overflow-y'];
17669		var overflowX = window.getComputedStyle( el )['overflow-x'];
17670
17671		var vertical   = (overflowY === 'scroll' || overflowY === 'auto') && el.scrollHeight > el.clientHeight;
17672		var horizontal = (overflowX === 'scroll' || overflowX === 'auto') && el.scrollWidth > el.clientWidth;
17673
17674		return vertical || horizontal;
17675	};
17676
17677	var isScrollable = function ( $el ) {
17678		var rez = false;
17679
17680		while ( true ) {
17681			rez	= hasScrollbars( $el.get(0) );
17682
17683			if ( rez ) {
17684				break;
17685			}
17686
17687			$el = $el.parent();
17688
17689			if ( !$el.length || $el.hasClass( 'fancybox-stage' ) || $el.is( 'body' ) ) {
17690				break;
17691			}
17692		}
17693
17694		return rez;
17695	};
17696
17697
17698	var Guestures = function ( instance ) {
17699		var self = this;
17700
17701		self.instance = instance;
17702
17703		self.$bg        = instance.$refs.bg;
17704		self.$stage     = instance.$refs.stage;
17705		self.$container = instance.$refs.container;
17706
17707		self.destroy();
17708
17709		self.$container.on( 'touchstart.fb.touch mousedown.fb.touch', $.proxy(self, 'ontouchstart') );
17710	};
17711
17712	Guestures.prototype.destroy = function() {
17713		this.$container.off( '.fb.touch' );
17714	};
17715
17716	Guestures.prototype.ontouchstart = function( e ) {
17717		var self = this;
17718
17719		var $target  = $( e.target );
17720		var instance = self.instance;
17721		var current  = instance.current;
17722		var $content = current.$content;
17723
17724		var isTouchDevice = ( e.type == 'touchstart' );
17725
17726		// Do not respond to both events
17727		if ( isTouchDevice ) {
17728	        self.$container.off( 'mousedown.fb.touch' );
17729	    }
17730
17731		// Ignore clicks while zooming or closing
17732		if ( !current || self.instance.isAnimating || self.instance.isClosing ) {
17733			e.stopPropagation();
17734			e.preventDefault();
17735
17736			return;
17737		}
17738
17739		// Ignore right click
17740		if ( e.originalEvent && e.originalEvent.button == 2 ) {
17741			return;
17742		}
17743
17744		// Ignore taping on links, buttons, input elements
17745		if ( !$target.length || isClickable( $target ) || isClickable( $target.parent() ) ) {
17746			return;
17747		}
17748
17749		// Ignore clicks on the scrollbar
17750		if ( e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left ) {
17751			return;
17752		}
17753
17754		self.startPoints = pointers( e );
17755
17756		// Prevent zooming if already swiping
17757		if ( !self.startPoints || ( self.startPoints.length > 1 && instance.isSliding ) ) {
17758			return;
17759		}
17760
17761		self.$target  = $target;
17762		self.$content = $content;
17763		self.canTap   = true;
17764
17765		$(document).off( '.fb.touch' );
17766
17767		$(document).on( isTouchDevice ? 'touchend.fb.touch touchcancel.fb.touch' : 'mouseup.fb.touch mouseleave.fb.touch',  $.proxy(self, "ontouchend"));
17768		$(document).on( isTouchDevice ? 'touchmove.fb.touch' : 'mousemove.fb.touch',  $.proxy(self, "ontouchmove"));
17769
17770		if ( !(instance.current.opts.touch || instance.canPan() ) || !( $target.is( self.$stage ) || self.$stage.find( $target ).length ) ) {
17771
17772			// Prevent ghosting
17773			if ( $target.is('img') ) {
17774				e.preventDefault();
17775			}
17776
17777			return;
17778		}
17779
17780		e.stopPropagation();
17781
17782		if ( !( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) ) {
17783			e.preventDefault();
17784		}
17785
17786		self.canvasWidth  = Math.round( current.$slide[0].clientWidth );
17787		self.canvasHeight = Math.round( current.$slide[0].clientHeight );
17788
17789		self.startTime = new Date().getTime();
17790		self.distanceX = self.distanceY = self.distance = 0;
17791
17792		self.isPanning = false;
17793		self.isSwiping = false;
17794		self.isZooming = false;
17795
17796		self.sliderStartPos  = self.sliderLastPos || { top: 0, left: 0 };
17797		self.contentStartPos = $.fancybox.getTranslate( self.$content );
17798		self.contentLastPos  = null;
17799
17800		if ( self.startPoints.length === 1 && !self.isZooming ) {
17801			self.canTap = !instance.isSliding;
17802
17803			if ( current.type === 'image' && ( self.contentStartPos.width > self.canvasWidth + 1 || self.contentStartPos.height > self.canvasHeight + 1 ) ) {
17804
17805				$.fancybox.stop( self.$content );
17806
17807				self.$content.css( 'transition-duration', '0ms' );
17808
17809				self.isPanning = true;
17810
17811			} else {
17812
17813				self.isSwiping = true;
17814			}
17815
17816			self.$container.addClass('fancybox-controls--isGrabbing');
17817		}
17818
17819		if ( self.startPoints.length === 2 && !instance.isAnimating && !current.hasError && current.type === 'image' && ( current.isLoaded || current.$ghost ) ) {
17820			self.isZooming = true;
17821
17822			self.isSwiping = false;
17823			self.isPanning = false;
17824
17825			$.fancybox.stop( self.$content );
17826
17827			self.$content.css( 'transition-duration', '0ms' );
17828
17829			self.centerPointStartX = ( ( self.startPoints[0].x + self.startPoints[1].x ) * 0.5 ) - $(window).scrollLeft();
17830			self.centerPointStartY = ( ( self.startPoints[0].y + self.startPoints[1].y ) * 0.5 ) - $(window).scrollTop();
17831
17832			self.percentageOfImageAtPinchPointX = ( self.centerPointStartX - self.contentStartPos.left ) / self.contentStartPos.width;
17833			self.percentageOfImageAtPinchPointY = ( self.centerPointStartY - self.contentStartPos.top  ) / self.contentStartPos.height;
17834
17835			self.startDistanceBetweenFingers = distance( self.startPoints[0], self.startPoints[1] );
17836		}
17837
17838	};
17839
17840	Guestures.prototype.ontouchmove = function( e ) {
17841
17842		var self = this;
17843
17844		self.newPoints = pointers( e );
17845
17846		if ( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) {
17847			e.stopPropagation();
17848
17849			self.canTap = false;
17850
17851			return;
17852		}
17853
17854		if ( !( self.instance.current.opts.touch || self.instance.canPan() ) || !self.newPoints || !self.newPoints.length ) {
17855			return;
17856		}
17857
17858		self.distanceX = distance( self.newPoints[0], self.startPoints[0], 'x' );
17859		self.distanceY = distance( self.newPoints[0], self.startPoints[0], 'y' );
17860
17861		self.distance = distance( self.newPoints[0], self.startPoints[0] );
17862
17863		// Skip false ontouchmove events (Chrome)
17864		if ( self.distance > 0 ) {
17865
17866			if ( !( self.$target.is( self.$stage ) || self.$stage.find( self.$target ).length ) ) {
17867				return;
17868			}
17869
17870			e.stopPropagation();
17871			e.preventDefault();
17872
17873			if ( self.isSwiping ) {
17874				self.onSwipe();
17875
17876			} else if ( self.isPanning ) {
17877				self.onPan();
17878
17879			} else if ( self.isZooming ) {
17880				self.onZoom();
17881			}
17882
17883		}
17884
17885	};
17886
17887	Guestures.prototype.onSwipe = function() {
17888
17889		var self = this;
17890
17891		var swiping = self.isSwiping;
17892		var left    = self.sliderStartPos.left || 0;
17893		var angle;
17894
17895		if ( swiping === true ) {
17896
17897			if ( Math.abs( self.distance ) > 10 )  {
17898
17899				self.canTap = false;
17900
17901				if ( self.instance.group.length < 2 && self.instance.opts.touch.vertical ) {
17902					self.isSwiping  = 'y';
17903
17904				} else if ( self.instance.isSliding || self.instance.opts.touch.vertical === false || ( self.instance.opts.touch.vertical === 'auto' && $( window ).width() > 800 ) ) {
17905					self.isSwiping  = 'x';
17906
17907				} else {
17908					angle = Math.abs( Math.atan2( self.distanceY, self.distanceX ) * 180 / Math.PI );
17909
17910					self.isSwiping = ( angle > 45 && angle < 135 ) ? 'y' : 'x';
17911				}
17912
17913				self.instance.isSliding = self.isSwiping;
17914
17915				// Reset points to avoid jumping, because we dropped first swipes to calculate the angle
17916				self.startPoints = self.newPoints;
17917
17918				$.each(self.instance.slides, function( index, slide ) {
17919					$.fancybox.stop( slide.$slide );
17920
17921					slide.$slide.css( 'transition-duration', '0ms' );
17922
17923					slide.inTransition = false;
17924
17925					if ( slide.pos === self.instance.current.pos ) {
17926						self.sliderStartPos.left = $.fancybox.getTranslate( slide.$slide ).left;
17927					}
17928				});
17929
17930				//self.instance.current.isMoved = true;
17931
17932				// Stop slideshow
17933				if ( self.instance.SlideShow && self.instance.SlideShow.isActive ) {
17934					self.instance.SlideShow.stop();
17935				}
17936			}
17937
17938		} else {
17939
17940			if ( swiping == 'x' ) {
17941
17942				// Sticky edges
17943				if ( self.distanceX > 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === 0 && !self.instance.current.opts.loop ) ) ) {
17944					left = left + Math.pow( self.distanceX, 0.8 );
17945
17946				} else if ( self.distanceX < 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop ) ) ) {
17947					left = left - Math.pow( -self.distanceX, 0.8 );
17948
17949				} else {
17950					left = left + self.distanceX;
17951				}
17952
17953			}
17954
17955			self.sliderLastPos = {
17956				top  : swiping == 'x' ? 0 : self.sliderStartPos.top + self.distanceY,
17957				left : left
17958			};
17959
17960			if ( self.requestId ) {
17961				cancelAFrame( self.requestId );
17962
17963				self.requestId = null;
17964			}
17965
17966			self.requestId = requestAFrame(function() {
17967
17968				if ( self.sliderLastPos ) {
17969					$.each(self.instance.slides, function( index, slide ) {
17970						var pos = slide.pos - self.instance.currPos;
17971
17972						$.fancybox.setTranslate( slide.$slide, {
17973							top  : self.sliderLastPos.top,
17974							left : self.sliderLastPos.left + ( pos * self.canvasWidth ) + ( pos * slide.opts.gutter )
17975						});
17976					});
17977
17978					self.$container.addClass( 'fancybox-is-sliding' );
17979				}
17980
17981			});
17982
17983		}
17984
17985	};
17986
17987	Guestures.prototype.onPan = function() {
17988
17989		var self = this;
17990
17991		var newOffsetX, newOffsetY, newPos;
17992
17993		self.canTap = false;
17994
17995		if ( self.contentStartPos.width > self.canvasWidth ) {
17996			newOffsetX = self.contentStartPos.left + self.distanceX;
17997
17998		} else {
17999			newOffsetX = self.contentStartPos.left;
18000		}
18001
18002		newOffsetY = self.contentStartPos.top + self.distanceY;
18003
18004		newPos = self.limitMovement( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
18005
18006		newPos.scaleX = self.contentStartPos.scaleX;
18007		newPos.scaleY = self.contentStartPos.scaleY;
18008
18009		self.contentLastPos = newPos;
18010
18011		if ( self.requestId ) {
18012			cancelAFrame( self.requestId );
18013
18014			self.requestId = null;
18015		}
18016
18017		self.requestId = requestAFrame(function() {
18018			$.fancybox.setTranslate( self.$content, self.contentLastPos );
18019		});
18020	};
18021
18022	// Make panning sticky to the edges
18023	Guestures.prototype.limitMovement = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
18024
18025		var self = this;
18026
18027		var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY;
18028
18029		var canvasWidth  = self.canvasWidth;
18030		var canvasHeight = self.canvasHeight;
18031
18032		var currentOffsetX = self.contentStartPos.left;
18033		var currentOffsetY = self.contentStartPos.top;
18034
18035		var distanceX = self.distanceX;
18036		var distanceY = self.distanceY;
18037
18038		// Slow down proportionally to traveled distance
18039
18040		minTranslateX = Math.max(0, canvasWidth  * 0.5 - newWidth  * 0.5 );
18041		minTranslateY = Math.max(0, canvasHeight * 0.5 - newHeight * 0.5 );
18042
18043		maxTranslateX = Math.min( canvasWidth  - newWidth,  canvasWidth  * 0.5 - newWidth  * 0.5 );
18044		maxTranslateY = Math.min( canvasHeight - newHeight, canvasHeight * 0.5 - newHeight * 0.5 );
18045
18046		if ( newWidth > canvasWidth ) {
18047
18048			//   ->
18049			if ( distanceX > 0 && newOffsetX > minTranslateX ) {
18050				newOffsetX = minTranslateX - 1 + Math.pow( -minTranslateX + currentOffsetX + distanceX, 0.8 ) || 0;
18051			}
18052
18053			//    <-
18054			if ( distanceX  < 0 && newOffsetX < maxTranslateX ) {
18055				newOffsetX = maxTranslateX + 1 - Math.pow( maxTranslateX - currentOffsetX - distanceX, 0.8 ) || 0;
18056			}
18057
18058		}
18059
18060		if ( newHeight > canvasHeight ) {
18061
18062			//   \/
18063			if ( distanceY > 0 && newOffsetY > minTranslateY ) {
18064				newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8 ) || 0;
18065			}
18066
18067			//   /\
18068			if ( distanceY < 0 && newOffsetY < maxTranslateY ) {
18069				newOffsetY = maxTranslateY + 1 - Math.pow ( maxTranslateY - currentOffsetY - distanceY, 0.8 ) || 0;
18070			}
18071
18072		}
18073
18074		return {
18075			top  : newOffsetY,
18076			left : newOffsetX
18077		};
18078
18079	};
18080
18081
18082	Guestures.prototype.limitPosition = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
18083
18084		var self = this;
18085
18086		var canvasWidth  = self.canvasWidth;
18087		var canvasHeight = self.canvasHeight;
18088
18089		if ( newWidth > canvasWidth ) {
18090			newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
18091			newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
18092
18093		} else {
18094
18095			// Center horizontally
18096			newOffsetX = Math.max( 0, canvasWidth / 2 - newWidth / 2 );
18097
18098		}
18099
18100		if ( newHeight > canvasHeight ) {
18101			newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
18102			newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
18103
18104		} else {
18105
18106			// Center vertically
18107			newOffsetY = Math.max( 0, canvasHeight / 2 - newHeight / 2 );
18108
18109		}
18110
18111		return {
18112			top  : newOffsetY,
18113			left : newOffsetX
18114		};
18115
18116	};
18117
18118	Guestures.prototype.onZoom = function() {
18119
18120		var self = this;
18121
18122		// Calculate current distance between points to get pinch ratio and new width and height
18123
18124		var currentWidth  = self.contentStartPos.width;
18125		var currentHeight = self.contentStartPos.height;
18126
18127		var currentOffsetX = self.contentStartPos.left;
18128		var currentOffsetY = self.contentStartPos.top;
18129
18130		var endDistanceBetweenFingers = distance( self.newPoints[0], self.newPoints[1] );
18131
18132		var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
18133
18134		var newWidth  = Math.floor( currentWidth  * pinchRatio );
18135		var newHeight = Math.floor( currentHeight * pinchRatio );
18136
18137		// This is the translation due to pinch-zooming
18138		var translateFromZoomingX = (currentWidth  - newWidth)  * self.percentageOfImageAtPinchPointX;
18139		var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
18140
18141		//Point between the two touches
18142
18143		var centerPointEndX = ((self.newPoints[0].x + self.newPoints[1].x) / 2) - $(window).scrollLeft();
18144		var centerPointEndY = ((self.newPoints[0].y + self.newPoints[1].y) / 2) - $(window).scrollTop();
18145
18146		// And this is the translation due to translation of the centerpoint
18147		// between the two fingers
18148
18149		var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
18150		var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
18151
18152		// The new offset is the old/current one plus the total translation
18153
18154		var newOffsetX = currentOffsetX + ( translateFromZoomingX + translateFromTranslatingX );
18155		var newOffsetY = currentOffsetY + ( translateFromZoomingY + translateFromTranslatingY );
18156
18157		var newPos = {
18158			top    : newOffsetY,
18159			left   : newOffsetX,
18160			scaleX : self.contentStartPos.scaleX * pinchRatio,
18161			scaleY : self.contentStartPos.scaleY * pinchRatio
18162		};
18163
18164		self.canTap = false;
18165
18166		self.newWidth  = newWidth;
18167		self.newHeight = newHeight;
18168
18169		self.contentLastPos = newPos;
18170
18171		if ( self.requestId ) {
18172			cancelAFrame( self.requestId );
18173
18174			self.requestId = null;
18175		}
18176
18177		self.requestId = requestAFrame(function() {
18178			$.fancybox.setTranslate( self.$content, self.contentLastPos );
18179		});
18180
18181	};
18182
18183	Guestures.prototype.ontouchend = function( e ) {
18184
18185		var self = this;
18186		var dMs  = Math.max( (new Date().getTime() ) - self.startTime, 1);
18187
18188		var swiping = self.isSwiping;
18189		var panning = self.isPanning;
18190		var zooming = self.isZooming;
18191
18192		self.endPoints = pointers( e );
18193
18194		self.$container.removeClass( 'fancybox-controls--isGrabbing' );
18195
18196		$(document).off( '.fb.touch' );
18197
18198		if ( self.requestId ) {
18199			cancelAFrame( self.requestId );
18200
18201			self.requestId = null;
18202		}
18203
18204		self.isSwiping = false;
18205		self.isPanning = false;
18206		self.isZooming = false;
18207
18208		if ( self.canTap )  {
18209			return self.onTap( e );
18210		}
18211
18212		self.speed = 366;
18213
18214		// Speed in px/ms
18215		self.velocityX = self.distanceX / dMs * 0.5;
18216		self.velocityY = self.distanceY / dMs * 0.5;
18217
18218		self.speedX = Math.max( self.speed * 0.5, Math.min( self.speed * 1.5, ( 1 / Math.abs( self.velocityX ) ) * self.speed ) );
18219
18220		if ( panning ) {
18221			self.endPanning();
18222
18223		} else if ( zooming ) {
18224			self.endZooming();
18225
18226		} else {
18227			self.endSwiping( swiping );
18228		}
18229
18230		return;
18231	};
18232
18233	Guestures.prototype.endSwiping = function( swiping ) {
18234
18235		var self = this;
18236		var ret = false;
18237
18238		self.instance.isSliding = false;
18239		self.sliderLastPos      = null;
18240
18241		// Close if swiped vertically / navigate if horizontally
18242		if ( swiping == 'y' && Math.abs( self.distanceY ) > 50 ) {
18243
18244			// Continue vertical movement
18245			$.fancybox.animate( self.instance.current.$slide, {
18246				top     : self.sliderStartPos.top + self.distanceY + ( self.velocityY * 150 ),
18247				opacity : 0
18248			}, 150 );
18249
18250			ret = self.instance.close( true, 300 );
18251
18252		} else if ( swiping == 'x' && self.distanceX > 50 && self.instance.group.length > 1 ) {
18253			ret = self.instance.previous( self.speedX );
18254
18255		} else if ( swiping == 'x' && self.distanceX < -50  && self.instance.group.length > 1 ) {
18256			ret = self.instance.next( self.speedX );
18257		}
18258
18259		if ( ret === false && ( swiping == 'x' || swiping == 'y' ) ) {
18260			self.instance.jumpTo( self.instance.current.index, 150 );
18261		}
18262
18263		self.$container.removeClass( 'fancybox-is-sliding' );
18264
18265	};
18266
18267	// Limit panning from edges
18268	// ========================
18269
18270	Guestures.prototype.endPanning = function() {
18271
18272		var self = this;
18273		var newOffsetX, newOffsetY, newPos;
18274
18275		if ( !self.contentLastPos ) {
18276			return;
18277		}
18278
18279		if ( self.instance.current.opts.touch.momentum === false ) {
18280			newOffsetX = self.contentLastPos.left;
18281			newOffsetY = self.contentLastPos.top;
18282
18283		} else {
18284
18285			// Continue movement
18286			newOffsetX = self.contentLastPos.left + ( self.velocityX * self.speed );
18287			newOffsetY = self.contentLastPos.top  + ( self.velocityY * self.speed );
18288		}
18289
18290		newPos = self.limitPosition( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
18291
18292		 newPos.width  = self.contentStartPos.width;
18293		 newPos.height = self.contentStartPos.height;
18294
18295		$.fancybox.animate( self.$content, newPos, 330 );
18296	};
18297
18298
18299	Guestures.prototype.endZooming = function() {
18300
18301		var self = this;
18302
18303		var current = self.instance.current;
18304
18305		var newOffsetX, newOffsetY, newPos, reset;
18306
18307		var newWidth  = self.newWidth;
18308		var newHeight = self.newHeight;
18309
18310		if ( !self.contentLastPos ) {
18311			return;
18312		}
18313
18314		newOffsetX = self.contentLastPos.left;
18315		newOffsetY = self.contentLastPos.top;
18316
18317		reset = {
18318		   	top    : newOffsetY,
18319		   	left   : newOffsetX,
18320		   	width  : newWidth,
18321		   	height : newHeight,
18322			scaleX : 1,
18323			scaleY : 1
18324	   };
18325
18326	   // Reset scalex/scaleY values; this helps for perfomance and does not break animation
18327	   $.fancybox.setTranslate( self.$content, reset );
18328
18329		if ( newWidth < self.canvasWidth && newHeight < self.canvasHeight ) {
18330			self.instance.scaleToFit( 150 );
18331
18332		} else if ( newWidth > current.width || newHeight > current.height ) {
18333			self.instance.scaleToActual( self.centerPointStartX, self.centerPointStartY, 150 );
18334
18335		} else {
18336
18337			newPos = self.limitPosition( newOffsetX, newOffsetY, newWidth, newHeight );
18338
18339			// Switch from scale() to width/height or animation will not work correctly
18340			$.fancybox.setTranslate( self.content, $.fancybox.getTranslate( self.$content ) );
18341
18342			$.fancybox.animate( self.$content, newPos, 150 );
18343		}
18344
18345	};
18346
18347	Guestures.prototype.onTap = function(e) {
18348		var self    = this;
18349		var $target = $( e.target );
18350
18351		var instance = self.instance;
18352		var current  = instance.current;
18353
18354		var endPoints = ( e && pointers( e ) ) || self.startPoints;
18355
18356		var tapX = endPoints[0] ? endPoints[0].x - self.$stage.offset().left : 0;
18357		var tapY = endPoints[0] ? endPoints[0].y - self.$stage.offset().top  : 0;
18358
18359		var where;
18360
18361		var process = function ( prefix ) {
18362
18363			var action = current.opts[ prefix ];
18364
18365			if ( $.isFunction( action ) ) {
18366				action = action.apply( instance, [ current, e ] );
18367			}
18368
18369			if ( !action) {
18370				return;
18371			}
18372
18373			switch ( action ) {
18374
18375				case "close" :
18376
18377					instance.close( self.startEvent );
18378
18379				break;
18380
18381				case "toggleControls" :
18382
18383					instance.toggleControls( true );
18384
18385				break;
18386
18387				case "next" :
18388
18389					instance.next();
18390
18391				break;
18392
18393				case "nextOrClose" :
18394
18395					if ( instance.group.length > 1 ) {
18396						instance.next();
18397
18398					} else {
18399						instance.close( self.startEvent );
18400					}
18401
18402				break;
18403
18404				case "zoom" :
18405
18406					if ( current.type == 'image' && ( current.isLoaded || current.$ghost ) ) {
18407
18408						if ( instance.canPan() ) {
18409							instance.scaleToFit();
18410
18411						} else if ( instance.isScaledDown() ) {
18412							instance.scaleToActual( tapX, tapY );
18413
18414						} else if ( instance.group.length < 2 ) {
18415							instance.close( self.startEvent );
18416						}
18417					}
18418
18419				break;
18420			}
18421
18422		};
18423
18424		// Ignore right click
18425		if ( e.originalEvent && e.originalEvent.button == 2 ) {
18426			return;
18427		}
18428
18429		// Skip if current slide is not in the center
18430		if ( instance.isSliding ) {
18431			return;
18432		}
18433
18434		// Skip if clicked on the scrollbar
18435		if ( tapX > $target[0].clientWidth + $target.offset().left ) {
18436			return;
18437		}
18438
18439		// Check where is clicked
18440		if ( $target.is( '.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container' ) ) {
18441			where = 'Outside';
18442
18443		} else if ( $target.is( '.fancybox-slide' ) ) {
18444			where = 'Slide';
18445
18446		} else if  ( instance.current.$content && instance.current.$content.has( e.target ).length ) {
18447		 	where = 'Content';
18448
18449		} else {
18450			return;
18451		}
18452
18453		// Check if this is a double tap
18454		if ( self.tapped ) {
18455
18456			// Stop previously created single tap
18457			clearTimeout( self.tapped );
18458			self.tapped = null;
18459
18460			// Skip if distance between taps is too big
18461			if ( Math.abs( tapX - self.tapX ) > 50 || Math.abs( tapY - self.tapY ) > 50 || instance.isSliding ) {
18462				return this;
18463			}
18464
18465			// OK, now we assume that this is a double-tap
18466			process( 'dblclick' + where );
18467
18468		} else {
18469
18470			// Single tap will be processed if user has not clicked second time within 300ms
18471			// or there is no need to wait for double-tap
18472			self.tapX = tapX;
18473			self.tapY = tapY;
18474
18475			if ( current.opts[ 'dblclick' + where ] && current.opts[ 'dblclick' + where ] !== current.opts[ 'click' + where ] ) {
18476				self.tapped = setTimeout(function() {
18477					self.tapped = null;
18478
18479					process( 'click' + where );
18480
18481				}, 300);
18482
18483			} else {
18484				process( 'click' + where );
18485			}
18486
18487		}
18488
18489		return this;
18490	};
18491
18492	$(document).on('onActivate.fb', function (e, instance) {
18493		if ( instance && !instance.Guestures ) {
18494			instance.Guestures = new Guestures( instance );
18495		}
18496	});
18497
18498	$(document).on('beforeClose.fb', function (e, instance) {
18499		if ( instance && instance.Guestures ) {
18500			instance.Guestures.destroy();
18501		}
18502	});
18503
18504
18505}(window, document, window.jQuery));
18506
18507// ==========================================================================
18508//
18509// SlideShow
18510// Enables slideshow functionality
18511//
18512// Example of usage:
18513// $.fancybox.getInstance().SlideShow.start()
18514//
18515// ==========================================================================
18516;(function (document, $) {
18517	'use strict';
18518
18519	var SlideShow = function( instance ) {
18520		this.instance = instance;
18521		this.init();
18522	};
18523
18524	$.extend( SlideShow.prototype, {
18525		timer    : null,
18526		isActive : false,
18527		$button  : null,
18528		speed    : 3000,
18529
18530		init : function() {
18531			var self = this;
18532
18533			self.$button = self.instance.$refs.toolbar.find('[data-fancybox-play]').on('click', function() {
18534				self.toggle();
18535			});
18536
18537			if ( self.instance.group.length < 2 || !self.instance.group[ self.instance.currIndex ].opts.slideShow ) {
18538				self.$button.hide();
18539			}
18540		},
18541
18542		set : function() {
18543			var self = this;
18544
18545			// Check if reached last element
18546			if ( self.instance && self.instance.current && (self.instance.current.opts.loop || self.instance.currIndex < self.instance.group.length - 1 )) {
18547				self.timer = setTimeout(function() {
18548					self.instance.next();
18549
18550				}, self.instance.current.opts.slideShow.speed || self.speed);
18551
18552			} else {
18553				self.stop();
18554				self.instance.idleSecondsCounter = 0;
18555				self.instance.showControls();
18556			}
18557
18558		},
18559
18560		clear : function() {
18561			var self = this;
18562
18563			clearTimeout( self.timer );
18564
18565			self.timer = null;
18566		},
18567
18568		start : function() {
18569			var self = this;
18570			var current = self.instance.current;
18571
18572			if ( self.instance && current && ( current.opts.loop || current.index < self.instance.group.length - 1 )) {
18573
18574				self.isActive = true;
18575
18576				self.$button
18577					.attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_STOP )
18578					.addClass( 'fancybox-button--pause' );
18579
18580				if ( current.isComplete ) {
18581					self.set();
18582				}
18583			}
18584		},
18585
18586		stop : function() {
18587			var self = this;
18588			var current = self.instance.current;
18589
18590			self.clear();
18591
18592			self.$button
18593				.attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_START )
18594				.removeClass( 'fancybox-button--pause' );
18595
18596			self.isActive = false;
18597		},
18598
18599		toggle : function() {
18600			var self = this;
18601
18602			if ( self.isActive ) {
18603				self.stop();
18604
18605			} else {
18606				self.start();
18607			}
18608		}
18609
18610	});
18611
18612	$(document).on({
18613		'onInit.fb' : function(e, instance) {
18614			if ( instance && !instance.SlideShow ) {
18615				instance.SlideShow = new SlideShow( instance );
18616			}
18617		},
18618
18619		'beforeShow.fb' : function(e, instance, current, firstRun) {
18620			var SlideShow = instance && instance.SlideShow;
18621
18622			if ( firstRun ) {
18623
18624				if ( SlideShow && current.opts.slideShow.autoStart ) {
18625					SlideShow.start();
18626				}
18627
18628			} else if ( SlideShow && SlideShow.isActive )  {
18629				SlideShow.clear();
18630			}
18631		},
18632
18633		'afterShow.fb' : function(e, instance, current) {
18634			var SlideShow = instance && instance.SlideShow;
18635
18636			if ( SlideShow && SlideShow.isActive ) {
18637				SlideShow.set();
18638			}
18639		},
18640
18641		'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
18642			var SlideShow = instance && instance.SlideShow;
18643
18644			// "P" or Spacebar
18645			if ( SlideShow && current.opts.slideShow && ( keycode === 80 || keycode === 32 ) && !$(document.activeElement).is( 'button,a,input' ) ) {
18646				keypress.preventDefault();
18647
18648				SlideShow.toggle();
18649			}
18650		},
18651
18652		'beforeClose.fb onDeactivate.fb' : function(e, instance) {
18653			var SlideShow = instance && instance.SlideShow;
18654
18655			if ( SlideShow ) {
18656				SlideShow.stop();
18657			}
18658		}
18659	});
18660
18661	// Page Visibility API to pause slideshow when window is not active
18662	$(document).on("visibilitychange", function() {
18663		var instance  = $.fancybox.getInstance();
18664		var SlideShow = instance && instance.SlideShow;
18665
18666		if ( SlideShow && SlideShow.isActive ) {
18667			if ( document.hidden ) {
18668				SlideShow.clear();
18669
18670			} else {
18671				SlideShow.set();
18672			}
18673		}
18674	});
18675
18676}(document, window.jQuery));
18677
18678// ==========================================================================
18679//
18680// FullScreen
18681// Adds fullscreen functionality
18682//
18683// ==========================================================================
18684;(function (document, $) {
18685	'use strict';
18686
18687	// Collection of methods supported by user browser
18688	var fn = (function () {
18689
18690		var fnMap = [
18691			[
18692				'requestFullscreen',
18693				'exitFullscreen',
18694				'fullscreenElement',
18695				'fullscreenEnabled',
18696				'fullscreenchange',
18697				'fullscreenerror'
18698			],
18699			// new WebKit
18700			[
18701				'webkitRequestFullscreen',
18702				'webkitExitFullscreen',
18703				'webkitFullscreenElement',
18704				'webkitFullscreenEnabled',
18705				'webkitfullscreenchange',
18706				'webkitfullscreenerror'
18707
18708			],
18709			// old WebKit (Safari 5.1)
18710			[
18711				'webkitRequestFullScreen',
18712				'webkitCancelFullScreen',
18713				'webkitCurrentFullScreenElement',
18714				'webkitCancelFullScreen',
18715				'webkitfullscreenchange',
18716				'webkitfullscreenerror'
18717
18718			],
18719			[
18720				'mozRequestFullScreen',
18721				'mozCancelFullScreen',
18722				'mozFullScreenElement',
18723				'mozFullScreenEnabled',
18724				'mozfullscreenchange',
18725				'mozfullscreenerror'
18726			],
18727			[
18728				'msRequestFullscreen',
18729				'msExitFullscreen',
18730				'msFullscreenElement',
18731				'msFullscreenEnabled',
18732				'MSFullscreenChange',
18733				'MSFullscreenError'
18734			]
18735		];
18736
18737		var val;
18738		var ret = {};
18739		var i, j;
18740
18741		for ( i = 0; i < fnMap.length; i++ ) {
18742			val = fnMap[ i ];
18743
18744			if ( val && val[ 1 ] in document ) {
18745				for ( j = 0; j < val.length; j++ ) {
18746					ret[ fnMap[ 0 ][ j ] ] = val[ j ];
18747				}
18748
18749				return ret;
18750			}
18751		}
18752
18753		return false;
18754	})();
18755
18756	// If browser does not have Full Screen API, then simply unset default button template and stop
18757	if ( !fn ) {
18758
18759		if ( $ && $.fancybox ) {
18760			$.fancybox.defaults.btnTpl.fullScreen = false;
18761		}
18762
18763		return;
18764	}
18765
18766	var FullScreen = {
18767
18768		request : function ( elem ) {
18769
18770			elem = elem || document.documentElement;
18771
18772			elem[ fn.requestFullscreen ]( elem.ALLOW_KEYBOARD_INPUT );
18773
18774		},
18775		exit : function () {
18776
18777			document[ fn.exitFullscreen ]();
18778
18779		},
18780		toggle : function ( elem ) {
18781
18782			elem = elem || document.documentElement;
18783
18784			if ( this.isFullscreen() ) {
18785				this.exit();
18786
18787			} else {
18788				this.request( elem );
18789			}
18790
18791		},
18792		isFullscreen : function()  {
18793
18794			return Boolean( document[ fn.fullscreenElement ] );
18795
18796		},
18797		enabled : function()  {
18798
18799			return Boolean( document[ fn.fullscreenEnabled ] );
18800
18801		}
18802	};
18803
18804	$(document).on({
18805		'onInit.fb' : function(e, instance) {
18806			var $container;
18807
18808			var $button = instance.$refs.toolbar.find('[data-fancybox-fullscreen]');
18809
18810			if ( instance && !instance.FullScreen && instance.group[ instance.currIndex ].opts.fullScreen ) {
18811				$container = instance.$refs.container;
18812
18813				$container.on('click.fb-fullscreen', '[data-fancybox-fullscreen]', function(e) {
18814
18815					e.stopPropagation();
18816					e.preventDefault();
18817
18818					FullScreen.toggle( $container[ 0 ] );
18819
18820				});
18821
18822				if ( instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true ) {
18823					FullScreen.request( $container[ 0 ] );
18824				}
18825
18826				// Expose API
18827				instance.FullScreen = FullScreen;
18828
18829			} else {
18830				$button.hide();
18831			}
18832
18833		},
18834
18835		'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
18836
18837			// "P" or Spacebar
18838			if ( instance && instance.FullScreen && keycode === 70 ) {
18839				keypress.preventDefault();
18840
18841				instance.FullScreen.toggle( instance.$refs.container[ 0 ] );
18842			}
18843
18844		},
18845
18846		'beforeClose.fb' : function( instance ) {
18847			if ( instance && instance.FullScreen ) {
18848				FullScreen.exit();
18849			}
18850		}
18851	});
18852
18853	$(document).on(fn.fullscreenchange, function() {
18854		var instance = $.fancybox.getInstance();
18855
18856		// If image is zooming, then force to stop and reposition properly
18857		if ( instance.current && instance.current.type === 'image' && instance.isAnimating ) {
18858			instance.current.$content.css( 'transition', 'none' );
18859
18860			instance.isAnimating = false;
18861
18862			instance.update( true, true, 0 );
18863		}
18864
18865		instance.trigger('onFullscreenChange', FullScreen.isFullscreen() );
18866
18867	});
18868
18869}(document, window.jQuery));
18870
18871// ==========================================================================
18872//
18873// Thumbs
18874// Displays thumbnails in a grid
18875//
18876// ==========================================================================
18877;(function (document, $) {
18878	'use strict';
18879
18880	var FancyThumbs = function( instance ) {
18881		this.instance = instance;
18882		this.init();
18883	};
18884
18885	$.extend( FancyThumbs.prototype, {
18886
18887		$button		: null,
18888		$grid		: null,
18889		$list		: null,
18890		isVisible	: false,
18891
18892		init : function() {
18893			var self = this;
18894
18895			var first  = self.instance.group[0],
18896				second = self.instance.group[1];
18897
18898			self.$button = self.instance.$refs.toolbar.find( '[data-fancybox-thumbs]' );
18899
18900			if ( self.instance.group.length > 1 && self.instance.group[ self.instance.currIndex ].opts.thumbs && (
18901		    		( first.type == 'image'  || first.opts.thumb  || first.opts.$thumb ) &&
18902		    		( second.type == 'image' || second.opts.thumb || second.opts.$thumb )
18903			)) {
18904
18905				self.$button.on('click', function() {
18906					self.toggle();
18907				});
18908
18909				self.isActive = true;
18910
18911			} else {
18912				self.$button.hide();
18913
18914				self.isActive = false;
18915			}
18916
18917		},
18918
18919		create : function() {
18920			var instance = this.instance,
18921				list,
18922				src;
18923
18924			this.$grid = $('<div class="fancybox-thumbs"></div>').appendTo( instance.$refs.container );
18925
18926			list = '<ul>';
18927
18928			$.each(instance.group, function( i, item ) {
18929
18930				src = item.opts.thumb || ( item.opts.$thumb ? item.opts.$thumb.attr('src') : null );
18931
18932				if ( !src && item.type === 'image' ) {
18933					src = item.src;
18934				}
18935
18936				if ( src && src.length ) {
18937					list += '<li data-index="' + i + '"  tabindex="0" class="fancybox-thumbs-loading"><img data-src="' + src + '" /></li>';
18938				}
18939
18940			});
18941
18942			list += '</ul>';
18943
18944			this.$list = $( list ).appendTo( this.$grid ).on('click', 'li', function() {
18945				instance.jumpTo( $(this).data('index') );
18946			});
18947
18948			this.$list.find('img').hide().one('load', function() {
18949
18950				var $parent		= $(this).parent().removeClass('fancybox-thumbs-loading'),
18951					thumbWidth	= $parent.outerWidth(),
18952					thumbHeight	= $parent.outerHeight(),
18953					width,
18954					height,
18955					widthRatio,
18956					heightRatio;
18957
18958				width  = this.naturalWidth	|| this.width;
18959				height = this.naturalHeight	|| this.height;
18960
18961				//Calculate thumbnail width/height and center it
18962
18963				widthRatio  = width  / thumbWidth;
18964				heightRatio = height / thumbHeight;
18965
18966				if (widthRatio >= 1 && heightRatio >= 1) {
18967					if (widthRatio > heightRatio) {
18968						width  = width / heightRatio;
18969						height = thumbHeight;
18970
18971					} else {
18972						width  = thumbWidth;
18973						height = height / widthRatio;
18974					}
18975				}
18976
18977				$(this).css({
18978					width         : Math.floor(width),
18979					height        : Math.floor(height),
18980					'margin-top'  : Math.min( 0, Math.floor(thumbHeight * 0.3 - height * 0.3 ) ),
18981					'margin-left' : Math.min( 0, Math.floor(thumbWidth  * 0.5 - width  * 0.5 ) )
18982				}).show();
18983
18984			})
18985			.each(function() {
18986				this.src = $( this ).data( 'src' );
18987			});
18988
18989		},
18990
18991		focus : function() {
18992
18993			if ( this.instance.current ) {
18994				this.$list
18995					.children()
18996					.removeClass('fancybox-thumbs-active')
18997					.filter('[data-index="' + this.instance.current.index  + '"]')
18998					.addClass('fancybox-thumbs-active')
18999					.focus();
19000			}
19001
19002		},
19003
19004		close : function() {
19005			this.$grid.hide();
19006		},
19007
19008		update : function() {
19009
19010			this.instance.$refs.container.toggleClass( 'fancybox-show-thumbs', this.isVisible );
19011
19012			if ( this.isVisible ) {
19013
19014				if ( !this.$grid ) {
19015					this.create();
19016				}
19017
19018				this.instance.trigger( 'onThumbsShow' );
19019
19020				this.focus();
19021
19022			} else if ( this.$grid ) {
19023				this.instance.trigger( 'onThumbsHide' );
19024			}
19025
19026			// Update content position
19027			this.instance.update();
19028
19029		},
19030
19031		hide : function() {
19032			this.isVisible = false;
19033			this.update();
19034		},
19035
19036		show : function() {
19037			this.isVisible = true;
19038			this.update();
19039		},
19040
19041		toggle : function() {
19042			this.isVisible = !this.isVisible;
19043			this.update();
19044		}
19045
19046	});
19047
19048	$(document).on({
19049
19050		'onInit.fb' : function(e, instance) {
19051			if ( instance && !instance.Thumbs ) {
19052				instance.Thumbs = new FancyThumbs( instance );
19053			}
19054		},
19055
19056		'beforeShow.fb' : function(e, instance, item, firstRun) {
19057			var Thumbs = instance && instance.Thumbs;
19058
19059			if ( !Thumbs || !Thumbs.isActive ) {
19060				return;
19061			}
19062
19063			if ( item.modal ) {
19064				Thumbs.$button.hide();
19065
19066				Thumbs.hide();
19067
19068				return;
19069			}
19070
19071			if ( firstRun && instance.opts.thumbs.autoStart === true ) {
19072				Thumbs.show();
19073			}
19074
19075			if ( Thumbs.isVisible ) {
19076				Thumbs.focus();
19077			}
19078		},
19079
19080		'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
19081			var Thumbs = instance && instance.Thumbs;
19082
19083			// "G"
19084			if ( Thumbs && Thumbs.isActive && keycode === 71 ) {
19085				keypress.preventDefault();
19086
19087				Thumbs.toggle();
19088			}
19089		},
19090
19091		'beforeClose.fb' : function( e, instance ) {
19092			var Thumbs = instance && instance.Thumbs;
19093
19094			if ( Thumbs && Thumbs.isVisible && instance.opts.thumbs.hideOnClose !== false ) {
19095				Thumbs.close();
19096			}
19097		}
19098
19099	});
19100
19101}(document, window.jQuery));
19102
19103// ==========================================================================
19104//
19105// Hash
19106// Enables linking to each modal
19107//
19108// ==========================================================================
19109;(function (document, window, $) {
19110	'use strict';
19111
19112	// Simple $.escapeSelector polyfill (for jQuery prior v3)
19113	if ( !$.escapeSelector ) {
19114		$.escapeSelector = function( sel ) {
19115			var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
19116			var fcssescape = function( ch, asCodePoint ) {
19117				if ( asCodePoint ) {
19118					// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
19119					if ( ch === "\0" ) {
19120						return "\uFFFD";
19121					}
19122
19123					// Control characters and (dependent upon position) numbers get escaped as code points
19124					return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
19125				}
19126
19127				// Other potentially-special ASCII characters get backslash-escaped
19128				return "\\" + ch;
19129			};
19130
19131			return ( sel + "" ).replace( rcssescape, fcssescape );
19132		};
19133	}
19134
19135	// Create new history entry only once
19136	var shouldCreateHistory = true;
19137
19138	// Variable containing last hash value set by fancyBox
19139	// It will be used to determine if fancyBox needs to close after hash change is detected
19140    var currentHash = null;
19141
19142	// Throttling the history change
19143	var timerID = null;
19144
19145	// Get info about gallery name and current index from url
19146    function parseUrl() {
19147        var hash    = window.location.hash.substr( 1 );
19148        var rez     = hash.split( '-' );
19149        var index   = rez.length > 1 && /^\+?\d+$/.test( rez[ rez.length - 1 ] ) ? parseInt( rez.pop( -1 ), 10 ) || 1 : 1;
19150        var gallery = rez.join( '-' );
19151
19152		// Index is starting from 1
19153		if ( index < 1 ) {
19154			index = 1;
19155		}
19156
19157        return {
19158            hash    : hash,
19159            index   : index,
19160            gallery : gallery
19161        };
19162    }
19163
19164	// Trigger click evnt on links to open new fancyBox instance
19165	function triggerFromUrl( url ) {
19166		var $el;
19167
19168        if ( url.gallery !== '' ) {
19169
19170			// If we can find element matching 'data-fancybox' atribute, then trigger click event for that ..
19171			$el = $( "[data-fancybox='" + $.escapeSelector( url.gallery ) + "']" ).eq( url.index - 1 );
19172
19173            if ( !$el.length ) {
19174				// .. if not, try finding element by ID
19175				$el = $( "#" + $.escapeSelector( url.gallery ) + "" );
19176			}
19177
19178			if ( $el.length ) {
19179				shouldCreateHistory = false;
19180
19181				$el.trigger( 'click' );
19182			}
19183
19184        }
19185	}
19186
19187	// Get gallery name from current instance
19188	function getGalleryID( instance ) {
19189		var opts;
19190
19191		if ( !instance ) {
19192			return false;
19193		}
19194
19195		opts = instance.current ? instance.current.opts : instance.opts;
19196
19197		return opts.hash || ( opts.$orig ? opts.$orig.data( 'fancybox' ) : ''  );
19198	}
19199
19200	// Star when DOM becomes ready
19201    $(function() {
19202
19203		// Small delay is used to allow other scripts to process "dom ready" event
19204		setTimeout(function() {
19205
19206			// Check if this module is not disabled
19207			if ( $.fancybox.defaults.hash === false ) {
19208				return;
19209			}
19210
19211			// Update hash when opening/closing fancyBox
19212		    $(document).on({
19213				'onInit.fb' : function( e, instance ) {
19214					var url, gallery;
19215
19216					if ( instance.group[ instance.currIndex ].opts.hash === false ) {
19217						return;
19218					}
19219
19220					url     = parseUrl();
19221					gallery = getGalleryID( instance );
19222
19223					// Make sure gallery start index matches index from hash
19224					if ( gallery && url.gallery && gallery == url.gallery ) {
19225						instance.currIndex = url.index - 1;
19226					}
19227
19228				},
19229
19230				'beforeShow.fb' : function( e, instance, current ) {
19231					var gallery;
19232
19233					if ( !current || current.opts.hash === false ) {
19234						return;
19235					}
19236
19237		            gallery = getGalleryID( instance );
19238
19239		            // Update window hash
19240		            if ( gallery && gallery !== '' ) {
19241
19242						if ( window.location.hash.indexOf( gallery ) < 0 ) {
19243			                instance.opts.origHash = window.location.hash;
19244			            }
19245
19246						currentHash = gallery + ( instance.group.length > 1 ? '-' + ( current.index + 1 ) : '' );
19247
19248						if ( 'replaceState' in window.history ) {
19249							if ( timerID ) {
19250								clearTimeout( timerID );
19251							}
19252
19253							timerID = setTimeout(function() {
19254								window.history[ shouldCreateHistory ? 'pushState' : 'replaceState' ]( {} , document.title, window.location.pathname + window.location.search + '#' +  currentHash );
19255
19256								timerID = null;
19257
19258								shouldCreateHistory = false;
19259
19260							}, 300);
19261
19262						} else {
19263							window.location.hash = currentHash;
19264						}
19265
19266		            }
19267
19268		        },
19269
19270				'beforeClose.fb' : function( e, instance, current ) {
19271					var gallery, origHash;
19272
19273					if ( timerID ) {
19274						clearTimeout( timerID );
19275					}
19276
19277					if ( current.opts.hash === false ) {
19278						return;
19279					}
19280
19281					gallery  = getGalleryID( instance );
19282					origHash = instance && instance.opts.origHash ? instance.opts.origHash : '';
19283
19284		            // Remove hash from location bar
19285		            if ( gallery && gallery !== '' ) {
19286
19287		                if ( 'replaceState' in history ) {
19288							window.history.replaceState( {} , document.title, window.location.pathname + window.location.search + origHash );
19289
19290		                } else {
19291							window.location.hash = origHash;
19292
19293							// Keep original scroll position
19294							$( window ).scrollTop( instance.scrollTop ).scrollLeft( instance.scrollLeft );
19295		                }
19296		            }
19297
19298					currentHash = null;
19299		        }
19300		    });
19301
19302			// Check if need to close after url has changed
19303			$(window).on('hashchange.fb', function() {
19304				var url = parseUrl();
19305
19306				if ( $.fancybox.getInstance() ) {
19307					if ( currentHash && currentHash !== url.gallery + '-' + url.index && !( url.index === 1 && currentHash == url.gallery ) ) {
19308						currentHash = null;
19309
19310						$.fancybox.close();
19311					}
19312
19313				} else if ( url.gallery !== '' ) {
19314					triggerFromUrl( url );
19315				}
19316			});
19317
19318			// Check current hash and trigger click event on matching element to start fancyBox, if needed
19319			triggerFromUrl( parseUrl() );
19320
19321		}, 50);
19322
19323    });
19324
19325}(document, window, window.jQuery));
19326
19327var $web5 = (typeof $web5 === 'undefined') ? {} : $web5;
19328$web5.data = ($web5.data == null) ? {} : $web5.data;
19329$web5.data.widgetsData = ($web5.data.widgetsData == null) ? {} : $web5.data.widgetsData;
19330$web5.data.widgetsTempData = ($web5.data.widgetsTempData == null) ? {} : $web5.data.widgetsTempData;
19331$web5.data.onReady = ($web5.data.onReady == null) ? {} : $web5.data.onReady;
19332$web5.data.onResize = ($web5.data.onResize == null) ? {} : $web5.data.onResize;
19333$web5.data.isReadyDone = false;
19334
19335$web5.data.windowWidth = null;
19336$web5.data.windowHeight = null;
19337
19338
19339$web5.getServerLanguageCode = function() {
19340
19341  let domain = document.domain;
19342  let lastDotIndex = domain.lastIndexOf(".");
19343  let langCode = domain.slice(lastDotIndex + 1, domain.length);
19344  if (langCode == "net" || domain == "localhost") langCode = "pl";
19345  if (langCode == 'eu') {
19346    let firstDotIndex = domain.indexOf('.');
19347    langCode = domain.slice(0, firstDotIndex);
19348  }
19349
19350  return langCode;
19351}
19352
19353$web5.getServerPath = function() {
19354  if (document.domain != 'localhost') {
19355    return ""
19356  }
19357  return "http://mf-dev.ceferty.net";
19358}
19359
19360$web5.getTargetDomainPath = function(relPath, absoluteTargetDomainUrl) {
19361  let domain = "";
19362  if (absoluteTargetDomainUrl) {
19363    domain = "https://" + $web5.settingsManager.accountMetaData.targetDomain + "/";
19364  }
19365  if ($web5.isStaticMode() || absoluteTargetDomainUrl) {
19366    return domain + relPath;
19367  }
19368
19369  if (relPath.indexOf("common/") != -1) {
19370    return domain + relPath;
19371  }
19372
19373  return $web5.getServerPath() + "/views/" + $web5.settingsManager.accountMetaData.targetDomain + '/editorv2/' + relPath;
19374}
19375
19376$web5.isStaticMode = function() {
19377  return typeof Web5Application === 'undefined';
19378}
19379
19380$web5.isAppMode = function() {
19381  return !$web5.isStaticMode();
19382}
19383
19384$web5.isSeam = function() {
19385  return typeof Seam !== 'undefined';
19386}
19387
19388
19389$web5.isPublishingActive = function() {
19390  return window.location.href.includes("/static/");
19391}
19392
19393$web5.addWidgetStaticData = function(widget, onReadyCallbackName, onResizeCallbackName) {
19394  $web5.data.widgetsData[widget.UID] = $web5.widgets[widget.UID].data;
19395  $web5.data.widgetsData[widget.UID].widgetTypeName = widget.typeName;
19396  $web5.data.widgetsTempData[widget.UID] = $web5.widgets[widget.UID].tempDataNotSerialized;
19397
19398  if (onReadyCallbackName) $web5.data.onReady[widget.UID] = onReadyCallbackName;
19399  if (onResizeCallbackName) $web5.data.onResize[widget.UID] = onResizeCallbackName;
19400}
19401
19402$web5.getWidgetDataByTypeName = function(widgetTypeName) {
19403  var datas = [];
19404  for (var index in $web5.data.widgetsData) {
19405    if ($web5.data.widgetsData[index].widgetTypeName != null && $web5.data.widgetsData[index].widgetTypeName == widgetTypeName) {
19406      datas.push($web5.data.widgetsData[index]);
19407    }
19408  }
19409
19410  return datas;
19411}
19412
19413$web5.addStaticData = function(propertyName, data, onReadyCallbackName) {
19414  $web5.data.widgetsData[propertyName] = data;
19415  if (onReadyCallbackName) $web5.data.onReady[propertyName] = onReadyCallbackName;
19416}
19417
19418$web5.removeWidgetStaticData = function(widget) {
19419  delete $web5.data.widgetsData[widget.UID];
19420  delete $web5.data.widgetsTempData[widget.UID];
19421  delete $web5.data.onReady[widget.UID];
19422  delete $web5.data.onResize[widget.UID];
19423}
19424
19425$web5.clearWidgets = function(widgets) {
19426  $web5.widgets = widgets;
19427  $web5.data.widgetsData = {}
19428  $web5.data.widgetsTempData = {};
19429};
19430
19431$web5.getData = function(propertyName) {
19432  return $web5.data.widgetsData[propertyName];
19433}
19434
19435
19436$web5.getWidgetData = function(widgetUID) {
19437
19438  if ($web5.widgets != null && $web5.widgets[widgetUID] == null) return null;
19439
19440  if (!$web5.isStaticMode()) {
19441    $web5.data.widgetsData[widgetUID] = $web5.widgets[widgetUID].data;
19442  }
19443
19444
19445  return $web5.data.widgetsData[widgetUID];
19446}
19447
19448$web5.getWidgetTempData = function(widgetUID) {
19449  if ($web5.isAppMode()) {
19450    if ($web5.widgets[widgetUID] == null || $web5.widgets[widgetUID].tempDataNotSerialized == null) return null;
19451    $web5.data.widgetsTempData[widgetUID] = $web5.widgets[widgetUID].tempDataNotSerialized;
19452  }
19453
19454  return $web5.data.widgetsTempData[widgetUID];
19455}
19456
19457$web5.getDomain = function() {
19458  if ($web5.isAppMode())
19459    return $web5.settingsManager.accountMetaData.targetDomain;
19460
19461  return window.location.host;
19462}
19463
19464
19465$(document).ready(function() {
19466  if ($web5.isStaticMode()) {
19467    for (var widgetUID in $web5.data.onReady) {
19468      var fName = $web5.data.onReady[widgetUID];
19469      eval(fName)(widgetUID);
19470    }
19471    $web5.data.isReadyDone = true;
19472  }
19473});
19474
19475$(window).resize(function(event, data) {
19476  if ($web5.isStaticMode() && this == event.target) { // resize dotyczy window a nie innego elementu, this to window
19477
19478    let width = $(window).width();
19479    //let height = $(window).height();
19480
19481    if (width == $web5.data.windowWidth) return;
19482
19483    $web5.data.windowWidth = width;
19484    //$web5.data.windowHeight = height;
19485
19486    let doOnResize = function() {
19487      if (!$web5.data.isReadyDone) {
19488        $web5.utilities.setTimoutOnce("doOnResize", doOnResize, 100);
19489        return;
19490      }
19491
19492      for (let widgetUID in $web5.data.onResize) {
19493        let fName = $web5.data.onResize[widgetUID];
19494        eval(fName)(widgetUID, data);
19495      }
19496    }
19497
19498    doOnResize();
19499  }
19500});
19501
19502$web5.Web5Audio = {};
19503$web5.Web5Audio.soundObjects = {};
19504
19505
19506
19507$web5.Web5Audio.getUrl = function(filePath) {
19508  if ($web5.isAppMode()) {
19509    if ($web5.settingsManager.accountMetaData == null || $web5.settingsManager.accountMetaData.targetDomain == "" || filePath == "") return "";
19510    return $web5.getTargetDomainPath(filePath);
19511  }
19512  return filePath;
19513}
19514
19515$web5.Web5Audio.playSound = function() {
19516  var data = $web5.getData("Web5Audio");
19517
19518  if (data.songs.length == 0) {
19519    return;
19520  };
19521
19522  //console.log("$web5.Web5Audio - playSound: " + data.songs.length + " " + data.currentTrack);
19523
19524  var currentTrackHolder = data.songs[data.currentTrack];
19525  var soundObject = $web5.Web5Audio.soundObjects[currentTrackHolder.songID];
19526
19527  var cannotPlay = function(data, soundObjectund) {
19528    data.playbackStatus = false;
19529    soundManager.stopAll();
19530    $web5.Web5Audio.updateUI();
19531    console.log("$web5.Web5Audio - cannot start music.");
19532  }
19533
19534  try {
19535    if (soundObject.playState == 0) {
19536      soundObject.play({ volume: data.volume });
19537    } else {
19538      soundObject.resume();
19539    };
19540
19541    data.playbackStatus = true;
19542
19543    if (soundObject.playState != 1) {
19544      cannotPlay(data, soundObject);
19545    }
19546
19547  } catch (err) {
19548    cannotPlay(data, soundObject);
19549  }
19550}
19551
19552$web5.Web5Audio.pauseSound = function() {
19553  var data = $web5.getData("Web5Audio");
19554  var currentTrackHolder = data.songs[data.currentTrack];
19555  var songID = currentTrackHolder.songID;
19556  soundManager.pause(songID);
19557  data.playbackStatus = false;
19558}
19559
19560
19561$web5.Web5Audio.togglePause = function() {
19562  var data = $web5.getData("Web5Audio");
19563
19564  if (data.playbackStatus == false) {
19565    $web5.Web5Audio.playSound();
19566  } else {
19567    $web5.Web5Audio.pauseSound();
19568  }
19569
19570  $web5.Web5Audio.updateUI();
19571}
19572
19573$web5.Web5Audio.nextSound = function() {
19574  var data = $web5.getData("Web5Audio");
19575  soundManager.stopAll();
19576
19577  if (data.songs.length == 0) {
19578    return
19579  };
19580
19581  data.currentTrack += 1;
19582
19583  if (data.currentTrack >= data.songs.length) {
19584    data.currentTrack = 0;
19585  }
19586
19587  if (data.playbackStatus == true) {
19588    $web5.Web5Audio.playSound();
19589  }
19590}
19591
19592$web5.Web5Audio.previousSound = function() {
19593  var data = $web5.getData("Web5Audio");
19594  soundManager.stopAll();
19595
19596  if (data.songs.length == 0) {
19597    return
19598  };
19599
19600  data.currentTrack -= 1;
19601
19602  if (data.currentTrack < 0) {
19603    data.currentTrack = data.songs.length - 1;
19604  }
19605
19606  if (data.playbackStatus == true) {
19607    $web5.Web5Audio.playSound();
19608  }
19609}
19610
19611
19612$web5.Web5Audio.playedTime = function() {
19613  var data = $web5.getData("Web5Audio");
19614  if (data.songs.length == 0) {
19615    return '00:00';
19616  }
19617  var soundHolder = data.songs[data.currentTrack];
19618  var soundObject = $web5.Web5Audio.soundObjects[soundHolder.songID];
19619
19620  if (soundObject != null) {
19621    return $web5.utilities.toMinSec(soundObject.position, true);
19622  }
19623  return '00:00';
19624}
19625
19626$web5.Web5Audio.progress = function() {
19627  var data = $web5.getData("Web5Audio");
19628  if (data.songs.length == 0) {
19629    return 0;
19630  }
19631  var soundHolder = data.songs[data.currentTrack];
19632  var soundObject = $web5.Web5Audio.soundObjects[soundHolder.songID];
19633
19634  if (soundObject == null || soundObject.playState == 0) {
19635    return 0;
19636  } else {
19637    var p = 100 * soundObject.position / soundObject.duration;
19638    return p;
19639  }
19640}
19641
19642
19643$web5.Web5Audio.findSongByID = function(songID) {
19644  var data = $web5.getData("Web5Audio");
19645  for (var index in data.songs) {
19646    var song = data.songs[index];
19647    if (song.songID == songID) return song;
19648  }
19649
19650  return null;
19651}
19652
19653$web5.Web5Audio.updateUI = function() {
19654  var data = $web5.getData("Web5Audio");
19655  var iconElement = $("#Web5AudioIcon");
19656
19657  if (iconElement.length == 0) return;
19658
19659  if (data.playbackStatus)
19660    iconElement.attr("src", "common/images/music_on.png");
19661  else
19662    iconElement.attr("src", "common/images/music_off.png");
19663}
19664
19665$web5.Web5Audio.onLoad = function() {
19666  var data = $web5.getData("Web5Audio");
19667  data.currentTrack = 0;
19668  $web5.Web5Audio.initData(data);
19669  $web5.Web5Audio.updateUI();
19670}
19671
19672$web5.Web5Audio.initData = function(data) {
19673  for (var index in data.songs) {
19674    var song = data.songs[index];
19675    $web5.Web5Audio.creatSoundObject(song);
19676  }
19677  // if (data.backgroundAudioOn && data.playbackStatus) {
19678  //   $web5.Web5Audio.playSound();
19679  // }
19680}
19681
19682
19683$web5.Web5Audio.creatSoundObject = function(song) {
19684  var soundObj = soundManager.createSound({
19685    url: $web5.Web5Audio.getUrl(song.url),
19686    autoLoad: true,
19687    autoPlay: false,
19688    id: song.songID,
19689    volume: '90',
19690    onfinish: function() {
19691      $web5.Web5Audio.nextSound();
19692    },
19693    onload: function() {
19694      song.duration = $web5.utilities.toMinSec(this.duration, true);
19695    },
19696  });
19697
19698  $web5.Web5Audio.soundObjects[song.songID] = soundObj;
19699}
19700
19701$web5.Web5Image = {};
19702var imageMaxWidthMargin = 0.1; //in %
19703$web5.Web5Image.lastImageParentWidth = {};
19704
19705$web5.Web5Image.busyImagePath = "common/images/";
19706$web5.Web5Image.busyImageFileName = "web5Busy.gif";
19707
19708$web5.Web5Image.getUrl = function(image, absoluteTargetDomainUrl) {
19709
19710  if ($web5.isAppMode() &&
19711    ($web5.settingsManager.accountMetaData == null || $web5.settingsManager.accountMetaData.targetDomain == "" || image.getFileName() == "")) return "";
19712
19713  return $web5.getTargetDomainPath(image.path + image.getFileName(), absoluteTargetDomainUrl);
19714}
19715
19716
19717
19718$web5.Web5Image.getThumbUrl = function(image, parentWidth, imageFixedHeight) {
19719
19720
19721  parentWidth == null ? 600 : parentWidth;
19722
19723  let imagePath = image.path + image.getFileName();
19724
19725  if (image.isLoading) return $web5.Web5Image.busyImagePath + $web5.Web5Image.busyImageFileName;
19726
19727
19728  let imageWidth = image.width;
19729
19730  thumbWidth = 0;
19731
19732  if (parentWidth <= 150 && imageWidth > 150) thumbWidth = 150;
19733  if (parentWidth > 150 && imageWidth > 300) thumbWidth = 300;
19734  if (parentWidth > 300 && imageWidth > 600) thumbWidth = 600;
19735  if (parentWidth > 600 && imageWidth > 900) thumbWidth = 900;
19736  if (parentWidth > 900 && imageWidth > 1200) thumbWidth = 1200;
19737
19738  if (parentWidth >= imageWidth) thumbWidth = 0;
19739
19740  if (imageFixedHeight != null) {
19741    let scale = image.height / image.width;
19742
19743    let scaledHeight = thumbWidth * scale;
19744    if (scaledHeight < imageFixedHeight && thumbWidth == 150 && imageWidth > 300) thumbWidth = 300;
19745
19746    scaledHeight = thumbWidth * scale;
19747    if (scaledHeight < imageFixedHeight && thumbWidth == 300 && imageWidth > 600) thumbWidth = 600;
19748
19749    scaledHeight = thumbWidth * scale;
19750    if (scaledHeight < imageFixedHeight && thumbWidth == 600 && imageWidth > 900) thumbWidth = 900;
19751
19752    scaledHeight = thumbWidth * scale;
19753    if (scaledHeight < imageFixedHeight && thumbWidth == 900 && imageWidth > 1200) thumbWidth = 1200;
19754
19755    scaledHeight = thumbWidth * scale;
19756    if (scaledHeight < imageFixedHeight && thumbWidth == 1200 && imageWidth > 1200) thumbWidth = 0;
19757
19758    scaledHeight = thumbWidth * scale;
19759    if (scaledHeight < imageFixedHeight) thumbWidth = 0;
19760  }
19761
19762
19763  if (thumbWidth == 1200) imagePath = image.path + "thumb1200_" + image.fileName;
19764  if (thumbWidth == 900) imagePath = image.path + "thumb900_" + image.fileName;
19765  if (thumbWidth == 600) imagePath = image.path + "thumb600_" + image.fileName;
19766  if (thumbWidth == 300) imagePath = image.path + "thumb300_" + image.fileName;
19767  if (thumbWidth == 150) imagePath = image.path + "thumb150_" + image.fileName;
19768  if (thumbWidth == 0) imagePath = image.path + image.fileName;
19769
19770  if (thumbWidth < parentWidth) {
19771    imagePath = image.path + image.fileName;
19772  }
19773
19774
19775  if ($web5.isAppMode()) {
19776    if ($web5.settingsManager.accountMetaData == null || $web5.settingsManager.accountMetaData.targetDomain == "" || image.fileName == "")
19777      return "";
19778
19779    return $web5.getTargetDomainPath(imagePath);
19780  }
19781
19782  return imagePath;
19783}
19784
19785$web5.Web5Image.getImageSize = function(image) {
19786  var tInfo = {};
19787  tInfo.naturalWidth = image.width;
19788  tInfo.naturalHeight = image.height;
19789
19790  return JSON.stringify(tInfo);
19791}
19792
19793
19794$web5.Web5Image.getFileName = function(image) {
19795  if (image.isLoading) return $web5.Web5Image.busyImageFileName;
19796  return image.fileName;
19797}
19798
19799
19800$web5.Web5Image.addImageMethods = function(image) {
19801  image.getUrl = function(absoluteTargetDomainUrl) {
19802    return $web5.Web5Image.getUrl(image, absoluteTargetDomainUrl);
19803  }
19804  image.getThumbUrl = function(maxAllowedWidth) {
19805    return $web5.Web5Image.getThumbUrl(image, maxAllowedWidth);
19806  }
19807
19808  image.getImageSize = function() {
19809    return $web5.Web5Image.getImageSize(image);
19810  }
19811
19812  image.getFileName = function() {
19813    return $web5.Web5Image.getFileName(image);
19814  }
19815
19816  $web5.link.addLinkMethods(image);
19817}
19818
19819
19820$web5.Web5Image.addImageListMethods = function(imageList) {
19821
19822  imageList.getList = function() {
19823    return this.images;
19824  }
19825
19826  imageList.length = function() {
19827    return this.images.length;
19828  }
19829}
19830
19831
19832$web5.Web5Image.adjustImageThumbStatic = function(imgElement) {
19833  var src = $(imgElement).attr('src');
19834  var thumbs = JSON.parse($(imgElement).attr("data-thumbs"));
19835
19836  if (src == null || thumbs == null || thumbs == "" || src == "") return;
19837  var width = $(imgElement).width();
19838
19839  var image = {};
19840  image.width = thumbs.naturalWidth;
19841  image.height = thumbs.naturalHeight;
19842  image.path = $web5.utilities.extractFilePathURL(src);
19843  image.fileName = $web5.utilities.extractFileNameWithExtentionURL(src).replace(/^thumb[\d]+_/, "");
19844  image.getFileName = function() {
19845    return image.fileName;
19846  }
19847
19848  var newSrc = $web5.Web5Image.getThumbUrl(image, width);
19849
19850  let lastWidth = $web5.Web5Image.lastImageParentWidth;
19851
19852  if (lastWidth[image.fileName] == null || lastWidth[image.fileName] != width) {
19853    lastWidth[image.fileName] = width;
19854    setTimeout(function() {
19855      $web5.Web5Image.adjustImageThumbStatic(imgElement);
19856    }, 300)
19857  }
19858
19859  let oldSrc = $(imgElement).attr('src');
19860  if (oldSrc != newSrc) $(imgElement).attr('src', newSrc);
19861
19862}
19863
19864
19865$web5.Web5Image.adjustThumbsStatic = function() {
19866
19867  if ($web5.isStaticMode()) {
19868    $("img[data-thumbs]").each(function() {
19869      $web5.Web5Image.adjustImageThumbStatic(this);
19870    });
19871  }
19872}
19873
19874$(window).resize(function() {
19875  $web5.Web5Image.adjustThumbsStatic();
19876});
19877
19878$(document).ready(function() {
19879  $web5.Web5Image.adjustThumbsStatic();
19880});
19881
19882$web5.link = {};
19883
19884
19885$web5.link.getTargeLinkURL = function(obj) {
19886  var data = obj.data == null ? obj : obj.data;
19887
19888  if (data.pageUID) {
19889    return obj.getTargetLinkPage().getPageURL();
19890  }
19891  return obj.currentLanguageData.customUrl;
19892}
19893
19894$web5.link.getTargetLinkPage = function(obj) {
19895  var data = obj.data == null ? obj : obj.data;
19896  return $web5.navigator.getPageByUID(data.pageUID);
19897}
19898
19899$web5.link.getTargeLinkURLAttr = function(obj) {
19900  var data = obj.data == null ? obj : obj.data;
19901  if (data.pageUID)
19902    return "";
19903  return "_blank";
19904}
19905
19906$web5.link.isLinkDefined = function(obj) {
19907  var data = obj.data == null ? obj : obj.data;
19908  return data.pageUID || !obj.isEmptyLanguageVeriableString("customUrl");
19909
19910}
19911
19912
19913$web5.link.addLinkMethods = function(obj, skipDataInit) {
19914
19915  if (!skipDataInit) $web5.multilingual.addLanguageVeriableProperty(obj, "currentLanguageData");
19916
19917  obj.getTargeLinkURL = function() {
19918    return $web5.link.getTargeLinkURL(obj);
19919  }
19920
19921  obj.getTargetLinkPage = function() {
19922    return $web5.link.getTargetLinkPage(obj);
19923  }
19924
19925  obj.getTargeLinkURLAttr = function() {
19926    return $web5.link.getTargeLinkURLAttr(obj);
19927  }
19928
19929  obj.isLinkDefined = function() {
19930    return $web5.link.isLinkDefined(obj);
19931  }
19932}
19933
19934$web5.multilingual = {};
19935
19936
19937$web5.multilingual.isLanguageDefined = function(obj, languageCode) {
19938  return obj.allLanguagesData[currentCode] != null;
19939}
19940
19941$web5.multilingual.getLanguageDataDontClone = function(obj, languageCode) {
19942  let currentCode = languageCode || obj.getCurrentSiteLanguageCode();
19943  let currentLanguageData = obj.allLanguagesData[currentCode];
19944  if (currentLanguageData == null) obj.allLanguagesData[currentCode] = {};
19945
19946  return obj.allLanguagesData[currentCode];
19947}
19948
19949$web5.multilingual.languageData = function(obj, languageCode) {
19950
19951  var currentCode = languageCode || obj.getCurrentSiteLanguageCode();
19952  var currentLanguageData = obj.allLanguagesData[currentCode];
19953  if (currentLanguageData == null && Object.keys(obj.allLanguagesData).length > 0) {
19954    var defaultLanguageCode = obj._getNotEmptyLanguageCode();
19955    obj._createDefaultLanguageValues(currentCode, defaultLanguageCode);
19956    return obj.allLanguagesData[currentCode];
19957  }
19958
19959  if (currentLanguageData == null && Object.keys(obj.allLanguagesData).length == 0) {
19960    return obj.allLanguagesData[currentCode] = {};
19961  }
19962
19963  return obj.allLanguagesData[currentCode];
19964
19965}
19966
19967$web5.multilingual._createDefaultLanguageValues = function(obj, currentLanguageCode, defaultLanguageCode) {
19968  obj.allLanguagesData[currentLanguageCode] = $web5.utilities.realCopyPlainData(obj.allLanguagesData[defaultLanguageCode]);
19969}
19970
19971$web5.multilingual._getNotEmptyLanguageCode = function(obj) {
19972  var defaultLanguageCode = obj.getCurrentEditorLanguageCode();
19973  if (obj.allLanguagesData[defaultLanguageCode] == null) {
19974    defaultLanguageCode = Object.keys(obj.allLanguagesData)[0];
19975  }
19976
19977  return defaultLanguageCode;
19978}
19979
19980$web5.multilingual.isEmptyLanguageVeriableString = function(obj, key) {
19981  for (let langCode in obj.allLanguagesData) {
19982    if (obj.allLanguagesData[langCode] != null && obj.allLanguagesData[langCode][key] != null && obj.allLanguagesData[langCode][key] != "") {
19983      return false;
19984    }
19985  }
19986  return true;
19987}
19988
19989$web5.multilingual.addLanguageVeriableProperty = function(obj, propertyName) {
19990
19991  obj.allLanguagesData = obj.allLanguagesData == null ? {} : obj.allLanguagesData;
19992
19993
19994  obj.getCurrentSiteLanguageCode = function() {
19995    return $("body").attr("data-siteLanguageCode");
19996  }
19997
19998  obj.getCurrentEditorLanguageCode = function() {
19999    return $("body").attr("data-editorLanguageCode");
20000  }
20001
20002  obj.getCurrentIndexSiteLanguageCode = function() {
20003    return $("body").attr("data-indexSiteLanguageCode");
20004  }
20005
20006  obj.isLanguageDefined = function(languageCode) {
20007    return $web5.multilingual.isLanguageDefined(obj, languageCode);
20008  }
20009
20010  obj.getLanguageDataDontClone = function(languageCode) {
20011    return $web5.multilingual.getLanguageDataDontClone(obj, languageCode);
20012  }
20013
20014  obj.languageData = function(languageCode) {
20015    return $web5.multilingual.languageData(obj, languageCode);
20016  }
20017
20018  obj.isEmptyLanguageVeriableString = function(key) {
20019    return $web5.multilingual.isEmptyLanguageVeriableString(obj, key);
20020  }
20021
20022  // private functions
20023
20024  obj._createDefaultLanguageValues = function(currentLanguageCode, defaultLanguageCode) {
20025    return $web5.multilingual._createDefaultLanguageValues(obj, currentLanguageCode, defaultLanguageCode);
20026  }
20027
20028  obj._getNotEmptyLanguageCode = function() {
20029    return $web5.multilingual._getNotEmptyLanguageCode(obj);
20030  }
20031
20032  obj.__defineGetter__(propertyName, function() {
20033    return obj.languageData();
20034  });
20035
20036  obj.__defineSetter__(propertyName, function(data) {
20037    obj.allLanguagesData[obj.getCurrentSiteLanguageCode()] = data;
20038  });
20039
20040  return obj;
20041};
20042
20043$web5.multilingual.staticSiteTextDB = function(key) {
20044
20045  var currentSiteLanguageCode = $("body").attr("data-siteLanguageCode");
20046  if (currentSiteLanguageCode == null || currentSiteLanguageCode == "") return null;
20047
20048  if (staticMessages[currentSiteLanguageCode] != null) {
20049    return staticMessages[currentSiteLanguageCode][key];
20050  }
20051
20052  return staticMessages['gb'][key];
20053}
20054
20055$web5.multilingual.getCurrentSiteLanguageCode = function() {
20056  return $("body").attr("data-siteLanguageCode");
20057}
20058
20059$web5.multilingual.getCurrentEditorLanguageCode = function() {
20060  return $("body").attr("data-editorLanguageCode");
20061}
20062
20063$web5.navigator = {};
20064
20065
20066$web5.navigator.getPageByUID = function(UID) {
20067  var allPages = $web5.getData("Web5Navigator");
20068
20069  for (var i = 0; i < allPages.length; i++) {
20070    var page = allPages[i];
20071    if (page.UID == UID) {
20072      return page;
20073    }
20074
20075    for (var j = 0; j < page.subpages.length; j++) {
20076      subPage = page.subpages[j];
20077      if (subPage.UID == UID) {
20078        return subPage;
20079      }
20080    }
20081  }
20082
20083  return null;
20084}
20085
20086$web5.navigator.getPageURL = function(page) {
20087  var allPages = $web5.getData("Web5Navigator");
20088  if (page == allPages[0] && page.getCurrentSiteLanguageCode() == page.getCurrentIndexSiteLanguageCode()) {
20089    return ""; // first page has always empty url -> domain.pl/
20090  }
20091
20092  if (page.currentLanguageData.customURL != "") {
20093    return page.currentLanguageData.customURL + ".html";
20094  }
20095  return page.currentLanguageData.relativeURL + ".html";
20096}
20097
20098$web5.navigator.addPageMethods = function(page) {
20099  page.getPageURL = function() {
20100    return $web5.navigator.getPageURL(page);
20101  }
20102}
20103
20104$web5.navigator.addPagesMethods = function() {
20105  if ($web5.isStaticMode()) {
20106    var allPages = $web5.getData("Web5Navigator");
20107    if (allPages != null) {
20108      for (var i = 0; i < allPages.length; i++) {
20109        var page = allPages[i];
20110        $web5.multilingual.addLanguageVeriableProperty(page, "currentLanguageData");
20111        $web5.navigator.addPageMethods(page);
20112        for (var j = 0; j < page.subpages.length; j++) {
20113          subPage = page.subpages[j];
20114          $web5.multilingual.addLanguageVeriableProperty(subPage, "currentLanguageData");
20115          $web5.navigator.addPageMethods(subPage);
20116        }
20117      }
20118    }
20119  }
20120}
20121
20122
20123$web5.navigator.addPagesMethods();
20124
20125$web5.shop = {};
20126
20127
20128$web5.shop.showBucket = function() {
20129
20130  let bucketHTML = $("#Web5Shop").html();
20131
20132  if (bucketHTML.includes("<!-- COMMENT START --> <!--")) {
20133    bucketHTML = bucketHTML.replace("<!-- COMMENT START --> <!--", "");
20134    bucketHTML = bucketHTML.replace("--> <!-- COMMENT END -->", "");
20135    $("#Web5Shop").html(bucketHTML);
20136  }
20137
20138  $web5.shop.setBucketDialgSize();
20139  $("#Web5Shop").show().focus().blur();
20140  $("#Web5ShopBuckt").show();
20141  $("#Web5ShopOrderData").hide();
20142  $("#Web5ShopOrderSend").hide();
20143  $("#Web5ShopOrderNotSend").hide();
20144  $("#Web5ShopSendingOrder").hide();
20145  $web5.shop.updateBucketUI();
20146}
20147
20148$web5.shop.hideBucket = function() {
20149  $("#Web5Shop").hide();
20150}
20151
20152$web5.shop.showOrderData = function() {
20153  var bucket = $web5.shop.getBucket();
20154  if (Object.keys(bucket).length == 0) return;
20155
20156  $("#Web5Shop").show();
20157  $("#Web5ShopBuckt").hide();
20158  $("#Web5ShopOrderSend").hide();
20159  $("#Web5ShopSendingOrder").hide();
20160  $("#Web5ShopOrderNotSend").hide();
20161  $("#Web5ShopOrderData").show();
20162}
20163
20164$web5.shop.showOrderSendDialog = function() {
20165  $("#Web5Shop").show();
20166  $("#Web5ShopBuckt").hide();
20167  $("#Web5ShopOrderData").hide();
20168  $("#Web5ShopSendingOrder").hide();
20169  $("#Web5ShopOrderNotSend").hide();
20170  $("#Web5ShopOrderSend").show();
20171}
20172
20173$web5.shop.showOrderSendingDialog = function() {
20174  $("#Web5Shop").show();
20175  $("#Web5ShopBuckt").hide();
20176  $("#Web5ShopOrderData").hide();
20177  $("#Web5ShopOrderSend").hide();
20178  $("#Web5ShopOrderNotSend").hide();
20179  $("#Web5ShopSendingOrder").show().focus();
20180}
20181
20182$web5.shop.showOrderNotSendDialog = function() {
20183  $("#Web5Shop").show();
20184  $("#Web5ShopBuckt").hide();
20185  $("#Web5ShopOrderData").hide();
20186  $("#Web5ShopOrderSend").hide();
20187  $("#Web5ShopSendingOrder").hide();
20188  $("#Web5ShopOrderNotSend").show().focus();
20189
20190}
20191
20192$web5.shop.offerToString = function(offer) {
20193  var title = offer.currentLanguageData.title;
20194  var price = offer.currentLanguageData.price;
20195  var bucketOffer = { title: title, price: price };
20196  var uriEncodedProduct = encodeURIComponent(JSON.stringify(bucketOffer));
20197  var encodedProduct = window.btoa(uriEncodedProduct);
20198
20199  return encodedProduct
20200}
20201
20202$web5.shop.offerFromString = function(offerString) {
20203  var decodedResult = window.atob(offerString);
20204  var uriDecodedResult = decodeURIComponent(decodedResult);
20205  var offer = JSON.parse(uriDecodedResult);
20206  return offer;
20207}
20208
20209
20210
20211$web5.shop.addOfferToBucket = function(offerUID, offerString) {
20212  var bucket = $web5.shop.getBucket();
20213  var offer = $web5.shop.offerFromString(offerString);
20214
20215  if (bucket[offerUID] == null) {
20216    bucket[offerUID] = {};
20217    bucket[offerUID].quantity = 1;
20218  } else {
20219    bucket[offerUID].quantity++;
20220  }
20221
20222  bucket[offerUID].title = offer.title;
20223  bucket[offerUID].price = offer.price;
20224
20225  $web5.shop.saveBucket(bucket);
20226  $web5.shop.showBucket();
20227
20228}
20229
20230$web5.shop.addQuantity = function(UID) {
20231  var bucket = $web5.shop.getBucket();
20232  bucket[UID].quantity += 1;
20233  $web5.shop.saveBucket(bucket);
20234  $web5.shop.updateBucketUI();
20235}
20236
20237$web5.shop.substractQuantity = function(UID) {
20238  var bucket = $web5.shop.getBucket();
20239  bucket[UID].quantity -= 1;
20240  if (bucket[UID].quantity <= 0) {
20241    delete bucket[UID];
20242  }
20243  $web5.shop.saveBucket(bucket);
20244  $web5.shop.updateBucketUI();
20245}
20246
20247$web5.shop.getBucket = function() {
20248  var result = $web5.utilities.mfCookie.read('mfShoppingCartEditorV2');
20249  if (result != null) {
20250    var decodedResult = window.atob(result);
20251    var uriDecodedResult = decodeURIComponent(decodedResult);
20252    var bucket = JSON.parse(uriDecodedResult);
20253    return bucket;
20254  }
20255  return {};
20256}
20257
20258$web5.shop.saveBucket = function(bucket) {
20259  var uriEncodedProductsList = encodeURIComponent(JSON.stringify(bucket));
20260  var encodedProductsList = window.btoa(uriEncodedProductsList);
20261  $web5.utilities.mfCookie.create('mfShoppingCartEditorV2', encodedProductsList, 30);
20262}
20263
20264$web5.shop.setBucketDialgSize = function() {
20265  var h = $(window).height();
20266  var w = $(window).width();
20267
20268  var marginLeft = 0;
20269
20270  if (w > 800) {
20271    marginLeft = Math.ceil((w - 800) / 2);
20272    w = 800;
20273  }
20274
20275  var marginTop = 0;
20276
20277  if (h > 1200) {
20278    marginTop = Math.ceil((w - 1200) / 2);
20279    h = 1200;
20280  }
20281
20282  $("#Web5Shop").css('width', w + "px");
20283  $("#Web5Shop").css('height', h + "px");
20284  $("#Web5Shop").css('margin-left', marginLeft + "px");
20285  $("#Web5Shop").css('margin-top', marginTop + "px");
20286}
20287
20288
20289$web5.shop.updateBucketUI = function() {
20290
20291  var bucketBodyElemnent = $("#Web5Shop_Products");
20292  var bucket = $web5.shop.getBucket();
20293  var totalPrice = 0;
20294  var sumPrice = 0;
20295
20296  var bucketHtml = "";
20297
20298  for (var UID in bucket) {
20299    var bucketItem = bucket[UID];
20300
20301    var productPrice = parseFloat(bucketItem.price.replace(/,/g, '.'));
20302    if (isNaN(productPrice)) {
20303      totalPrice = "";
20304    } else {
20305      totalPrice = productPrice * bucketItem.quantity;
20306    }
20307
20308    if (!isNaN(productPrice)) {
20309      sumPrice += (productPrice * bucketItem.quantity);
20310    }
20311
20312    var itemHtml = "";
20313    itemHtml += "\n<tr>";
20314    itemHtml += "\n    <td style=\"text-align: left; display:table-cell; vertical-align:middle; min-width: 96px\">" + bucketItem.quantity;
20315    itemHtml += "\n            <button type=\"button\" class=\"btn btn-mini btn-success\" onclick=\"$web5.shop.addQuantity('" + UID + "')\"";
20316    itemHtml += "\n                style=\"display:table-cell; vertical-align:middle;\" alt=\"" + $web5.multilingual.staticSiteTextDB('shop_add_to_cart_text') + "\"><b>+<\/b><\/button>";
20317    itemHtml += "\n            <button type=\"button\" class=\"btn btn-mini btn-danger\" onclick=\"$web5.shop.substractQuantity('" + UID + "')\"";
20318    itemHtml += "\n                style=\"display:table-cell; vertical-align:middle;\"><b>-<\/b><\/button> ";
20319    itemHtml += "\n    <\/td>";
20320    itemHtml += "\n    <td style=\"text-align: left; display:table-cell; vertical-align:middle; width:auto;\">" + bucketItem.title + "<\/td>";
20321    itemHtml += "\n    <td style=\"text-align: right; display:table-cell; vertical-align:middle; \">" + bucketItem.price + "<\/td>";
20322
20323    itemHtml += "\n    <td style=\"text-align: right; display:table-cell; vertical-align:middle; \">" + totalPrice + "<\/td>";
20324
20325    itemHtml += "\n<\/tr>";
20326
20327    bucketHtml += itemHtml
20328  }
20329
20330  bucketBodyElemnent.html(bucketHtml);
20331
20332  var bucketBodyElemnentSummary = $("#Web5Shop_Summary");
20333  bucketBodyElemnentSummary.html(sumPrice)
20334
20335}
20336
20337$web5.shop.placeOrder = function() {
20338  var bucket = $web5.shop.getBucket();
20339  var order = [];
20340  for (var i in bucket) {
20341    var bucketItem = bucket[i];
20342    var item = {};
20343    item['number'] = bucketItem.quantity;
20344    item['productType'] = { 'name': bucketItem.title, 'price': bucketItem.price };
20345    order.push(item);
20346  }
20347
20348  var productsList = JSON.stringify(order);
20349  if (productsList.indexOf('"') === 0) { //JSON implementation fix for editor
20350    productsList = productsList.substring(1, productsList.length - 1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
20351  }
20352  var uriEncodedProductsList = encodeURIComponent(productsList)
20353  var encodedProductsList = window.btoa(uriEncodedProductsList);
20354
20355  //var confirmationLang = $("#Web5Shop").attr('data-language');
20356  var confirmationLocale = $("#Web5Shop").attr('data-locale');
20357  var email = $("#Web5ShopBucketEmail").val();
20358  var phone = $("#Web5ShopBucketPhone").val();
20359  var message = $("#Web5ShopBucketMessage").val();
20360
20361  if (phone != null && phone != "") {
20362    message += ". " + $web5.multilingual.staticSiteTextDB('tel_no') + ": " + phone;
20363  }
20364
20365  if (!$web5.utilities.isValidEmail(email)) {
20366    $("#Web5ShopBucketEmailError").removeClass('hidden');
20367    setTimeout(function() { $("#Web5ShopBucketEmailError").addClass('hidden'); }, 5000);
20368    return;
20369  }
20370
20371  var sendingInProgress = false;
20372
20373  if ($web5.isSeam()) {
20374    sendingInProgress = true;
20375    $web5.shop.showOrderSendingDialog();
20376    Seam.Component.getInstance('shopCheckoutAction').sendCheckoutEmailEditorV2(email, message, encodedProductsList, confirmationLocale, $web5.getDomain(),
20377      function() {
20378        $web5.shop.showOrderSendDialog();
20379        $web5.shop.saveBucket({});
20380        sendingInProgress = false;
20381      });
20382    setTimeout(function() {
20383      if (sendingInProgress) {
20384        $web5.shop.showOrderNotSendDialog();
20385        sendingInProgress = false;
20386      }
20387    }, 10000);
20388  } else {
20389    $web5.shop.hideBucket();
20390  }
20391}
20392
20393$(window).resize($web5.shop.setBucketDialgSize);
20394
20395$web5.uiTheme = {};
20396
20397$web5.uiTheme.googleFontsList = ['IM Fell DW Pica', 'Inconsolata', 'Sorts Mill Goudy', 'Reenie Beanie', 'Lobster',
20398  'Yanone Kaffeesatz', 'Cantarell', 'PT Serif', 'Oswald', 'Open Sans', 'Lato', 'Fira Sans', 'Fira Sans Extra Condensed', 'Josefin Sans', 'BenchNine',
20399  'Dancing Script', 'Pacifico', 'Courgette',  'Cormorant Garamond', 'Roboto Mono', 'Architects Daughter', 'Patrick Hand'
20400];
20401
20402
20403$web5.uiTheme.fontsList = $web5.uiTheme.googleFontsList.concat(['Josefin Sans Light']);
20404
20405$web5.utilities = {};
20406$web5.utilities.timers = {};
20407$web5.utilities.timers.time = {};
20408
20409$web5.utilities.betterExtendInplaceJSONDataOnly = function(objA, objB, objC) {
20410  let a = objA;
20411
20412  if (objB == null) {
20413    objB = {};
20414  }
20415
20416  let b = $web5.utilities.realCopyPlainData(objB);
20417
20418  _.mergeWith(a, b, function(a, b) {
20419    if (_.isArray(b)) {
20420      return b;
20421    }
20422  });
20423
20424  if (objC != null) {
20425    let c = $web5.utilities.realCopyPlainData(objC);
20426    _.mergeWith(a, c, function(a, c) {
20427      if (_.isArray(c)) {
20428        return c;
20429      }
20430    });
20431  }
20432  return a;
20433}
20434
20435$web5.utilities.realCopyPlainDataNoTempLangAngular = function(data) {
20436  return JSON.stringify(data, function(key, value) {
20437    if (key !== 'tempDataNotSerialized' && key !== 'currentLanguageData' && key !== '$$hashKey') {
20438      return value;
20439    };
20440  });
20441}
20442
20443
20444$web5.utilities.realCopyPlainData = function(data) {
20445  if (data == null) return null;
20446  return JSON.parse(JSON.stringify(data));
20447}
20448
20449
20450$web5.utilities.toMinSec = function(ms, leadingZero) {
20451  let seconds = Math.floor(ms / 1000);
20452  let minutes = '' + (Math.floor(seconds / 60));
20453  seconds = '' + (seconds - (minutes * 60));
20454  if (leadingZero == true) {
20455    minutes = minutes.length == 2 ? minutes : "0" + minutes;
20456    seconds = seconds.length == 2 ? seconds : "0" + seconds;
20457  }
20458  let format = minutes + ':' + seconds;
20459  return format;
20460}
20461
20462
20463$web5.utilities.isOnlyFileName = function(filePath) {
20464  let slashIndex = filePath.lastIndexOf("/");
20465  return slashIndex == -1;
20466}
20467
20468$web5.utilities.createNewFileNameNewTimeStamp = function(fileName) {
20469  let fileNameNoExtention = $web5.utilities.extractFileNameNoExtention(fileName);
20470  let fileExtention = $web5.utilities.extractFileExtention(fileName);
20471  fileNameNoExtention = fileNameNoExtention.replace(/\d+$/, "");
20472  fileNameNoExtention = fileNameNoExtention.replace(/\_$/, "");
20473
20474  return fileNameNoExtention + "_" + new Date().getTime() + "." + fileExtention;
20475}
20476
20477$web5.utilities.extractFileNameNoExtention = function(filePath) {
20478  let slashIndex = filePath.lastIndexOf("/");
20479  if (slashIndex > -1) {
20480    filePath = filePath.substr(slashIndex + 1);
20481  }
20482  let dotIndex = filePath.lastIndexOf(".");
20483  if (dotIndex > -1) {
20484    return filePath.substr(0, dotIndex);
20485  }
20486  return filePath;
20487}
20488
20489$web5.utilities.extractFileNameWithExtention = function(filePath) {
20490  let slashIndex = filePath.lastIndexOf("/");
20491  if (slashIndex == -1) {
20492    return filePath;
20493  }
20494  return filePath.substr(slashIndex + 1);
20495}
20496
20497$web5.utilities.extractFileNameWithExtentionURL = function(filePath) {
20498  filePath = decodeURI(filePath);
20499  return $web5.utilities.extractFileNameWithExtention(filePath);
20500}
20501
20502$web5.utilities.extractFilePath = function(filePath) {
20503  let slashIndex = filePath.lastIndexOf("/");
20504  if (slashIndex == -1) {
20505    return "";
20506  }
20507  return filePath.substr(0, slashIndex + 1);
20508}
20509
20510$web5.utilities.extractFilePathURL = function(filePath) {
20511  filePath = decodeURI(filePath);
20512  return $web5.utilities.extractFilePath(filePath);
20513}
20514
20515$web5.utilities.extractFileExtention = function(filePath) {
20516  let slashIndex = filePath.lastIndexOf("/");
20517  if (slashIndex > -1) {
20518    filePath = filePath.substr(slashIndex + 1);
20519  }
20520  let dotIndex = filePath.lastIndexOf(".");
20521  if (dotIndex > -1) {
20522    return (filePath.substr(dotIndex + 1)).toLowerCase();
20523  }
20524
20525  return "";
20526}
20527
20528
20529$web5.utilities.fancybox = function() {
20530  $().fancybox({
20531    selector: '[data-fancybox="images"][href!=""]',
20532    loop: true,
20533    infobar: true,
20534    caption: function(instance, item) {
20535      let caption = $(this).attr('data-caption') || '';
20536      return '<center>(<span data-fancybox-index></span>/<span data-fancybox-count></span>)' + (caption.length ? ' ' + caption : '') + '</center>';
20537    },
20538  });
20539
20540  $().fancybox({
20541    selector: '[data-fancybox="slideshow"][href!=""]',
20542    loop: true,
20543    infobar: true,
20544    caption: function(instance, item) {
20545      let caption = $(this).attr('data-caption') || '';
20546      return '<center>(<span data-fancybox-index></span>/<span data-fancybox-count></span>)' + (caption.length ? ' ' + caption : '') + '</center>';
20547    },
20548  });
20549}
20550
20551$web5.utilities.setClass = function(id, onTrueClassName, onFalseClassName, condition) {
20552  let e = $("#" + id);
20553  if (e == null) return;
20554  if (eval(condition)) {
20555    e.addClass(onTrueClassName);
20556    e.removeClass(onFalseClassName);
20557  } else {
20558    e.addClass(onFalseClassName);
20559    e.removeClass(onTrueClassName);
20560  }
20561}
20562
20563$web5.utilities.isValidEmail = function(emailAddress) {
20564  let pattern = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
20565
20566  return pattern.test(emailAddress);
20567}
20568
20569$web5.utilities.timerID = null;
20570
20571$web5.utilities.hideProcessingDialog = function() {
20572  $("#processingDialogMessage").html("");
20573  $("#processingDialog").hide();
20574  $("#processingDialog").removeClass("processingSuccess");
20575  $("#processingDialog").removeClass("processingError");
20576  if ($web5.utilities.timerID != null) {
20577    clearTimeout($web5.utilities.timerID);
20578    $web5.utilities.timerID = null;
20579  }
20580};
20581
20582$web5.utilities.showProcessingDialog = function(message, type, timeoutVal, onTimeout) {
20583
20584  timeoutVal = timeoutVal == null ? 6000 : timeoutVal;
20585
20586  $web5.utilities.hideProcessingDialog();
20587  $("#processingDialogMessage").html(message);
20588  $("#processingDialog").show();
20589  if (type == "success") {
20590    $("#processingDialog").addClass("processingSuccess");
20591  }
20592  if (type == "error") {
20593    $("#processingDialog").addClass("processingError");
20594  }
20595
20596  $web5.utilities.timerID = setTimeout(function() {
20597    $web5.utilities.timerID = null;
20598    $web5.utilities.hideProcessingDialog();
20599    if (onTimeout != null) onTimeout();
20600  }, timeoutVal);
20601
20602};
20603
20604$web5.utilities.setTimoutOnceCancel = function(key) {
20605  let promise = $web5.utilities.timers[key];
20606  if (promise != null) {
20607    clearTimeout(promise);
20608    delete $web5.utilities.timers[key];
20609    delete $web5.utilities.timers.time[key];
20610  }
20611}
20612
20613$web5.utilities.setTimoutOnce = function(key, f, time) {
20614
20615  let promise = $web5.utilities.timers[key];
20616  if (promise != null) {
20617    clearTimeout(promise);
20618  }
20619
20620  let oldTime = $web5.utilities.timers.time[key];
20621  if (oldTime != null && oldTime != time) {
20622    //console.log("New time: ", time, " | old time:", oldTime);
20623    time = Math.max(time, oldTime);
20624  }
20625
20626  $web5.utilities.timers.time[key] = time;
20627
20628  $web5.utilities.timers[key] = function() {
20629    delete $web5.utilities.timers[key];
20630    delete $web5.utilities.timers.time[key];
20631    f();
20632  }
20633
20634  setTimeout($web5.utilities.timers[key], time);
20635}
20636
20637$web5.utilities.delay = function(t, v) {
20638  return new Promise(function(resolve) {
20639    setTimeout(resolve.bind(null, v), t)
20640  });
20641}
20642
20643// Test via a getter in the options object to see if the passive property is accessed
20644$web5.utilities.supportsPassive = false;
20645try {
20646  var opts = Object.defineProperty({}, 'passive', {
20647    get: function() {
20648      $web5.utilities.supportsPassive = true;
20649      //console.log("Passive listeners for supported");
20650    }
20651  });
20652  testButton = document.createElement("button");
20653  testButton.addEventListener("testPassive", null, opts);
20654  testButton.removeEventListener("testPassive", null, opts);
20655  window.addEventListener("testPassive", null, opts);
20656  window.removeEventListener("testPassive", null, opts);
20657} catch (e) {
20658  console.log("Passive listeners not supported");
20659}
20660
20661
20662$web5.utilities.mfCookie = {
20663  create: function(name, value, days) {
20664    let expires = "";
20665
20666    if (days) {
20667      let date = new Date();
20668      date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
20669      expires = "; expires=" + date.toGMTString();
20670    }
20671
20672    document.cookie = name + "=" + value + expires + "; path=/";
20673  },
20674  read: function(name) {
20675    let nameEQ = name + "=";
20676    let ca = document.cookie.split(';');
20677    let len = ca.length;
20678    for (let i = 0; i < len; i++) {
20679      let c = ca[i];
20680      while (c.charAt(0) == ' ') c = c.substring(1, c.length);
20681      if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
20682    }
20683    return null;
20684  },
20685  del: function(name) {
20686    this.create(name, "", -1);
20687  }
20688}
20689
20690$(document).ready(function() {
20691  $web5.utilities.fancybox();
20692});
20693
20694$web5.audioPlayer = {};
20695$web5.audioPlayer.soundManagerIsReady = false;
20696$web5.audioPlayer.soundObjects = {};
20697
20698$web5.audioPlayer.getSongsList = function(widgetUID) {
20699  return $web5.getWidgetData(widgetUID).songsList;
20700}
20701
20702$web5.audioPlayer.setVolumeSelectedSong = function(widgetUID) {
20703  var volume = $("#volume" + widgetUID).val();
20704  var selectedSong = $web5.audioPlayer.getSelectedSong(widgetUID);
20705  var soundObject = selectedSong == null ? null : $web5.audioPlayer.soundObjects[selectedSong.ID];
20706
20707  if (soundObject != null) {
20708    soundObject.setVolume(volume);
20709  }
20710}
20711
20712$web5.audioPlayer.getSelectedSong = function(widgetUID) {
20713  return $web5.getWidgetTempData(widgetUID).selectedSong;
20714}
20715
20716$web5.audioPlayer.songTitle = function(widgetUID) {
20717  var selected = $web5.audioPlayer.getSelectedSong(widgetUID);
20718  return selected == null ? '' : selected.currentLanguageData.title;
20719}
20720
20721$web5.audioPlayer.progress = function(widgetUID) {
20722  var selected = $web5.audioPlayer.getSelectedSong(widgetUID);
20723  var soundObject = selected == null ? null : $web5.audioPlayer.soundObjects[selected.ID];
20724
20725  if (soundObject == null || soundObject.playState == 0) {
20726    return "0%";
20727  } else {
20728    var p = 100 * soundObject.position / soundObject.duration;
20729    return p + "%";
20730  }
20731}
20732
20733$web5.audioPlayer.playedTime = function(widgetUID) {
20734  var selected = $web5.audioPlayer.getSelectedSong(widgetUID);
20735  var soundObject = selected == null ? null : $web5.audioPlayer.soundObjects[selected.ID];
20736
20737  if (soundObject == null || soundObject.playState == 0) {
20738    return '0:0';
20739  } else {
20740    return $web5.utilities.toMinSec(soundObject.position);
20741  }
20742}
20743
20744$web5.audioPlayer.duration = function(widgetUID) {
20745  var selected = $web5.audioPlayer.getSelectedSong(widgetUID);
20746  var soundObject = selected == null ? null : $web5.audioPlayer.soundObjects[selected.ID];
20747
20748  if (soundObject != null) {
20749    return $web5.utilities.toMinSec(soundObject.duration);
20750  }
20751  return '0:0';
20752}
20753
20754$web5.audioPlayer.selectSong = function(songID, widgetUID) {
20755  var songs = $web5.audioPlayer.getSongsList(widgetUID);
20756
20757  isSong = function(song) {
20758    return song.ID == songID;
20759  }
20760
20761  $web5.getWidgetTempData(widgetUID).selectedSong = songs.find(isSong);
20762
20763  $web5.audioPlayer.stopAudio();
20764  $web5.audioPlayer.playPause(widgetUID);
20765}
20766
20767$web5.audioPlayer.stopAudio = function() {
20768  soundManager.stopAll();
20769}
20770
20771$web5.audioPlayer.isPlaying = function(widgetUID) {
20772  var selected = $web5.audioPlayer.getSelectedSong(widgetUID);
20773  var soundObject = selected == null ? null : $web5.audioPlayer.soundObjects[selected.ID];
20774
20775  return !(soundObject == null || soundObject.playState == 0);
20776}
20777
20778$web5.audioPlayer.playPause = function(widgetUID) {
20779  var self = this;
20780
20781  if (!$web5.audioPlayer.soundManagerIsReady) {
20782    return;
20783  }
20784
20785  self.onFinishPlaying = function() {
20786    if ($web5.getWidgetData(widgetUID).repeat) {
20787      $web5.audioPlayer.nextSong(widgetUID);
20788    }
20789  }
20790
20791  var selected = $web5.audioPlayer.getSelectedSong(widgetUID);
20792  if (selected == null) {
20793    return;
20794  }
20795
20796  var soundObject = $web5.audioPlayer.soundObjects[selected.ID];
20797
20798  if (soundObject == null) {
20799
20800    var onUpdate = function() {
20801      $web5.audioPlayer.updateAudioUI(widgetUID);
20802    }
20803
20804    $web5.audioPlayer.soundObjects[selected.ID] = soundManager.createSound({
20805      id: selected.ID,
20806      url: $web5.audioPlayer.getSongURL(selected.url),
20807      autoLoad: true,
20808      autoPlay: true,
20809      onfinish: self.onFinishPlaying,
20810      whileplaying: onUpdate
20811    });
20812  } else {
20813    if ($web5.audioPlayer.soundObjects[selected.ID].playState == 0) {
20814      soundManager.stopAll();
20815      soundManager.play(selected.ID);
20816    } else {
20817      soundManager.stopAll();
20818    }
20819  }
20820
20821  $web5.audioPlayer.setVolumeSelectedSong(widgetUID);
20822  $web5.audioPlayer.updateAudioUI(widgetUID);
20823}
20824
20825$web5.audioPlayer.nextSong = function(widgetUID) {
20826
20827  var selectedSongIndex = $web5.audioPlayer.getSongsList(widgetUID).indexOf($web5.getWidgetTempData(widgetUID).selectedSong);
20828
20829  if (selectedSongIndex < 0) {
20830    return;
20831  }
20832
20833  var newSongIndex = selectedSongIndex + 1;
20834  if (newSongIndex >= $web5.audioPlayer.getSongsList(widgetUID).length) {
20835    newSongIndex = 0;
20836  }
20837  $web5.audioPlayer.selectSong($web5.audioPlayer.getSongsList(widgetUID)[newSongIndex].ID, widgetUID);
20838}
20839
20840$web5.audioPlayer.previousSong = function(widgetUID) {
20841  var selectedSongIndex = $web5.audioPlayer.getSongsList(widgetUID).indexOf($web5.getWidgetTempData(widgetUID).selectedSong);
20842  if (selectedSongIndex < 0) {
20843    return;
20844  }
20845  var newSongIndex = selectedSongIndex - 1;
20846  if (newSongIndex < 0) {
20847    newSongIndex = $web5.audioPlayer.getSongsList(widgetUID).length - 1;
20848  }
20849  $web5.audioPlayer.selectSong($web5.audioPlayer.getSongsList(widgetUID)[newSongIndex].ID, widgetUID);
20850}
20851
20852
20853$web5.audioPlayer.getSongURL = function(songURL) {
20854  if ($web5.utilities.isOnlyFileName(songURL)) {
20855    if ($web5.isAppMode()) {
20856      return $web5.getTargetDomainPath("audio/" + songURL);
20857    } else {
20858      return "audio/" + songURL;
20859    }
20860  } else {
20861    return songURL;
20862  }
20863}
20864
20865$web5.audioPlayer.updateAudioUI = function(widgetUID) {
20866  $("#songTitle" + widgetUID).html($web5.audioPlayer.songTitle(widgetUID));
20867  $("#playedTime" + widgetUID).html($web5.audioPlayer.playedTime(widgetUID));
20868  $("#duration" + widgetUID).html($web5.audioPlayer.duration(widgetUID));
20869
20870  $web5.utilities.setClass('playButton' + widgetUID, 'glyphicon-pause', 'glyphicon-play', $web5.audioPlayer.isPlaying(widgetUID));
20871
20872
20873  var songs = $web5.audioPlayer.getSongsList(widgetUID);
20874  var selectedSong = $web5.audioPlayer.getSelectedSong(widgetUID);
20875  for (var i = 0; i < songs.length; i++) {
20876    var song = songs[i];
20877    var sElement = $("#song" + widgetUID + "_" + song.ID);
20878    if (song == selectedSong) {
20879      sElement.addClass("selected");
20880    } else {
20881      sElement.removeClass("selected");
20882    }
20883  }
20884}
20885
20886
20887$web5.audioPlayer.onLoad = function(widgetUID) {
20888  var data = $web5.getWidgetData(widgetUID);
20889
20890  for (let index in data.songsList) {
20891    $web5.multilingual.addLanguageVeriableProperty(data.songsList[index], "currentLanguageData");
20892  }
20893}
20894
20895
20896
20897soundManager.setup({
20898  url: 'common/soundmanager/swf/',
20899  preferFlash: false,
20900  debugMode: false,
20901  flashVersion: 9, // optional: 9 - shiny features (default = 8)
20902  // optional: ignore Flash where possible, use 100% HTML5 mode
20903  onready: function() { $web5.audioPlayer.soundManagerIsReady = true; },
20904  ontimeout: function() {
20905    console.log("SoundManager did not start.")
20906  }
20907});
20908
20909$web5.chapter = {};
20910
20911$web5.chapter.hideShow = function(widgetUID) {
20912  let e = $("#chapterContent" + widgetUID);
20913  let icon = $("#chapterIcon" + widgetUID);
20914  let expanded = e.attr('aria-expanded');
20915  if (expanded == 'false') {
20916    icon.removeClass('glyphicon-collapse-up');
20917    icon.addClass('glyphicon-collapse-down');
20918  } else {
20919    icon.removeClass('glyphicon-collapse-down');
20920    icon.addClass('glyphicon-collapse-up');
20921  }
20922
20923  expanded = expanded == 'true';
20924
20925  $web5.slideshow.updateSlideshowsInChapter(widgetUID, expanded);
20926  $web5.imageGallery.updateImageGalleryInChapter(widgetUID, expanded);
20927
20928  setTimeout($web5.Web5Image.adjustThumbsStatic, 400);
20929  setTimeout($web5.Web5Image.adjustThumbsStatic, 1000);
20930}
20931
20932$web5.contactForm = {};
20933$web5.contactForm.internalCaptchaID = {};
20934
20935var captchaOnLoad = function() {
20936
20937  $web5.contactForm.loaded = true;
20938
20939  if ($web5.isAppMode()) return;
20940
20941  $("[id^=contactFormCaptchaPlaceholder]").each(function() {
20942    let captchaID = $(this).attr('id');
20943    let widgetUID = captchaID.replace('contactFormCaptchaPlaceholder', '');
20944    $web5.contactForm.showCaptcha(widgetUID);
20945  });
20946}
20947
20948$web5.contactForm.resetCaptcha = function() {
20949  for (id in $web5.contactForm.internalCaptchaID) {
20950    grecaptcha.reset($web5.contactForm.internalCaptchaID[id]);
20951  }
20952}
20953
20954$web5.contactForm.showCaptcha = function(widgetUID) {
20955
20956  if ($web5.contactForm.loaded == null) {
20957    setTimeout(function() {
20958      $web5.contactForm.showCaptcha(widgetUID);
20959    }, 100);
20960    return;
20961  }
20962
20963  if ($web5.editor != null && $web5.editor.publishingMode) return;
20964
20965  let captchaElement = document.getElementById('contactFormCaptchaPlaceholder' + widgetUID);
20966  let button = $('#contactFormCaptchaButton' + widgetUID);
20967
20968  if (captchaElement == null || button == null) {
20969    setTimeout(function() {
20970      $web5.contactForm.showCaptcha(widgetUID);
20971    }, 100);
20972    return;
20973  }
20974
20975  if (captchaElement.childNodes.length > 0) return; // captcha already rendered
20976
20977  let internalCaptchaID = grecaptcha.render(captchaElement, {
20978    'sitekey': '6LcvkdQUAAAAALHOhmXlJwSzgTXR4qxUiv6ZXvFZ',
20979    'size': 'invisible',
20980    'callback': function(captchaToken) {
20981      $web5.contactForm.resetCaptcha();
20982      $web5.contactForm.sendEmailAjax(widgetUID, captchaToken);
20983    },
20984    'expired-callback': function() {
20985      $web5.contactForm.resetCaptcha();
20986    }
20987  });
20988
20989  $web5.contactForm.internalCaptchaID[widgetUID] = internalCaptchaID;
20990}
20991
20992$web5.contactForm.sendEmail = function(widgetUID) {
20993
20994  let emailPhone = $("#emailPhone" + widgetUID).val();
20995  let senderName = $("#senderName" + widgetUID).val();
20996  let message = $("#message" + widgetUID).val();
20997  let error = false;
20998  let widgetData = $web5.getWidgetData(widgetUID);
20999
21000  if (emailPhone.length < 3) {
21001    $("#emailPhoneWarning" + widgetUID).removeClass('hidden');
21002    setTimeout(function() { $("#emailPhoneWarning" + widgetUID).addClass('hidden'); }, 3000);
21003    error = true;
21004  }
21005
21006  if (widgetData.showName && senderName.length < 3) {
21007    $("#senderNameWarning" + widgetUID).removeClass('hidden');
21008    setTimeout(function() { $("#senderNameWarning" + widgetUID).addClass('hidden'); }, 3000);
21009    error = true;
21010  }
21011
21012
21013  if (message.length < 3) {
21014    $("#messageWarning" + widgetUID).removeClass('hidden');
21015    setTimeout(function() { $("#messageWarning" + widgetUID).addClass('hidden'); }, 3000);
21016    error = true;
21017  }
21018
21019  if (error) return;
21020
21021  let internalCaptchaID = $web5.contactForm.internalCaptchaID[widgetUID];
21022  grecaptcha.execute(internalCaptchaID);
21023}
21024
21025$web5.contactForm.sendEmailAjax = function(widgetUID, captchaToken) {
21026  let locale = $("#form" + widgetUID).attr("data-locale");
21027  let siteDomain = ($web5.isAppMode()) ? $web5.settingsManager.accountMetaData.targetDomain : window.location.hostname;
21028  let emailPhoneElement = $("#emailPhone" + widgetUID);
21029  let senderNameElement = $("#senderName" + widgetUID);
21030  let messageElement = $("#message" + widgetUID);
21031  let widgetData = $web5.getWidgetData(widgetUID);
21032
21033  _sendSuccessAction = function() {
21034    $web5.utilities.showProcessingDialog($web5.multilingual.staticSiteTextDB('send_success'), 'success');
21035    $web5.contactForm.resetCaptcha();
21036  }
21037
21038  _sendFailAction = function() {
21039    $web5.utilities.showProcessingDialog($web5.multilingual.staticSiteTextDB('send_fail'), 'error');
21040    $web5.contactForm.resetCaptcha();
21041  }
21042
21043  $web5.utilities.showProcessingDialog($web5.multilingual.staticSiteTextDB('sending'), null, 60000, function() {
21044    $web5.utilities.showProcessingDialog($web5.multilingual.staticSiteTextDB('send_fail'), 'error');
21045  });
21046
21047  $.ajax({
21048    type: 'POST',
21049    url: '/actions/sendcontactform.seam',
21050    contentType: 'application/x-www-form-urlencoded;charset=utf-8',
21051    data: {
21052      sendFrom: emailPhoneElement.val(),
21053      sendFromName: senderNameElement.length == 0 ? "" : senderNameElement.val(),
21054      sendMessage: messageElement.val(),
21055      sendTo: siteDomain,
21056      sendLang: locale,
21057      captchaToken: captchaToken,
21058      sendToEmail: widgetData.sendToEmail,
21059      captchaVersion : "2"
21060    },
21061    success: function(data) {
21062      if (data === 'sent') {
21063        _sendSuccessAction();
21064        emailPhoneElement.val("");
21065        senderNameElement.val("");
21066        messageElement.val("");
21067      } else {
21068        _sendFailAction();
21069      }
21070    },
21071    error: function() {
21072      _sendFailAction();
21073    }
21074  });
21075}
21076
21077$web5.Web5guestbook = {};
21078$web5.Web5guestbook.path = "/seam/resource/rest/fadeb9b0-9bff-4c80-b503-43649cbbbe46/";
21079$web5.Web5guestbook.items = [];
21080
21081$web5.Web5guestbook.getPath = function () {
21082  return $web5.getServerPath() + $web5.Web5guestbook.path;
21083}
21084
21085
21086$web5.Web5guestbook.loadPosts = function (callback) {
21087  var address = $web5.getDomain();
21088
21089  if (address == null || address == "") return;
21090
21091  var xhttp = new XMLHttpRequest();
21092  xhttp.onreadystatechange = function () {
21093    if (this.readyState == 4 && this.status == 200) {
21094      $web5.Web5guestbook.items = JSON.parse(xhttp.responseText);
21095      if (callback != null) callback($web5.Web5guestbook.items);
21096    }
21097  };
21098  xhttp.open("GET", $web5.Web5guestbook.getPath() + "?address=" + address, true);
21099  xhttp.send();
21100}
21101
21102$web5.Web5guestbook.addPostButtonClick = function (widgetUID) {
21103  let author = $("#GuestbookName" + widgetUID).val();
21104  let message = $("#GuestbookMessage" + widgetUID).val();
21105
21106  if (author == "") {
21107    $("#GuestbookName" + widgetUID).addClass("guestbook-error");
21108    return;
21109  }
21110
21111  if (message == "") {
21112    $("#GuestbookMessage" + widgetUID).addClass("guestbook-error");
21113    return;
21114  }
21115  $("#GuestbookName" + widgetUID).removeClass("guestbook-error");
21116  $("#GuestbookMessage" + widgetUID).removeClass("guestbook-error");
21117
21118  let date = "Feb 1, 1000 1:00:00 PM";
21119  let hidden = true;
21120  let position = -1;
21121  $web5.Web5guestbook.addPost(widgetUID, author, message, date, hidden, position);
21122}
21123
21124
21125$web5.Web5guestbook.addPost = function (widgetUID, author, message, date, hidden, position) {
21126
21127  let lines = message.split("\n");
21128
21129  message = "";
21130  for (let i in lines) {
21131    let strStart = lines[i].substring(0, 3);
21132    if (strStart == "<p>") {
21133      lines[i] = lines[i].substring(3, lines[i].length - 4);
21134    }
21135    lines[i] = lines[i].replace(/</g, "&lt;").replace(/>/g, "&gt;");
21136    message += "<p>" + lines[i] + "</p>";
21137
21138  }
21139
21140  if (lines.length == 0) {
21141    lines.push(message);
21142  }
21143
21144  var post = {};
21145  post.text = message;
21146  post.author = author;
21147  post.position = position;
21148  post.date = date;
21149  post.hidden = hidden;
21150  var pJSON = JSON.stringify(post);
21151
21152  if ($web5.isSeam() && Seam.Component.getInstance('guestbookActions') != null) {
21153    Seam.Component.getInstance('guestbookActions').addEntryEditorV2($web5.getDomain(), pJSON, function (isSuccess) {
21154      if (isSuccess == true) {
21155        if (widgetUID != null) {
21156          $("#GuestbookName" + widgetUID).val("");
21157          $("#GuestbookMessage" + widgetUID).val("");
21158          $web5.utilities.showProcessingDialog($web5.multilingual.staticSiteTextDB('sendEntrySuccess'), 'success');
21159        } else {
21160          $web5.utilities.hideProcessingDialog();
21161        }
21162
21163        if ($web5.isAppMode()) {
21164          $web5.Web5guestbook.loadPosts(function () {
21165            $web5.$rootScope.$applyAsync();
21166            if (widgetUID != null) { // dodajemy w undo
21167              $web5.undo.addCalbackToUndoList(function () {
21168                $web5.Web5guestbook.removeLastPost()
21169              }, 'blog_addPost');
21170            }
21171          });
21172        }
21173      } else {
21174        $web5.utilities.showProcessingDialog($web5.multilingual.staticSiteTextDB('send_fail'), 'error');
21175      }
21176    });
21177  }
21178
21179  $web5.utilities.showProcessingDialog($web5.multilingual.staticSiteTextDB('sending'));
21180}
21181
21182$web5.iconsLogo = {};
21183$web5.iconsLogo.selector = "p, li, span, .web5_plain_text_wraper, .web5_text_wraper, ._web5contactData_contact, .slideshowCaption, .newsWidgetNavigation button";
21184
21185$web5.iconsLogo.switchContrast = function(event) {
21186
21187  event.preventDefault();
21188  if ($web5.isAppMode()) return;
21189
21190
21191  $($web5.iconsLogo.selector).each(function() {
21192
21193    let bColor = $(this).attr("oryginal-background-color");
21194    let fColor = $(this).attr("oryginal-font-color");
21195
21196    if (bColor == null) {
21197      bColor = $(this).css("background-color");
21198      fColor = $(this).css("color");
21199      $(this).attr("oryginal-background-color", bColor);
21200      $(this).attr("oryginal-font-color", fColor);
21201      $(this).attr("colors-state", "0");
21202    }
21203
21204    let state = $(this).attr("colors-state");
21205
21206    if (state == "0") {
21207      $(this).css("background-color", "yellow");
21208      $(this).css("color", "black");
21209      $(this).attr("colors-state", "1");
21210    } else {
21211      $(this).css("background-color", bColor);
21212      $(this).css("color", fColor);
21213      $(this).attr("colors-state", "0");
21214    }
21215  });
21216
21217  return false;
21218
21219}
21220
21221$web5.iconsLogo.increseFontSize = function(event) {
21222
21223  event.preventDefault();
21224  if ($web5.isAppMode()) return;
21225
21226  $($web5.iconsLogo.selector).each(function() {
21227
21228    let oryginalSize = $(this).attr("oryginal-font-size");
21229    if (oryginalSize == null) {
21230      oryginalSize = $(this).css("font-size");
21231      $(this).attr("oryginal-font-size", oryginalSize);
21232      $(this).attr("oryginal-font-size-counter", 0);
21233    }
21234
21235    let counter = parseInt($(this).attr("oryginal-font-size-counter"));
21236    counter += 1;
21237    $(this).attr("oryginal-font-size-counter", counter);
21238
21239    if (counter == 4) {
21240      $(this).attr("oryginal-font-size-counter", 0);
21241      let size = $(this).attr("oryginal-font-size");
21242      $(this).css("font-size", size)
21243    } else {
21244      let size = $(this).css("font-size");
21245      size = parseInt(size) * 1.2;
21246      let limit = Math.max(32, parseInt(oryginalSize));
21247      size = Math.min(size, limit);
21248      $(this).css("font-size", size)
21249    }
21250  });
21251
21252  return false;
21253}
21254
21255$web5.iconsLogo.updateSloganTextSize = function() {
21256
21257  let iconsLogoWidgets = $(".slogansWrapper");
21258
21259  iconsLogoWidgets.each(function() {
21260
21261    let sloganSmallerBy = parseInt($(this).attr('data-slogan-smaller'));
21262    let maxFontSize = parseInt($(this).attr('data-slogan-max-size'));
21263    let firstSloganFontSize = null;
21264
21265    let slogansAreaWidth = $(this).width();
21266    let slogans = $(this).find(".web5_plain_text_wraper");
21267    slogans.each(function() {
21268
21269      let targetFontSize = 8;
21270      widthShort = $(this).find(".web5_text_wraper_8").width();
21271      widthLong = $(this).find(".web5_text_wraper_10").width();
21272
21273      widthShortNext = $(this).find(".web5_text_wraper_10").width();
21274      widthLongNext = $(this).find(".web5_text_wraper_12").width();
21275      if (widthShortNext < slogansAreaWidth) {
21276        targetFontSize = 10;
21277        widthShort = widthShortNext;
21278        widthLong = widthLongNext;
21279      }
21280
21281      widthShortNext = $(this).find(".web5_text_wraper_14").width();
21282      widthLongNext = $(this).find(".web5_text_wraper_16").width();
21283      if (widthShortNext < slogansAreaWidth) {
21284        targetFontSize = 14;
21285        widthShort = widthShortNext;
21286        widthLong = widthLongNext;
21287      }
21288
21289      widthShortNext = $(this).find(".web5_text_wraper_18").width();
21290      widthLongNext = $(this).find(".web5_text_wraper_20").width();
21291      if (widthShortNext < slogansAreaWidth) {
21292        targetFontSize = 18;
21293        widthShort = widthShortNext;
21294        widthLong = widthLongNext;
21295      }
21296
21297      widthShortNext = $(this).find(".web5_text_wraper_24").width();
21298      widthLongNext = $(this).find(".web5_text_wraper_26").width();
21299      if (widthShortNext < slogansAreaWidth) {
21300        targetFontSize = 24;
21301        widthShort = widthShortNext;
21302        widthLong = widthLongNext;
21303      }
21304
21305      widthShortNext = $(this).find(".web5_text_wraper_30").width();
21306      widthLongNext = $(this).find(".web5_text_wraper_32").width();
21307      if (widthShortNext < slogansAreaWidth) {
21308        targetFontSize = 30;
21309        widthShort = widthShortNext;
21310        widthLong = widthLongNext;
21311      }
21312
21313      widthShortNext = $(this).find(".web5_text_wraper_42").width();
21314      widthLongNext = $(this).find(".web5_text_wraper_44").width();
21315      if (widthShortNext < slogansAreaWidth) {
21316        targetFontSize = 42;
21317        widthShort = widthShortNext;
21318        widthLong = widthLongNext;
21319      }
21320
21321
21322      let additionalSteps = 0;
21323      if (widthShort != null && widthLong != null) {
21324        let step = (widthLong - widthShort) / 2.0;
21325        for (let i = 0; i <= 60; i++) {
21326          let width = Math.ceil(1.1 * (widthShort + step * i));
21327          if (width < slogansAreaWidth) {
21328            additionalSteps = i;
21329          } else {
21330            break;
21331          }
21332        }
21333
21334        targetFontSize = targetFontSize + additionalSteps;
21335
21336        if (targetFontSize > 65) targetFontSize = 65;
21337        if (targetFontSize < 12) targetFontSize = 12;
21338        if ($web5.editor != null && $web5.editor.publishingMode) targetFontSize = 12;
21339
21340        if (targetFontSize > maxFontSize) targetFontSize = maxFontSize;
21341
21342
21343        if (firstSloganFontSize == null) {
21344          firstSloganFontSize = targetFontSize;
21345        } else {
21346          targetFontSize = Math.min(targetFontSize, firstSloganFontSize + sloganSmallerBy);
21347          if (targetFontSize > 65) targetFontSize = 65;
21348          if (targetFontSize < 12) targetFontSize = 12;
21349          if ($web5.editor != null && $web5.editor.publishingMode) targetFontSize = 12;
21350        }
21351
21352        if (widthShort == 0) {
21353          // pusty string, nie chcemy pokazywac olbrzymiego palceholder na slogan
21354          $(this).css('font-size', '18px');
21355          $(this).css('line-height', '18px');
21356
21357        } else {
21358          $(this).css('font-size', targetFontSize + 'px');
21359          $(this).css('line-height', targetFontSize + 'px');
21360        }
21361      }
21362
21363    });
21364  });
21365}
21366
21367
21368$web5.iconsLogo.onReady = function(widgetUID) {
21369  let data = $web5.getWidgetData(widgetUID);
21370  if (data.logoImage != null) $web5.Web5Image.addImageMethods(data.logoImage);
21371}
21372
21373
21374$(window).resize(function(event, data) {
21375  // resize dotyczy window a nie innego elementu, this to window
21376  if (this == event.target) {
21377    $web5.utilities.setTimoutOnce("updateSloganTextSize1", function() { $web5.iconsLogo.updateSloganTextSize() }, 100);
21378    $web5.utilities.setTimoutOnce("updateSloganTextSize2", function() { $web5.iconsLogo.updateSloganTextSize() }, 500);
21379    $web5.utilities.setTimoutOnce("updateSloganTextSize3", function() { $web5.iconsLogo.updateSloganTextSize() }, 1000);
21380    $web5.utilities.setTimoutOnce("updateSloganTextSize4", function() { $web5.iconsLogo.updateSloganTextSize() }, 2000);
21381  }
21382
21383});
21384
21385$(document).ready(function() {
21386  $web5.utilities.setTimoutOnce("updateSloganTextSize1", function() { $web5.iconsLogo.updateSloganTextSize() }, 100);
21387  $web5.utilities.setTimoutOnce("updateSloganTextSize2", function() { $web5.iconsLogo.updateSloganTextSize() }, 500);
21388  $web5.utilities.setTimoutOnce("updateSloganTextSize3", function() { $web5.iconsLogo.updateSloganTextSize() }, 1000);
21389  $web5.utilities.setTimoutOnce("updateSloganTextSize4", function() { $web5.iconsLogo.updateSloganTextSize() }, 2000);
21390});
21391
21392$web5.imageGallery = {};
21393$web5.imageGallery.BUTTON_MARGIN = 10;
21394$web5.imageGallery.htmlCreationInProgress = {};
21395
21396$web5.imageGallery.getPanelWidth = function(widgetUID) {
21397  let galleryPanel = document.getElementById('web5GalleryImagePanel' + widgetUID);
21398  let panelWidth = $(galleryPanel).width();
21399  return panelWidth;
21400}
21401
21402$web5.imageGallery.getImagesPerRow = function(widgetUID) {
21403
21404  let widgetData = $web5.getWidgetData(widgetUID);
21405  let imgPerRow = widgetData.layout;
21406
21407  if (widgetData.layout == 'inline') {
21408    imgPerRow = Math.max(1, widgetData.images.length());
21409  }
21410
21411  if (widgetData.images.length() < widgetData.layout) {
21412    imgPerRow = widgetData.images.length();
21413  }
21414
21415  let panelWidth = $web5.imageGallery.getPanelWidth(widgetUID);
21416
21417  if (panelWidth < 450) {
21418    imgPerRow = Math.min(imgPerRow, 2);
21419  }
21420
21421  if (panelWidth < 300) {
21422    imgPerRow = 1;
21423  }
21424
21425  return imgPerRow;
21426}
21427
21428$web5.imageGallery.getRowsNumber = function(widgetUID) {
21429  let widgetData = $web5.getWidgetData(widgetUID);
21430  let imgPerRow = $web5.imageGallery.getImagesPerRow(widgetUID);
21431  let rows = Math.ceil(widgetData.images.length() / imgPerRow);
21432  return rows;
21433}
21434
21435$web5.imageGallery.getBackgroundPadding = function(widgetUID) {
21436  let galleryPanel = document.getElementById('web5GalleryImagePanel' + widgetUID);
21437  let imgBackground = $(galleryPanel).find(".imageGalleryWidget_Image_background")[0];
21438
21439  let backgroundSize = parseInt($(imgBackground).css("padding-left")) + parseInt($(imgBackground).css("padding-right"));
21440  backgroundSize /= 2;
21441
21442  let panelWidth = $web5.imageGallery.getPanelWidth(widgetUID);
21443  if (panelWidth < 600) {
21444    backgroundSize = Math.min(backgroundSize, 8);
21445  }
21446
21447  return backgroundSize;
21448}
21449
21450$web5.imageGallery.returnImageWidthInRow = function(widgetUID) {
21451  return 100 / $web5.imageGallery.getImagesPerRow(widgetUID) + "%"
21452}
21453
21454$web5.imageGallery.updateGallery = function(widgetUID) {
21455  let widgetTmpData = $web5.getWidgetTempData(widgetUID);
21456  if (widgetTmpData == null) return;
21457  widgetTmpData.isGalleryHTMLReady = false;
21458  $web5.utilities.setTimoutOnce("updateGalleryStart" + widgetUID, function() { $web5.imageGallery.updateGalleryStart(widgetUID); }, 100);
21459}
21460
21461$web5.imageGallery.updateGalleryStart = function(widgetUID) {
21462
21463  let galleryParent = $('#web5GalleryParent-' + widgetUID);
21464  if (galleryParent.length == 0) return; // element nie istnieje
21465
21466  $(".web5ImageElement-" + widgetUID).css("width", "0px");
21467  $(".web5ImageElement-" + widgetUID).css("height", "0px");
21468
21469  galleryParent.find(".web5-image-gallery_link-button, .web5-image-gallery_title").each(
21470    function() {
21471      $(this).css('height', "auto");
21472    });
21473
21474  setTimeout(function() { $web5.imageGallery.updateGalleryRender(widgetUID) }, 50);
21475}
21476
21477
21478$web5.imageGallery.updateGalleryRender = function(widgetUID) {
21479
21480  let widgetData = $web5.getWidgetData(widgetUID);
21481  if (widgetData == null) return;
21482
21483
21484  let widgetTmpData = $web5.getWidgetTempData(widgetUID);
21485  let galleryParent = document.getElementById('web5GalleryParent-' + widgetUID);
21486  if (galleryParent == null) {
21487    widgetTmpData.isGalleryHTMLReady = true;
21488    return;
21489  }
21490
21491
21492  let galeryPanel = $(document.getElementById('web5GalleryImagePanel' + widgetUID));
21493  let imgParents = document.querySelectorAll('.web5ImageParent-' + widgetUID);
21494  let imgElements = document.querySelectorAll('.web5ImageElement-' + widgetUID);
21495  let imgButtons = document.querySelectorAll('.imageButtonElement-' + widgetUID);
21496  let plainTextElementsWraper = $("plain-text-editor");
21497  let plainTextElementsRenderedTexts = plainTextElementsWraper.find(".web5_text_class")
21498
21499  if (imgElements.length != imgParents.length || imgElements.length == 0 ||
21500    plainTextElementsWraper.length != plainTextElementsRenderedTexts.length) { // || galleryParent.offsetWidth == 0
21501    // angular jeszcze nie wyrenderowal calosci
21502    console.log("angular jeszcze nie wyrenderowal calosci");
21503    setTimeout(function() { $web5.imageGallery.updateGalleryRender(widgetUID) }, 100);
21504    return;
21505  }
21506
21507  if (galeryPanel.width() < 0) {
21508    widgetTmpData.isGalleryHTMLReady = true;
21509    return;
21510  }
21511
21512
21513  $(".web5ImageElement-" + widgetUID).css("width", "100%");
21514  $(".web5ImageElement-" + widgetUID).css("height", "auto");
21515
21516  for (let i = 0; i < imgParents.length; i++) {
21517    $(imgParents[i]).parent().css('width', $web5.imageGallery.returnImageWidthInRow(widgetUID));
21518  }
21519
21520
21521  let getMaxElementsHeight = function(elementsSelector, addMarginPadding, imgPerRow, rowIndex) {
21522    let maxElementHeight = 0;
21523
21524    for (let i = 0; i < imgParents.length; i++) {
21525      let rIndex = Math.floor(i / imgPerRow);
21526      if (rIndex != rowIndex) continue;
21527
21528      let img = widgetData.images.getList()[i];
21529      let element = $("#web5GalleryImagePanel" + widgetUID + " [data-img-id=" + img.id + "]").find(elementsSelector);
21530      if (element.length == 0) continue;
21531
21532      if (addMarginPadding)
21533        maxElementHeight = Math.max(maxElementHeight, $(element).outerHeight());
21534      else
21535        maxElementHeight = Math.max(maxElementHeight, $(element).height());
21536    }
21537
21538    return maxElementHeight;
21539  }
21540
21541  let setElementsHeight = function(elementsSelector, rowIndex, height) {
21542
21543    for (let i = 0; i < imgParents.length; i++) {
21544      let rIndex = Math.floor(i / imgPerRow);
21545      if (rIndex != rowIndex) continue;
21546
21547      let img = widgetData.images.getList()[i];
21548      let element = $("#web5GalleryImagePanel" + widgetUID + " [data-img-id=" + img.id + "]").find(elementsSelector);
21549      if (element.length == 0) continue;
21550
21551      $(element).height(height);
21552    }
21553  }
21554
21555  let imagePadding = $web5.imageGallery.getBackgroundPadding(widgetUID);
21556
21557  let imgPerRow = $web5.imageGallery.getImagesPerRow(widgetUID);
21558  let imgGalleryInnerWidth = $(galleryParent).width();
21559  let borderWidth = parseInt($(imgParents[0]).css("border-left-width")) + parseInt($(imgParents[0]).css("border-right-width"));
21560
21561  imgGalleryInnerWidth -= widgetData.imgDistance * (1 * imgPerRow - 1); // po lewej i prawej nie ma marginesu
21562  imgGalleryInnerWidth -= imagePadding * 2 * imgPerRow;
21563  imgGalleryInnerWidth -= borderWidth * imgPerRow;
21564  
21565
21566
21567  let rowsNumber = $web5.imageGallery.getRowsNumber(widgetUID);
21568  let imgBoxRowHeights = {};
21569  for (let row = 0; row < rowsNumber; row++) {
21570
21571    let imgBoxHeight = 0;
21572    let imgBoxWidth = Math.round(imgGalleryInnerWidth / imgPerRow);
21573    for (let i = 0; i < widgetData.images.length(); i++) {
21574      let rowIndex = Math.floor(i / imgPerRow);
21575      if (rowIndex != row) continue;
21576      let img = widgetData.images.getList()[i];
21577      let scale = imgBoxWidth / img.width;
21578      let scaledHeight = img.height * scale;
21579      scaledHeight = Math.min(scaledHeight, 2 * img.height); // obrazek max 2 razy większy niż fizyczny
21580      imgBoxHeight = Math.max(imgBoxHeight, scaledHeight);
21581    }
21582    imgBoxHeight = Math.round(Math.min(imgBoxWidth, imgBoxHeight, widgetData.maxHeight));
21583    if (widgetData.cssShape == "img-real-circle" || widgetData.cssShape == "img-real-circle-photo" || widgetData.cssShape == "square") {
21584      imgBoxWidth = Math.min(imgBoxWidth, imgBoxHeight);
21585      imgBoxHeight = Math.min(imgBoxWidth, imgBoxHeight);
21586    }
21587
21588    imgBoxRowHeights[row] = imgBoxHeight;
21589
21590    for (let i = 0; i < imgParents.length; i++) {
21591      let rowIndex = Math.floor(i / imgPerRow);
21592      if (rowIndex != row) continue;
21593      let columnIndex = i - (rowIndex * imgPerRow);
21594
21595      let img = widgetData.images.getList()[i];
21596      $(imgElements[i]).css('max-height', imgBoxHeight + "px");
21597
21598      let scale = imgBoxHeight / img.height;
21599      let scaledWidth = img.width * scale;
21600      scaledWidth = Math.min(scaledWidth, imgBoxWidth);
21601      $(imgElements[i]).css('max-width', scaledWidth + "px");
21602      $(imgElements[i]).css('top', "");
21603
21604      if (widgetData.cssShape == "img-real-circle" || widgetData.cssShape == "img-real-circle-photo" || widgetData.cssShape == "square") {
21605        $(imgElements[i]).css('max-height', imgBoxWidth + "px");
21606        $(imgElements[i]).css('max-width', imgBoxWidth + "px");
21607        $(imgElements[i]).css('height', imgBoxWidth + "px");
21608        $(imgElements[i]).css('width', imgBoxWidth + "px");
21609      }
21610
21611      $(imgParents[i]).css('padding', $web5.imageGallery.getBackgroundPadding(widgetUID) + 'px');
21612
21613      if (columnIndex == 0) {
21614        $(imgParents[i]).css('margin-left', 0 + 'px');
21615      } else {
21616        $(imgParents[i]).css('margin-left', Math.round(widgetData.imgDistance / 2.0) + 'px');
21617      }
21618
21619      if (columnIndex == (imgPerRow - 1)) {
21620        $(imgParents[i]).css('margin-right', 0 + 'px');
21621      } else {
21622        $(imgParents[i]).css('margin-right', Math.round(widgetData.imgDistance / 2.0) + 'px');
21623      }
21624
21625      $(imgParents[i]).parent().css('width', $web5.imageGallery.returnImageWidthInRow(widgetUID));
21626      $(imgParents[i]).find(".imageButtonSelectorClass").css('margin-right', $web5.imageGallery.getBackgroundPadding(widgetUID));
21627      $(imgParents[i]).find(".imageButtonSelectorClass").css('margin-left', $web5.imageGallery.getBackgroundPadding(widgetUID));
21628    }
21629  }
21630
21631  for (let row = 0; row < rowsNumber; row++) {
21632    let imgBoxHeight = imgBoxRowHeights[row];
21633    for (let i = 0; i < widgetData.images.length(); i++) {
21634      let rowIndex = Math.floor(i / imgPerRow);
21635      if (rowIndex != row) continue;
21636      let columnIndex = i - (rowIndex * imgPerRow);
21637      let img = widgetData.images.getList()[i];
21638      if (i % imgPerRow == 0) {
21639        let maxButtonHeight = getMaxElementsHeight(".web5-image-gallery_link-button", false, imgPerRow, rowIndex);
21640        setElementsHeight(".web5-image-gallery_link-button", rowIndex, maxButtonHeight);
21641        let maxTitleHeight = getMaxElementsHeight(".web5-image-gallery_title", false, imgPerRow, rowIndex);
21642        setElementsHeight(".web5-image-gallery_title", rowIndex, maxTitleHeight);
21643      }
21644
21645      if (img.isLinkDefined() && widgetData.linkShape == 'button') {
21646        let maxButtonHeight = getMaxElementsHeight(".web5-image-gallery_link-button", true, imgPerRow, rowIndex);
21647        $(imgParents[i]).css('height', (16 + imgBoxHeight + maxButtonHeight + (2 * imagePadding)) + "px");
21648        $(imgElements[i]).css('bottom', "auto");
21649      } else {
21650        $(imgParents[i]).css('height', (imgBoxHeight + (2 * imagePadding)) + "px");
21651        let titleElement = $(imgParents[i]).parent().find(".web5-image-gallery_title");
21652        if (titleElement.length != 0) {
21653          titleElement.css('margin-left', Math.round(widgetData.imgDistance / 2.0) + 'px');
21654          titleElement.css('margin-right', Math.round(widgetData.imgDistance / 2.0) + 'px');
21655          if (columnIndex == 0) {
21656            titleElement.css('margin-left', 0 + 'px');
21657          }
21658          if (columnIndex == (imgPerRow - 1)) {
21659            titleElement.css('margin-right', 0 + 'px');
21660          }
21661        }
21662      }
21663    }
21664  }
21665
21666  $(imgButtons).each(
21667    function() {
21668      $(this).css('bottom', (imagePadding) + "px");
21669    });
21670
21671  setTimeout(function() {
21672    let widgetTmpData = $web5.getWidgetTempData(widgetUID);
21673    widgetTmpData.isGalleryHTMLReady = true;
21674    $web5.Web5Image.adjustThumbsStatic();
21675  }, 50)
21676
21677}
21678
21679
21680$web5.imageGallery.onReady = function(widgetUID) {
21681  let data = $web5.getWidgetData(widgetUID);
21682  $web5.Web5Image.addImageListMethods(data.images);
21683  let images = data.images.getList();
21684
21685  for (let imgIndex in images) {
21686    let image = images[imgIndex];
21687    $web5.Web5Image.addImageMethods(image);
21688  }
21689
21690  $web5.imageGallery.updateGallery(widgetUID);
21691
21692}
21693
21694$web5.imageGallery.onResize = function(widgetUID) {
21695  $web5.imageGallery.updateGallery(widgetUID);
21696}
21697
21698
21699$web5.imageGallery.updateImageGalleryInChapter = function(widgetUID, expanded) {
21700  if (expanded) return;
21701
21702  $("#chapterContent" + widgetUID).find("._web5ImageGallery_wraper").each(function() {
21703    let galleryWidgetUID = $(this).attr('id').replace("web5GalleryParent-", "");
21704    $web5.imageGallery.updateGallery(galleryWidgetUID);
21705  });
21706}
21707
21708$web5.layout = {};
21709
21710
21711$web5.layout.wasCookieInfoSeen = function() {
21712  return $web5.utilities.mfCookie.read("cookie_box") != null;
21713}
21714
21715$web5.layout.closeInfo = function(event) {
21716  event.preventDefault();
21717  $web5.utilities.mfCookie.create("cookie_box", "0", 365);
21718  $("#cookieBox").hide();
21719}
21720
21721$web5.showCookie = function() {
21722
21723  let cookieHTML = $("#cookieBox").html();
21724
21725  if (cookieHTML != null && cookieHTML.includes("<!-- COMMENT START --> <!--")) {
21726    cookieHTML = cookieHTML.replace("<!-- COMMENT START --> <!--", "");
21727    cookieHTML = cookieHTML.replace("--> <!-- COMMENT END -->", "");
21728    $("#cookieBox").html(cookieHTML);
21729  }
21730
21731  if ($web5.editor != null && $web5.editor.publishingMode) {
21732    $("#cookieBox").css("display", "none");
21733    return
21734  }
21735
21736  if (!$web5.layout.wasCookieInfoSeen()) {
21737    $("#cookieBox").css("display", "table");
21738  } else {
21739    $("#cookieBox").css("display", "none");
21740  }
21741}
21742
21743$web5.layout.getSiteBlockedLink = function() {
21744  let langCode = $web5.multilingual.getCurrentEditorLanguageCode();
21745  let hostname = "pl.mfirma.eu";
21746
21747  if (langCode == 'de' || langCode == 'cz' || langCode == 'ro' || langCode == 'ru' || langCode == 'ua') {
21748    hostname = langCode + ".mfirma.eu";
21749  }
21750
21751  if (langCode == 'si') {
21752    hostname = "web5.si";
21753  }
21754
21755  return "https://" + hostname + "/?utm_source=" + hostname + "/block&utm_medium=popup&utm_campaign=" + hostname;
21756}
21757
21758$web5.layout.showSiteBlocked = function() {
21759
21760  if ($web5.isAppMode()) return;
21761
21762  let innerPanel = $("#siteBlockedInnerPanel");
21763  let langCode = $web5.multilingual.getCurrentSiteLanguageCode();
21764  let siteExpiredTitle = staticMessages[langCode].siteExpiredTitle;
21765  let siteBlockedMessage = staticMessages[langCode].siteExpiredMessage;
21766  let closeButton = staticMessages[langCode].shop_close_text;
21767
21768  let siteBlockedTxt = '<body style="background:transparent"><div class="panel panel-default">' +
21769    '      <div class="panel-heading siteBlockedHeader">' +
21770    '        <div class="siteBlockedHeaderText">' + siteExpiredTitle + '</div>' +
21771    '        <img class="siteBlockedHeaderLogo" src="/specific/gfx/new/portal/logo.png">' +
21772    '      </div>' +
21773    '      <div class="panel-body">' +
21774    '        <p class="siteBlockedText">' + siteBlockedMessage + '</p>' +
21775    '        <center><a class="btn btn-success" target="_parent" href="' + $web5.layout.getSiteBlockedLink() + '" rel="nofollow">' + closeButton + '</a></center>' +
21776    '      </div>' +
21777    '    </div></body>';
21778
21779  let head = "<head>\n";
21780
21781  $("link").each(function() {
21782    let hrefLink = $(this).attr('href');
21783    if (hrefLink.includes("styles")) {
21784      head += "<link rel='stylesheet' href='" + hrefLink + "'>\n";
21785    }
21786  });
21787
21788  head += "</head>\n";
21789  siteBlockedTxt = head + siteBlockedTxt;
21790
21791  var iframe = document.createElement('iframe');
21792  iframe.setAttribute("scrolling", "no");
21793  $(innerPanel).append(iframe);
21794  iframe.contentWindow.document.open();
21795  iframe.contentWindow.document.write(siteBlockedTxt);
21796  iframe.contentWindow.document.close();
21797
21798  $(iframe).css("width", "100%");
21799  $(iframe).css("min-height", "260px");
21800  $(iframe).css("border", "none");
21801}
21802
21803
21804$(document).ready(function() {
21805  setTimeout($web5.showCookie, 3000);
21806  setTimeout($web5.layout.showSiteBlocked, 3000);
21807});
21808
21809$web5.Web5menu = {};
21810
21811$web5.Web5menu.maxMenuItemHeight = function(UID) {
21812  var highestBox = 0;
21813  var className = '.menuItemLink' + UID;
21814  $(className).each(function() {
21815    if ($(this).outerHeight() > highestBox) {
21816      highestBox = $(this).outerHeight();
21817    }
21818  });
21819  return highestBox;
21820}
21821
21822$web5.Web5menu.adjustHeight = function(UID) {
21823  var className = '.menuItem' + UID;
21824  var maxHeight = $web5.Web5menu.maxMenuItemHeight(UID);
21825  if(maxHeight > 12) $(className).css('min-height', maxHeight + "px");
21826}
21827
21828$web5.news = {};
21829
21830$web5.news.emptyPost = {};
21831$web5.news.emptyPost.currentLanguageData = {};
21832$web5.news.emptyPost.currentLanguageData.title = "";
21833$web5.news.emptyPost.currentLanguageData.text = "";
21834$web5.news.emptyPost.currentLanguageData.imageTitle = "";
21835$web5.news.emptyPost.currentLanguageData.customUrl = "";
21836$web5.news.emptyPost.pageUID = null;
21837$web5.news.emptyPost.date = new Date().getTime();
21838$web5.news.emptyPost.image = null;
21839$web5.news.emptyPost.imageScale = 20;
21840$web5.news.emptyPost.imagePosition = "left";
21841
21842
21843$web5.news.getPostString = function(widgetUID, postIndex) {
21844  let post = $web5.news.getPost(widgetUID, postIndex);
21845  return $web5.news.getDateString(post.date);
21846}
21847
21848$web5.news.getPost = function(widgetUID, postIndex) {
21849  let widgetData = $web5.getWidgetData(widgetUID);
21850  let newsCollectionID = widgetData.newsCollectionID;
21851  let posts = $web5.getData("Web5News")[newsCollectionID];
21852  var numberOfPosts = posts.length;
21853  var pageSize = widgetData.pageSize;
21854  var currentPage = $web5.getWidgetTempData(widgetUID).currentPage;
21855
21856  postIndex = currentPage * pageSize + postIndex
21857
21858  if (postIndex < numberOfPosts) {
21859    return posts[postIndex];
21860  }
21861  return $web5.news.emptyPost;
21862}
21863
21864$web5.news.getCurrentPageIndex = function(widgetUID) {
21865  return $web5.getWidgetTempData(widgetUID).currentPage;
21866}
21867
21868$web5.news.goToPage = function(widgetUID, index) {
21869  var widgetData = $web5.getWidgetTempData(widgetUID);
21870  widgetData.currentPage = index;
21871  $web5.news.updateNewsUI(widgetUID);
21872}
21873
21874$web5.news.nextPage = function(widgetUID) {
21875  var numberOfPages = $web5.news.getNumberOfPages(widgetUID);
21876  var widgetData = $web5.getWidgetTempData(widgetUID);
21877
21878  if (widgetData.currentPage < numberOfPages - 1) widgetData.currentPage++;
21879
21880  $web5.news.updateNewsUI(widgetUID);
21881}
21882
21883
21884$web5.news.previousPage = function(widgetUID) {
21885  var widgetData = $web5.getWidgetTempData(widgetUID);
21886
21887  if (widgetData.currentPage > 0)
21888    widgetData.currentPage--;
21889
21890  $web5.news.updateNewsUI(widgetUID);
21891}
21892
21893$web5.news.getNumberOfPages = function(widgetUID) {
21894  let widgetData = $web5.getWidgetData(widgetUID);
21895  let newsCollectionID = widgetData.newsCollectionID;
21896  let numberOfPosts = $web5.getData("Web5News")[newsCollectionID].length;
21897  let pageSize = widgetData.pageSize;
21898
21899  return Math.ceil(numberOfPosts / pageSize);
21900}
21901
21902$web5.news.getNumberOfPosts = function(widgetUID) {
21903  let widgetData = $web5.getWidgetData(widgetUID);
21904  let newsCollectionID = widgetData.newsCollectionID;
21905  let numberOfPosts = $web5.getData("Web5News")[newsCollectionID].length;
21906
21907  return numberOfPosts;
21908}
21909
21910$web5.news.isPost = function(widgetUID, postIndex) {
21911  return $web5.news.getPost(widgetUID, postIndex) != null;
21912}
21913
21914$web5.news.getPostNavigationText = function(widgetUID) {
21915  return (1 + $web5.news.getCurrentPageIndex(widgetUID)) + "/" + $web5.news.getNumberOfPages(widgetUID);
21916}
21917
21918$web5.news.getPostImageWrapperStyle = function(widgetUID, postIndex) {
21919  var post = $web5.news.getPost(widgetUID, postIndex);
21920  return {
21921    'width': post.imageScale + "%",
21922    'float': post.imagePosition == 'center' ? 'none' : post.imagePosition,
21923    'display': post.image == null ? 'none' : 'block'
21924  }
21925}
21926
21927$web5.news.showOnlyVisibleImageTitle = function(widgetUID, postIndex) {
21928  var post = $web5.news.getPost(widgetUID, postIndex);
21929  var isVisible = post.currentLanguageData.imageTitle != '' || ($web5.isAppMode() && $web5.editor.editorMode);
21930
21931  return {
21932    'display': isVisible ? 'block' : 'none'
21933  }
21934}
21935
21936$web5.news.getPostSeeMoreStyle = function(widgetUID, postIndex) {
21937  var post = $web5.news.getPost(widgetUID, postIndex);
21938  var isHidden = post == $web5.news.emptyPost || !post.isLinkDefined();
21939
21940  return {
21941    'display': isHidden ? 'none' : 'block'
21942  }
21943}
21944
21945$web5.news.getPostStyle = function(widgetUID, postIndex) {
21946  var post = $web5.news.getPost(widgetUID, postIndex);
21947  var isVisible = post != $web5.news.emptyPost;
21948
21949  return {
21950    'display': isVisible ? 'block' : 'none'
21951  }
21952}
21953
21954$web5.news.getDateString = function(date) {
21955  let dateObj = new Date(date);
21956  let month = dateObj.getMonth() + 1;
21957  let day = dateObj.getDate();
21958  let year = dateObj.getFullYear();
21959
21960  if (month < 10) month = "0" + month;
21961
21962  let dateString = day + "." + month + "." + year;
21963
21964  return dateString;
21965
21966}
21967
21968$web5.news.updateNewsUI = function(widgetUID) {
21969
21970  if ($web5.isAppMode()) {
21971    $(window).trigger('renderNewsEvent');
21972    return;
21973  }
21974
21975  $("#newsWidgetPanel" + widgetUID).each(function() {
21976
21977    var navText = $web5.news.getPostNavigationText(widgetUID);
21978    $(".postsNavigation" + widgetUID).each(function() {
21979      $(this).html($web5.news.getPostNavigationText(widgetUID));
21980    });
21981
21982    var pageSize = $web5.getWidgetData(widgetUID).pageSize;
21983
21984
21985    for (var index = 0; index < pageSize; index++) {
21986
21987      var post = $web5.news.getPost(widgetUID, index);
21988      if (post != $web5.news.emptyPost) {
21989        $("#post" + widgetUID + "_" + index).attr('style', 'display:block');
21990
21991        var title = post.currentLanguageData.title;
21992        $("#postTitle" + widgetUID + "_" + index).html(title);
21993
21994        let dateString = $web5.news.getDateString(post.date);
21995        $("#postDate" + widgetUID + "_" + index).html(dateString);
21996
21997        var postStyle = $web5.news.getPostImageWrapperStyle(widgetUID, index);
21998        var styleAttr = "width:" + postStyle.width + ";float:" + postStyle.float + ";display:" + postStyle.display;
21999        $("#postImageWrapper" + widgetUID + "_" + index).attr('style', styleAttr);
22000
22001        var postImageMaxWidth = $("#postImage" + widgetUID + "_" + index).width();
22002
22003        var imageLink = post.image == null ? "" : post.image.getUrl();
22004        var imageTitle = post.image == null ? "" : post.currentLanguageData.imageTitle;
22005        var imageURL = post.image == null ? "" : post.image.getThumbUrl(postImageMaxWidth);
22006        $("#postImageLink" + widgetUID + "_" + index).attr('href', imageLink);
22007        $("#postImageLink" + widgetUID + "_" + index).attr('data-caption', imageTitle);
22008
22009        var postImageTitleElement = $("#postImageTitle" + widgetUID + "_" + index);
22010
22011        postImageTitleElement.find(".web5_text_class").text(imageTitle);
22012
22013        var isVisible = imageTitle != '' || ($web5.isAppMode() && $web5.editor.editorMode);
22014        if (isVisible)
22015          postImageTitleElement.parent().attr('style', 'display:block');
22016        else
22017          postImageTitleElement.parent().attr('style', 'display:none');
22018
22019        var postSeeMoreWraperElement = $("#postSeeMoreWraper" + widgetUID + "_" + index);
22020        if (post.isLinkDefined())
22021          postSeeMoreWraperElement.attr('style', 'display:block');
22022        else
22023          postSeeMoreWraperElement.attr('style', 'display:none');
22024
22025        $("#postImage" + widgetUID + "_" + index).attr('src', imageURL);
22026        if (post.image != null) {
22027          $("#postImage" + widgetUID + "_" + index).attr('data-thumbs', post.image.getImageSize());
22028          $("#postImage" + widgetUID + "_" + index).attr('alt', imageTitle);
22029          $("#postImage" + widgetUID + "_" + index).attr('title', imageTitle);
22030        }
22031        $("#postText" + widgetUID + "_" + index).html(post.currentLanguageData.text);
22032        $("#postSeeMoreLink" + widgetUID + "_" + index).attr('href', post.getTargeLinkURL());
22033        $("#postSeeMoreLink" + widgetUID + "_" + index).attr('target', post.getTargeLinkURLAttr());
22034      } else {
22035        $("#post" + widgetUID + "_" + index).attr('style', 'display:none');
22036      }
22037      $web5.utilities.fancybox();
22038    }
22039  });
22040}
22041
22042$web5.news.addPostMethods = function(post, skipDataInit) {
22043  var image = post.image;
22044  if (image != null) {
22045    $web5.Web5Image.addImageMethods(image);
22046  }
22047  $web5.link.addLinkMethods(post, skipDataInit);
22048}
22049
22050$web5.news.addPostsMethods = function() {
22051  if ($web5.isStaticMode()) {
22052    var newsCollections = $web5.getData("Web5News");
22053    for (let cIndex in newsCollections) {
22054      posts = newsCollections[cIndex];
22055      for (let i = 0; i < posts.length; i++) {
22056        let post = posts[i];
22057        $web5.news.addPostMethods(post);
22058      }
22059    }
22060  }
22061}
22062
22063
22064$web5.news.addPostsMethods();
22065$web5.news.addPostMethods($web5.news.emptyPost, true);
22066
22067$web5.slideshow = {};
22068$web5.slideshow.htmlCreationInProgress = {};
22069$web5.slideshow.sliders = {};
22070$web5.slideshow.previousParentWidth = {};
22071$web5.slideshow.dontRenderSlideshow = false;
22072$web5.slideshow.schowOneSlideIndex = null;
22073
22074
22075$web5.slideshow.restartSlideshow = function(widgetUID, imageIndex, force) {
22076
22077  if ($web5.slideshow.htmlCreationInProgress[widgetUID]) return;
22078
22079  let sliderPanelElement = $("#slideshowPanel" + widgetUID);
22080
22081  // jak $web5.getWidgetData(widgetUID)jest  null to znaczy ze widget juz nie istnieje ale calllback byl zanim usunieto widget
22082  if (sliderPanelElement.length == 0 || $web5.isPublishingActive() ||
22083    $web5.getWidgetData(widgetUID) == null ||
22084    ($web5.isAppMode() && $web5.slideshow.dontRenderSlideshow)) {
22085    delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22086    return;
22087  }
22088
22089  let currentPanelWidth = sliderPanelElement.width();
22090
22091  if (currentPanelWidth < 50) {
22092    //console.log("restartSlideshow - width below 50 (ofeten -4), dont render", currentPanelWidth);
22093    delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22094    return;
22095  }
22096
22097  if (!force && $web5.slideshow.previousParentWidth[widgetUID] == currentPanelWidth) {
22098    delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22099    return; // dont render if width is the same
22100  }
22101
22102
22103  $web5.slideshow.htmlCreationInProgress[widgetUID] = true;
22104
22105  let slideshowsInProgress = Object.keys($web5.slideshow.htmlCreationInProgress).length;
22106  setTimeout(function() {
22107    //console.log("restartSlideshow | ", widgetUID, " | width: ", currentPanelWidth, " | slideshowsInProgress: ", slideshowsInProgress);
22108    $web5.slideshow.restartSlideshowStart(widgetUID, imageIndex, force);
22109  }, slideshowsInProgress * 300);
22110
22111}
22112
22113$web5.slideshow.restartSlideshowStart = function(widgetUID, imageIndex, force) {
22114
22115  $web5.slideshow.updateImageList(widgetUID);
22116  let data = $web5.getWidgetData(widgetUID);
22117
22118  if (data.animation == "movingSlides") {
22119    $("#slideshowPanel" + widgetUID).css("visibility", "hidden");
22120    $("#slideshowPanel" + widgetUID).css("height", "0px");
22121    $("#slideshowPanel" + widgetUID).css("overflow", "hidden");
22122    $web5.slideshow.destroySlider(widgetUID).then($web5.slideshow.buildHTMLThumbs);
22123    return;
22124  }
22125
22126  $web5.slideshow.destroySlider(widgetUID).then($web5.slideshow.buildHTMLBanner).then($web5.slideshow.addSlider).then(function() {
22127    if ($web5.slideshow.sliders[widgetUID] != null && imageIndex != null) {
22128      $web5.slideshow.sliders[widgetUID].$GoTo(imageIndex);
22129    }
22130  })
22131}
22132
22133$web5.slideshow.destroySlider = function(widgetUID) {
22134
22135  if ($web5.slideshow.sliders[widgetUID] != null) {
22136    $web5.slideshow.sliders[widgetUID].$Destroy();
22137    delete $web5.slideshow.sliders[widgetUID];
22138  }
22139
22140  let slickElementID = "#movingThumbsSlick" + widgetUID;
22141  $(slickElementID).slick('unslick');
22142
22143  $("#sliderWrapper" + widgetUID).html("");
22144  return $web5.utilities.delay(0).then(function() {
22145    return widgetUID;
22146  });
22147}
22148
22149
22150$web5.slideshow.buildHTMLThumbs = function(widgetUID) {
22151
22152  let sliderPanelElement = $("#slideshowPanel" + widgetUID).width();
22153  if (sliderPanelElement == null) {
22154    console.log("buildHTMLThumbs sliderPanelElement == null | ", widgetUID);
22155    setTimeout(function() { $web5.slideshow.buildHTMLThumbs(widgetUID) }, 250);
22156    return;
22157  }
22158
22159  if (sliderPanelElement < 0) {
22160    delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22161    return;
22162  }
22163
22164  $web5.slideshow.previousParentWidth[widgetUID] = $("#slideshowPanel" + widgetUID).width();
22165
22166  let thumbsHeight = $web5.slideshow.getMovingThumbsHeight(widgetUID);
22167  let sliderHTML = "<div style='width:" + sliderPanelElement + "px' id='movingThumbsSlick" + widgetUID + "'>"
22168  let images = $web5.slideshow.getImages(widgetUID);
22169  let oryginalThumbSize = images.length;
22170  var thumbList = [];
22171
22172  let thumbsMinSize = 8;
22173  for (let i = 0; i < thumbsMinSize; i++) {
22174    if (thumbList.length < thumbsMinSize) {
22175      thumbList = thumbList.concat(images);
22176    } else {
22177      break;
22178    }
22179  }
22180
22181  let imgClassStr = $("#slideshowPanel" + widgetUID).attr('data-web5-image-stylename');
22182
22183  for (let imgIndex = 0; imgIndex < thumbList.length; imgIndex++) {
22184    let image = thumbList[imgIndex];
22185    let ratio = thumbsHeight / image.height;
22186    let imageThumbURL = $web5.Web5Image.getThumbUrl(image, image.width * ratio);
22187    let imageURL = $web5.Web5Image.getUrl(image);
22188
22189    sliderHTML += "<div class='slideshow-image-background thumbWrapper " + imgClassStr + "' href='" + imageURL + "'" + " onclick='$web5.slideshow.showFancyBox(\"" + widgetUID + "\"," + imgIndex % oryginalThumbSize + ")'>";
22190    sliderHTML += "<img style='cursor:pointer;height:" + thumbsHeight + "px' src=\"" + imageThumbURL + "\" alt=\"" + image.currentLanguageData.title + "\"></div>";
22191
22192  }
22193
22194  sliderHTML += "</div>";
22195
22196  $("#sliderWrapper" + widgetUID).css('height', 'auto');
22197  $("#sliderWrapper" + widgetUID).html(sliderHTML);
22198
22199
22200
22201
22202  setTimeout(function() {
22203
22204    let data = $web5.getWidgetData(widgetUID);
22205    let slickElementID = "#movingThumbsSlick" + widgetUID;
22206
22207    let stopAutoplay = $web5.isAppMode() && $web5.editor.editorMode || $web5.isPublishingActive();
22208
22209    let autoplay = data.autoplay && !stopAutoplay;
22210    let arrows = !autoplay;
22211    let slidesToScroll = 1;
22212    let slidesToShow = 3;
22213    let centerMode = true;
22214    let speed = 1000;
22215    let autoplaySpeed = null;
22216    let cssEase = "ease-in-out";
22217
22218    if (autoplay && data.animationSpeed == "smooth") {
22219      speed = 1000;
22220      autoplaySpeed = 2000;
22221    }
22222
22223    if (autoplay && data.animationSpeed == "fast") {
22224      speed = 500;
22225      autoplaySpeed = 1500;
22226    }
22227
22228
22229    let slidderOptions = {
22230      dots: false,
22231      infinite: true,
22232      speed: speed,
22233      slidesToShow: slidesToShow,
22234      slidesToScroll: slidesToScroll,
22235      autoplay: autoplay,
22236      autoplaySpeed: autoplaySpeed,
22237      variableWidth: true,
22238      centerMode: centerMode,
22239      arrows: arrows,
22240      variableWidth: true,
22241      cssEase: cssEase,
22242    }
22243
22244    setTimeout(function() {
22245      delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22246      $("#slideshowPanel" + widgetUID).css("height", "auto");
22247      $("#slideshowPanel" + widgetUID).css("overflow", "visible");
22248      $("#slideshowPanel" + widgetUID).css("visibility", "visible");
22249
22250      $(slickElementID).not('.slick-initialized').slick(slidderOptions);
22251    }, 100);
22252  }, 100);
22253}
22254
22255$web5.slideshow.buildHTMLBanner = function(widgetUID) {
22256
22257  let data = $web5.getWidgetData(widgetUID);
22258
22259  // w tle robimy import szablonów i widgetu moze w tym callbacku juz nie być
22260  if (data == null) {
22261    delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22262    return widgetUID;
22263  }
22264
22265  let wraperElement = $("#sliderWrapper" + widgetUID);
22266  let images = $web5.slideshow.getImages(widgetUID);
22267
22268  if (wraperElement.length != 1 || $web5.slideshow.htmlCreationInProgress[widgetUID] == null || images == null || images.length == 0) {
22269    delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22270    return widgetUID;
22271  }
22272
22273  return $web5.utilities.delay(100).then(function() {
22274
22275    let data = $web5.getWidgetData(widgetUID);
22276    // w tle robimy import szablonów i widgetu moze w tym callbacku juz nie być
22277    if (data == null) {
22278      delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22279      return widgetUID;
22280    }
22281
22282    let parentWidth = $("#slideshowPanel" + widgetUID).width();
22283    $web5.slideshow.previousParentWidth[widgetUID] = parentWidth;
22284
22285    let imgTitle = $("#imageTitle" + widgetUID);
22286
22287    // jeśli w tle robimy import szablonów i widgetu moze w tym callbacku juz nie być
22288    if (imgTitle.length == 0) {
22289      delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22290      return
22291    }
22292
22293    let slideshowHeight = 200;
22294    let firstImage = images[0];
22295
22296    if (data.imagesSource == 'banner') {
22297      slideshowHeight = Math.round(firstImage.height * (parentWidth / firstImage.width));
22298      if (slideshowHeight > 2000) slideshowHeight = 2000;
22299    }
22300
22301    let screenWidth = Math.min(1300, $(window).width());
22302    let widthRatio = screenWidth / 1300;
22303    let heightRatio = 1;
22304
22305    let bodyWidth = $("body").width();
22306    if (data.height != 'auto' && bodyWidth >= 900) {
22307      let defaultSlideshowHeight = slideshowHeight;
22308      slideshowHeight = parseInt(data.height);
22309      slideshowHeight = Math.round(slideshowHeight * widthRatio);
22310      heightRatio = slideshowHeight / defaultSlideshowHeight;
22311    }
22312
22313    if ($web5.editor && $web5.editor.publishingMode) {
22314      let ratio = 320 / parentWidth;
22315      parentWidth = Math.floor(width * ratio);
22316      slideshowHeight = Math.floor(slideshowHeight * ratio);
22317    }
22318
22319    width = parentWidth + "px";
22320    height = slideshowHeight + "px";
22321
22322    let navigatorHTML = "";
22323    navigatorHTML += "  <div data-u=\"navigator\" class=\"jssorb031\" style=\"position:absolute;top:12px;right:12px;\" data-autocenter=\"1\" data-scale=\"0.5\" data-scale-bottom=\"0.75\">";
22324    navigatorHTML += "   <div data-u=\"prototype\" class=\"i\" style=\"width:16px;height:16px;\">";
22325    navigatorHTML += "       <svg viewBox=\"0 0 16000 16000\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;\">";
22326    navigatorHTML += "           <circle class=\"b\" cx=\"8000\" cy=\"8000\" r=\"5800\"><\/circle>";
22327    navigatorHTML += "       <\/svg>";
22328    navigatorHTML += "   <\/div>";
22329    navigatorHTML += "  <\/div>";
22330
22331    let sliderHTML = "";
22332
22333    sliderHTML += "    <div id=\"slider" + widgetUID + "\" style=\"position:absolute;top:0px;left:0px;
22333width:" + width + ";height:" + height + ";overflow:hidden;\">";
22334    sliderHTML += "      <div data-u=\"slides\" style=\"position:absolute;top:0px;left:0px;width:" + width + ";height:" + height + ";overflow:hidden;\">";
22335
22336
22337    for (let imgIndex = 0; imgIndex < images.length; imgIndex++) {
22338
22339      let classList = imgTitle.attr('class').replace("slideshowHiddenTitle", "");
22340
22341      let imageURL = $web5.slideshow.getThumbUrl(widgetUID, imgIndex, parentWidth * Math.max(1, heightRatio));
22342
22343      sliderHTML += "<div>";
22344      sliderHTML += "<img data-u='image' src=\"" + imageURL + "\" alt=\"" + images[imgIndex].currentLanguageData.title + "\">";
22345
22346      if (images[imgIndex].currentLanguageData.title != '' && data.titleVisible) {
22347        sliderHTML += "<div class='slideshowCaption " + classList + " slideshowResponsiveCaption'>" + images[imgIndex].currentLanguageData.title + "<\/div>";
22348      }
22349      sliderHTML += "<\/div>";
22350    }
22351    sliderHTML += "      <\/div>";
22352
22353    if ($web5.isAppMode() && $web5.editor.editorMode && data.imagesSource == 'banner') {
22354      sliderHTML += navigatorHTML;
22355    }
22356
22357    sliderHTML += "  <\/div>";
22358    $("#sliderWrapper" + widgetUID).html(sliderHTML);
22359    $("#sliderWrapper" + widgetUID).height(height);
22360
22361    return widgetUID;
22362  });
22363}
22364
22365
22366
22367$web5.slideshow.addSlider = function(widgetUID) {
22368
22369  if ($web5.slideshow.htmlCreationInProgress[widgetUID] == null) return widgetUID;
22370
22371  return $web5.utilities.delay(0).then(function() {
22372    let data = $web5.getWidgetData(widgetUID);
22373    let sliderElement = document.getElementById('slider' + widgetUID);
22374    if (sliderElement == null) return;
22375
22376    let speed = 3000;
22377
22378    let rotUpX = { $Duration: speed, x: 0.25, y: 0.5, $Rotate: -0.1, $Easing: { $Left: $Jease$.$InQuad, $Top: $Jease$.$InQuad, $Opacity: $Jease$.$Linear, $Rotate: $Jease$.$InQuad }, $Opacity: 2, $Brother: { $Duration: speed, x: -0.1, y: -0.7, $Rotate: 0.1, $Easing: { $Left: $Jease$.$InQuad, $Top: $Jease$.$InQuad, $Opacity: $Jease$.$Linear, $Rotate: $Jease$.$InQuad }, $Opacity: 2 } };
22379    let rotDownX = { $Duration: speed, x: -0.1, y: -0.7, $Rotate: 0.1, $During: { $Left: [0.6, 0.4], $Top: [0.6, 0.4], $Rotate: [0.6, 0.4] }, $Easing: { $Left: $Jease$.$InQuad, $Top: $Jease$.$InQuad, $Opacity: $Jease$.$Linear, $Rotate: $Jease$.$InQuad }, $Opacity: 2, $Brother: { $Duration: speed, x: 0.2, y: 0.5, $Rotate: -0.1, $Easing: { $Left: $Jease$.$InQuad, $Top: $Jease$.$InQuad, $Opacity: $Jease$.$Linear, $Rotate: $Jease$.$InQuad }, $Opacity: 2 } };
22380    let curtain = { $Duration: speed, x: 1, y: 2, $Cols: 2, $Zoom: 11, $Rotate: 1, $ChessMode: { $Column: 19 }, $Easing: { $Left: $Jease$.$InCubic, $Top: $Jease$.$InCubic, $Zoom: $Jease$.$InCubic, $Opacity: $Jease$.$OutQuad, $Rotate: $Jease$.$InCubic }, $Assembly: 2049, $Opacity: 2, $Round: { $Rotate: 0.8 } };
22381    let tiles1 = { $Duration: speed, $Delay: 12, $Cols: 10, $Rows: 5, $Clip: 15, $SlideOut: true, $Formation: $JssorSlideshowFormations$.$FormationStraightStairs, $Easing: $Jease$.$OutQuad, $Opacity: 2, $Assembly: 2049 };
22382    let tiles2 = { $Duration: speed, $Delay: 12, $Cols: 10, $Rows: 5, $Clip: 15, $SlideOut: true, $Formation: $JssorSlideshowFormations$.$FormationZigZag, $Easing: $Jease$.$OutQuad, $Opacity: 2 };
22383    let slideDown = { $Duration: speed, y: 1, $Easing: $Jease$.$InQuad, $Opacity: 2 };
22384    let slideTop = { $Duration: speed, y: -1, $Easing: { $Top: $Jease$.$InCubic }, $Opacity: 2 };
22385    let slideLeft = { $Duration: speed, x: -1, $Easing: $Jease$.$InQuad, $Opacity: 2 };
22386    let slideRight = { $Duration: speed, x: 1, $Easing: { $Top: $Jease$.$InCubic }, $Opacity: 2 };
22387
22388    let effects = {
22389      rotUpX: [rotUpX],
22390      rotDownX: [rotDownX],
22391      curtain: [curtain],
22392      tiles1: [tiles1],
22393      tiles2: [tiles2],
22394      slideDown: [slideDown],
22395      slideTop: [slideTop],
22396      slideLeft: [slideLeft],
22397      slideRight: [slideRight],
22398      random: [rotUpX, curtain, tiles1, rotDownX, slideRight, slideDown, tiles2, slideLeft, slideTop],
22399    }
22400
22401    let slideshowTransitions = effects[data.animation];
22402    let showSlides = ($web5.isAppMode() && $web5.editor.editorMode) || $web5.isPublishingActive() || $web5.slideshow.schowOneSlideIndex != null ? 0 : 1;
22403
22404    let options = {
22405      $AutoPlay: showSlides,
22406      $FillMode: data.fill,
22407      $SlideshowOptions: {
22408        $Class: $JssorSlideshowRunner$,
22409        $Transitions: slideshowTransitions,
22410        $TransitionsOrder: 1
22411      }
22412    };
22413
22414    if ($web5.slideshow.schowOneSlideIndex != null) {
22415      let images = $web5.slideshow.getImages(widgetUID);
22416      options.$StartIndex = $web5.slideshow.schowOneSlideIndex % images.length;
22417    }
22418
22419
22420    if ($web5.isAppMode() && ($web5.editor.editorMode || $web5.editor.publishingMode) && data.imagesSource == 'banner') {
22421      options.$BulletNavigatorOptions = {
22422        $Class: $JssorBulletNavigator$,
22423        $ChanceToShow: 2, //[Required] 0 Never, 1 Mouse Over, 2 Always
22424        $AutoCenter: 1, //[Optional] Auto center navigator in parent container, 0 None, 1 Horizontal, 2 Vertical, 3 Both, default value is 0
22425        $Steps: 1, //[Optional] Steps to go for each navigation request, default value is 1
22426        $Rows: 1, //[Optional] Specify lanes to arrange items, default value is 1
22427        $SpacingX: 10, //[Optional] Horizontal space between each item in pixel, default value is 0
22428        $SpacingY: 10, //[Optional] Vertical space between each item in pixel, default value is 0
22429        $Orientation: 1 //[Optional] The orientation of the navigator, 1 horizontal, 2 vertical, default value is 1
22430      }
22431    }
22432
22433
22434    $web5.slideshow.sliders[widgetUID] = new $JssorSlider$(sliderElement, options);
22435
22436    delete $web5.slideshow.htmlCreationInProgress[widgetUID];
22437    return widgetUID;
22438  });
22439}
22440
22441
22442$web5.slideshow.getImages = function(widgetUID) {
22443  let data = $web5.getWidgetData(widgetUID);
22444  if ($web5.isAppMode()) {
22445    $web5.slideshow.updateImageList(widgetUID);
22446  }
22447  let images = data.externalImages;
22448
22449  if (data.imagesSource == 'banner') {
22450    images = data.images.images;
22451  }
22452
22453  return images;
22454}
22455
22456$web5.slideshow.getMovingThumbsHeight = function(widgetUID) {
22457  let data = $web5.getWidgetData(widgetUID);
22458  let height = 250;
22459  if (data.height != "auto") height = parseInt(data.height);
22460  return height;
22461}
22462
22463$web5.slideshow.showFancyBox = function(widgetUID, index) {
22464  let images = $web5.slideshow.getImages(widgetUID);
22465  let slideshowImages = [];
22466
22467  for (let i = 0; i < images.length; i++) {
22468    let image = images[i];
22469    let imageURL = $web5.Web5Image.getUrl(image);
22470    slideshowImages.push({ src: imageURL })
22471  }
22472
22473  let instance = $.fancybox.open(slideshowImages, {
22474    infobar: true,
22475    loop: true
22476  });
22477
22478  instance.jumpTo(index);
22479}
22480
22481
22482$web5.slideshow.getThumbUrl = function(widgetUID, imgIndex, imageMaxWidth) {
22483  let images = $web5.slideshow.getImages(widgetUID);
22484  if (images != null) {
22485    return images[imgIndex].getThumbUrl(imageMaxWidth);
22486  } else {
22487    return "";
22488  }
22489}
22490
22491
22492$web5.slideshow.getAvaliableGalleries = function() {
22493  let widgets = $web5.widgetsManager.getWidgetsByType('image_gallery');
22494
22495  widgets.sort(function(a, b) {
22496    return b.data.images.length() - a.data.images.length();
22497  });
22498
22499  return widgets;
22500}
22501
22502$web5.slideshow.updateImageList = function(widgetUID) {
22503  if ($web5.isStaticMode()) return;
22504
22505  let data = $web5.getWidgetData(widgetUID);
22506  let images = [];
22507  if (data.imagesSource == 'banner') {
22508    data.externalImages = null;
22509  } else {
22510    if (data.externalGalleryUID != null && $web5.widgetsManager.getWidgetByUID(data.externalGalleryUID) != null) {
22511      images = $web5.widgetsManager.getWidgetByUID(data.externalGalleryUID).data.images.getList();
22512    } else {
22513      let imgWidgets = $web5.slideshow.getAvaliableGalleries();
22514      if (imgWidgets.length != 0) {
22515        images = imgWidgets[0].data.images.getList();
22516      }
22517      data.externalGalleryUID = null;
22518    }
22519    data.externalImages = images;
22520  }
22521}
22522
22523
22524$web5.slideshow.onLoad = function(widgetUID) {
22525  let images = $web5.slideshow.getImages(widgetUID);
22526
22527  for (let imgIndex in images) {
22528    let image = images[imgIndex];
22529    $web5.Web5Image.addImageMethods(image);
22530  }
22531
22532  if ($web5.isStaticMode()) {
22533    $web5.utilities.setTimoutOnce("Slideshow" + widgetUID, function() {
22534      $web5.slideshow.restartSlideshow(widgetUID, null, true);
22535    }, 0);
22536  }
22537}
22538
22539$web5.slideshow.onResize = function(widgetUID, data) {
22540  $web5.utilities.setTimoutOnce("Slideshow" + widgetUID, function() {
22541    $web5.slideshow.restartSlideshow(widgetUID, null, true);
22542  }, 100);
22543}
22544
22545$web5.slideshow.updateSlideshowsInChapter = function(widgetUID) {
22546  $("#chapterContent" + widgetUID).find(".sliderWrapper").each(function() {
22547    let slideshowWidgetUID = $(this).attr('id').replace("sliderWrapper", "");
22548
22549    let slickElement = $("#movingThumbsSlick" + slideshowWidgetUID);
22550    if (slickElement.length != 0) return;
22551
22552    $web5.utilities.setTimoutOnce("Slideshow" + slideshowWidgetUID, function() {
22553      $web5.slideshow.restartSlideshow(slideshowWidgetUID, null, true);
22554    }, 300);
22555  });
22556}
22557
22558$web5.socialIcons = {};
22559
22560
22561
22562$web5.Web5menu = {};
22563
22564$web5.Web5menu.maxMenuItemHeight = function(UID) {
22565  var highestBox = 0;
22566  var className = '.menuItemLink' + UID;
22567  $(className).each(function() {
22568    if ($(this).outerHeight() > highestBox) {
22569      highestBox = $(this).outerHeight();
22570    }
22571  });
22572  return highestBox;
22573}
22574
22575$web5.Web5menu.adjustHeight = function(UID) {
22576  var className = '.menuItem' + UID;
22577  var maxHeight = $web5.Web5menu.maxMenuItemHeight(UID);
22578  if(maxHeight > 12) $(className).css('min-height', maxHeight + "px");
22579}
22580
22581$web5.visitsCounter = {};
22582
22583
22584$web5.visitsCounter.getVisitsCount = function(callback) {
22585
22586  var self = this;
22587  var mfVisCookie = $web5.utilities.mfCookie.read('mf_visits');
22588
22589  if (mfVisCookie === null) {
22590    if ($web5.isSeam() && Seam.Component.getInstance('visitsCounterAction') != null) {
22591      Seam.Component.getInstance('visitsCounterAction').getVisitsCount($web5.getDomain(), function(data) {
22592        if (!isNaN(data)) { // setting value from server
22593          $web5.utilities.mfCookie.create('mf_visits', data, (1 / 24) / 4); //15 minutes as fration of day
22594          if (callback) callback(data);
22595        }
22596      });
22597    }
22598    return;
22599  }
22600
22601  if (callback) callback(mfVisCookie);
22602}
22603
22604$web5.visitsCounter.getCounterTypes = function() {
22605  return $web5.getData('counterTypes');
22606}
22607
22608$web5.visitsCounter.getCounterCategory = function(widgetUID) {
22609  let widgetData = $web5.getWidgetData(widgetUID);
22610  return $web5.visitsCounter.getCounterTypes()[widgetData.type].category;
22611}
22612
22613$web5.visitsCounter.getCSSStyle = function(position, widgetUID, visits) {
22614
22615  var widgetData = $web5.getWidgetData(widgetUID);
22616  var type = widgetData.type;
22617  var counter = $web5.visitsCounter.getCounterTypes()[type];
22618
22619  var styleObj = {
22620    width: counter.width,
22621    height: counter.height
22622  };
22623
22624  let urlPrefix = 'url(common/images/visits_counter/';
22625  if ($web5.editor != null) urlPrefix = 'url(/common/images/visits_counter/';
22626
22627  if (position !== null) {
22628    var digitOffset = visits.toString().charAt(position) * $web5.visitsCounter.getCounterTypes()[widgetData.type].width;
22629    styleObj.background = urlPrefix + type + '/counter.png) no-repeat -' + digitOffset + 'px 0';
22630  } else {
22631    styleObj['background-image'] = urlPrefix + type + '/counter.png)';
22632    styleObj['padding-top'] = counter.paddingTop;
22633    styleObj['padding-left'] = counter.paddingLeft;
22634  }
22635
22636  return styleObj;
22637};
22638
22639
22640
22641
22642$web5.visitsCounter.updateUI = function(widgetUID) {
22643  $web5.visitsCounter.getVisitsCount(function(visits) {
22644
22645    var counterNumberElement = $("#counterNumber" + widgetUID);
22646    var counterNumberElementMobile = $("#counterNumberMobile" + widgetUID);
22647
22648    counterNumberElement.each(function() {
22649      $(this).html(visits);
22650    })
22651
22652    counterNumberElementMobile.each(function() {
22653      $(this).html(visits);
22654    })
22655
22656    var counterDigitsWrapperElement = $("#counterDigitsWrapper" + widgetUID);
22657    if (counterDigitsWrapperElement.length !== 0) {
22658      counterDigitsWrapperElement.empty();
22659      var digits = visits.toString().length;
22660      for (var i = 0; i < digits; i++) {
22661        var digitElement = $("<span class='counter-digit'></span>");
22662        var style = $web5.visitsCounter.getCSSStyle(i, widgetUID, visits);
22663        digitElement.css(style);
22664        counterDigitsWrapperElement.append(digitElement);
22665      }
22666    }
22667  });
22668}
22669
22670$(document).ready(function() {
22671  if ($web5.isStaticMode() && $web5.isSeam() && $web5.utilities.mfCookie.read('mf_visits_count') !== 'false') {
22672    var address = window.location.host;
22673    var seamCounter = Seam.Component.getInstance('visitsCounterAction');
22674    if (seamCounter != null) {
22675      seamCounter.incrementVisitsCount(address, $web5.visitsCounter.updateUI);
22676      $web5.utilities.mfCookie.create('mf_visits_count', 'false', (1 / 24) / 4); //15 minut
22677    }
22678  }
22679});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.