From 15ae43bc55fffc8a9ccbf8215883532daf0d4a82 Mon Sep 17 00:00:00 2001 From: Borek Bernard Date: Mon, 27 Feb 2012 20:42:06 +0100 Subject: Colon is no longer rewritten to semicolon for IIS 7.x and for older versions of IIS, semicolon is displayed as is, not URL-encoded. --- inc/common.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/inc/common.php b/inc/common.php index 0c769c50d..26904dd46 100644 --- a/inc/common.php +++ b/inc/common.php @@ -323,12 +323,14 @@ function idfilter($id,$ue=true){ if ($conf['useslash'] && $conf['userewrite']){ $id = strtr($id,':','/'); }elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && - $conf['userewrite']) { + $conf['userewrite'] && + strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7.') === false) { $id = strtr($id,':',';'); } if($ue){ $id = rawurlencode($id); $id = str_replace('%3A',':',$id); //keep as colon + $id = str_replace('%3B',';',$id); //keep as semicolon $id = str_replace('%2F','/',$id); //keep as slash } return $id; -- cgit v1.2.3 From 9664a2b801ce91ae3707306f01fb4cad528b1258 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 14 Jul 2012 09:54:42 +0200 Subject: changed the link in the installer to point to wiki:welcome --- inc/lang/ar/lang.php | 4 ++-- inc/lang/az/lang.php | 4 ++-- inc/lang/bg/lang.php | 4 ++-- inc/lang/ca-valencia/lang.php | 4 ++-- inc/lang/ca/lang.php | 4 ++-- inc/lang/cs/lang.php | 4 ++-- inc/lang/da/lang.php | 4 ++-- inc/lang/de-informal/lang.php | 4 ++-- inc/lang/de/lang.php | 4 ++-- inc/lang/el/lang.php | 4 ++-- inc/lang/en/lang.php | 4 ++-- inc/lang/eo/lang.php | 4 ++-- inc/lang/es/lang.php | 4 ++-- inc/lang/et/lang.php | 4 ++-- inc/lang/eu/lang.php | 4 ++-- inc/lang/fa/lang.php | 4 ++-- inc/lang/fi/lang.php | 4 ++-- inc/lang/fr/lang.php | 4 ++-- inc/lang/gl/lang.php | 4 ++-- inc/lang/he/lang.php | 4 ++-- inc/lang/hr/lang.php | 4 ++-- inc/lang/hu/lang.php | 4 ++-- inc/lang/ia/lang.php | 4 ++-- inc/lang/id/lang.php | 4 ++-- inc/lang/it/lang.php | 4 ++-- inc/lang/ja/lang.php | 4 ++-- inc/lang/ko/lang.php | 4 ++-- inc/lang/la/lang.php | 4 ++-- inc/lang/lv/lang.php | 4 ++-- inc/lang/mk/lang.php | 4 ++-- inc/lang/mr/lang.php | 4 ++-- inc/lang/ne/lang.php | 4 ++-- inc/lang/nl/lang.php | 4 ++-- inc/lang/no/lang.php | 4 ++-- inc/lang/pl/lang.php | 4 ++-- inc/lang/pt-br/lang.php | 4 ++-- inc/lang/pt/lang.php | 4 ++-- inc/lang/ro/lang.php | 4 ++-- inc/lang/ru/lang.php | 4 ++-- inc/lang/sk/lang.php | 4 ++-- inc/lang/sl/lang.php | 4 ++-- inc/lang/sq/lang.php | 4 ++-- inc/lang/sr/lang.php | 4 ++-- inc/lang/sv/lang.php | 4 ++-- inc/lang/tr/lang.php | 4 ++-- inc/lang/uk/lang.php | 4 ++-- inc/lang/zh-tw/lang.php | 4 ++-- inc/lang/zh/lang.php | 4 ++-- 48 files changed, 96 insertions(+), 96 deletions(-) diff --git a/inc/lang/ar/lang.php b/inc/lang/ar/lang.php index 350e26695..0f5566471 100644 --- a/inc/lang/ar/lang.php +++ b/inc/lang/ar/lang.php @@ -284,8 +284,8 @@ $lang['i_badhash'] = 'الملف dokuwiki.php غير مصنف أو (hash=%s)'; $lang['i_badval'] = 'القيمة %s غير شرعية أو فارغة'; $lang['i_success'] = 'الإعدادات تمت بنجاح، يرجى حذف الملف install.php الآن. -ثم تابع إلى دوكو ويكي الجديدة'; -$lang['i_failure'] = 'بعض الأخطاء حدثت أثنا كتابة ملفات الإعدادات، عليك تعديلها يدوياً قبل أن تستطيع استخدام دوكو ويكي الجديدة'; +ثم تابع إلى دوكو ويكي الجديدة'; +$lang['i_failure'] = 'بعض الأخطاء حدثت أثنا كتابة ملفات الإعدادات، عليك تعديلها يدوياً قبل أن تستطيع استخدام دوكو ويكي الجديدة'; $lang['i_policy'] = 'تصريح ACL مبدئي'; $lang['i_pol0'] = 'ويكي مفتوحة؛ أي القراءة والكتابة والتحميل مسموحة للجميع'; $lang['i_pol1'] = 'ويكي عامة؛ أي القراءة للجميع ولكن الكتابة والتحميل للمشتركين المسجلين فقط'; diff --git a/inc/lang/az/lang.php b/inc/lang/az/lang.php index fff6f34b7..384a347b7 100644 --- a/inc/lang/az/lang.php +++ b/inc/lang/az/lang.php @@ -208,8 +208,8 @@ $lang['i_writeerr'] = '%s yaradıla bilmədi. Faylın/qo $lang['i_badhash'] = 'dokuwiki.php tanıla bilmir və ya dəyişdirilmişdir (hash=%s)'; $lang['i_badval'] = '%s - səhv ya boş qiymətdir'; $lang['i_success'] = 'Konfiqurasiya uğurla başa çatdı. İndi siz install.php faylını silə bilərsiniz. - Yeni DokuWiki-nizə xoş gəlmişsiniz!'; -$lang['i_failure'] = 'Konfiqurasiya fayllarına məlumat yazan zaman səhvlər tapıldı. Yəgin ki, yeni DokuWiki-nizi istifadə etmədən öncə, Siz o xətaları əl ilə düzəltməli olacaqsınız.'; + Yeni DokuWiki-nizə xoş gəlmişsiniz!'; +$lang['i_failure'] = 'Konfiqurasiya fayllarına məlumat yazan zaman səhvlər tapıldı. Yəgin ki, yeni DokuWiki-nizi istifadə etmədən öncə, Siz o xətaları əl ilə düzəltməli olacaqsınız.'; $lang['i_policy'] = 'İlkin giriş haqları siyasəti'; $lang['i_pol0'] = 'Tam açıq wiki (oxumaq, yazmaq, fayl yükləmək hamıya olar)'; $lang['i_pol1'] = 'Acıq wiki (oxumaq hamıya olar, yazmaq və fayl yükləmək ancaq üzv olan istifadəçilərə olar)'; diff --git a/inc/lang/bg/lang.php b/inc/lang/bg/lang.php index 562dc78b3..7a9a20469 100644 --- a/inc/lang/bg/lang.php +++ b/inc/lang/bg/lang.php @@ -298,10 +298,10 @@ $lang['i_confexists'] = '%s вече съществува' $lang['i_writeerr'] = '%s не можа да бъде създаден. Трябва да проверите правата за достъп до директорията/файла и да създадете файла ръчно.'; $lang['i_badhash'] = 'Файлът dokuwiki.php не може да бъде разпознат или е променен (hash=%s)'; $lang['i_badval'] = '%s - непозволена или празна стойност'; -$lang['i_success'] = 'Настройването приключи успешно. Вече можете да изтриете файла install.php. Продължете към Вашето ново DokuWiki.'; +$lang['i_success'] = 'Настройването приключи успешно. Вече можете да изтриете файла install.php. Продължете към Вашето ново DokuWiki.'; $lang['i_failure'] = 'Възникнаха грешки при записването на файловете с настройки. Вероятно ще се наложи да ги поправите ръчно, - за да можете да ползвате Вашето ново DokuWiki.'; + за да можете да ползвате Вашето ново DokuWiki.'; $lang['i_policy'] = 'Първоначална политика за достъп'; $lang['i_pol0'] = 'Отворено Wiki (всеки може да чете, пише и качва)'; $lang['i_pol1'] = 'Публично Wiki (всеки може да чете, само регистрирани пишат и качват)'; diff --git a/inc/lang/ca-valencia/lang.php b/inc/lang/ca-valencia/lang.php index e299f6427..e62010418 100644 --- a/inc/lang/ca-valencia/lang.php +++ b/inc/lang/ca-valencia/lang.php @@ -211,9 +211,9 @@ $lang['i_writeerr'] = 'No es pot crear %s. Haurà de com $lang['i_badhash'] = 'dokuwiki.php substituït o modificat (hash=%s)'; $lang['i_badval'] = '%s - valor illegal o buit'; $lang['i_success'] = 'La configuració ha finalisat correctament. Ya pot borrar l\'archiu install.php. Passe al -nou DokuWiki.'; +nou DokuWiki.'; $lang['i_failure'] = 'Han aparegut alguns erros escrivint els archius de configuració. Deurà arreglar-los manualment abans de que -puga utilisar el nou DokuWiki.'; +puga utilisar el nou DokuWiki.'; $lang['i_policy'] = 'Política inicial ACL'; $lang['i_pol0'] = 'Wiki obert (llegir, escriure i enviar tots)'; $lang['i_pol1'] = 'Wiki públic (llegir tots, escriure i enviar només usuaris registrats)'; diff --git a/inc/lang/ca/lang.php b/inc/lang/ca/lang.php index 3a1412617..7fc078419 100644 --- a/inc/lang/ca/lang.php +++ b/inc/lang/ca/lang.php @@ -208,8 +208,8 @@ $lang['i_confexists'] = '%s ja existeix'; $lang['i_writeerr'] = 'No es pot crear %s. Comproveu els permisos del directori i/o del fitxer i creeu el fitxer manualment.'; $lang['i_badhash'] = 'dokuwiki.php no reconegut o modificat (hash=%s)'; $lang['i_badval'] = '%s - valor il·legal o buit'; -$lang['i_success'] = 'La configuració s\'ha acabat amb èxit. Ara podeu suprimir el fitxer install.php. Aneu al vostre nou DokuWiki.'; -$lang['i_failure'] = 'S\'han produït alguns errors en escriure els fitxers de configuració. Potser caldrà que els arregleu manualment abans d\'utilitzar el vostre nou DokuWiki.'; +$lang['i_success'] = 'La configuració s\'ha acabat amb èxit. Ara podeu suprimir el fitxer install.php. Aneu al vostre nou DokuWiki.'; +$lang['i_failure'] = 'S\'han produït alguns errors en escriure els fitxers de configuració. Potser caldrà que els arregleu manualment abans d\'utilitzar el vostre nou DokuWiki.'; $lang['i_policy'] = 'Política ACL inicial'; $lang['i_pol0'] = 'Wiki obert (tothom pot llegir, escriure i penjar fitxers)'; $lang['i_pol1'] = 'Wiki públic (tothom pot llegir, els usuaris registrats poden escriure i penjar fitxers)'; diff --git a/inc/lang/cs/lang.php b/inc/lang/cs/lang.php index 608beafd8..11033ff68 100644 --- a/inc/lang/cs/lang.php +++ b/inc/lang/cs/lang.php @@ -278,8 +278,8 @@ $lang['i_confexists'] = '%s již existuje'; $lang['i_writeerr'] = 'Nelze vytvořit %s. Budete muset zkontrolovat práva k souborům či adresářům a vytvořit tento soubor ručně.'; $lang['i_badhash'] = 'soubor dokuwiki.php (hash=%s) nebyl rozpoznán nebo byl upraven'; $lang['i_badval'] = '%s - neplatná nebo prázdná hodnota'; -$lang['i_success'] = 'Konfigurace byla úspěšně dokončena. Nyní můžete smazat soubor install.php. Pokračujte do své nové DokuWiki.'; -$lang['i_failure'] = 'Vyskytly se nějaké chyby při zápisu do konfiguračních souborů. Budete je nejspíš muset upravit ručně před použitím své nové DokuWiki.'; +$lang['i_success'] = 'Konfigurace byla úspěšně dokončena. Nyní můžete smazat soubor install.php. Pokračujte do své nové DokuWiki.'; +$lang['i_failure'] = 'Vyskytly se nějaké chyby při zápisu do konfiguračních souborů. Budete je nejspíš muset upravit ručně před použitím své nové DokuWiki.'; $lang['i_policy'] = 'Úvodní politika ACL'; $lang['i_pol0'] = 'Otevřená wiki (čtení, zápis a upload pro všechny)'; $lang['i_pol1'] = 'Veřejná wiki (čtení pro všechny, zápis a upload pro registrované uživatele)'; diff --git a/inc/lang/da/lang.php b/inc/lang/da/lang.php index 97f2138b4..2c26cd3da 100644 --- a/inc/lang/da/lang.php +++ b/inc/lang/da/lang.php @@ -285,8 +285,8 @@ $lang['i_confexists'] = '%s eksisterer allerede'; $lang['i_writeerr'] = 'Kunne ikke oprette %s. Du bliver nød til at tjekke mappe/fil- tilladelserne og oprette filen manuelt.'; $lang['i_badhash'] = 'uigenkendelig eller modificeret dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - ulovlig eller tom værdi'; -$lang['i_success'] = 'Konfigurationen fulførtedes med success. Du kan nu slette install.php filen. Fortsætte til din nye DokuWiki.'; -$lang['i_failure'] = 'Nogle fejl forekom mens konfigurations filerne skulle skrives. Du er mulighvis nød til at fixe dem manuelt før du kan bruge din nye DokuWiki.'; +$lang['i_success'] = 'Konfigurationen fulførtedes med success. Du kan nu slette install.php filen. Fortsætte til din nye DokuWiki.'; +$lang['i_failure'] = 'Nogle fejl forekom mens konfigurations filerne skulle skrives. Du er mulighvis nød til at fixe dem manuelt før du kan bruge din nye DokuWiki.'; $lang['i_policy'] = 'Begyndende ACL politik'; $lang['i_pol0'] = 'Åben Wiki (alle kan læse, skrive og uploade)'; $lang['i_pol1'] = 'Offentlig Wiki (alle kan læse, kun registrerede brugere kan skrive og overføre)'; diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php index 37469522f..cce898b15 100644 --- a/inc/lang/de-informal/lang.php +++ b/inc/lang/de-informal/lang.php @@ -287,8 +287,8 @@ $lang['i_confexists'] = '%s existiert bereits'; $lang['i_writeerr'] = '%s konnte nicht erzeugt werden. Du solltest die Verzeichnis-/Datei-Rechte überprüfen und die Datei manuell anlegen.'; $lang['i_badhash'] = 'Unbekannte oder modifizierte dokuwiki.php (Hash=%s)'; $lang['i_badval'] = '%s - unerlaubter oder leerer Wert'; -$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Du kannst jetzt die install.php löschen. Dein neues DokuWiki ist jetzt für dich bereit.'; -$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Du musst diese vermutlich von Hand beheben, bevor du dein neues DokuWiki nutzen kannst.'; +$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Du kannst jetzt die install.php löschen. Dein neues DokuWiki ist jetzt für dich bereit.'; +$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Du musst diese vermutlich von Hand beheben, bevor du dein neues DokuWiki nutzen kannst.'; $lang['i_policy'] = 'Anfangseinstellung für Zugangskontrolle (ACL)'; $lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben, hochladen für alle)'; $lang['i_pol1'] = 'Öffentliches Wiki (lesen für alle, schreiben und hochladen für registrierte Nutzer)'; diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php index 4ea75157b..07052fb3d 100644 --- a/inc/lang/de/lang.php +++ b/inc/lang/de/lang.php @@ -289,8 +289,8 @@ $lang['i_confexists'] = '%s existiert bereits'; $lang['i_writeerr'] = '%s konnte nicht erzeugt werden. Sie sollten die Verzeichnis-/Datei-Rechte überprüfen und die Datei manuell anlegen.'; $lang['i_badhash'] = 'Unbekannte oder modifizierte dokuwiki.php (Hash=%s)'; $lang['i_badval'] = '%s - unerlaubter oder leerer Wert'; -$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Sie können jetzt die install.php löschen. Ihr neues DokuWiki ist jetzt für Sie bereit.'; -$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Sie müssen diese vermutlich von Hand beheben, bevor Sie Ihr neues DokuWiki nutzen können.'; +$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Sie können jetzt die install.php löschen. Ihr neues DokuWiki ist jetzt für Sie bereit.'; +$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Sie müssen diese vermutlich von Hand beheben, bevor Sie Ihr neues DokuWiki nutzen können.'; $lang['i_policy'] = 'Anfangseinstellung für Zugangskontrolle (ACL)'; $lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben, hochladen für alle)'; $lang['i_pol1'] = 'Öffentliches Wiki (lesen für alle, schreiben und hochladen für registrierte Nutzer)'; diff --git a/inc/lang/el/lang.php b/inc/lang/el/lang.php index 95f1a1ea5..d5bde6929 100644 --- a/inc/lang/el/lang.php +++ b/inc/lang/el/lang.php @@ -270,8 +270,8 @@ $lang['i_confexists'] = '%s υπάρχει ήδη'; $lang['i_writeerr'] = 'Δεν είναι δυνατή η δημιουργία του %s. Πρέπει να διορθώσετε τα δικαιώματα πρόσβασης αυτού του φακέλου/αρχείου και να δημιουργήσετε το αρχείο χειροκίνητα!'; $lang['i_badhash'] = 'Μη αναγνωρίσιμο ή τροποποιημένο αρχείο dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - λάθος ή ανύπαρκτη τιμή'; -$lang['i_success'] = 'Η εγκατάσταση ολοκληρώθηκε επιτυχώς. Μπορείτε πλέον να διαγράψετε το αρχείο install.php. Συνεχίστε στο νέο σας DokuWiki.'; -$lang['i_failure'] = 'Εμφανίστηκαν κάποια προβλήματα στη διαδικασία ανανέωσης των αρχείων ρυθμίσεων. Πιθανόν να χρειάζεται να τα τροποποιήσετε χειροκίνητα ώστε να μπορείτε να χρησιμοποιήσετε το νέο σας DokuWiki.'; +$lang['i_success'] = 'Η εγκατάσταση ολοκληρώθηκε επιτυχώς. Μπορείτε πλέον να διαγράψετε το αρχείο install.php. Συνεχίστε στο νέο σας DokuWiki.'; +$lang['i_failure'] = 'Εμφανίστηκαν κάποια προβλήματα στη διαδικασία ανανέωσης των αρχείων ρυθμίσεων. Πιθανόν να χρειάζεται να τα τροποποιήσετε χειροκίνητα ώστε να μπορείτε να χρησιμοποιήσετε το νέο σας DokuWiki.'; $lang['i_policy'] = 'Αρχική πολιτική Λίστας Δικαιωμάτων Πρόσβασης - ACL'; $lang['i_pol0'] = 'Ανοιχτό Wiki (όλοι μπορούν να διαβάσουν ή να δημιουργήσουν/τροποποιήσουν σελίδες και να μεταφορτώσουν αρχεία)'; $lang['i_pol1'] = 'Δημόσιο Wiki (όλοι μπορούν να διαβάσουν σελίδες αλλά μόνο οι εγγεγραμμένοι χρήστες μπορούν να δημιουργήσουν/τροποποιήσουν σελίδες και να μεταφορτώσουν αρχεία)'; diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 3c51ba224..73c3522fd 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -302,9 +302,9 @@ $lang['i_writeerr'] = 'Unable to create %s. You will nee $lang['i_badhash'] = 'unrecognised or modified dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - illegal or empty value'; $lang['i_success'] = 'The configuration was finished successfully. You may delete the install.php file now. Continue to - your new DokuWiki.'; + your new DokuWiki.'; $lang['i_failure'] = 'Some errors occurred while writing the configuration files. You may need to fix them manually before - you can use your new DokuWiki.'; + you can use your new DokuWiki.'; $lang['i_policy'] = 'Initial ACL policy'; $lang['i_pol0'] = 'Open Wiki (read, write, upload for everyone)'; $lang['i_pol1'] = 'Public Wiki (read for everyone, write and upload for registered users)'; diff --git a/inc/lang/eo/lang.php b/inc/lang/eo/lang.php index b2c64b2a6..3e0d86386 100644 --- a/inc/lang/eo/lang.php +++ b/inc/lang/eo/lang.php @@ -278,8 +278,8 @@ $lang['i_confexists'] = '%s jam ekzistas'; $lang['i_writeerr'] = 'Ne eblas krei "%s". Vi bezonas kontroli la permesojn de la dosier(uj)oj kaj mem krej la dosieron.'; $lang['i_badhash'] = 'dokuwiki.php ne estas rekonebla aŭ ĝi estas modifita (hash=%s)'; $lang['i_badval'] = '%s - malvalida aŭ malplena valoro'; -$lang['i_success'] = 'La agordado sukcese kompletiĝis. Vi povas forigi la dosieron nun. Pluiru al via nova DokuWiki.'; -$lang['i_failure'] = 'Kelkaj eraroj okazis dum la konservo de la agordaj dosieroj. Vi devas senpere korekti ilin antaŭ ol vi povos uzi vian novan DokuWiki-on. '; +$lang['i_success'] = 'La agordado sukcese kompletiĝis. Vi povas forigi la dosieron nun. Pluiru al via nova DokuWiki.'; +$lang['i_failure'] = 'Kelkaj eraroj okazis dum la konservo de la agordaj dosieroj. Vi devas senpere korekti ilin antaŭ ol vi povos uzi vian novan DokuWiki-on. '; $lang['i_policy'] = 'Komenca ACL-a agordo'; $lang['i_pol0'] = 'Malferma Vikio (legi, skribi, alŝuti povas ĉiuj)'; $lang['i_pol1'] = 'Publika Vikio (legi povas ĉiuj, skribi kaj alŝuti povas registritaj uzantoj)'; diff --git a/inc/lang/es/lang.php b/inc/lang/es/lang.php index ee3da258b..c09b12121 100644 --- a/inc/lang/es/lang.php +++ b/inc/lang/es/lang.php @@ -287,8 +287,8 @@ $lang['i_confexists'] = '%s ya existe'; $lang['i_writeerr'] = 'Imposible crear %s. Se necesita que usted controle los permisos del fichero/directorio y que cree el fichero manualmente.'; $lang['i_badhash'] = 'dokuwiki.php no reconocido o modificado (hash=%s)'; $lang['i_badval'] = '%s - valor ilegal o vacío'; -$lang['i_success'] = 'La configuración ha concluido correctamente. Ahora puede eliminar el archivo install.php. Visite su nuevo DokuWiki.'; -$lang['i_failure'] = 'Han ocurrido algunos errores durante la escritura de los ficheros de configuración. Puede ser que necesite corregirlos manualmente antes de poder usar su nuevo DokuWiki.'; +$lang['i_success'] = 'La configuración ha concluido correctamente. Ahora puede eliminar el archivo install.php. Visite su nuevo DokuWiki.'; +$lang['i_failure'] = 'Han ocurrido algunos errores durante la escritura de los ficheros de configuración. Puede ser que necesite corregirlos manualmente antes de poder usar su nuevo DokuWiki.'; $lang['i_policy'] = 'Política de ACL inicial'; $lang['i_pol0'] = 'Wiki abierto (leer, escribir y subir archivos para todos)'; $lang['i_pol1'] = 'Wiki público (leer para todos, escribir y subir archivos para usuarios registrados únicamente)'; diff --git a/inc/lang/et/lang.php b/inc/lang/et/lang.php index 5e5caa1c8..37d4538ec 100644 --- a/inc/lang/et/lang.php +++ b/inc/lang/et/lang.php @@ -223,8 +223,8 @@ $lang['i_permfail'] = 'Dokuwiki ei saa kirjutada faili %svotre nouveau DokuWiki.'; -$lang['i_failure'] = 'Des erreurs sont survenues lors de l\'écriture des fichiers de configuration. Il vous faudra les corriger manuellement avant de pouvoir utiliser votre nouveau DokuWiki.'; +$lang['i_success'] = 'L\'installation s\'est terminée avec succès. Vous pouvez maintenant supprimer le fichier « install.php ». Continuer avec votre nouveau DokuWiki.'; +$lang['i_failure'] = 'Des erreurs sont survenues lors de l\'écriture des fichiers de configuration. Il vous faudra les corriger manuellement avant de pouvoir utiliser votre nouveau DokuWiki.'; $lang['i_policy'] = 'Politique d\'ACL initiale'; $lang['i_pol0'] = 'Wiki ouvert (lecture, écriture, envoi de fichiers pour tout le monde)'; $lang['i_pol1'] = 'Wiki public (lecture pour tout le monde, écriture et envoi de fichiers pour les utilisateurs enregistrés)'; diff --git a/inc/lang/gl/lang.php b/inc/lang/gl/lang.php index 9636d6c15..466f0fb8c 100644 --- a/inc/lang/gl/lang.php +++ b/inc/lang/gl/lang.php @@ -269,9 +269,9 @@ $lang['i_writeerr'] = 'Non se puido crear %s. Terás de $lang['i_badhash'] = 'dokuwiki.php irrecoñecíbel ou modificado (hash=%s)'; $lang['i_badval'] = '%s - ilegal ou valor baleiro'; $lang['i_success'] = 'A configuración rematou correctamente. Agora podes eliminar o arquivo install.php. Continúa deica o - teu novo DokuWiki.'; + teu novo DokuWiki.'; $lang['i_failure'] = 'Houbo algúns erros ao tentar escribir os arquivos de configuración. Pode que precises solucionalos de xeito manual antes - de poderes empregar o teu novo DokuWiki.'; + de poderes empregar o teu novo DokuWiki.'; $lang['i_policy'] = 'Regras iniciais da ACL'; $lang['i_pol0'] = 'Wiki Aberto (lectura, escritura, subida de arquivos para todas as persoas)'; $lang['i_pol1'] = 'Wiki Público (lectura para todas as persoas, escritura e subida de arquivos para usuarios rexistrados)'; diff --git a/inc/lang/he/lang.php b/inc/lang/he/lang.php index 00eb4549b..9cbcc3c4f 100644 --- a/inc/lang/he/lang.php +++ b/inc/lang/he/lang.php @@ -249,8 +249,8 @@ $lang['i_confexists'] = '%s כבר קיים'; $lang['i_writeerr'] = 'אין אפשרות ליצור את %s. נא לבדוק את הרשאות הקובץ/תיקייה וליצור את הקובץ ידנית.'; $lang['i_badhash'] = 'הקובץ Dokuwiki.php אינו מזוהה או שעבר שינויים (hash=%s)'; $lang['i_badval'] = '%s - הערך אינו חוקי או ריק'; -$lang['i_success'] = 'תהליך ההגדרה הסתיים בהצלחה. כעת ניתן למחוק את הקובץ install.php ולהמשיך אל ה־DokuWiki החדש שלך.'; -$lang['i_failure'] = 'מספר שגיאות אירעו בעת כתיבת קובצי התצורה. יתכן כי יהיה צורך לתקנם ידנית לפני שניתן יהיה להשתמש ב־DokuWiki החדש שלך.'; +$lang['i_success'] = 'תהליך ההגדרה הסתיים בהצלחה. כעת ניתן למחוק את הקובץ install.php ולהמשיך אל ה־DokuWiki החדש שלך.'; +$lang['i_failure'] = 'מספר שגיאות אירעו בעת כתיבת קובצי התצורה. יתכן כי יהיה צורך לתקנם ידנית לפני שניתן יהיה להשתמש ב־DokuWiki החדש שלך.'; $lang['i_policy'] = 'מדיניות ACL התחלתית'; $lang['i_pol0'] = 'ויקי פתוח (קריאה, כתיבה והעלאה לכולם)'; $lang['i_pol1'] = ' ויקי ציבורי (קריאה לכולם, כתיבה והעלאה למשתמשים רשומים)'; diff --git a/inc/lang/hr/lang.php b/inc/lang/hr/lang.php index a0438d915..ac2a740ef 100644 --- a/inc/lang/hr/lang.php +++ b/inc/lang/hr/lang.php @@ -247,8 +247,8 @@ $lang['i_confexists'] = '%s već postoji'; $lang['i_writeerr'] = 'Ne može se kreirati %s. Trebate provjeriti dozvole direktorija/datoteke i kreirati dokument ručno.'; $lang['i_badhash'] = 'neprepoznat ili promijenjen dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - nedozvoljena ili prazna vrijednost'; -$lang['i_success'] = 'Konfiguracija je uspješno završena. Sada možete obrisati install.php datoteku. Nastavite na vaš novi DokuWiki.'; -$lang['i_failure'] = 'Pojavile su se neke greške prilikom pisanja konfiguracijskih datoteka. Morati ćete ih ručno ispraviti da bi mogli koristiti vaš novi DokuWiki.'; +$lang['i_success'] = 'Konfiguracija je uspješno završena. Sada možete obrisati install.php datoteku. Nastavite na vaš novi DokuWiki.'; +$lang['i_failure'] = 'Pojavile su se neke greške prilikom pisanja konfiguracijskih datoteka. Morati ćete ih ručno ispraviti da bi mogli koristiti vaš novi DokuWiki.'; $lang['i_policy'] = 'Inicijalna ACL politika'; $lang['i_pol0'] = 'Otvoreni Wiki (čitanje, pisanje, učitavanje za sve)'; $lang['i_pol1'] = 'Javni Wiki (čitanje za sve, pisanje i učitavanje za registrirane korisnike)'; diff --git a/inc/lang/hu/lang.php b/inc/lang/hu/lang.php index 671b225f2..43b79b41b 100644 --- a/inc/lang/hu/lang.php +++ b/inc/lang/hu/lang.php @@ -252,8 +252,8 @@ $lang['i_confexists'] = '%s már létezik.'; $lang['i_writeerr'] = 'Nem tudom ezt létrehozni: %s. Ellenőrizd a könyvtár/fájl jogosultságokat, és hozd létre az állományt kézzel.'; $lang['i_badhash'] = 'A dokuwiki.php nem felismerhető vagy módosított (hash=%s)'; $lang['i_badval'] = '%s - nem helyes vagy üres érték'; -$lang['i_success'] = 'A beállítás sikeresen befejeződött. Most már letörölhető az install.php fájl. Látogasd meg az új DokuWikidet!'; -$lang['i_failure'] = 'Hiba lépett fel a konfigurációs állományok írásakor. Ki kell javítanod kézzel, mielőtt használni kezded az új DokuWikidet.'; +$lang['i_success'] = 'A beállítás sikeresen befejeződött. Most már letörölhető az install.php fájl. Látogasd meg az új DokuWikidet!'; +$lang['i_failure'] = 'Hiba lépett fel a konfigurációs állományok írásakor. Ki kell javítanod kézzel, mielőtt használni kezded az új DokuWikidet.'; $lang['i_policy'] = 'Kezdeti hozzáférési politika'; $lang['i_pol0'] = 'Nyitott Wiki (mindenki olvashatja, írhatja, és fájlokat tölthet fel)'; $lang['i_pol1'] = 'Publikus Wiki (mindenki olvashatja, de csak regisztrált felhasználók írhatják, és tölthetnek fel fájlokat)'; diff --git a/inc/lang/ia/lang.php b/inc/lang/ia/lang.php index d7be1eff3..aff133698 100644 --- a/inc/lang/ia/lang.php +++ b/inc/lang/ia/lang.php @@ -247,9 +247,9 @@ $lang['i_writeerr'] = 'Impossibile crear %s. Tu debe ver $lang['i_badhash'] = 'dokuwiki.php non recognoscite o modificate (hash=%s)'; $lang['i_badval'] = '%s - valor vacue o invalide'; $lang['i_success'] = 'Le configuration ha succedite. Tu pote ora deler le file install.php. Continua a -tu nove DokuWiki.'; +tu nove DokuWiki.'; $lang['i_failure'] = 'Alcun errores occurreva durante le scriptura del files de configuration. Es possibile que tu debe remediar iste errores manualmente ante que -tu pote usar tu nove DokuWiki.'; +tu pote usar tu nove DokuWiki.'; $lang['i_policy'] = 'Politica de ACL interne'; $lang['i_pol0'] = 'Wiki aperte (lectura, scriptura, incargamento pro omnes)'; $lang['i_pol1'] = 'Wiki public (lectura pro omnes, scriptura e incargamento pro usatores registrate)'; diff --git a/inc/lang/id/lang.php b/inc/lang/id/lang.php index 2302d4f6f..566e8dcb0 100644 --- a/inc/lang/id/lang.php +++ b/inc/lang/id/lang.php @@ -188,8 +188,8 @@ $lang['i_confexists'] = '%s sudah ada'; $lang['i_writeerr'] = 'Tidak dapat membuat %s. Anda harus memeriksa konfigurasi hak akses direktori/berkas dan membuatnya secara manual.'; $lang['i_badhash'] = 'dokuwiki.php tidak dikenal atau sudah diubah (hash=%s)'; $lang['i_badval'] = '%s - tidak valid atau belum diisi'; -$lang['i_success'] = 'Konfigurasi telah berhasil. Anda boleh menghapus berkas install.php sekarang. Lanjutkan ke DokuWiki baru Anda.'; -$lang['i_failure'] = 'Terdapat beberapa kesalahan dalam menulis berkas konfigurasi. Anda harus memperbaikinnya sendiri sebelum dapat menggunakan DokuWiki baru Anda.'; +$lang['i_success'] = 'Konfigurasi telah berhasil. Anda boleh menghapus berkas install.php sekarang. Lanjutkan ke DokuWiki baru Anda.'; +$lang['i_failure'] = 'Terdapat beberapa kesalahan dalam menulis berkas konfigurasi. Anda harus memperbaikinnya sendiri sebelum dapat menggunakan DokuWiki baru Anda.'; $lang['i_policy'] = 'Policy ACL awal'; $lang['i_pol0'] = 'Wiki Terbuka (baca, tulis, upload untuk semua orang)'; $lang['i_pol1'] = 'Wiki Publik (baca untuk semua orang, tulis dan upload untuk pengguna terdaftar)'; diff --git a/inc/lang/it/lang.php b/inc/lang/it/lang.php index 70082caae..6ae864f8b 100644 --- a/inc/lang/it/lang.php +++ b/inc/lang/it/lang.php @@ -281,8 +281,8 @@ $lang['i_confexists'] = '%s esiste già'; $lang['i_writeerr'] = 'Impossibile creare %s. E\' necessario verificare i permessi della directory o del file oppure creare il file manualmente.'; $lang['i_badhash'] = 'dokuwiki.php (hash=%s) non riconosciuto o modificato'; $lang['i_badval'] = '%s - valore vuoto o non valido'; -$lang['i_success'] = 'La configurazione è stata completata correttamente. Ora è possibile eliminare il file install.php. Poi, visita il tuo nuovo DokuWiki.'; -$lang['i_failure'] = 'Si sono verificati errori durante la scrittura dei file di configurazione. Potrebbe essere necessario correggerli manualmente prima di poter utilizzare il tuo nuovo DokuWiki.'; +$lang['i_success'] = 'La configurazione è stata completata correttamente. Ora è possibile eliminare il file install.php. Poi, visita il tuo nuovo DokuWiki.'; +$lang['i_failure'] = 'Si sono verificati errori durante la scrittura dei file di configurazione. Potrebbe essere necessario correggerli manualmente prima di poter utilizzare il tuo nuovo DokuWiki.'; $lang['i_policy'] = 'Regole di accesso iniziali'; $lang['i_pol0'] = 'Wiki Aperto (lettura, scrittura, caricamento file per tutti)'; $lang['i_pol1'] = 'Wiki Pubblico (lettura per tutti, scrittura e caricamento file per gli utenti registrati)'; diff --git a/inc/lang/ja/lang.php b/inc/lang/ja/lang.php index 490c84cc9..93300e20e 100644 --- a/inc/lang/ja/lang.php +++ b/inc/lang/ja/lang.php @@ -278,8 +278,8 @@ $lang['i_confexists'] = '%s は既に存在します'; $lang['i_writeerr'] = '%s を作成できません。ディレクトリとファイルの権限を確認し、それらを手動で作成する必要があります。'; $lang['i_badhash'] = 'dokuwiki.php が認識できないか、編集されています(hash=%s)'; $lang['i_badval'] = '%s - 正しくない、もしくは値が空です'; -$lang['i_success'] = '設定ファイルは正しく作成されました。作成した DokuWikiを使用するには install.php を削除してください。'; -$lang['i_failure'] = '設定ファイルの作成中にエラーが発生しました。作成した DokuWikiを使用する前に、それらの問題を手動で修正する必要があります。'; +$lang['i_success'] = '設定ファイルは正しく作成されました。作成した DokuWikiを使用するには install.php を削除してください。'; +$lang['i_failure'] = '設定ファイルの作成中にエラーが発生しました。作成した DokuWikiを使用する前に、それらの問題を手動で修正する必要があります。'; $lang['i_policy'] = 'ACL初期設定'; $lang['i_pol0'] = 'オープン Wiki(全ての人に、閲覧・書き込み・アップロードを許可)'; $lang['i_pol1'] = 'パブリック Wiki(閲覧は全ての人が可能、書き込み・アップロードは登録ユーザーのみ)'; diff --git a/inc/lang/ko/lang.php b/inc/lang/ko/lang.php index 7b4e30a49..1a618f1a7 100644 --- a/inc/lang/ko/lang.php +++ b/inc/lang/ko/lang.php @@ -279,8 +279,8 @@ $lang['i_confexists'] = '%s(은)는 이미 존재합니다 $lang['i_writeerr'] = '%s(을)를 만들 수 없습니다. 먼저 디렉토리/파일 권한을 확인하고 파일을 수동으로 만들기 바랍니다.'; $lang['i_badhash'] = 'dokuwiki.php를 인식할 수 없거나 원본 파일이 아닙니다. (해시=%s)'; $lang['i_badval'] = '%s - 유효하지 않거나 빈 값입니다.'; -$lang['i_success'] = '환경 설정이 성공적으로 끝났습니다. 지금 install.php를 지워도 상관없습니다. 새 DokuWiki로 들어갑니다.'; -$lang['i_failure'] = '환경 설정 파일에 쓰는 도중에 오류가 발생했습니다. 새 DokuWiki를 사용하기 전에 수동으로 문제를 해결할 필요가 있습니다.'; +$lang['i_success'] = '환경 설정이 성공적으로 끝났습니다. 지금 install.php를 지워도 상관없습니다. 새 DokuWiki로 들어갑니다.'; +$lang['i_failure'] = '환경 설정 파일에 쓰는 도중에 오류가 발생했습니다. 새 DokuWiki를 사용하기 전에 수동으로 문제를 해결할 필요가 있습니다.'; $lang['i_policy'] = '초기 ACL 정책'; $lang['i_pol0'] = '열린 위키 (누구나 읽기, 쓰기, 올리기가 가능합니다.)'; $lang['i_pol1'] = '공개 위키 (누구나 읽을 수 있지만, 등록된 사용자만 쓰기와 올리기가 가능합니다.)'; diff --git a/inc/lang/la/lang.php b/inc/lang/la/lang.php index 3970f453a..c7d654e96 100644 --- a/inc/lang/la/lang.php +++ b/inc/lang/la/lang.php @@ -246,8 +246,8 @@ $lang['i_confexists'] = '%s iam est.'; $lang['i_writeerr'] = '%s non creari potest. Manu illum creas.'; $lang['i_badhash'] = 'Ignotum uel mutatum dokuwiki.php (%s)'; $lang['i_badval'] = '%s non legitimum uel uacuom'; -$lang['i_success'] = 'Administratio feliciter perficitur. Delere install.php documentum potes. I ad hanc paginam ut continues.'; -$lang['i_failure'] = 'Aliqui errores dum documenta administrantur sunt. Manu onerare omnes potes priusquam tuo nouo uice uteris.'; +$lang['i_success'] = 'Administratio feliciter perficitur. Delere install.php documentum potes. I ad hanc paginam ut continues.'; +$lang['i_failure'] = 'Aliqui errores dum documenta administrantur sunt. Manu onerare omnes potes priusquam tuo nouo uice uteris.'; $lang['i_policy'] = 'ICA ratio prima'; $lang['i_pol0'] = 'Vicem aperire (omnes legere, scribere, onerare possunt)'; $lang['i_pol1'] = 'Publicus uicis (omnes legere, Sodales scribere et onerare possunt)'; diff --git a/inc/lang/lv/lang.php b/inc/lang/lv/lang.php index b02e7f471..67480abfc 100644 --- a/inc/lang/lv/lang.php +++ b/inc/lang/lv/lang.php @@ -264,8 +264,8 @@ $lang['i_confexists'] = '%s jau ir'; $lang['i_writeerr'] = 'Nevar izveidot %s. Jāpārbauda direktorijas/faila tiesības un fails jāizveido pašam.'; $lang['i_badhash'] = 'nepazīstams vai izmainīts dokuwiki.php fails (hash=%s)'; $lang['i_badval'] = '%s - neatļauta vai tukša vērtība'; -$lang['i_success'] = 'Konfigurēšana veiksmīgi pabeigta. Tagad vari nodzēst failu install.php. Tālāk turpini savā jaunajā DokuWiki.'; -$lang['i_failure'] = 'Rakstot konfigurācijas failu, gadījās dažas kļūmes. Pirms lieto savu jauno DokuWiki, tās varbūt jāizlabo.'; +$lang['i_success'] = 'Konfigurēšana veiksmīgi pabeigta. Tagad vari nodzēst failu install.php. Tālāk turpini savā jaunajā DokuWiki.'; +$lang['i_failure'] = 'Rakstot konfigurācijas failu, gadījās dažas kļūmes. Pirms lieto savu jauno DokuWiki, tās varbūt jāizlabo.'; $lang['i_policy'] = 'Sākotnējā ACL politika'; $lang['i_pol0'] = 'Atvērts Wiki (raksta, lasa un augšupielādē ikviens)'; $lang['i_pol1'] = 'Publisks Wiki (lasa ikviens, raksta un augšupielādē reģistrēti lietotāji)'; diff --git a/inc/lang/mk/lang.php b/inc/lang/mk/lang.php index 62400063c..f04c51e37 100644 --- a/inc/lang/mk/lang.php +++ b/inc/lang/mk/lang.php @@ -214,8 +214,8 @@ $lang['i_confexists'] = '%s веќе постои'; $lang['i_writeerr'] = 'Не може да се креира %s. Треба да ги проверите пермисиите на директориумот/датотеката и рачно да ја креирате датотеката.'; $lang['i_badhash'] = 'непозната или изменете dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - нелегална или празна вредност'; -$lang['i_success'] = 'Конфигурацијата успешно заврши. Сега можете да ја избришете датотеката install.php. Продолжете до вашето ново DokuWiki.'; -$lang['i_failure'] = 'Се појавија некои грешки при запишувањето на конфигурациските датотеки. Можеби треба да ги поравите рачно пред да можете да го користите вашето ново DokuWiki.'; +$lang['i_success'] = 'Конфигурацијата успешно заврши. Сега можете да ја избришете датотеката install.php. Продолжете до вашето ново DokuWiki.'; +$lang['i_failure'] = 'Се појавија некои грешки при запишувањето на конфигурациските датотеки. Можеби треба да ги поравите рачно пред да можете да го користите вашето ново DokuWiki.'; $lang['i_policy'] = 'Почетна ACL политика'; $lang['i_pol0'] = 'Отвори вики (читај, запиши, качи за сите)'; $lang['i_pol1'] = 'Јавно вики (читај за сите, запиши и качи за регистрирани корисници)'; diff --git a/inc/lang/mr/lang.php b/inc/lang/mr/lang.php index 32781e6d4..c6064a610 100644 --- a/inc/lang/mr/lang.php +++ b/inc/lang/mr/lang.php @@ -258,8 +258,8 @@ $lang['i_confexists'] = '%s आधीच अस्ति $lang['i_writeerr'] = '%s निर्माण करू शकलो नाही. तुम्हाला डिरेक्टरी / फाइल च्या परवानग्या तपासून स्वतःच ही फाइल बनवावी लागेल.'; $lang['i_badhash'] = 'अनाकलनीय किंवा बदललेले dokuwiki.php (hash=%s)'; $lang['i_badval'] = 'code>%s - अवैध किंवा रिकामा मजकूर.'; -$lang['i_success'] = 'व्यवस्था लावण्याचे काम यशस्वीरीत्या पार पडले. आता तुम्ही install.php डिलीट करू शकता. तुमच्या नविन डॉक्युविकि वर जा.'; -$lang['i_failure'] = 'कॉन्फिगुरेशनच्या फाइल सुरक्षित करताना काही अडचणी आल्या आहेत. तुमची नवीन डॉक्युविकि वापरण्याआधी तुम्हाला ह्या फाइल स्वतः ठीक कराव्या लागतील.'; +$lang['i_success'] = 'व्यवस्था लावण्याचे काम यशस्वीरीत्या पार पडले. आता तुम्ही install.php डिलीट करू शकता. तुमच्या नविन डॉक्युविकि वर जा.'; +$lang['i_failure'] = 'कॉन्फिगुरेशनच्या फाइल सुरक्षित करताना काही अडचणी आल्या आहेत. तुमची नवीन डॉक्युविकि वापरण्याआधी तुम्हाला ह्या फाइल स्वतः ठीक कराव्या लागतील.'; $lang['i_policy'] = 'आरंभीची ACL पॉलिसी'; $lang['i_pol0'] = 'मुक्त विकी ( सर्वांना वाचन, लेखन व अपलोड करण्याची परवानगी )'; $lang['i_pol1'] = 'सार्वजनिक विकी ( सर्वांना वाचण्याची मुभा , लेखन व अपलोडची परवानगी फक्त नोंदणीकृत सदस्यांना )'; diff --git a/inc/lang/ne/lang.php b/inc/lang/ne/lang.php index 82ca389f7..bde40a670 100644 --- a/inc/lang/ne/lang.php +++ b/inc/lang/ne/lang.php @@ -191,8 +191,8 @@ $lang['i_confexists'] = '%s पहिले देखि $lang['i_writeerr'] = '%s बनाउन असमर्थ । तपाईले डाइरेक्टरी / फाइल अनुमति जाच्नु पर्छ र फाइल आफैले बनाउनु पर्छ ।'; $lang['i_badhash'] = 'पहिचान हुन नसकेको वा परिवर्तित okuwiki.php (hash=code>%s)'; $lang['i_badval'] = '%s - अवैध वा रित्तो मान '; -$lang['i_success'] = 'स्थापना सफलरुपमा समाप्त भयो ।तपाई install.php मेट्न सक्नुहु्न्छ । तपाईको नयाँ DokuWiki निरन्तर गर्न सक्नुहुन्छ ।'; -$lang['i_failure'] = 'स्थापना समयमा केहि त्रुटि फेला पर्यो ।तपाईले आफैले यसलाई तपाईको नयाँ DokuWiki प्रयोग गर्नु अगि सच्याउनुपर्ने हुन्छ ।'; +$lang['i_success'] = 'स्थापना सफलरुपमा समाप्त भयो ।तपाई install.php मेट्न सक्नुहु्न्छ । तपाईको नयाँ DokuWiki निरन्तर गर्न सक्नुहुन्छ ।'; +$lang['i_failure'] = 'स्थापना समयमा केहि त्रुटि फेला पर्यो ।तपाईले आफैले यसलाई तपाईको नयाँ DokuWiki प्रयोग गर्नु अगि सच्याउनुपर्ने हुन्छ ।'; $lang['i_policy'] = 'सुरुको ACL निति'; $lang['i_pol0'] = 'खुल्ला विकि (पठन, लेखन , अपलोड ) सबैका लागि'; $lang['i_pol1'] = 'Public विकि (पठन सवैका लागि,लेखन र अपलोड दर्ता गरिएका प्रयपगकर्ताका लागि ) '; diff --git a/inc/lang/nl/lang.php b/inc/lang/nl/lang.php index 911ffdc10..6d14a0e4b 100644 --- a/inc/lang/nl/lang.php +++ b/inc/lang/nl/lang.php @@ -286,8 +286,8 @@ $lang['i_confexists'] = '%s bestaat reeds'; $lang['i_writeerr'] = 'Niet mogelijk om %s aan te maken. Controleer de directory/bestandspermissies en maak het bestand handmatig aan.'; $lang['i_badhash'] = 'Onbekende of aangepaste dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - onjuiste of lege waarde'; -$lang['i_success'] = 'De configuratie is succesvol afgerond. Je kunt nu het bestand install.php verwijderen. Ga naar je nieuwe DokuWiki.'; -$lang['i_failure'] = 'Fouten deden zich voor tijdens het schrijven naar de configuratiebestanden. Pas deze aan voor je gebruik kunt maken van je nieuwe DokuWiki.'; +$lang['i_success'] = 'De configuratie is succesvol afgerond. Je kunt nu het bestand install.php verwijderen. Ga naar je nieuwe DokuWiki.'; +$lang['i_failure'] = 'Fouten deden zich voor tijdens het schrijven naar de configuratiebestanden. Pas deze aan voor je gebruik kunt maken van je nieuwe DokuWiki.'; $lang['i_policy'] = 'Initieel ACL-beleid'; $lang['i_pol0'] = 'Open wiki (lezen, schrijven, uploaden voor iedereen)'; $lang['i_pol1'] = 'Publieke wiki (lezen voor iedereen, schrijven en uploaden voor geregistreerde gebruikers)'; diff --git a/inc/lang/no/lang.php b/inc/lang/no/lang.php index 97ef741ef..81aa39612 100644 --- a/inc/lang/no/lang.php +++ b/inc/lang/no/lang.php @@ -282,9 +282,9 @@ $lang['i_writeerr'] = 'Kunne ikke opprette %s. Du må sj $lang['i_badhash'] = 'ikke gjenkjent eller modifisert dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - ugyldig eller tom verdi'; $lang['i_success'] = 'Konfigurasjonen ble vellykket fullført. Du kan slette install.php filen nå. Fortsett til - din nye DokuWiki.'; + din nye DokuWiki.'; $lang['i_failure'] = 'En eller flere feil oppstod ved skriving til konfigurasjonsfilene. Du må kanskje fikse dem manuelt før - du kan bruke din nye DokuWiki.'; + du kan bruke din nye DokuWiki.'; $lang['i_policy'] = 'Innledende ACL-politikk'; $lang['i_pol0'] = 'Åpen Wiki (les, skriv og opplasting for alle)'; $lang['i_pol1'] = 'Offentlig Wiki (les for alle, skriving og opplasting bare for registrerte brukere)'; diff --git a/inc/lang/pl/lang.php b/inc/lang/pl/lang.php index 79d18bbf5..0f0381e8f 100644 --- a/inc/lang/pl/lang.php +++ b/inc/lang/pl/lang.php @@ -285,8 +285,8 @@ $lang['i_confexists'] = '%s już istnieje'; $lang['i_writeerr'] = 'Nie można utworzyć %s. Sprawdź uprawnienia do katalogu lub pliku i stwórz plik ręcznie.'; $lang['i_badhash'] = 'nierozpoznany lub zmodyfikowany plik dokuwiki.php (skrót=%s)'; $lang['i_badval'] = '%s - nieprawidłowa wartość lub jej brak'; -$lang['i_success'] = 'Konfiguracja pomyślnie zakończona. Możesz teraz usunąć plik install.php. Przejdź do Twojego nowego DokuWiki.'; -$lang['i_failure'] = 'Podczas zapisu plików konfiguracyjnych wystąpiły błędy. Musisz usunąć wszystkie problemy, zanim zaczniesz korzystać z Twojego nowego DokuWiki.'; +$lang['i_success'] = 'Konfiguracja pomyślnie zakończona. Możesz teraz usunąć plik install.php. Przejdź do Twojego nowego DokuWiki.'; +$lang['i_failure'] = 'Podczas zapisu plików konfiguracyjnych wystąpiły błędy. Musisz usunąć wszystkie problemy, zanim zaczniesz korzystać z Twojego nowego DokuWiki.'; $lang['i_policy'] = 'Wstępna polityka uprawnień ACL'; $lang['i_pol0'] = 'Otwarte Wiki (odczyt, zapis i dodawanie plików dla wszystkich)'; $lang['i_pol1'] = 'Publiczne Wiki (odczyt dla wszystkich, zapis i dodawanie plików tylko dla zarejestrowanych użytkowników)'; diff --git a/inc/lang/pt-br/lang.php b/inc/lang/pt-br/lang.php index d6dc8f96b..26a73bfae 100644 --- a/inc/lang/pt-br/lang.php +++ b/inc/lang/pt-br/lang.php @@ -261,8 +261,8 @@ $lang['i_confexists'] = '%s já existe'; $lang['i_writeerr'] = 'Não foi possível criar %s. É necessário checar as permissões de arquivos/diretórios e criar o arquivo manualmente.'; $lang['i_badhash'] = 'dokuwiki.php não reconhecido ou modificado (hash=%s)'; $lang['i_badval'] = '%s - valor ilegal ou em branco'; -$lang['i_success'] = 'A configuração terminou com sucesso. Agora você deve excluir o arquivo install.php. Conheça o seu novo DokuWiki!'; -$lang['i_failure'] = 'Ocorreram alguns erros durante a escrita dos arquivos de configuração. É necessário corrigi-los manualmente antes de usar seu novo DokuWiki'; +$lang['i_success'] = 'A configuração terminou com sucesso. Agora você deve excluir o arquivo install.php. Conheça o seu novo DokuWiki!'; +$lang['i_failure'] = 'Ocorreram alguns erros durante a escrita dos arquivos de configuração. É necessário corrigi-los manualmente antes de usar seu novo DokuWiki'; $lang['i_policy'] = 'Política inicial de permissões'; $lang['i_pol0'] = 'Wiki aberto (leitura, escrita e envio de arquivos por todos)'; $lang['i_pol1'] = 'Wiki público (leitura por todos, escrita e envio de arquivos por usuários registrados)'; diff --git a/inc/lang/pt/lang.php b/inc/lang/pt/lang.php index a0b0f57e8..37b3fba8c 100644 --- a/inc/lang/pt/lang.php +++ b/inc/lang/pt/lang.php @@ -268,8 +268,8 @@ $lang['i_confexists'] = '%s já existe'; $lang['i_writeerr'] = 'Não foi possível criar %s. É preciso verificar as permissões e criar o ficheiro manualmente.'; $lang['i_badhash'] = 'dokuwiki.php não é o original ou não é reconhecido (hash=%s)'; $lang['i_badval'] = '%s - valor ilegal ou vazio'; -$lang['i_success'] = 'A instalação e configuração inicial foram bem sucedidas. Pode remover o install.php. Aceda ao seu novo Wiki a correr o DokuWiki.'; -$lang['i_failure'] = 'Ocorreram alguns erros durante a escrita nos ficheiros de configuração. Poderá ser preciso corrigi-los manualmente antes de poder aceder ao seu novo Wiki a correr o DokuWiki.'; +$lang['i_success'] = 'A instalação e configuração inicial foram bem sucedidas. Pode remover o install.php. Aceda ao seu novo Wiki a correr o DokuWiki.'; +$lang['i_failure'] = 'Ocorreram alguns erros durante a escrita nos ficheiros de configuração. Poderá ser preciso corrigi-los manualmente antes de poder aceder ao seu novo Wiki a correr o DokuWiki.'; $lang['i_policy'] = 'Politica ACL inicial'; $lang['i_pol0'] = 'Wiki Aberto (ler, escrever e carregar para todos)'; $lang['i_pol1'] = 'Wiki Público (ler para todos, escrever e carregar para utilizadores inscritos)'; diff --git a/inc/lang/ro/lang.php b/inc/lang/ro/lang.php index 41727e521..cb8e2ed0c 100644 --- a/inc/lang/ro/lang.php +++ b/inc/lang/ro/lang.php @@ -280,8 +280,8 @@ $lang['i_confexists'] = '%s există deja'; $lang['i_writeerr'] = 'Nu s-a putut crea %s. Trebuie să verificaţi drepturile directorului/fişierului şi să creaţi fişierul manual.'; $lang['i_badhash'] = 'dokuwiki.php nu a fost recunoscut sau a fost modificat (hash=%s)'; $lang['i_badval'] = '%s - valoare nepemisă sau neintrodusă'; -$lang['i_success'] = 'Configurarea a fost finalizată cu succes. Acum puteţi sterge fişierul install.php. Continuaţi cu your new DokuWiki.'; -$lang['i_failure'] = 'Au apărut erori la scrierea fişierelor de configurare. Va trebui să le corectaţi manual înainte de a putea folosi your new DokuWiki.'; +$lang['i_success'] = 'Configurarea a fost finalizată cu succes. Acum puteţi sterge fişierul install.php. Continuaţi cu your new DokuWiki.'; +$lang['i_failure'] = 'Au apărut erori la scrierea fişierelor de configurare. Va trebui să le corectaţi manual înainte de a putea folosi your new DokuWiki.'; $lang['i_policy'] = 'Politica ACL iniţială'; $lang['i_pol0'] = 'Wiki Deschisă (citeşte, scrie şi încarcă oricine)'; $lang['i_pol1'] = 'Wiki Deschisă (citeste oricine, scrie şi încarcă doar utilizatorul înregistrat)'; diff --git a/inc/lang/ru/lang.php b/inc/lang/ru/lang.php index 4c3d26b1d..920bc907f 100644 --- a/inc/lang/ru/lang.php +++ b/inc/lang/ru/lang.php @@ -291,8 +291,8 @@ $lang['i_writeerr'] = 'Не удалось создать %sсвоей новой «ДокуВики».'; +$lang['i_failure'] = 'При записи в файлы конфигурации были обнаружены ошибки. Возможно, вам придётся исправить их вручную, прежде чем вы сможете использовать свою новую «ДокуВики».'; $lang['i_policy'] = 'Исходная политика прав доступа'; $lang['i_pol0'] = 'Открытая вики (чтение, запись, закачка файлов для всех)'; $lang['i_pol1'] = 'Общедоступная вики (чтение для всех, запись и загрузка файлов для зарегистрированных пользователей)'; diff --git a/inc/lang/sk/lang.php b/inc/lang/sk/lang.php index 85e899b06..79a13ac35 100644 --- a/inc/lang/sk/lang.php +++ b/inc/lang/sk/lang.php @@ -268,8 +268,8 @@ $lang['i_confexists'] = '%s už existuje'; $lang['i_writeerr'] = 'Nie je možné vytvoriť %s. Potrebujete skontrolovať prístupové práva pre adresár/súbor a vytvoriť ho manuálne.'; $lang['i_badhash'] = 'neznámy alebo zmenený súbor dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - nesprávna alebo žiadna hodnota'; -$lang['i_success'] = 'Konfigurácia bola úspešne ukončená. Teraz môžete zmazať súbor install.php. Pokračujte vo vašej novej DokuWiki.'; -$lang['i_failure'] = 'Pri zápise konfiguračného súboru nastali nejaké chyby. Potrebujete ich opraviť manuálne pred tým, ako budete môcť používať vašu novú DokuWiki.'; +$lang['i_success'] = 'Konfigurácia bola úspešne ukončená. Teraz môžete zmazať súbor install.php. Pokračujte vo vašej novej DokuWiki.'; +$lang['i_failure'] = 'Pri zápise konfiguračného súboru nastali nejaké chyby. Potrebujete ich opraviť manuálne pred tým, ako budete môcť používať vašu novú DokuWiki.'; $lang['i_policy'] = 'Počiatočná ACL politika'; $lang['i_pol0'] = 'Otvorená Wiki (čítanie, zápis a nahrávanie pre každého)'; $lang['i_pol1'] = 'Verejná Wiki (čítanie pre každého, zápis a nahrávanie pre registrovaných užívateľov)'; diff --git a/inc/lang/sl/lang.php b/inc/lang/sl/lang.php index b34ab67e4..7cd16f7ed 100644 --- a/inc/lang/sl/lang.php +++ b/inc/lang/sl/lang.php @@ -271,8 +271,8 @@ $lang['i_confexists'] = 'Predmet %s že obstaja.'; $lang['i_writeerr'] = 'Ni mogoče ustvariti predmeta %s. Preveriti je treba dovoljenja datotek in map in nato ustvariti datoteko ročno.'; $lang['i_badhash'] = 'nepoznana ali spremenjena datoteka dokuwiki.php (razpršilo=%s)'; $lang['i_badval'] = '%s - neveljavna ali prazna vrednost'; -$lang['i_success'] = 'Nastavitev je uspešno končana. Datoteko install.php lahko sedaj izbrišete. Nadaljujte v novi DokuWiki.'; -$lang['i_failure'] = 'Med zapisovanjem nastavitvenih datotek je prišlo do napak. Preden lahko uporabite vaš DokuWiki, jih je treba odpraviti.'; +$lang['i_success'] = 'Nastavitev je uspešno končana. Datoteko install.php lahko sedaj izbrišete. Nadaljujte v novi DokuWiki.'; +$lang['i_failure'] = 'Med zapisovanjem nastavitvenih datotek je prišlo do napak. Preden lahko uporabite vaš DokuWiki, jih je treba odpraviti.'; $lang['i_policy'] = 'Začetna določila ACL'; $lang['i_pol0'] = 'Odprt Wiki (branje, zapis, nalaganje datotek je javno za vse)'; $lang['i_pol1'] = 'Javni Wiki (branje za vse, zapis in nalaganje datotek za prijavljene uporabnike)'; diff --git a/inc/lang/sq/lang.php b/inc/lang/sq/lang.php index 0e56b89d9..3c58d708d 100644 --- a/inc/lang/sq/lang.php +++ b/inc/lang/sq/lang.php @@ -223,8 +223,8 @@ $lang['i_confexists'] = '%s ekziston njëherë'; $lang['i_writeerr'] = '%s nuk mundi të krijohej. Duhet të kontrolloni lejet e dirkektorisë/skedarit dhe ta krijoni skedarin manualisht.'; $lang['i_badhash'] = 'dokuwiki.php e panjohur ose e ndryshuar (hash=code>%s)'; $lang['i_badval'] = '%s - vlerë e palejuar ose boshe'; -$lang['i_success'] = 'Konfigurimi u mbarua me sukses. Tani mund ta fshini skedarin install.php. Vazhdoni tek DokuWiki juaj i ri..'; -$lang['i_failure'] = 'Ndodhën disa gabime gjatë shkrimit të skedarit të konfigurimit. Do t\'ju duhet t\'i rregulloni manualisht para se të përdorni DokuWiki-in tuaj të ri..'; +$lang['i_success'] = 'Konfigurimi u mbarua me sukses. Tani mund ta fshini skedarin install.php. Vazhdoni tek DokuWiki juaj i ri..'; +$lang['i_failure'] = 'Ndodhën disa gabime gjatë shkrimit të skedarit të konfigurimit. Do t\'ju duhet t\'i rregulloni manualisht para se të përdorni DokuWiki-in tuaj të ri..'; $lang['i_policy'] = 'Veprimi fillestar ACL'; $lang['i_pol0'] = 'Wiki i Hapur (lexim, shkrim, ngarkim për këdo)'; $lang['i_pol1'] = 'Wiki Publike (lexim për këdo, shkrim dhe ngarkim për përdoruesit e regjistruar)'; diff --git a/inc/lang/sr/lang.php b/inc/lang/sr/lang.php index a53f14ac9..875b1d695 100644 --- a/inc/lang/sr/lang.php +++ b/inc/lang/sr/lang.php @@ -244,8 +244,8 @@ $lang['i_confexists'] = '%s већ постоји'; $lang['i_writeerr'] = 'Не могу да направим %s. Проверите дозволе а затим ручно направите ову датотеку.'; $lang['i_badhash'] = 'dokuwiki.php није препознат или је измењен (hash=%s)'; $lang['i_badval'] = '%s - недозвољена или празна вредност'; -$lang['i_success'] = 'Подешавања су завршена. Сада можете обрисати датотеку install.php. Наставите у Ваш нови DokuWiki.'; -$lang['i_failure'] = 'Појавили су се проблеми при писању датотеке са подешавањима. Требало би да их ручно исправите пре него што ћете моћи да користите Ваш нови DokuWiki.'; +$lang['i_success'] = 'Подешавања су завршена. Сада можете обрисати датотеку install.php. Наставите у Ваш нови DokuWiki.'; +$lang['i_failure'] = 'Појавили су се проблеми при писању датотеке са подешавањима. Требало би да их ручно исправите пре него што ћете моћи да користите Ваш нови DokuWiki.'; $lang['i_policy'] = 'Иницијалне корисничке дозволе'; $lang['i_pol0'] = 'Отворени вики (читање, писање, слање датотека за све)'; $lang['i_pol1'] = 'Јавни вики (читање за све, писање и слање датотека само за регистроване кориснике)'; diff --git a/inc/lang/sv/lang.php b/inc/lang/sv/lang.php index 0c8f3276d..4cc97e8c6 100644 --- a/inc/lang/sv/lang.php +++ b/inc/lang/sv/lang.php @@ -246,9 +246,9 @@ $lang['i_writeerr'] = 'Kan inte skapa %s. Kontrollera fi $lang['i_badhash'] = 'okänd eller ändrad dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - felaktig eller blank'; $lang['i_success'] = 'Konfigurationen avslutades utan fel. Du kan radera filen install.php nu. Fortsätt till - din nya DokuWiki.'; + din nya DokuWiki.'; $lang['i_failure'] = 'Fel uppstod vid skrivning av konfigurationsfilerna. Du kan behöva ordna till dem manuellt innan - du kan använda din nya DokuWiki.'; + du kan använda din nya DokuWiki.'; $lang['i_policy'] = 'Initial ACL-policy'; $lang['i_pol0'] = 'Öppen wiki (alla får läsa, skriva och ladda upp filer)'; $lang['i_pol1'] = 'Publik wiki (alla får läsa, registrerade användare för skriva och ladda upp filer)'; diff --git a/inc/lang/tr/lang.php b/inc/lang/tr/lang.php index 77518ac36..cf75aac9d 100644 --- a/inc/lang/tr/lang.php +++ b/inc/lang/tr/lang.php @@ -225,8 +225,8 @@ $lang['i_confexists'] = '%s zaten var'; $lang['i_writeerr'] = '%s oluşturulamadı. Dosya/Klasör izin ayarlarını gözden geçirip dosyayı elle oluşturmalısınız.'; $lang['i_badhash'] = 'dokuwiki.php tanınamadı ya da değiştirilmiş (hash=%s)'; $lang['i_badval'] = '%s - Yanlış veya boş değer'; -$lang['i_success'] = 'Kurulum başarıyla tamamlandı. Şimdi install.php dosyasını silebilirsiniz. Yeni DokuWikinizi kullanabilirsiniz.'; -$lang['i_failure'] = 'Ayar dosyalarını yazarken bazı hatalar oluştu. Yeni DokuWikinizi kullanmadan önce bu hatalarınızı elle düzeltmeniz gerekebilir.'; +$lang['i_success'] = 'Kurulum başarıyla tamamlandı. Şimdi install.php dosyasını silebilirsiniz. Yeni DokuWikinizi kullanabilirsiniz.'; +$lang['i_failure'] = 'Ayar dosyalarını yazarken bazı hatalar oluştu. Yeni DokuWikinizi kullanmadan önce bu hatalarınızı elle düzeltmeniz gerekebilir.'; $lang['i_policy'] = 'İlk ACL ayarı'; $lang['i_pol0'] = 'Tamamen Açık Wiki (herkes okuyabilir, yazabilir ve dosya yükleyebilir)'; $lang['i_pol1'] = 'Açık Wiki (herkes okuyabilir, ancak sadece üye olanlar yazabilir ve dosya yükleyebilir)'; diff --git a/inc/lang/uk/lang.php b/inc/lang/uk/lang.php index b06cb9158..e38db2300 100644 --- a/inc/lang/uk/lang.php +++ b/inc/lang/uk/lang.php @@ -253,9 +253,9 @@ $lang['i_writeerr'] = 'Неможливо створити %s%s)'; $lang['i_badval'] = '%s - невірне або пусте значення.'; $lang['i_success'] = 'Налаштування завершено. Ви можете знищити файл install.php. -Перейдіть до вашої нової ДокуВікі'; +Перейдіть до вашої нової ДокуВікі'; $lang['i_failure'] = 'При збереженні файлу конфігурації виникли помилки. Можливо вам доведеться виправити їх самостійно -до початку використання вашої нової ДокуВікі.'; +до початку використання вашої нової ДокуВікі.'; $lang['i_policy'] = 'Початкова політика ACL'; $lang['i_pol0'] = 'Відкрита Вікі (читання, запис та завантаження файлів для всіх)'; $lang['i_pol1'] = 'Публічна Вікі (читання для всіх, запис та завантаження для зареєстрованих користувачів)'; diff --git a/inc/lang/zh-tw/lang.php b/inc/lang/zh-tw/lang.php index bbbbb71a6..41c79f57c 100644 --- a/inc/lang/zh-tw/lang.php +++ b/inc/lang/zh-tw/lang.php @@ -272,8 +272,8 @@ $lang['i_writeerr'] = '無法建立 %s。您必須檢查 $lang['i_badhash'] = '無法辨識或被變更的 dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - 非法或空白的值'; $lang['i_success'] = '設定已成功完成。您現在可以刪除 install.php 檔案。繼續到 -您的新 DokuWiki.'; -$lang['i_failure'] = '寫入設定檔時發生了一些錯誤。您必須在使用您的新 Dokuwiki 之前手動修正它們。'; +您的新 DokuWiki.'; +$lang['i_failure'] = '寫入設定檔時發生了一些錯誤。您必須在使用您的新 Dokuwiki 之前手動修正它們。'; $lang['i_policy'] = '初步的 ACL 政策'; $lang['i_pol0'] = '開放的維基 (任何人可讀取、寫入、上傳)'; $lang['i_pol1'] = '公開的維基 (任何人可讀取,註冊使用者可寫入與上傳)'; diff --git a/inc/lang/zh/lang.php b/inc/lang/zh/lang.php index 9ea0f5e7f..8b9644262 100644 --- a/inc/lang/zh/lang.php +++ b/inc/lang/zh/lang.php @@ -288,8 +288,8 @@ $lang['i_writeerr'] = '无法创建 %s。您需要检查 $lang['i_badhash'] = '无法识别的或被修改的 dokuwiki.php(值=%s)'; $lang['i_badval'] = '%s - 非法或空值'; $lang['i_success'] = '配置成功完成。您现在可以删除 install.php 了。继续进入 - 您全新的 DokuWiki。'; -$lang['i_failure'] = '写入配置文件的时候产生一些错误。在使用 您全新安装的 DokuWiki 前 + 您全新的 DokuWiki。'; +$lang['i_failure'] = '写入配置文件的时候产生一些错误。在使用 您全新安装的 DokuWiki 前 您需要手动修复它们。'; $lang['i_policy'] = '初始的 ACL 政策'; $lang['i_pol0'] = '开放的维基(任何人都有读、写、上传的权限)'; -- cgit v1.2.3 From e682d3e4f1dd8d90365f71f9e8ba35984cd80bef Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 14 Jul 2012 09:55:23 +0200 Subject: added welcome page --- data/pages/wiki/welcome.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 data/pages/wiki/welcome.txt diff --git a/data/pages/wiki/welcome.txt b/data/pages/wiki/welcome.txt new file mode 100644 index 000000000..b3fcc70f5 --- /dev/null +++ b/data/pages/wiki/welcome.txt @@ -0,0 +1,28 @@ +====== Welcome to your new DokuWiki ====== + +Congratulations, your wiki is now up and running. Here are a few more tips to get you started. + +Enjoy your work with DokuWiki,\\ +-- the developers + +===== Create your first pages ===== + +Your wiki needs to have a start page. As long as it doesn't exist, this link will be red: [[:start]]. + +Go on, follow that link and create the page. If you need help with using the syntax you can always refer to the [[wiki:syntax|syntax page]]. + +You might also want to use a sidebar. To create it, just edit the [[:sidebar]] page. Everything in that page will be shown in a margin column on the left side. A sidebar is a good place for a navigation, just place a list of links in it. + +===== Customize your Wiki ===== + +Once you're comfortable with creating and editing pages you might want to have a look at the [[this>doku.php?do=admin&page=config|configuration settings]] (be sure to login as superuser first). + +You may also want to see what [[doku>plugins|plugins]] and [[doku>templates|templates]] are available at DokuWiki.org to extend the functionality and looks of your DokuWiki installation. + +===== Join the Community ===== + +DokuWiki is an Open Source project that thrives through user contributions. A good way to stay informed on what's going on and to get useful tips in using DokuWiki is subscribing to the [[doku>newsletter]]. + +The [[http://forum.dokuwiki.org|DokuWiki User Forum]] is an excellent way to get in contact with other DokuWiki users and is just one of the many ways to get [[doku>faq:support|support]]. + +Of course we'd more than happy to have you [[doku>devel:getting_involved|getting involved]] into DokuWiki. -- cgit v1.2.3 From 3b9de95c982ab5724e7641f4cf2a165a78e209d9 Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Sat, 14 Jul 2012 13:13:56 +0100 Subject: improved welcome text --- data/pages/wiki/welcome.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/pages/wiki/welcome.txt b/data/pages/wiki/welcome.txt index b3fcc70f5..472e2cabc 100644 --- a/data/pages/wiki/welcome.txt +++ b/data/pages/wiki/welcome.txt @@ -11,7 +11,8 @@ Your wiki needs to have a start page. As long as it doesn't exist, this link wil Go on, follow that link and create the page. If you need help with using the syntax you can always refer to the [[wiki:syntax|syntax page]]. -You might also want to use a sidebar. To create it, just edit the [[:sidebar]] page. Everything in that page will be shown in a margin column on the left side. A sidebar is a good place for a navigation, just place a list of links in it. +You might also want to use a sidebar. To create it, just edit the [[:sidebar]] page. Everything in that page will be shown in a margin column on the side. A sidebar is a good place for a navigation, just place a list of links in it or install and use one of the [[http://www.dokuwiki.org/plugins?plugintag=navigation#extension__table|navigation plugins]]. +Please be aware that not all templates support sidebars. ===== Customize your Wiki ===== @@ -25,4 +26,4 @@ DokuWiki is an Open Source project that thrives through user contributions. A go The [[http://forum.dokuwiki.org|DokuWiki User Forum]] is an excellent way to get in contact with other DokuWiki users and is just one of the many ways to get [[doku>faq:support|support]]. -Of course we'd more than happy to have you [[doku>devel:getting_involved|getting involved]] into DokuWiki. +Of course we'd be more than happy to have you [[doku>devel:getting_involved|getting involved]] with DokuWiki. -- cgit v1.2.3 From 4385447c9cf849f461e148b68a596b60117fb313 Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Sat, 14 Jul 2012 13:15:07 +0100 Subject: added initial pages to not be ignored by git --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index eb2474a3f..ecdaae6b1 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,9 @@ /data/media_attic/* /data/meta/* /data/pages/* +!/data/pages/wiki/dokuwiki.txt +!/data/pages/wiki/syntax.txt +!/data/pages/wiki/welcome.txt /data/tmp/* /lib/tpl/* !/lib/tpl/default -- cgit v1.2.3 From b1730bd21bd9ce8807b80c4cfb044858c7af60d8 Mon Sep 17 00:00:00 2001 From: Tom N Harris Date: Tue, 17 Jul 2012 19:45:48 -0400 Subject: Translatable string for "None" license selection The position of the option was moved to the end of the list so the English label "None of the above" will make sense. --- inc/lang/en/lang.php | 1 + install.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 3c51ba224..2592b9a5c 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -311,6 +311,7 @@ $lang['i_pol1'] = 'Public Wiki (read for everyone, write and uplo $lang['i_pol2'] = 'Closed Wiki (read, write, upload for registered users only)'; $lang['i_retry'] = 'Retry'; $lang['i_license'] = 'Please choose the license you want to put your content under:'; +$lang['i_license_none'] = 'None of the above'; $lang['recent_global'] = 'You\'re currently watching the changes inside the %s namespace. You can also view the recent changes of the whole wiki.'; $lang['years'] = '%d years ago'; diff --git a/install.php b/install.php index 488cf58ab..07e0451ea 100644 --- a/install.php +++ b/install.php @@ -210,12 +210,12 @@ function print_form($d){

'None', 'url'=>'')); + array_push($license,array('name' => $lang['i_license_none'], 'url'=>'')); if(empty($d['license'])) $d['license'] = 'cc-by-sa'; foreach($license as $key => $lic){ echo ''; -- cgit v1.2.3 From 1ea7a6bada66fc9b7a45f61b4892e4ea23196d89 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 28 Jul 2012 14:55:45 +0200 Subject: support CONNECT for tunneling SSL via HTTP proxies FS#2431 The included test cases currently expect a squid at localhost:3128 --- _test/tests/inc/httpclient_http_proxy.test.php | 19 +++++++ _test/tests/inc/httpclient_https.test.php | 1 + _test/tests/inc/httpclient_https_proxy.test.php | 15 ++++++ inc/HTTPClient.php | 66 +++++++++++++++++++++++-- 4 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 _test/tests/inc/httpclient_http_proxy.test.php create mode 100644 _test/tests/inc/httpclient_https_proxy.test.php diff --git a/_test/tests/inc/httpclient_http_proxy.test.php b/_test/tests/inc/httpclient_http_proxy.test.php new file mode 100644 index 000000000..81abdbca0 --- /dev/null +++ b/_test/tests/inc/httpclient_http_proxy.test.php @@ -0,0 +1,19 @@ +proxy_host = 'localhost'; //FIXME we need a public server + $http->proxy_port = 3128; + + $data = $http->get($this->url); + $this->assertFalse($data === false, 'HTTP response'); + $this->assertTrue(strpos($data,'DokuWiki') !== false, 'response content'); + } + +} \ No newline at end of file diff --git a/_test/tests/inc/httpclient_https.test.php b/_test/tests/inc/httpclient_https.test.php index 26a0f86db..955d467ec 100644 --- a/_test/tests/inc/httpclient_https.test.php +++ b/_test/tests/inc/httpclient_https.test.php @@ -1,4 +1,5 @@ markTestSkipped('No SSL support available.'); + } + parent::setUp(); + } +} \ No newline at end of file diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php index a25846c31..8d2c10be1 100644 --- a/inc/HTTPClient.php +++ b/inc/HTTPClient.php @@ -254,11 +254,7 @@ class HTTPClient { if(!empty($uri['port'])) $headers['Host'].= ':'.$uri['port']; $headers['User-Agent'] = $this->agent; $headers['Referer'] = $this->referer; - if ($this->keep_alive) { - $headers['Connection'] = 'Keep-Alive'; - } else { - $headers['Connection'] = 'Close'; - } + if($method == 'POST'){ if(is_array($data)){ if($headers['Content-Type'] == 'multipart/form-data'){ @@ -299,6 +295,14 @@ class HTTPClient { return false; } + // try establish a CONNECT tunnel for SSL + if($this->_ssltunnel($socket, $request_url)){ + // no keep alive for tunnels + $this->keep_alive = false; + // tunnel is authed already + if(isset($headers['Proxy-Authentication'])) unset($headers['Proxy-Authentication']); + } + // keep alive? if ($this->keep_alive) { self::$connections[$connectionId] = $socket; @@ -307,6 +311,15 @@ class HTTPClient { } } + if ($this->keep_alive && !$this->proxy_host) { + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server. We still do keep the connection the + // proxy alive (well except for CONNECT tunnels) + $headers['Connection'] = 'Keep-Alive'; + } else { + $headers['Connection'] = 'Close'; + } + try { //set non-blocking stream_set_blocking($socket, false); @@ -484,6 +497,49 @@ class HTTPClient { return true; } + /** + * Tries to establish a CONNECT tunnel via Proxy + * + * Protocol, Servername and Port will be stripped from the request URL when a successful CONNECT happened + * + * @param ressource &$socket + * @param string &$requesturl + * @return bool true if a tunnel was established + */ + function _ssltunnel(&$socket, &$requesturl){ + if(!$this->proxy_host) return false; + $requestinfo = parse_url($requesturl); + if($requestinfo['scheme'] != 'https') return false; + if(!$requestinfo['port']) $requestinfo['port'] = 443; + + // build request + $request = "CONNECT {$requestinfo['host']}:{$requestinfo['port']} HTTP/1.0".HTTP_NL; + $request .= "Host: {$requestinfo['host']}".HTTP_NL; + if($this->proxy_user) { + 'Proxy-Authorization Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass).HTTP_NL; + } + $request .= HTTP_NL; + + $this->_debug('SSL Tunnel CONNECT',$request); + $this->_sendData($socket, $request, 'SSL Tunnel CONNECT'); + + // read headers from socket + $r_headers = ''; + do{ + $r_line = $this->_readLine($socket, 'headers'); + $r_headers .= $r_line; + }while($r_line != "\r\n" && $r_line != "\n"); + + $this->_debug('SSL Tunnel Response',$r_headers); + if(preg_match('/^HTTP\/1\.0 200/i',$r_headers)){ + if (stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)) { + $requesturl = $requestinfo['path']; + return true; + } + } + return false; + } + /** * Safely write data to a socket * -- cgit v1.2.3 From 2240ea1f316156f3cb4475ea23a16246c999b6f0 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 12:00:37 +0200 Subject: first start at refactoring the subscription system BROKEN This introduces a class for nicer wrapping and easier testing. Some functions were changed to provide nicer APIs (no throwing around of unescaped regexps) and to simplify things (hopefully). The refactoring isn't completed yet, so this will break the subscription system. The goal is to move as much subscription related stuff to this class as possible. Currently there is some code in lib/exe/indexer.php and maybe elsewhere (common.php?). Additionally everything should be covered by tests. A few tests are included here already. --- _test/tests/inc/subscription.test.php | 121 ++++++ inc/load.php | 1 + inc/subscription.php | 724 ++++++++++++++++++---------------- 3 files changed, 497 insertions(+), 349 deletions(-) create mode 100644 _test/tests/inc/subscription.test.php diff --git a/_test/tests/inc/subscription.test.php b/_test/tests/inc/subscription.test.php new file mode 100644 index 000000000..77bf3e830 --- /dev/null +++ b/_test/tests/inc/subscription.test.php @@ -0,0 +1,121 @@ +buildregex($test[0], $test[1], $test[2]); + $this->assertFalse(empty($re), "test line $row"); + $result = preg_grep($re, $data); + $this->assertEquals($test[3], count($result), "test line $row. $re got\n".print_r($result, true)); + + $row++; + } + } + + function test_addremove(){ + $sub = new MockupSubscription(); + + // no subscriptions + $this->assertArrayNotHasKey( + 'wiki:dokuwiki', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // add page subscription + $sub->add('wiki:dokuwiki', 'testuser', 'every'); + + // one subscription + $this->assertArrayHasKey( + 'wiki:dokuwiki', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // remove page subscription + $sub->remove('wiki:dokuwiki', 'testuser'); + + // no subscription + $this->assertArrayNotHasKey( + 'wiki:dokuwiki', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // add namespace subscription + $sub->add('wiki:', 'testuser', 'every'); + + // one subscription + $this->assertArrayHasKey( + 'wiki:', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // remove (non existing) page subscription + $sub->remove('wiki:dokuwiki', 'testuser'); + + // still one subscription + $this->assertArrayHasKey( + 'wiki:', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // change namespace subscription + $sub->add('wiki:', 'testuser', 'digest', '1234567'); + + // still one subscription + $this->assertArrayHasKey( + 'wiki:', + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + + // check contents + $this->assertEquals( + array('wiki:' => array('testuser' => array('digest', '1234567'))), + $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + ); + } + + + +} + +/** + * makes protected methods visible for testing + */ +class MockupSubscription extends Subscription { + public function buildregex($user = null, $style = null, $data = null) { + return parent::buildregex($user, $style, $data); + } +} + +//Setup VIM: ex: et ts=4 : diff --git a/inc/load.php b/inc/load.php index b676518e7..bd6d39814 100644 --- a/inc/load.php +++ b/inc/load.php @@ -81,6 +81,7 @@ function load_autoload($name){ 'Mailer' => DOKU_INC.'inc/Mailer.class.php', 'RemoteAPI' => DOKU_INC.'inc/remote.php', 'RemoteAPICore' => DOKU_INC.'inc/RemoteAPICore.php', + 'Subscription' => DOKU_INC.'inc/subscription.php', 'DokuWiki_Action_Plugin' => DOKU_PLUGIN.'action.php', 'DokuWiki_Admin_Plugin' => DOKU_PLUGIN.'admin.php', diff --git a/inc/subscription.php b/inc/subscription.php index 1f1aedfa4..856836cd5 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -12,399 +12,425 @@ * - subscription_lock * - subscription_unlock * + * @fixme handle $conf['subscribers'] and disable actions + * * @author Adrian Lang + * @author Andreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ -/** - * Get the name of the metafile tracking subscriptions to target page or - * namespace - * - * @author Adrian Lang - * - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return string - */ -function subscription_filename($id) { - $meta_fname = '.mlist'; - if ((substr($id, -1, 1) === ':')) { - $meta_froot = getNS($id); - $meta_fname = '/' . $meta_fname; - } else { - $meta_froot = $id; +class Subscription { + + /** + * Return the subscription meta file for the given ID + * + * @author Adrian Lang + * + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return string + */ + protected function file($id) { + $meta_fname = '.mlist'; + if((substr($id, -1, 1) === ':')) { + $meta_froot = getNS($id); + $meta_fname = '/'.$meta_fname; + } else { + $meta_froot = $id; + } + return metaFN((string) $meta_froot, $meta_fname); } - return metaFN((string) $meta_froot, $meta_fname); -} -/** - * Lock subscription info for an ID - * - * @author Adrian Lang - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return string - */ -function subscription_lock_filename ($id){ - global $conf; - return $conf['lockdir'].'/_subscr_' . md5($id) . '.lock'; -} + /** + * Lock subscription info + * + * We don't use io_lock() her because we do not wait for the lock and use a larger stale time + * + * @author Adrian Lang + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return bool true, if you got a succesful lock + */ + protected function lock($id) { + global $conf; -/** - * Creates a lock file for writing subscription data - * - * @todo add lock time parameter to io_lock() and use this instead - * @param $id - * @return bool - */ -function subscription_lock($id) { - global $conf; - $lock = subscription_lock_filename($id); + $lock = $conf['lockdir'].'/_subscr_'.md5($id).'.lock'; - if (is_dir($lock) && time()-@filemtime($lock) > 60*5) { - // looks like a stale lock - remove it - @rmdir($lock); + if(is_dir($lock) && time() - @filemtime($lock) > 60 * 5) { + // looks like a stale lock - remove it + @rmdir($lock); + } + + // try creating the lock directory + if(!@mkdir($lock, $conf['dmode'])) { + return false; + } + + if($conf['dperm']) chmod($lock, $conf['dperm']); + return true; } - // try creating the lock directory - if (!@mkdir($lock,$conf['dmode'])) { - return false; + /** + * Unlock subscription info + * + * @author Adrian Lang + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @return bool + */ + protected function unlock($id) { + global $conf; + $lock = $conf['lockdir'].'/_subscr_'.md5($id).'.lock'; + return @rmdir($lock); } - if($conf['dperm']) chmod($lock, $conf['dperm']); - return true; -} + /** + * Construct a regular expression for parsing a subscription definition line + * + * @author Andreas Gohr + * + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return string complete regexp including delimiters + * @throws Exception when no data is passed + */ + protected function buildregex($user = null, $style = null, $data = null) { + // always work with arrays + $user = (array) $user; + $style = (array) $style; + $data = (array) $data; -/** - * Unlock subscription info for an ID - * - * @author Adrian Lang - * @param string $id The target page or namespace, specified by id; Namespaces - * are identified by appending a colon. - * @return bool - */ -function subscription_unlock($id) { - $lockf = subscription_lock_filename($id); - return @rmdir($lockf); -} + // clean + $user = array_filter(array_map('trim', $user)); + $style = array_filter(array_map('trim', $style)); + $data = array_filter(array_map('trim', $data)); -/** - * Set subscription information - * - * Allows to set subscription information for permanent storage in meta files. - * Subscriptions consist of a target object, a subscribing user, a subscribe - * style and optional data. - * A subscription may be deleted by specifying an empty subscribe style. - * Only one subscription per target and user is allowed. - * The function returns false on error, otherwise true. Note that no error is - * returned if a subscription should be deleted but the user is not subscribed - * and the subscription meta file exists. - * - * @author Adrian Lang - * - * @param string $user The subscriber or unsubscriber - * @param string $page The target object (page or namespace), specified by - * id; Namespaces are identified by a trailing colon. - * @param string $style The subscribe style; DokuWiki currently implements - * “every”, “digest”, and “list”. - * @param string $data An optional data blob - * @param bool $overwrite Whether an existing subscription may be overwritten - * @return bool - */ -function subscription_set($user, $page, $style, $data = null, - $overwrite = false) { - global $lang; - if (is_null($style)) { - // Delete subscription. - $file = subscription_filename($page); - if (!@file_exists($file)) { - msg(sprintf($lang['subscr_not_subscribed'], $user, - prettyprint_id($page)), -1); - return false; - } + // user names are encoded + $user = array_map('auth_nameencode', $user); - // io_deleteFromFile does not return false if no line matched. - return io_deleteFromFile($file, - subscription_regex(array('user' => auth_nameencode($user))), - true); - } + // quote + $user = array_map('preg_quote_cb', $user); + $style = array_map('preg_quote_cb', $style); + $data = array_map('preg_quote_cb', $data); - // Delete subscription if one exists and $overwrite is true. If $overwrite - // is false, fail. - $subs = subscription_find($page, array('user' => $user)); - if (count($subs) > 0 && array_pop(array_keys($subs)) === $page) { - if (!$overwrite) { - msg(sprintf($lang['subscr_already_subscribed'], $user, - prettyprint_id($page)), -1); - return false; + // join + $user = join('|', $user); + $style = join('|', $style); + $data = join('|', $data); + + // any data at all? + if($user.$style.$data === '') throw new Exception('no data passed'); + + // replace empty values, set which ones are optional + $sopt = ''; + $dopt = ''; + if($user === '') { + $user = '\S+'; } - // Fail if deletion failed, else continue. - if (!subscription_set($user, $page, null)) { - return false; + if($style === '') { + $style = '\S+'; + $sopt = '?'; + } + if($data === '') { + $data = '\S+'; + $dopt = '?'; } - } - $file = subscription_filename($page); - $content = auth_nameencode($user) . ' ' . $style; - if (!is_null($data)) { - $content .= ' ' . $data; + // assemble + return "/^($user)(?:\\s+($style))$sopt(?:\\s+($data))$dopt$/"; } - return io_saveFile($file, $content . "\n", true); -} -/** - * Recursively search for matching subscriptions - * - * This function searches all relevant subscription files for a page or - * namespace. - * - * @author Adrian Lang - * @see function subscription_regex for $pre documentation - * - * @param string $page The target object’s (namespace or page) id - * @param array $pre A hash of predefined values - * @return array - */ -function subscription_find($page, $pre) { - // Construct list of files which may contain relevant subscriptions. - $filenames = array(':' => subscription_filename(':')); - do { - $filenames[$page] = subscription_filename($page); - $page = getNS(rtrim($page, ':')) . ':'; - } while ($page !== ':'); - - // Handle files. - $matches = array(); - foreach ($filenames as $cur_page => $filename) { - if (!@file_exists($filename)) { - continue; - } - $subscriptions = file($filename); - foreach ($subscriptions as $subscription) { - if (strpos($subscription, ' ') === false) { - // This is an old subscription file. - $subscription = trim($subscription) . " every\n"; - } + /** + * Recursively search for matching subscriptions + * + * This function searches all relevant subscription files for a page or + * namespace. + * + * @author Adrian Lang + * + * @param string $page The target object’s (namespace or page) id + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return array + */ + public function subscribers($page, $user = null, $style = null, $data = null) { + // Construct list of files which may contain relevant subscriptions. + $files = array(':' => $this->file(':')); + do { + $files[$page] = $this->file($page); + $page = getNS(rtrim($page, ':')).':'; + } while($page !== ':'); - list($user, $rest) = explode(' ', $subscription, 2); - $subscription = rawurldecode($user) . " " . $rest; + $re = $this->buildregex($user, $style, $data); - if (preg_match(subscription_regex($pre), $subscription, - $line_matches) === 0) { - continue; - } - $match = array_slice($line_matches, 1); - if (!isset($matches[$cur_page])) { - $matches[$cur_page] = array(); + // Handle files. + $result = array(); + foreach($files as $target => $file) { + if(!@file_exists($file)) continue; + + $lines = file($file); + foreach($lines as $line) { + // fix old style subscription files + if(strpos($line, ' ') === false) $line = trim($line)." every\n"; + + // check for matching entries + if(!preg_match($re, $line, $m)) continue; + + $u = rawurldecode($m[1]); // decode the user name + if(!isset($result[$target])) $result[$target] = array(); + $result[$target][$u] = array($m[2], $m[3]); // add to result } - $matches[$cur_page][] = $match; } + return array_reverse($result); } - return array_reverse($matches); -} -/** - * Get data for $INFO['subscribed'] - * - * $INFO['subscribed'] is either false if no subscription for the current page - * and user is in effect. Else it contains an array of arrays with the fields - * “target”, “style”, and optionally “data”. - * - * @author Adrian Lang - */ -function get_info_subscribed() { - global $ID; - global $conf; - if (!$conf['subscribers']) { - return false; - } + /** + * Adds a new subscription for the given page or namespace + * + * This will automatically overwrite any existent subscription for the given user on this + * *exact* page or namespace. It will *not* modify any subscription that may exist in higher namespaces. + * + * @param string $id The target page or namespace, specified by id; Namespaces + * are identified by appending a colon. + * @param string $user + * @param string $style + * @param string $data + * @throws Exception when user or style is empty + * @return bool + */ + public function add($id, $user, $style, $data = '') { + // delete any existing subscription + $this->remove($id, $user); - $subs = subscription_find($ID, array('user' => $_SERVER['REMOTE_USER'])); - if (count($subs) === 0) { - return false; - } + $user = auth_nameencode(trim($user)); + $style = trim($style); + $data = trim($data); - $_ret = array(); - foreach ($subs as $target => $subs_data) { - $new = array('target' => $target, - 'style' => $subs_data[0][0]); - if (count($subs_data[0]) > 1) { - $new['data'] = $subs_data[0][1]; - } - $_ret[] = $new; + if(!$user) throw new Exception('no subscription user given'); + if(!$style) throw new Exception('no subscription style given'); + + $line = "$user $style"; + if($data) $line .= " $data"; + $line .= "\n"; + + $file = $this->file($id); + + return io_saveFile($file, $line, true); } - return $_ret; -} + /** + * Removes a subscription for the given page or namespace + * + * This removes all subscriptions matching the given criteria on the given page or + * namespace. It will *not* modify any subscriptions that may exist in higher + * namespaces. + * + * @param string $id The target object’s (namespace or page) id + * @param string|array $user + * @param string|array $style + * @param string|array $data + * @return bool + */ + public function remove($id, $user = null, $style = null, $data = null) { + $file = $this->file($id); + if(!file_exists($file)) return true; -/** - * Construct a regular expression parsing a subscription definition line - * - * @author Adrian Lang - * - * @param array $pre A hash of predefined values; “user”, “style”, and - * “data” may be set to limit the results to - * subscriptions matching these parameters. If - * “escaped” is true, these fields are inserted into the - * regular expression without escaping. - * - * @return string complete regexp including delimiters - */ -function subscription_regex($pre = array()) { - if (!isset($pre['escaped']) || $pre['escaped'] === false) { - $pre = array_map('preg_quote_cb', $pre); + $re = $this->buildregex($user, $style, $data); + return io_deleteFromFile($file, $re, true); } - foreach (array('user', 'style', 'data') as $key) { - if (!isset($pre[$key])) { - $pre[$key] = '(\S+)'; + + /** + * Get data for $INFO['subscribed'] + * + * $INFO['subscribed'] is either false if no subscription for the current page + * and user is in effect. Else it contains an array of arrays with the fields + * “target”, “style”, and optionally “data”. + * + * @param string $id Page ID, defaults to global $ID + * @param string $user User, defaults to $_SERVER['REMOTE_USER'] + * @return array + * @author Adrian Lang + */ + function user_subscription($id='', $user='') { + global $ID; + global $conf; + if(!$conf['subscribers']) return false; + + if(!$id) $id = $ID; + if(!$user) $user = $_SERVER['REMOTE_USER']; + + + $subs = $this->subscribers($id, $user); + if(!count($subs)) return false; + + $result = array(); + foreach($subs as $target => $data) { + $result[] = array( + 'target' => $target, + 'style' => $data[$user][0], + 'data' => $data[$user][1] + ); } + + return $result; } - return '/^' . $pre['user'] . '(?: ' . $pre['style'] . - '(?: ' . $pre['data'] . ')?)?$/'; -} -/** - * Return a string with the email addresses of all the - * users subscribed to a page - * - * This is the default action for COMMON_NOTIFY_ADDRESSLIST. - * - * @author Steven Danz - * @author Adrian Lang - * - * @todo this does NOT return a string but uses a reference to write back, either fix function or docs - * @param array $data Containing $id (the page id), $self (whether the author - * should be notified, $addresslist (current email address - * list) - * @return string - */ -function subscription_addresslist(&$data){ - global $conf; - /** @var auth_basic $auth */ - global $auth; + /** + * Return a string with the email addresses of all the + * users subscribed to a page + * + * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * + * @author Steven Danz + * @author Adrian Lang + * + * @todo this does NOT return a string but uses a reference to write back, either fix function or docs + * @param array $data Containing $id (the page id), $self (whether the author + * should be notified, $addresslist (current email address + * list) + * @return string + */ + function subscription_addresslist(&$data) { + global $conf; + /** @var auth_basic $auth */ + global $auth; - $id = $data['id']; - $self = $data['self']; - $addresslist = $data['addresslist']; + $id = $data['id']; + $self = $data['self']; + $addresslist = $data['addresslist']; - if (!$conf['subscribers'] || $auth === null) { - return ''; - } - $pres = array('style' => 'every', 'escaped' => true); - if (!$self && isset($_SERVER['REMOTE_USER'])) { - $pres['user'] = '((?!' . preg_quote_cb($_SERVER['REMOTE_USER']) . - '(?: |$))\S+)'; - } - $subs = subscription_find($id, $pres); - $emails = array(); - foreach ($subs as $by_targets) { - foreach ($by_targets as $sub) { - $info = $auth->getUserData($sub[0]); - if ($info === false) continue; - $level = auth_aclcheck($id, $sub[0], $info['grps']); - if ($level >= AUTH_READ) { - if (strcasecmp($info['mail'], $conf['notify']) != 0) { - $emails[$sub[0]] = $info['mail']; + if(!$conf['subscribers'] || $auth === null) { + return ''; + } + $pres = array('style' => 'every', 'escaped' => true); + if(!$self && isset($_SERVER['REMOTE_USER'])) { + $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). + '(?: |$))\S+)'; + } + $subs = subscription_find($id, $pres); + $emails = array(); + foreach($subs as $by_targets) { + foreach($by_targets as $sub) { + $info = $auth->getUserData($sub[0]); + if($info === false) continue; + $level = auth_aclcheck($id, $sub[0], $info['grps']); + if($level >= AUTH_READ) { + if(strcasecmp($info['mail'], $conf['notify']) != 0) { + $emails[$sub[0]] = $info['mail']; + } } } } + $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); } - $data['addresslist'] = trim($addresslist . ',' . implode(',', $emails), ','); -} -/** - * Send a digest mail - * - * Sends a digest mail showing a bunch of changes. - * - * @author Adrian Lang - * - * @param string $subscriber_mail The target mail address - * @param array $id The ID - * @param int $lastupdate Time of the last notification - */ -function subscription_send_digest($subscriber_mail, $id, $lastupdate) { - $n = 0; - do { - $rev = getRevisions($id, $n++, 1); - $rev = (count($rev) > 0) ? $rev[0] : null; - } while (!is_null($rev) && $rev > $lastupdate); - - $replaces = array('NEWPAGE' => wl($id, '', true, '&'), - 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&')); - if (!is_null($rev)) { - $subject = 'changed'; - $replaces['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $replaces['DIFF'] = $dformat->format($df); - } else { - $subject = 'newpage'; - $replaces['OLDPAGE'] = 'none'; - $replaces['DIFF'] = rawWiki($id); + /** + * Send a digest mail + * + * Sends a digest mail showing a bunch of changes. + * + * @author Adrian Lang + * + * @param string $subscriber_mail The target mail address + * @param array $id The ID + * @param int $lastupdate Time of the last notification + */ + function subscription_send_digest($subscriber_mail, $id, $lastupdate) { + $n = 0; + do { + $rev = getRevisions($id, $n++, 1); + $rev = (count($rev) > 0) ? $rev[0] : null; + } while(!is_null($rev) && $rev > $lastupdate); + + $replaces = array( + 'NEWPAGE' => wl($id, '', true, '&'), + 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') + ); + if(!is_null($rev)) { + $subject = 'changed'; + $replaces['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); + $df = new Diff(explode("\n", rawWiki($id, $rev)), + explode("\n", rawWiki($id))); + $dformat = new UnifiedDiffFormatter(); + $replaces['DIFF'] = $dformat->format($df); + } else { + $subject = 'newpage'; + $replaces['OLDPAGE'] = 'none'; + $replaces['DIFF'] = rawWiki($id); + } + subscription_send( + $subscriber_mail, $replaces, $subject, $id, + 'subscr_digest' + ); } - subscription_send($subscriber_mail, $replaces, $subject, $id, - 'subscr_digest'); -} -/** - * Send a list mail - * - * Sends a list mail showing a list of changed pages. - * - * @author Adrian Lang - * - * @param string $subscriber_mail The target mail address - * @param array $ids Array of ids - * @param string $ns_id The id of the namespace - */ -function subscription_send_list($subscriber_mail, $ids, $ns_id) { - if (count($ids) === 0) return; - global $conf; - $list = ''; - foreach ($ids as $id) { - $list .= '* ' . wl($id, array(), true) . NL; + /** + * Send a list mail + * + * Sends a list mail showing a list of changed pages. + * + * @author Adrian Lang + * + * @param string $subscriber_mail The target mail address + * @param array $ids Array of ids + * @param string $ns_id The id of the namespace + */ + function subscription_send_list($subscriber_mail, $ids, $ns_id) { + if(count($ids) === 0) return; + global $conf; + $list = ''; + foreach($ids as $id) { + $list .= '* '.wl($id, array(), true).NL; + } + subscription_send( + $subscriber_mail, + array( + 'DIFF' => rtrim($list), + 'SUBSCRIBE' => wl( + $ns_id.$conf['start'], + array('do' => 'subscribe'), + true, '&' + ) + ), + 'subscribe_list', + prettyprint_id($ns_id), + 'subscr_list' + ); } - subscription_send($subscriber_mail, - array('DIFF' => rtrim($list), - 'SUBSCRIBE' => wl($ns_id . $conf['start'], - array('do' => 'subscribe'), - true, '&')), - 'subscribe_list', - prettyprint_id($ns_id), - 'subscr_list'); -} -/** - * Helper function for sending a mail - * - * @author Adrian Lang - * - * @param string $subscriber_mail The target mail address - * @param array $replaces Predefined parameters used to parse the - * template - * @param string $subject The lang id of the mail subject (without the - * prefix “mail_”) - * @param string $id The page or namespace id - * @param string $template The name of the mail template - * @return bool - */ -function subscription_send($subscriber_mail, $replaces, $subject, $id, $template) { - global $lang; - - $text = rawLocale($template); - $trep = array_merge($replaces, array('PAGE' => $id)); - - $subject = $lang['mail_' . $subject] . ' ' . $id; - $mail = new Mailer(); - $mail->bcc($subscriber_mail); - $mail->subject($subject); - $mail->setBody($text,$trep); - $mail->setHeader( - 'List-Unsubscribe', - '<'.wl($id,array('do'=>'subscribe'),true,'&').'>', - false - ); - return $mail->send(); -} + /** + * Helper function for sending a mail + * + * @author Adrian Lang + * + * @param string $subscriber_mail The target mail address + * @param array $replaces Predefined parameters used to parse the + * template + * @param string $subject The lang id of the mail subject (without the + * prefix “mail_”) + * @param string $id The page or namespace id + * @param string $template The name of the mail template + * @return bool + */ + function subscription_send($subscriber_mail, $replaces, $subject, $id, $template) { + global $lang; + + $text = rawLocale($template); + $trep = array_merge($replaces, array('PAGE' => $id)); + + $subject = $lang['mail_'.$subject].' '.$id; + $mail = new Mailer(); + $mail->bcc($subscriber_mail); + $mail->subject($subject); + $mail->setBody($text, $trep); + $mail->setHeader( + 'List-Unsubscribe', + '<'.wl($id, array('do'=> 'subscribe'), true, '&').'>', + false + ); + return $mail->send(); + } + +} \ No newline at end of file -- cgit v1.2.3 From e920a0a10c3027700e61166a6f8d4ea29a9ff102 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 14:00:53 +0200 Subject: handle empty changelog in getRecentsSince() --- inc/changelog.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/changelog.php b/inc/changelog.php index 24583b341..7ca7c62e9 100644 --- a/inc/changelog.php +++ b/inc/changelog.php @@ -254,6 +254,7 @@ function getRecentsSince($from,$to=null,$ns='',$flags=0){ } else { $lines = @file($conf['changelog']); } + if(!$lines) return $recent; // we start searching at the end of the list $lines = array_reverse($lines); -- cgit v1.2.3 From adec979fd5453cf213b776d7dceaaaac4eb05713 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 15:07:03 +0200 Subject: more subscription refactoring BROKEN now the actual sending of bulk messages (digest, list) is reimplemented and partially tested. Still not complete --- _test/tests/inc/subscription.test.php | 97 ++++++++++++++--- inc/common.php | 4 +- inc/subscription.php | 191 ++++++++++++++++++++++++++-------- lib/exe/indexer.php | 86 ++------------- 4 files changed, 238 insertions(+), 140 deletions(-) diff --git a/_test/tests/inc/subscription.test.php b/_test/tests/inc/subscription.test.php index 77bf3e830..b3d49a533 100644 --- a/_test/tests/inc/subscription.test.php +++ b/_test/tests/inc/subscription.test.php @@ -2,7 +2,7 @@ class subscription_test extends DokuWikiTest { - function test_regexp(){ + function test_regexp() { // data to test against $data = array( "casper every\n", @@ -19,13 +19,13 @@ class subscription_test extends DokuWikiTest { array('casper', null, null, 1), array('nope', null, null, 0), array('lights', null, null, 0), - array(array('Cold Fusion','casper','nope'), null, null, 2), + array(array('Cold Fusion', 'casper', 'nope'), null, null, 2), array(null, 'list', null, 1), array(null, 'every', null, 2), array(null, 'digest', null, 3), array(null, array('list', 'every'), null, 3), array('casper', 'digest', null, 0), - array('casper', array('digest','every'), null, 1), + array('casper', array('digest', 'every'), null, 1), array('zioth', 'list', '1344691369', 1), array('zioth', null, '1344691369', 1), array('zioth', 'digest', '1344691369', 0), @@ -34,7 +34,7 @@ class subscription_test extends DokuWikiTest { $sub = new MockupSubscription(); $row = 0; - foreach($tests as $test){ + foreach($tests as $test) { $re = $sub->buildregex($test[0], $test[1], $test[2]); $this->assertFalse(empty($re), "test line $row"); $result = preg_grep($re, $data); @@ -44,13 +44,13 @@ class subscription_test extends DokuWikiTest { } } - function test_addremove(){ + function test_addremove() { $sub = new MockupSubscription(); // no subscriptions $this->assertArrayNotHasKey( 'wiki:dokuwiki', - $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) ); // add page subscription @@ -59,7 +59,7 @@ class subscription_test extends DokuWikiTest { // one subscription $this->assertArrayHasKey( 'wiki:dokuwiki', - $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) ); // remove page subscription @@ -68,7 +68,7 @@ class subscription_test extends DokuWikiTest { // no subscription $this->assertArrayNotHasKey( 'wiki:dokuwiki', - $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) ); // add namespace subscription @@ -77,7 +77,7 @@ class subscription_test extends DokuWikiTest { // one subscription $this->assertArrayHasKey( 'wiki:', - $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) ); // remove (non existing) page subscription @@ -86,7 +86,7 @@ class subscription_test extends DokuWikiTest { // still one subscription $this->assertArrayHasKey( 'wiki:', - $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) ); // change namespace subscription @@ -95,17 +95,66 @@ class subscription_test extends DokuWikiTest { // still one subscription $this->assertArrayHasKey( 'wiki:', - $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) ); // check contents $this->assertEquals( array('wiki:' => array('testuser' => array('digest', '1234567'))), - $sub->subscribers('wiki:dokuwiki', null, array('every','list','digest')) + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) + ); + + // change subscription data + $sub->add('wiki:', 'testuser', 'digest', '7654321'); + + // still one subscription + $this->assertArrayHasKey( + 'wiki:', + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) + ); + + // check contents + $this->assertEquals( + array('wiki:' => array('testuser' => array('digest', '7654321'))), + $sub->subscribers('wiki:dokuwiki', null, array('every', 'list', 'digest')) ); } + function test_bulkdigest(){ + $sub = new MockupSubscription(); + + // let's start with nothing + $this->assertEquals(0, $sub->send_bulk('sub1:test')); + + // create a subscription + $sub->add('sub1:', 'testuser', 'digest', '978328800'); // last mod 2001-01-01 + + // now create change + $_SERVER['REMOTE_USER'] = 'someguy'; + saveWikiText('sub1:test', 'foo bar', 'a subscription change', false); + // should trigger a mail + $this->assertEquals(1, $sub->send_bulk('sub1:test')); + $this->assertEquals(array('arthur@example.com'), $sub->mails); + + $sub->reset(); + + // now create more changes + $_SERVER['REMOTE_USER'] = 'someguy'; + saveWikiText('sub1:sub2:test', 'foo bar', 'a subscription change', false); + saveWikiText('sub1:another_test', 'foo bar', 'a subscription change', false); + + // should not trigger a mail, because the subscription time has not been reached, yet + $this->assertEquals(0, $sub->send_bulk('sub1:test')); + $this->assertEquals(array(), $sub->mails); + + // reset the subscription time + $sub->add('sub1:', 'testuser', 'digest', '978328800'); // last mod 2001-01-01 + + // we now should get mails for three changes + $this->assertEquals(3, $sub->send_bulk('sub1:test')); + $this->assertEquals(array('arthur@example.com','arthur@example.com','arthur@example.com'), $sub->mails); + } } @@ -113,9 +162,27 @@ class subscription_test extends DokuWikiTest { * makes protected methods visible for testing */ class MockupSubscription extends Subscription { - public function buildregex($user = null, $style = null, $data = null) { - return parent::buildregex($user, $style, $data); - } + public $mails; // we keep sent mails here + + public function __construct(){ + $this->reset(); + } + + /** + * resets the mail array + */ + public function reset(){ + $this->mails = array(); + } + + public function buildregex($user = null, $style = null, $data = null) { + return parent::buildregex($user, $style, $data); + } + + protected function send($subscriber_mail, $replaces, $subject, $id, $template){ + $this->mails[] = $subscriber_mail; + return true; + } } //Setup VIM: ex: et ts=4 : diff --git a/inc/common.php b/inc/common.php index ac7e744d8..29940d8a6 100644 --- a/inc/common.php +++ b/inc/common.php @@ -107,9 +107,11 @@ function pageinfo() { $info['isadmin'] = false; $info['ismanager'] = false; if(isset($_SERVER['REMOTE_USER'])) { + $sub = new Subscription(); + $info['userinfo'] = $USERINFO; $info['perm'] = auth_quickaclcheck($ID); - $info['subscribed'] = get_info_subscribed(); + $info['subscribed'] = $sub->user_subscription(); $info['client'] = $_SERVER['REMOTE_USER']; if($info['perm'] == AUTH_ADMIN) { diff --git a/inc/subscription.php b/inc/subscription.php index 856836cd5..804776ced 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -253,24 +253,23 @@ class Subscription { * @return array * @author Adrian Lang */ - function user_subscription($id='', $user='') { + function user_subscription($id = '', $user = '') { global $ID; global $conf; if(!$conf['subscribers']) return false; - if(!$id) $id = $ID; + if(!$id) $id = $ID; if(!$user) $user = $_SERVER['REMOTE_USER']; - $subs = $this->subscribers($id, $user); if(!count($subs)) return false; $result = array(); - foreach($subs as $target => $data) { + foreach($subs as $target => $info) { $result[] = array( 'target' => $target, - 'style' => $data[$user][0], - 'data' => $data[$user][1] + 'style' => $info[$user][0], + 'data' => $info[$user][1] ); } @@ -278,52 +277,100 @@ class Subscription { } /** - * Return a string with the email addresses of all the - * users subscribed to a page + * Send digest and list subscriptions * - * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * This sends mails to all subscribers that have a subscription for namespaces above + * the given page if the needed $conf['subscribe_time'] has passed already. * - * @author Steven Danz - * @author Adrian Lang + * This function is called form lib/exe/indexer.php * - * @todo this does NOT return a string but uses a reference to write back, either fix function or docs - * @param array $data Containing $id (the page id), $self (whether the author - * should be notified, $addresslist (current email address - * list) - * @return string + * @param string $page + * @return int number of sent mails */ - function subscription_addresslist(&$data) { - global $conf; + public function send_bulk($page) { /** @var auth_basic $auth */ global $auth; + global $conf; + global $USERINFO; + $count = 0; - $id = $data['id']; - $self = $data['self']; - $addresslist = $data['addresslist']; + $subscriptions = $this->subscribers($page, null, array('digest', 'list')); - if(!$conf['subscribers'] || $auth === null) { - return ''; - } - $pres = array('style' => 'every', 'escaped' => true); - if(!$self && isset($_SERVER['REMOTE_USER'])) { - $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). - '(?: |$))\S+)'; - } - $subs = subscription_find($id, $pres); - $emails = array(); - foreach($subs as $by_targets) { - foreach($by_targets as $sub) { - $info = $auth->getUserData($sub[0]); - if($info === false) continue; - $level = auth_aclcheck($id, $sub[0], $info['grps']); - if($level >= AUTH_READ) { - if(strcasecmp($info['mail'], $conf['notify']) != 0) { - $emails[$sub[0]] = $info['mail']; + // remember current user info + $olduinfo = $USERINFO; + $olduser = $_SERVER['REMOTE_USER']; + + foreach($subscriptions as $target => $users) { + if(!$this->lock($target)) continue; + + foreach($users as $user => $info) { + list($style, $lastupdate) = $info; + + $lastupdate = (int) $lastupdate; + if($lastupdate + $conf['subscribe_time'] > time()) { + // Less than the configured time period passed since last + // update. + continue; + } + + // Work as the user to make sure ACLs apply correctly + $USERINFO = $auth->getUserData($user); + $_SERVER['REMOTE_USER'] = $user; + if($USERINFO === false) continue; + if(!$USERINFO['mail']) continue; + + if(substr($target, -1, 1) === ':') { + // subscription target is a namespace, get all changes within + $changes = getRecentsSince($lastupdate, null, getNS($target)); + } else { + // single page subscription, check ACL ourselves + if(auth_quickaclcheck($target) < AUTH_READ) continue; + $meta = p_get_metadata($target); + $changes = array($meta['last_change']); + } + + // Filter out pages only changed in small and own edits + $change_ids = array(); + foreach($changes as $rev) { + $n = 0; + while(!is_null($rev) && $rev['date'] >= $lastupdate && + ($_SERVER['REMOTE_USER'] === $rev['user'] || + $rev['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT)) { + $rev = getRevisions($rev['id'], $n++, 1); + $rev = (count($rev) > 0) ? $rev[0] : null; + } + + if(!is_null($rev) && $rev['date'] >= $lastupdate) { + // Some change was not a minor one and not by myself + $change_ids[] = $rev['id']; } } + + // send it + if($style === 'digest') { + foreach($change_ids as $change_id) { + $this->send_digest( + $USERINFO['mail'], $change_id, + $lastupdate + ); + $count++; + } + } elseif($style === 'list') { + $this->send_list($USERINFO['mail'], $change_ids, $target); + $count++; + } + // TODO: Handle duplicate subscriptions. + + // Update notification time. + $this->add($target, $user, $style, time()); } + $this->unlock($target); } - $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); + + // restore current user info + $USERINFO = $olduinfo; + $_SERVER['REMOTE_USER'] = $olduser; + return $count; } /** @@ -337,7 +384,7 @@ class Subscription { * @param array $id The ID * @param int $lastupdate Time of the last notification */ - function subscription_send_digest($subscriber_mail, $id, $lastupdate) { + protected function send_digest($subscriber_mail, $id, $lastupdate) { $n = 0; do { $rev = getRevisions($id, $n++, 1); @@ -360,7 +407,7 @@ class Subscription { $replaces['OLDPAGE'] = 'none'; $replaces['DIFF'] = rawWiki($id); } - subscription_send( + $this->send( $subscriber_mail, $replaces, $subject, $id, 'subscr_digest' ); @@ -377,14 +424,14 @@ class Subscription { * @param array $ids Array of ids * @param string $ns_id The id of the namespace */ - function subscription_send_list($subscriber_mail, $ids, $ns_id) { + protected function send_list($subscriber_mail, $ids, $ns_id) { if(count($ids) === 0) return; global $conf; $list = ''; foreach($ids as $id) { $list .= '* '.wl($id, array(), true).NL; } - subscription_send( + $this->send( $subscriber_mail, array( 'DIFF' => rtrim($list), @@ -414,7 +461,7 @@ class Subscription { * @param string $template The name of the mail template * @return bool */ - function subscription_send($subscriber_mail, $replaces, $subject, $id, $template) { + protected function send($subscriber_mail, $replaces, $subject, $id, $template) { global $lang; $text = rawLocale($template); @@ -433,4 +480,58 @@ class Subscription { return $mail->send(); } + + + // FIXME no refactoring below, yet + + /** + * Return a string with the email addresses of all the + * users subscribed to a page + * + * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * + * @author Steven Danz + * @author Adrian Lang + * + * @todo this does NOT return a string but uses a reference to write back, either fix function or docs + * @param array $data Containing $id (the page id), $self (whether the author + * should be notified, $addresslist (current email address + * list) + * @return string + */ + function subscription_addresslist(&$data) { + global $conf; + /** @var auth_basic $auth */ + global $auth; + + $id = $data['id']; + $self = $data['self']; + $addresslist = $data['addresslist']; + + if(!$conf['subscribers'] || $auth === null) { + return ''; + } + $pres = array('style' => 'every', 'escaped' => true); + if(!$self && isset($_SERVER['REMOTE_USER'])) { + $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). + '(?: |$))\S+)'; + } + $subs = subscription_find($id, $pres); + $emails = array(); + foreach($subs as $by_targets) { + foreach($by_targets as $sub) { + $info = $auth->getUserData($sub[0]); + if($info === false) continue; + $level = auth_aclcheck($id, $sub[0], $info['grps']); + if($level >= AUTH_READ) { + if(strcasecmp($info['mail'], $conf['notify']) != 0) { + $emails[$sub[0]] = $info['mail']; + } + } + } + } + $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); + } + + } \ No newline at end of file diff --git a/lib/exe/indexer.php b/lib/exe/indexer.php index e149770c0..270341fe6 100644 --- a/lib/exe/indexer.php +++ b/lib/exe/indexer.php @@ -166,92 +166,20 @@ function runSitemapper(){ * @author Adrian Lang */ function sendDigest() { - echo 'sendDigest(): started'.NL; - global $ID; global $conf; + global $ID; + + echo 'sendDigest(): started'.NL; if (!$conf['subscribers']) { echo 'sendDigest(): disabled'.NL; return false; } - $subscriptions = subscription_find($ID, array('style' => '(digest|list)', - 'escaped' => true)); - global $auth; - global $lang; - global $conf; - global $USERINFO; - - // remember current user info - $olduinfo = $USERINFO; - $olduser = $_SERVER['REMOTE_USER']; - - foreach($subscriptions as $id => $users) { - if (!subscription_lock($id)) { - continue; - } - foreach($users as $data) { - list($user, $style, $lastupdate) = $data; - $lastupdate = (int) $lastupdate; - if ($lastupdate + $conf['subscribe_time'] > time()) { - // Less than the configured time period passed since last - // update. - continue; - } - - // Work as the user to make sure ACLs apply correctly - $USERINFO = $auth->getUserData($user); - $_SERVER['REMOTE_USER'] = $user; - if ($USERINFO === false) { - continue; - } - - if (substr($id, -1, 1) === ':') { - // The subscription target is a namespace - $changes = getRecentsSince($lastupdate, null, getNS($id)); - } else { - if(auth_quickaclcheck($id) < AUTH_READ) continue; - - $meta = p_get_metadata($id); - $changes = array($meta['last_change']); - } - - // Filter out pages only changed in small and own edits - $change_ids = array(); - foreach($changes as $rev) { - $n = 0; - while (!is_null($rev) && $rev['date'] >= $lastupdate && - ($_SERVER['REMOTE_USER'] === $rev['user'] || - $rev['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT)) { - $rev = getRevisions($rev['id'], $n++, 1); - $rev = (count($rev) > 0) ? $rev[0] : null; - } - - if (!is_null($rev) && $rev['date'] >= $lastupdate) { - // Some change was not a minor one and not by myself - $change_ids[] = $rev['id']; - } - } - - if ($style === 'digest') { - foreach($change_ids as $change_id) { - subscription_send_digest($USERINFO['mail'], $change_id, - $lastupdate); - } - } elseif ($style === 'list') { - subscription_send_list($USERINFO['mail'], $change_ids, $id); - } - // TODO: Handle duplicate subscriptions. - - // Update notification time. - subscription_set($user, $id, $style, time(), true); - } - subscription_unlock($id); - } + $sub = new Subscription(); + $sent = $sub->send_bulk($ID); - // restore current user info - $USERINFO = $olduinfo; - $_SERVER['REMOTE_USER'] = $olduser; + echo "sendDigest(): sent $sent mails".NL; echo 'sendDigest(): finished'.NL; - return true; + return (bool) $sent; } /** -- cgit v1.2.3 From 8c7bcacde38ed7306d14a7e5769d6d1f2f8b9a21 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 16:50:37 +0200 Subject: added list test --- _test/tests/inc/subscription.test.php | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/_test/tests/inc/subscription.test.php b/_test/tests/inc/subscription.test.php index b3d49a533..be2e68b74 100644 --- a/_test/tests/inc/subscription.test.php +++ b/_test/tests/inc/subscription.test.php @@ -156,6 +156,43 @@ class subscription_test extends DokuWikiTest { $this->assertEquals(array('arthur@example.com','arthur@example.com','arthur@example.com'), $sub->mails); } + function test_bulklist(){ + $sub = new MockupSubscription(); + + // let's start with nothing + $this->assertEquals(0, $sub->send_bulk('sub1:test')); + + // create a subscription + $sub->add('sub1:', 'testuser', 'list', '978328800'); // last mod 2001-01-01 + + // now create change + $_SERVER['REMOTE_USER'] = 'someguy'; + saveWikiText('sub1:test', 'foo bar', 'a subscription change', false); + + // should trigger a mail + $this->assertEquals(1, $sub->send_bulk('sub1:test')); + $this->assertEquals(array('arthur@example.com'), $sub->mails); + + $sub->reset(); + + // now create more changes + $_SERVER['REMOTE_USER'] = 'someguy'; + saveWikiText('sub1:sub2:test', 'foo bar', 'a subscription change', false); + saveWikiText('sub1:another_test', 'foo bar', 'a subscription change', false); + + // should not trigger a mail, because the subscription time has not been reached, yet + $this->assertEquals(0, $sub->send_bulk('sub1:test')); + $this->assertEquals(array(), $sub->mails); + + // reset the subscription time + $sub->add('sub1:', 'testuser', 'list', '978328800'); // last mod 2001-01-01 + + // we now should get a single mail for all three changes + $this->assertEquals(1, $sub->send_bulk('sub1:test')); + $this->assertEquals(array('arthur@example.com'), $sub->mails); + } + + } /** -- cgit v1.2.3 From 835242b0f53a72a555ad30543a1677108ce210af Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 17:17:34 +0200 Subject: subscription system should work now again This readds the last part of the subscription system: the normal "every" subscriptions. --- inc/common.php | 2 +- inc/subscription.php | 57 ++++++++++++++++++++++------------------------------ 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/inc/common.php b/inc/common.php index 29940d8a6..3cfeb3092 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1122,7 +1122,7 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = $data = array('id' => $id, 'addresslist' => '', 'self' => false); trigger_event( 'COMMON_NOTIFY_ADDRESSLIST', $data, - 'subscription_addresslist' + array(new Subscription(), 'notifyaddresses') ); $bcc = $data['addresslist']; if(empty($bcc)) return false; diff --git a/inc/subscription.php b/inc/subscription.php index 804776ced..9b02225f9 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -12,7 +12,7 @@ * - subscription_lock * - subscription_unlock * - * @fixme handle $conf['subscribers'] and disable actions + * @fixme handle $conf['subscribers'] and disable actions and $auth == null * * @author Adrian Lang * @author Andreas Gohr @@ -480,26 +480,23 @@ class Subscription { return $mail->send(); } - - - // FIXME no refactoring below, yet - /** - * Return a string with the email addresses of all the - * users subscribed to a page + * Default callback for COMMON_NOTIFY_ADDRESSLIST * - * This is the default action for COMMON_NOTIFY_ADDRESSLIST. + * Aggregates all email addresses of user who have subscribed the given page with 'every' style * * @author Steven Danz * @author Adrian Lang * - * @todo this does NOT return a string but uses a reference to write back, either fix function or docs - * @param array $data Containing $id (the page id), $self (whether the author - * should be notified, $addresslist (current email address - * list) + * @todo move the whole functionality into this class, trigger SUBSCRIPTION_NOTIFY_ADDRESSLIST instead, + * use an array for the addresses within it + * + * @param array &$data Containing $id (the page id), $self (whether the author + * should be notified, $addresslist (current email address + * list) * @return string */ - function subscription_addresslist(&$data) { + public function notifyaddresses(&$data) { global $conf; /** @var auth_basic $auth */ global $auth; @@ -508,30 +505,24 @@ class Subscription { $self = $data['self']; $addresslist = $data['addresslist']; - if(!$conf['subscribers'] || $auth === null) { - return ''; - } - $pres = array('style' => 'every', 'escaped' => true); - if(!$self && isset($_SERVER['REMOTE_USER'])) { - $pres['user'] = '((?!'.preg_quote_cb($_SERVER['REMOTE_USER']). - '(?: |$))\S+)'; - } - $subs = subscription_find($id, $pres); - $emails = array(); - foreach($subs as $by_targets) { - foreach($by_targets as $sub) { - $info = $auth->getUserData($sub[0]); - if($info === false) continue; - $level = auth_aclcheck($id, $sub[0], $info['grps']); + $subscriptions = $this->subscribers($id, null, 'every'); + + $result = array(); + foreach($subscriptions as $target => $users) { + foreach($users as $user => $info) { + $userinfo = $auth->getUserData($user); + if($userinfo === false) continue; + if(!$userinfo['mail']) continue; + if(!$self && $user == $_SERVER['REMOTE_USER']) continue; //skip our own changes + + $level = auth_aclcheck($id, $user, $userinfo['grps']); if($level >= AUTH_READ) { - if(strcasecmp($info['mail'], $conf['notify']) != 0) { - $emails[$sub[0]] = $info['mail']; + if(strcasecmp($userinfo['mail'], $conf['notify']) != 0) { //skip user who get notified elsewhere + $result[$user] = $userinfo['mail']; } } } } - $data['addresslist'] = trim($addresslist.','.implode(',', $emails), ','); + $data['addresslist'] = trim($addresslist.','.implode(',', $result), ','); } - - } \ No newline at end of file -- cgit v1.2.3 From 84c1127cc070777c8cbcf488f5422bc4b71470a8 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 17:30:01 +0200 Subject: correctly check if subscriptions are enabled --- _test/tests/inc/subscription.test.php | 4 ++++ inc/common.php | 2 +- inc/subscription.php | 26 ++++++++++++++++++++++---- lib/exe/indexer.php | 2 +- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/_test/tests/inc/subscription.test.php b/_test/tests/inc/subscription.test.php index be2e68b74..80548160a 100644 --- a/_test/tests/inc/subscription.test.php +++ b/_test/tests/inc/subscription.test.php @@ -212,6 +212,10 @@ class MockupSubscription extends Subscription { $this->mails = array(); } + public function isenabled(){ + return true; + } + public function buildregex($user = null, $style = null, $data = null) { return parent::buildregex($user, $style, $data); } diff --git a/inc/common.php b/inc/common.php index 3cfeb3092..b4a57b154 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1117,7 +1117,7 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = $to = $conf['notify']; $bcc = ''; } elseif($who == 'subscribers') { - if(!$conf['subscribers']) return false; //subscribers enabled? + if(!actionOK('subscribe')) return false; //subscribers enabled? if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return false; //skip minors $data = array('id' => $id, 'addresslist' => '', 'self' => false); trigger_event( diff --git a/inc/subscription.php b/inc/subscription.php index 9b02225f9..742f5b1a0 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -21,6 +21,15 @@ class Subscription { + /** + * Check if subscription system is enabled + * + * @return bool + */ + public function isenabled() { + return actionOK('subscribe'); + } + /** * Return the subscription meta file for the given ID * @@ -156,6 +165,8 @@ class Subscription { * @return array */ public function subscribers($page, $user = null, $style = null, $data = null) { + if(!$this->isenabled()) return array(); + // Construct list of files which may contain relevant subscriptions. $files = array(':' => $this->file(':')); do { @@ -201,6 +212,8 @@ class Subscription { * @return bool */ public function add($id, $user, $style, $data = '') { + if(!$this->isenabled()) return false; + // delete any existing subscription $this->remove($id, $user); @@ -234,6 +247,8 @@ class Subscription { * @return bool */ public function remove($id, $user = null, $style = null, $data = null) { + if(!$this->isenabled()) return false; + $file = $this->file($id); if(!file_exists($file)) return true; @@ -254,10 +269,9 @@ class Subscription { * @author Adrian Lang */ function user_subscription($id = '', $user = '') { - global $ID; - global $conf; - if(!$conf['subscribers']) return false; + if(!$this->isenabled()) return false; + global $ID; if(!$id) $id = $ID; if(!$user) $user = $_SERVER['REMOTE_USER']; @@ -288,6 +302,8 @@ class Subscription { * @return int number of sent mails */ public function send_bulk($page) { + if(!$this->isenabled()) return 0; + /** @var auth_basic $auth */ global $auth; global $conf; @@ -497,9 +513,11 @@ class Subscription { * @return string */ public function notifyaddresses(&$data) { - global $conf; + if(!$this->isenabled()) return false; + /** @var auth_basic $auth */ global $auth; + global $conf; $id = $data['id']; $self = $data['self']; diff --git a/lib/exe/indexer.php b/lib/exe/indexer.php index 270341fe6..bbfd51b39 100644 --- a/lib/exe/indexer.php +++ b/lib/exe/indexer.php @@ -170,7 +170,7 @@ function sendDigest() { global $ID; echo 'sendDigest(): started'.NL; - if (!$conf['subscribers']) { + if(!actionOK('subscribe')) { echo 'sendDigest(): disabled'.NL; return false; } -- cgit v1.2.3 From a0519fdaeb59bd96d9071681a68c2dc1b646fc68 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 17:47:47 +0200 Subject: fixed subscription management now adding and removing subscriptions works again --- inc/actions.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/inc/actions.php b/inc/actions.php index 62b0e1800..721492bd4 100644 --- a/inc/actions.php +++ b/inc/actions.php @@ -700,21 +700,28 @@ function act_subscription($act){ $target = $params['target']; $style = $params['style']; - $data = $params['data']; $action = $params['action']; // Perform action. - if (!subscription_set($_SERVER['REMOTE_USER'], $target, $style, $data)) { + $sub = new Subscription(); + if($action == 'unsubscribe'){ + $ok = $sub->remove($target, $_SERVER['REMOTE_USER'], $style); + }else{ + $ok = $sub->add($target, $_SERVER['REMOTE_USER'], $style); + } + + if($ok) { + msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']), + prettyprint_id($target)), 1); + act_redirect($ID, $act); + } else { throw new Exception(sprintf($lang["subscr_{$action}_error"], hsc($INFO['userinfo']['name']), prettyprint_id($target))); } - msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']), - prettyprint_id($target)), 1); - act_redirect($ID, $act); // Assure that we have valid data if act_redirect somehow fails. - $INFO['subscribed'] = get_info_subscribed(); + $INFO['subscribed'] = $sub->user_subscription(); return 'show'; } -- cgit v1.2.3 From 02308d17ed15cd633ba1fd5cab11994c42065121 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 18:01:30 +0200 Subject: initialize new subscriptions with current time We don't want to create a bunch of mails whenever a namespace is subscribed. Only changes *after* the subscription should be considered. This patch adds the timestamp to "every" style subscriptions as well, though this data is ignored. --- inc/subscription.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/subscription.php b/inc/subscription.php index 742f5b1a0..800329cb5 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -223,6 +223,7 @@ class Subscription { if(!$user) throw new Exception('no subscription user given'); if(!$style) throw new Exception('no subscription style given'); + if(!$data) $data = time(); //always add current time for new subscriptions $line = "$user $style"; if($data) $line .= " $data"; -- cgit v1.2.3 From f036cff4fde59f0265f6123f6faf92cb8ba8bb26 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 12 Aug 2012 18:07:20 +0200 Subject: minor cleanup --- inc/subscription.php | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/inc/subscription.php b/inc/subscription.php index 800329cb5..74f4e4d03 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -1,24 +1,11 @@ * @author Andreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ - class Subscription { /** @@ -511,10 +498,9 @@ class Subscription { * @param array &$data Containing $id (the page id), $self (whether the author * should be notified, $addresslist (current email address * list) - * @return string */ public function notifyaddresses(&$data) { - if(!$this->isenabled()) return false; + if(!$this->isenabled()) return; /** @var auth_basic $auth */ global $auth; -- cgit v1.2.3 From 2ed38036a53a489d2fcadc46ce601f8c876fca31 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 21 Sep 2012 11:53:17 +0200 Subject: consolidate more notification code in subscription class This is untested and probably broken currently --- _test/tests/inc/subscription.test.php | 2 +- inc/auth.php | 11 +-- inc/common.php | 45 ++-------- inc/subscription.php | 159 ++++++++++++++++++++++++---------- 4 files changed, 127 insertions(+), 90 deletions(-) diff --git a/_test/tests/inc/subscription.test.php b/_test/tests/inc/subscription.test.php index 80548160a..c6f33dec7 100644 --- a/_test/tests/inc/subscription.test.php +++ b/_test/tests/inc/subscription.test.php @@ -220,7 +220,7 @@ class MockupSubscription extends Subscription { return parent::buildregex($user, $style, $data); } - protected function send($subscriber_mail, $replaces, $subject, $id, $template){ + protected function send($subscriber_mail, $subject, $id, $template, $trep, $hrep){ $this->mails[] = $subscriber_mail; return true; } diff --git a/inc/auth.php b/inc/auth.php index cedfdee36..3fb937613 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -778,23 +778,18 @@ function register() { return false; } - // create substitutions for use in notification email - $substitutions = array( - 'NEWUSER' => $_POST['login'], - 'NEWNAME' => $_POST['fullname'], - 'NEWEMAIL' => $_POST['email'], - ); + $subscription = new Subscription(); if(!$conf['autopasswd']) { msg($lang['regsuccess2'], 1); - notify('', 'register', '', $_POST['login'], false, $substitutions); + $subscription->send_register($_POST['login'], $_POST['fullname'], $_POST['email']); return true; } // autogenerated password? then send him the password if(auth_sendPassword($_POST['login'], $pass)) { msg($lang['regsuccess'], 1); - notify('', 'register', '', $_POST['login'], false, $substitutions); + $subscription->send_register($_POST['login'], $_POST['fullname'], $_POST['email']); return true; } else { msg($lang['regmailfail'], -1); diff --git a/inc/common.php b/inc/common.php index b4a57b154..d17061a1b 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1113,9 +1113,8 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = // decide if there is something to do, eg. whom to mail if($who == 'admin') { if(empty($conf['notify'])) return false; //notify enabled? - $text = rawLocale('mailtext'); - $to = $conf['notify']; - $bcc = ''; + $tpl = 'mailtext'; + $to = $conf['notify']; } elseif($who == 'subscribers') { if(!actionOK('subscribe')) return false; //subscribers enabled? if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return false; //skip minors @@ -1124,57 +1123,29 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = 'COMMON_NOTIFY_ADDRESSLIST', $data, array(new Subscription(), 'notifyaddresses') ); - $bcc = $data['addresslist']; - if(empty($bcc)) return false; - $to = ''; - $text = rawLocale('subscr_single'); + $to = $data['addresslist']; + if(empty($to)) return false; + $tpl = 'subscr_single'; } elseif($who == 'register') { if(empty($conf['registernotify'])) return false; $text = rawLocale('registermail'); $to = $conf['registernotify']; - $bcc = ''; } else { return false; //just to be safe } - // prepare replacements (keys not set in hrep will be taken from trep) - $trep = array( - 'NEWPAGE' => wl($id, '', true, '&'), - 'PAGE' => $id, - 'SUMMARY' => $summary - ); - $trep = array_merge($trep, $replace); - $hrep = array(); - // prepare content if($who == 'register') { $subject = $lang['mail_new_user'].' '.$summary; - } elseif($rev) { - $subject = $lang['mail_changed'].' '.$id; - $trep['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $tdiff = $dformat->format($df); - - $DIFF_INLINESTYLES = true; - $dformat = new InlineDiffFormatter(); - $hdiff = $dformat->format($df); - $hdiff = ''.$hdiff.'
'; - $DIFF_INLINESTYLES = false; } else { - $subject = $lang['mail_newpage'].' '.$id; - $trep['OLDPAGE'] = '---'; - $tdiff = rawWiki($id); - $hdiff = nl2br(hsc($tdiff)); + $subscription = new Subscription(); + return $subscription->send_diff($to, $tpl, $id, $rev, $summary); } - $trep['DIFF'] = $tdiff; - $hrep['DIFF'] = $hdiff; + // send mail $mail = new Mailer(); $mail->to($to); - $mail->bcc($bcc); $mail->subject($subject); $mail->setBody($text, $trep, $hrep); if($who == 'subscribers') { diff --git a/inc/subscription.php b/inc/subscription.php index 74f4e4d03..4757b216c 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -377,16 +377,90 @@ class Subscription { return $count; } + /** + * Send the diff for some page change + * + * @param string $subscriber_mail The target mail address + * @param string $template Mail template, should be 'subscr_digest' or 'subscr_single' + * @param string $id Page for which the notification is + * @param int|null $rev Old revision if any + * @param string $summary Change summary if any + * @return bool true if successfully sent + */ + public function send_diff($subscriber_mail, $template, $id, $rev = null, $summary = '') { + global $DIFF_INLINESTYLES; + + // prepare replacements (keys not set in hrep will be taken from trep) + $trep = array( + 'PAGE' => $id, + 'NEWPAGE' => wl($id, '', true, '&'), + 'SUMMARY' => $summary, + 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') + ); + $hrep = array(); + + if($rev) { + $subject = 'changed'; + $trep['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); + $df = new Diff(explode("\n", rawWiki($id, $rev)), + explode("\n", rawWiki($id))); + $dformat = new UnifiedDiffFormatter(); + $tdiff = $dformat->format($df); + + $DIFF_INLINESTYLES = true; + $dformat = new InlineDiffFormatter(); + $hdiff = $dformat->format($df); + $hdiff = ''.$hdiff.'
'; + $DIFF_INLINESTYLES = false; + + } else { + $subject = 'newpage'; + $trep['OLDPAGE'] = '---'; + $tdiff = rawWiki($id); + $hdiff = nl2br(hsc($tdiff)); + } + + $trep['DIFF'] = $tdiff; + $hrep['DIFF'] = $hdiff; + + return $this->send( + $subscriber_mail, $subject, $id, + $template, $trep, $hrep + ); + } + + public function send_register($login, $fullname, $email) { + global $conf; + global $ID; + if(empty($conf['registernotify'])) return false; + + $trep = array( + 'NEWUSER' => $login, + 'NEWNAME' => $fullname, + 'NEWEMAIL' => $email, + ); + + return $this->send( + $conf['registernotify'], + 'new_user', + $ID, + 'registermail', + $trep + ); + } + /** * Send a digest mail * - * Sends a digest mail showing a bunch of changes. + * Sends a digest mail showing a bunch of changes of a single page. Basically the same as send_diff() + * but determines the last known revision first * * @author Adrian Lang * * @param string $subscriber_mail The target mail address * @param array $id The ID * @param int $lastupdate Time of the last notification + * @return bool */ protected function send_digest($subscriber_mail, $id, $lastupdate) { $n = 0; @@ -395,25 +469,10 @@ class Subscription { $rev = (count($rev) > 0) ? $rev[0] : null; } while(!is_null($rev) && $rev > $lastupdate); - $replaces = array( - 'NEWPAGE' => wl($id, '', true, '&'), - 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') - ); - if(!is_null($rev)) { - $subject = 'changed'; - $replaces['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $replaces['DIFF'] = $dformat->format($df); - } else { - $subject = 'newpage'; - $replaces['OLDPAGE'] = 'none'; - $replaces['DIFF'] = rawWiki($id); - } - $this->send( - $subscriber_mail, $replaces, $subject, $id, - 'subscr_digest' + return $this->send_diff( + $subscriber_mail, + 'subscr_digest', + $id, $rev ); } @@ -427,27 +486,35 @@ class Subscription { * @param string $subscriber_mail The target mail address * @param array $ids Array of ids * @param string $ns_id The id of the namespace + * @return bool */ protected function send_list($subscriber_mail, $ids, $ns_id) { if(count($ids) === 0) return; - global $conf; - $list = ''; + + $tlist = ''; + $hlist = '
    '; foreach($ids as $id) { - $list .= '* '.wl($id, array(), true).NL; + $link = wl($id, array(), true); + $tlist .= '* '.$link.NL; + $hlist .= '
  • '.hsc($id).'
  • '.NL; } - $this->send( + $hlist = '
'; + + $id = prettyprint_id($ns_id); + $trep = array( + 'DIFF' => rtrim($tlist), + 'PAGE' => $id, + 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') + ); + $hrep = array( + 'DIFF' => $hlist + ); + + return $this->send( $subscriber_mail, - array( - 'DIFF' => rtrim($list), - 'SUBSCRIBE' => wl( - $ns_id.$conf['start'], - array('do' => 'subscribe'), - true, '&' - ) - ), 'subscribe_list', - prettyprint_id($ns_id), - 'subscr_list' + + 'subscr_list', $trep, $hrep ); } @@ -457,30 +524,34 @@ class Subscription { * @author Adrian Lang * * @param string $subscriber_mail The target mail address - * @param array $replaces Predefined parameters used to parse the - * template * @param string $subject The lang id of the mail subject (without the * prefix “mail_”) * @param string $id The page or namespace id * @param string $template The name of the mail template + * @param array $trep Predefined parameters used to parse the + * template (in text format) + * @param array $hrep Predefined parameters used to parse the + * template (in HTML format), null to default to $trep * @return bool */ - protected function send($subscriber_mail, $replaces, $subject, $id, $template) { + protected function send($subscriber_mail, $subject, $id, $template, $trep, $hrep = null) { global $lang; $text = rawLocale($template); - $trep = array_merge($replaces, array('PAGE' => $id)); + $trep = array_merge( + $trep, array( + + ) + ); $subject = $lang['mail_'.$subject].' '.$id; $mail = new Mailer(); $mail->bcc($subscriber_mail); $mail->subject($subject); - $mail->setBody($text, $trep); - $mail->setHeader( - 'List-Unsubscribe', - '<'.wl($id, array('do'=> 'subscribe'), true, '&').'>', - false - ); + $mail->setBody($text, $trep, $hrep); + if(isset($trep['SUBSCRIBE'])){ + $mail->setHeader('List-Unsubscribe', '<'.$trep['SUBSCRIBE'].'>', false); + } return $mail->send(); } -- cgit v1.2.3 From bee9f377bc547c99fe99b4e38199cb92cf668554 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 3 Nov 2012 17:54:02 +0100 Subject: Completely rewritten Tar library This new class is only losely based on our previous library. The whole API was changed to make it more flexible and memory saving. Some fisrt unit tests are included --- _test/tests/inc/tar.test.php | 134 +++++++ _test/tests/inc/tar/foobar/testdata2.txt | 1 + _test/tests/inc/tar/test.tar | Bin 0 -> 10240 bytes _test/tests/inc/tar/test.tbz | Bin 0 -> 217 bytes _test/tests/inc/tar/test.tgz | Bin 0 -> 220 bytes _test/tests/inc/tar/testdata1.txt | 1 + _test/tests/inc/tarlib.test.php | 0 inc/Tar.class.php | 614 +++++++++++++++++++++++++++++++ inc/load.php | 1 + 9 files changed, 751 insertions(+) create mode 100644 _test/tests/inc/tar.test.php create mode 100644 _test/tests/inc/tar/foobar/testdata2.txt create mode 100644 _test/tests/inc/tar/test.tar create mode 100644 _test/tests/inc/tar/test.tbz create mode 100644 _test/tests/inc/tar/test.tgz create mode 100644 _test/tests/inc/tar/testdata1.txt delete mode 100644 _test/tests/inc/tarlib.test.php create mode 100644 inc/Tar.class.php diff --git a/_test/tests/inc/tar.test.php b/_test/tests/inc/tar.test.php new file mode 100644 index 000000000..706516d9e --- /dev/null +++ b/_test/tests/inc/tar.test.php @@ -0,0 +1,134 @@ +create(); + $tar->AddFile("$dir/testdata1.txt"); + $tar->AddFile("$dir/foobar/testdata2.txt", 'noway/testdata2.txt'); + $tar->addData('another/testdata3.txt', 'testcontent3'); + + $data = $tar->getArchive(); + + $this->assertTrue(strpos($data, 'testcontent1') !== false, 'Content in TAR'); + $this->assertTrue(strpos($data, 'testcontent2') !== false, 'Content in TAR'); + $this->assertTrue(strpos($data, 'testcontent3') !== false, 'Content in TAR'); + + $this->assertTrue(strpos($data, "$dir/testdata1.txt") !== false, 'Path in TAR'); + $this->assertTrue(strpos($data, 'noway/testdata2.txt') !== false, 'Path in TAR'); + $this->assertTrue(strpos($data, 'another/testdata3.txt') !== false, 'Path in TAR'); + + $this->assertTrue(strpos($data, "$dir/foobar/testdata2.txt") === false, 'Path not in TAR'); + $this->assertTrue(strpos($data, "foobar") === false, 'Path not in TAR'); + } + + /** + * simple test that checks that the given filenames and contents can be grepped from the + * uncompressed tar file + * + * No check for format correctness + */ + public function test_createfile(){ + $tar = new Tar(); + + $dir = dirname(__FILE__).'/tar'; + $tmp = tempnam(sys_get_temp_dir(), 'dwtartest'); + + $tar->create($tmp, Tar::COMPRESS_NONE); + $tar->AddFile("$dir/testdata1.txt"); + $tar->AddFile("$dir/foobar/testdata2.txt", 'noway/testdata2.txt'); + $tar->addData('another/testdata3.txt', 'testcontent3'); + $tar->close(); + + $this->assertTrue(filesize($tmp) > 30); //arbitrary non-zero number + $data = file_get_contents($tmp); + + $this->assertTrue(strpos($data, 'testcontent1') !== false, 'Content in TAR'); + $this->assertTrue(strpos($data, 'testcontent2') !== false, 'Content in TAR'); + $this->assertTrue(strpos($data, 'testcontent3') !== false, 'Content in TAR'); + + $this->assertTrue(strpos($data, "$dir/testdata1.txt") !== false, 'Path in TAR'); + $this->assertTrue(strpos($data, 'noway/testdata2.txt') !== false, 'Path in TAR'); + $this->assertTrue(strpos($data, 'another/testdata3.txt') !== false, 'Path in TAR'); + + $this->assertTrue(strpos($data, "$dir/foobar/testdata2.txt") === false, 'Path not in TAR'); + $this->assertTrue(strpos($data, "foobar") === false, 'Path not in TAR'); + + @unlink($tmp); + } + + /** + * List the contents of the prebuilt TAR files + */ + public function test_tarcontent(){ + $dir = dirname(__FILE__).'/tar'; + + foreach(array('tar','tgz','tbz') as $ext){ + $tar = new Tar(); + $file = "$dir/test.$ext"; + + $tar->open($file); + $content = $tar->contents(); + + $this->assertCount(4, $content, "Contents of $file"); + $this->assertEquals('tar/testdata1.txt', $content[1]['filename'], "Contents of $file"); + $this->assertEquals(13, $content[1]['size'], "Contents of $file"); + + $this->assertEquals('tar/foobar/testdata2.txt', $content[3]['filename'], "Contents of $file"); + $this->assertEquals(13, $content[1]['size'], "Contents of $file"); + } + } + + /** + * Extract the prebuilt tar files + */ + public function test_tarextract(){ + $dir = dirname(__FILE__).'/tar'; + $out = sys_get_temp_dir().'/dwtartest'.md5(time()); + + foreach(array('tar', 'tgz', 'tbz') as $ext){ + $tar = new Tar(); + $file = "$dir/test.$ext"; + + $tar->open($file); + $tar->extract($out); + + clearstatcache(); + + $this->assertFileExists($out.'/tar/testdata1.txt', "Extracted $file"); + $this->assertEquals(13, filesize($out.'/tar/testdata1.txt'), "Extracted $file"); + + $this->assertFileExists($out.'/tar/foobar/testdata2.txt', "Extracted $file"); + $this->assertEquals(13, filesize($out.'/tar/foobar/testdata2.txt'), "Extracted $file"); + + TestUtils::rdelete($out); + } + + } + + /** + * Check the extension to compression guesser + */ + public function test_filetype(){ + $tar = new Tar(); + $this->assertEquals(Tar::COMPRESS_NONE, $tar->filetype('foo')); + $this->assertEquals(Tar::COMPRESS_GZIP, $tar->filetype('foo.tgz')); + $this->assertEquals(Tar::COMPRESS_GZIP, $tar->filetype('foo.tGZ')); + $this->assertEquals(Tar::COMPRESS_GZIP, $tar->filetype('foo.tar.GZ')); + $this->assertEquals(Tar::COMPRESS_GZIP, $tar->filetype('foo.tar.gz')); + $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tbz')); + $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tBZ')); + $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tar.BZ2')); + $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tar.bz2')); + } +} \ No newline at end of file diff --git a/_test/tests/inc/tar/foobar/testdata2.txt b/_test/tests/inc/tar/foobar/testdata2.txt new file mode 100644 index 000000000..a7db15771 --- /dev/null +++ b/_test/tests/inc/tar/foobar/testdata2.txt @@ -0,0 +1 @@ +testcontent2 diff --git a/_test/tests/inc/tar/test.tar b/_test/tests/inc/tar/test.tar new file mode 100644 index 000000000..931866b0b Binary files /dev/null and b/_test/tests/inc/tar/test.tar differ diff --git a/_test/tests/inc/tar/test.tbz b/_test/tests/inc/tar/test.tbz new file mode 100644 index 000000000..5a7374019 Binary files /dev/null and b/_test/tests/inc/tar/test.tbz differ diff --git a/_test/tests/inc/tar/test.tgz b/_test/tests/inc/tar/test.tgz new file mode 100644 index 000000000..b00319649 Binary files /dev/null and b/_test/tests/inc/tar/test.tgz differ diff --git a/_test/tests/inc/tar/testdata1.txt b/_test/tests/inc/tar/testdata1.txt new file mode 100644 index 000000000..ac65bb32e --- /dev/null +++ b/_test/tests/inc/tar/testdata1.txt @@ -0,0 +1 @@ +testcontent1 diff --git a/_test/tests/inc/tarlib.test.php b/_test/tests/inc/tarlib.test.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/inc/Tar.class.php b/inc/Tar.class.php new file mode 100644 index 000000000..7f5e5af4a --- /dev/null +++ b/inc/Tar.class.php @@ -0,0 +1,614 @@ +open('myfile.tgz'); + * $toc = $tar->contents(); + * print_r($toc); + * + * To extract the contents of an existing TAR archive, open() it and use extract() on it: + * + * $tar = new Tar(); + * $tar->open('myfile.tgz'); + * $tar->extract(/tmp); + * + * To create a new TAR archive directly on the filesystem (low memory requirements), create() it, + * add*() files and close() it: + * + * $tar = new Tar(); + * $tar->create('myfile.tgz'); + * $tar->addFile(...); + * $tar->addData(...); + * ... + * $tar->close(); + * + * To create a TAR archive directly in memory, create() it, add*() files and then either save() + * or getData() it: + * + * $tar = new Tar(); + * $tar->create(); + * $tar->addFile(...); + * $tar->addData(...); + * ... + * $tar->save('myfile.tgz'); // compresses and saves it + * echo $tar->getArchive(Tar::COMPRESS_GZIP); // compresses and returns it + * + * @author Andreas Gohr + * @author Bouchon (Maxg) + * @license GPL 2 + */ +class Tar { + + const COMPRESS_AUTO = 0; + const COMPRESS_NONE = 1; + const COMPRESS_GZIP = 2; + const COMPRESS_BZIP = 3; + + protected $file = ''; + protected $comptype = Tar::COMPRESS_AUTO; + protected $fh; + protected $memory = ''; + protected $closed = true; + protected $writeaccess = false; + + /** + * Open an existing TAR file for reading + * + * @param string $file + * @param int $comptype + * @throws TarIOException + */ + public function open($file, $comptype = Tar::COMPRESS_AUTO) { + // determine compression + if($comptype == Tar::COMPRESS_AUTO) $comptype = $this->filetype($file); + $this->compressioncheck($comptype); + + $this->comptype = $comptype; + $this->file = $file; + + if($this->comptype === Tar::COMPRESS_GZIP) { + $this->fh = @gzopen($this->file, 'rb'); + } elseif($this->comptype === Tar::COMPRESS_BZIP) { + $this->fh = @bzopen($this->file, 'r'); + } else { + $this->fh = @fopen($this->file, 'rb'); + } + + if(!$this->fh) throw(new TarIOException('Could not open file for reading: '.$this->file)); + $this->closed = false; + } + + /** + * Read the contents of a TAR archive + * + * This function lists the files stored in the archive, and returns an indexed array of associative + * arrays containing for each file the following information: + * + * checksum Tar Checksum of the file + * filename The full name of the stored file (up to 100 c.) + * mode UNIX permissions in DECIMAL, not octal + * uid The Owner ID + * gid The Group ID + * size Uncompressed filesize + * mtime Timestamp of last modification + * typeflag Empty for files, set for folders + * link Is it a symlink? + * uname Owner name + * gname Group name + * + * The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams. + * Reopen the file with open() again if you want to do additional operations + */ + public function contents() { + if($this->closed || !$this->file) throw(new TarIOException('Can not read from a closed archive')); + + $result = Array(); + while($read = $this->readbytes(512)) { + $header = $this->parseHeader($read); + if(!is_array($header)) continue; + + $this->skipbytes(ceil($header['size'] / 512) * 512, 1); + $result[] = $header; + } + + $this->close(); + return $result; + } + + /** + * Extract an existing TAR archive + * + * The $strip parameter allows you to strip a certain number of path components from the filenames + * found in the tar file, similar to the --strip-components feature of GNU tar. This is triggered when + * an integer is passed as $strip. + * Alternatively a fixed string prefix may be passed in $strip. If the filename matches this prefix, + * the prefix will be stripped. It is recommended to give prefixes with a trailing slash. + * + * By default this will extract all files found in the archive. You can restrict the output using the $include + * and $exclude parameter. Both expect a full regular expression (including delimiters and modifiers). If + * $include is set only files that match this expression will be extracted. Files that match the $exclude + * expression will never be extracted. Both parameters can be used in combination. Expressions are matched against + * stripped filenames as described above. + * + * The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams. + * Reopen the file with open() again if you want to do additional operations + * + * @param string $outdir the target directory for extracting + * @param int|string $strip either the number of path components or a fixed prefix to strip + * @param string $exclude a regular expression of files to exclude + * @param string $include a regular expression of files to include + * @throws TarIOException + * @return array + */ + function extract($outdir, $strip='', $exclude='', $include='') { + if($this->closed || !$this->file) throw(new TarIOException('Can not read from a closed archive')); + + $outdir = rtrim($outdir,'/'); + io_mkdir_p($outdir); + $striplen = strlen($strip); + + $extracted = array(); + + while($dat = $this->readbytes(512)) { + // read the file header + $header = $this->parseHeader($dat); + if(!is_array($header)) continue; + if(!$header['filename']) continue; + + // strip prefix + $filename = $this->cleanPath($header['filename']); + if(is_int($strip)) { + // if $strip is an integer we strip this many path components + $parts = explode('/',$filename); + if(!$header['typeflag']){ + $base = array_pop($parts); // keep filename itself + }else{ + $base = ''; + } + $filename = join('/',array_slice($parts,$strip)); + if($base) $filename .= "/$base"; + }else{ + // ifstrip is a string, we strip a prefix here + if(substr($filename,0,$striplen) == $strip) $filename = substr($filename,$striplen); + } + + // check if this should be extracted + $extract = true; + if(!$filename){ + $extract = false; + }else{ + if($include){ + if(preg_match($include, $filename)){ + $extract = true; + }else{ + $extract = false; + } + } + if($exclude && preg_match($exclude, $filename)){ + $extract = false; + } + } + + // Now do the extraction (or not) + if($extract) { + $extracted[] = $header; + + $output = "$outdir/$filename"; + $directory = ($header['typeflag']) ? $output : dirname($output); + io_mkdir_p($directory); + + // is this a file? + if(!$header['typeflag']){ + $fp = @fopen($output, "wb"); + if(!$fp) throw(new TarIOException('Could not open file for writing: '.$output)); + + $size = floor($header['size'] / 512); + for($i = 0; $i < $size; $i++) { + fwrite($fp, $this->readbytes(512), 512); + } + if(($header['size'] % 512) != 0) fwrite($fp, $this->readbytes(512), $header['size'] % 512); + + fclose($fp); + touch($output, $header['mtime']); + chmod($output, $header['perm']); + }else{ + $this->skipbytes(ceil($header['size'] / 512) * 512); // the size is usually 0 for directories + } + }else{ + $this->skipbytes(ceil($header['size'] / 512) * 512); + } + } + + $this->close(); + return $extracted; + } + + /** + * Create a new TAR file + * + * If $file is empty, the tar file will be created in memory + * + * @param string $file + * @param int $comptype + * @param int $complevel + * @throws TarIOException + * @throws TarIllegalCompressionException + */ + public function create($file = '', $comptype = Tar::COMPRESS_AUTO, $complevel = 9) { + // determine compression + if($comptype == Tar::COMPRESS_AUTO) $comptype = $this->filetype($file); + $this->compressioncheck($comptype); + + $this->comptype = $comptype; + $this->file = $file; + $this->memory = ''; + $this->fh = 0; + + if($this->file) { + if($this->comptype === Tar::COMPRESS_GZIP) { + $this->fh = @gzopen($this->file, 'wb'.$complevel); + } elseif($this->comptype === Tar::COMPRESS_BZIP) { + $this->fh = @bzopen($this->file, 'w'); + } else { + $this->fh = @fopen($this->file, 'wb'); + } + + if(!$this->fh) throw(new TarIOException('Could not open file for writing: '.$this->file)); + } + $this->writeaccess = false; + $this->closed = false; + } + + /** + * Add a file to the current TAR archive using an existing file in the filesystem + * + * @todo handle directory adding + * @param string $file the original file + * @param string $name the name to use for the file in the archive + * @throws TarBadFilename + * @throws TarIOException + */ + public function addFile($file, $name = '') { + if($this->closed) throw(new TarIOException('Archive has been closed, files can no longer be added')); + + if(!$name) $name = $file; + $name = $this->cleanPath($name); + + // FIXME ustar should support up 256 chars + if(strlen($name) > 99) throw(new TarBadFilename('Filenames may not exceed 99 bytes: '.$name)); + + $fp = fopen($file, 'rb'); + if(!$fp) throw(new TarIOException('Could not open file for reading: '.$file)); + + // create file header and copy all stat info from the original file + clearstatcache(false, $file); + $stat = stat($file); + $this->writeFileHeader( + $name, + $stat[4], + $stat[5], + fileperms($file), + filesize($file), + filemtime($file), + false + ); + + while(!feof($fp)) { + $packed = pack("a512", fread($fp, 512)); + $this->writebytes($packed); + } + fclose($fp); + } + + /** + * Add a file to the current TAR archive using in memory data + * + * @param $name + * @param $data + * @param int $uid + * @param int $gid + * @param int $perm + * @param int $mtime + * @throws TarIOException + * @throws TarBadFilename + */ + public function addData($name, $data, $uid = 0, $gid = 0, $perm = 0666, $mtime = 0) { + if($this->closed) throw(new TarIOException('Archive has been closed, files can no longer be added')); + + $name = $this->cleanPath($name); + + // FIXME ustar should support up 256 chars + if(strlen($name) > 99) throw(new TarBadFilename('Filenames may not exceed 99 bytes: '.$name)); + + $len = strlen($data); + + $this->writeFileHeader( + $name, + $uid, + $gid, + $perm, + $len, + ($mtime) ? $mtime : time(), + false + ); + + for($s = 0; $s < $len; $s += 512) { + $this->writebytes(pack("a512", substr($data, $s, 512))); + } + } + + /** + * Add the closing footer to the archive if in write mode, close all file handles + * + * After a call to this function no more data can be added to the archive, for + * read access no reading is allowed anymore + * + * "Physically, an archive consists of a series of file entries terminated by an end-of-archive entry, which + * consists of two 512 blocks of zero bytes" + * + * @link http://www.gnu.org/software/tar/manual/html_chapter/tar_8.html#SEC134 + */ + public function close() { + if($this->closed) return; // we did this already + + // write footer + if($this->writeaccess){ + $this->writebytes(pack("a512", "")); + $this->writebytes(pack("a512", "")); + } + + // close file handles + if($this->file){ + if($this->comptype === Tar::COMPRESS_GZIP){ + gzclose($this->fh); + }elseif($this->comptype === Tar::COMPRESS_BZIP){ + bzclose($this->fh); + }else{ + fclose($this->fh); + } + + $this->file = ''; + $this->fh = 0; + } + + $this->closed = true; + } + + /** + * Returns the created in-memory archive data + * + * This implicitly calls close() on the Archive + */ + public function getArchive($comptype = Tar::COMPRESS_AUTO, $complevel = 9) { + $this->close(); + + if($comptype === Tar::COMPRESS_AUTO) $comptype = $this->comptype; + $this->compressioncheck($comptype); + + if($comptype === Tar::COMPRESS_GZIP) return gzcompress($this->memory, $complevel); + if($comptype === Tar::COMPRESS_BZIP) return bzcompress($this->memory); + return $this->memory; + } + + /** + * Save the created in-memory archive data + * + * Note: It more memory effective to specify the filename in the create() function and + * let the library work on the new file directly. + * + * @param $file + * @param int $comptype + * @param int $complevel + * @throws TarIOException + */ + public function save($file, $comptype = Tar::COMPRESS_AUTO, $complevel = 9) { + if($comptype === Tar::COMPRESS_AUTO) $comptype = $this->filetype($file); + + if(!file_put_contents($file, $this->getArchive($comptype, $complevel))) { + throw(new TarIOException('Could not write to file: '.$file)); + } + } + + /** + * Read from the open file pointer + * + * @param int $length bytes to read + * @return string + */ + protected function readbytes($length) { + if($this->comptype === Tar::COMPRESS_GZIP) { + return @gzread($this->fh, $length); + } elseif($this->comptype === Tar::COMPRESS_BZIP) { + return @bzread($this->fh, $length); + } else { + return @fread($this->fh, $length); + } + } + + /** + * Write to the open filepointer or memory + * + * @param string $data + * @throws TarIOException + * @return int number of bytes written + */ + protected function writebytes($data) { + if(!$this->file) { + $this->memory .= $data; + $written = strlen($data); + } elseif($this->comptype === Tar::COMPRESS_GZIP) { + $written = @gzwrite($this->fh, $data); + } elseif($this->comptype === Tar::COMPRESS_BZIP) { + $written = @bzwrite($this->fh, $data); + } else { + $written = @fwrite($this->fh, $data); + } + if($written === false) throw(new TarIOException('Failed to write to archive stream')); + return $written; + } + + /** + * Skip forward in the open file pointer + * + * This is basically a wrapper around seek() (and a workarounf for bzip2) + * + * @param int $bytes seek to this position + */ + function skipbytes($bytes) { + if($this->comptype === Tar::COMPRESS_GZIP){ + @gzseek($this->fh, $bytes, SEEK_CUR); + }elseif($this->comptype === Tar::COMPRESS_BZIP){ + // there is no seek in bzip2, we simply read on + @bzread($this->fh, $bytes); + }else{ + @fseek($this->fh, $bytes, SEEK_CUR); + } + } + + /** + * Write a file header + * + * @param string $name + * @param int $uid + * @param int $gid + * @param int $perm + * @param int $size + * @param int $mtime + * @param bool $isdir + */ + protected function writeFileHeader($name, $uid, $gid, $perm, $size, $mtime, $isdir = false) { + // values are needed in octal + $uid = sprintf("%6s ", DecOct($uid)); + $gid = sprintf("%6s ", DecOct($gid)); + $perm = sprintf("%6s ", DecOct($perm)); + $size = sprintf("%11s ", DecOct($size)); + $mtime = sprintf("%11s", DecOct($mtime)); + $dir = ($isdir) ? '5' : ''; + + $data_first = pack("a100a8a8a8a12A12", $name, $perm, $uid, $gid, $size, $mtime); + $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $dir, '', '', '', '', '', '', '', '', ""); + + for($i = 0, $chks = 0; $i < 148; $i++) + $chks += ord($data_first[$i]); + + for($i = 156, $chks += 256, $j = 0; $i < 512; $i++, $j++) + $chks += ord($data_last[$j]); + + $this->writebytes($data_first); + + $chks = pack("a8", sprintf("%6s ", DecOct($chks))); + $this->writebytes($chks.$data_last); + } + + /** + * Decode the given tar file header + * + * @todo how to handle filenames >100 chars? + * @param string $block a 512 byte block containign the header data + * @return array|bool + */ + protected function parseHeader($block) { + if(!$block || strlen($block) != 512) return false; + + for($i = 0, $chks = 0; $i < 148; $i++) + $chks += ord($block[$i]); + + for($i = 156, $chks += 256; $i < 512; $i++) + $chks += ord($block[$i]); + + $headers = @unpack("a100filename/a8perm/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $block); + if(!$headers) return false; + + $return['checksum'] = OctDec(trim($headers['checksum'])); + if($return['checksum'] != $chks) return false; + + $return['filename'] = trim($headers['filename']); + $return['perm'] = OctDec(trim($headers['perm'])); + $return['uid'] = OctDec(trim($headers['uid'])); + $return['gid'] = OctDec(trim($headers['gid'])); + $return['size'] = OctDec(trim($headers['size'])); + $return['mtime'] = OctDec(trim($headers['mtime'])); + $return['typeflag'] = $headers['typeflag']; + $return['link'] = trim($headers['link']); + $return['uname'] = trim($headers['uname']); + $return['gname'] = trim($headers['gname']); + + return $return; + } + + /** + * Cleans up a path and removes relative parts + * + * @param string $p_dir + * @return string + */ + protected function cleanPath($p_dir) { + $r = ''; + if($p_dir) { + $subf = explode("/", $p_dir); + + for($i = count($subf) - 1; $i >= 0; $i--) { + if($subf[$i] == ".") { + # do nothing + } elseif($subf[$i] == "..") { + $i--; + } elseif(!$subf[$i] && $i != count($subf) - 1 && $i) { + # do nothing + } else { + $r = $subf[$i].($i != (count($subf) - 1) ? "/".$r : ""); + } + } + } + return $r; + } + + /** + * Checks if the given compression type is available and throws an exception if not + * + * @param $comptype + * @throws TarIllegalCompressionException + */ + protected function compressioncheck($comptype) { + if($comptype === Tar::COMPRESS_GZIP && !function_exists('gzopen')) { + throw(new TarIllegalCompressionException('No gzip support available')); + } + + if($comptype === Tar::COMPRESS_BZIP && !function_exists('bzopen')) { + throw(new TarIllegalCompressionException('No bzip2 support available')); + } + } + + /** + * Guesses the wanted compression from the given filename extension + * + * You don't need to call this yourself. It's used when you pass Tar::COMPRESS_AUTO somewhere + * + * @param string $file + * @return int + */ + public function filetype($file) { + $file = strtolower($file); + if(substr($file, -3) == '.gz' || substr($file, -4) == '.tgz') { + $comptype = Tar::COMPRESS_GZIP; + } elseif(substr($file, -4) == '.bz2' || substr($file, -4) == '.tbz') { + $comptype = Tar::COMPRESS_BZIP; + } else { + $comptype = Tar::COMPRESS_NONE; + } + return $comptype; + } +} + +class TarBadFilename extends Exception { +} + +class TarIOException extends Exception { +} + +class TarIllegalCompressionException extends Exception { +} \ No newline at end of file diff --git a/inc/load.php b/inc/load.php index b8a279523..49c307054 100644 --- a/inc/load.php +++ b/inc/load.php @@ -71,6 +71,7 @@ function load_autoload($name){ 'IXR_IntrospectionServer' => DOKU_INC.'inc/IXR_Library.php', 'Doku_Plugin_Controller'=> DOKU_INC.'inc/plugincontroller.class.php', 'GeSHi' => DOKU_INC.'inc/geshi.php', + 'Tar' => DOKU_INC.'inc/Tar.class.php', 'TarLib' => DOKU_INC.'inc/TarLib.class.php', 'ZipLib' => DOKU_INC.'inc/ZipLib.class.php', 'DokuWikiFeedCreator' => DOKU_INC.'inc/feedcreator.class.php', -- cgit v1.2.3 From 7252880f21c842017c334eb15c6a7a174f950798 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 3 Nov 2012 18:30:52 +0100 Subject: added test cases for Tar::extract parameters --- _test/tests/inc/tar.test.php | 103 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/_test/tests/inc/tar.test.php b/_test/tests/inc/tar.test.php index 706516d9e..4de9e668d 100644 --- a/_test/tests/inc/tar.test.php +++ b/_test/tests/inc/tar.test.php @@ -113,9 +113,112 @@ class Tar_TestCase extends DokuWikiTest { TestUtils::rdelete($out); } + } + + /** + * Extract the prebuilt tar files with component stripping + */ + public function test_compstripextract(){ + $dir = dirname(__FILE__).'/tar'; + $out = sys_get_temp_dir().'/dwtartest'.md5(time()); + + foreach(array('tar', 'tgz', 'tbz') as $ext){ + $tar = new Tar(); + $file = "$dir/test.$ext"; + + $tar->open($file); + $tar->extract($out,1); + + clearstatcache(); + + $this->assertFileExists($out.'/testdata1.txt', "Extracted $file"); + $this->assertEquals(13, filesize($out.'/testdata1.txt'), "Extracted $file"); + + $this->assertFileExists($out.'/foobar/testdata2.txt', "Extracted $file"); + $this->assertEquals(13, filesize($out.'/foobar/testdata2.txt'), "Extracted $file"); + + TestUtils::rdelete($out); + } + } + + /** + * Extract the prebuilt tar files with prefix stripping + */ + public function test_prefixstripextract(){ + $dir = dirname(__FILE__).'/tar'; + $out = sys_get_temp_dir().'/dwtartest'.md5(time()); + foreach(array('tar', 'tgz', 'tbz') as $ext){ + $tar = new Tar(); + $file = "$dir/test.$ext"; + + $tar->open($file); + $tar->extract($out,'tar/foobar/'); + + clearstatcache(); + + $this->assertFileExists($out.'/tar/testdata1.txt', "Extracted $file"); + $this->assertEquals(13, filesize($out.'/tar/testdata1.txt'), "Extracted $file"); + + $this->assertFileExists($out.'/testdata2.txt', "Extracted $file"); + $this->assertEquals(13, filesize($out.'/testdata2.txt'), "Extracted $file"); + + TestUtils::rdelete($out); + } } + /** + * Extract the prebuilt tar files with include regex + */ + public function test_includeextract(){ + $dir = dirname(__FILE__).'/tar'; + $out = sys_get_temp_dir().'/dwtartest'.md5(time()); + + foreach(array('tar', 'tgz', 'tbz') as $ext){ + $tar = new Tar(); + $file = "$dir/test.$ext"; + + $tar->open($file); + $tar->extract($out,'','','/\/foobar\//'); + + clearstatcache(); + + $this->assertFileNotExists($out.'/tar/testdata1.txt', "Extracted $file"); + + + $this->assertFileExists($out.'/tar/foobar/testdata2.txt', "Extracted $file"); + $this->assertEquals(13, filesize($out.'/tar/foobar/testdata2.txt'), "Extracted $file"); + + TestUtils::rdelete($out); + } + } + + /** + * Extract the prebuilt tar files with exclude regex + */ + public function test_excludeextract(){ + $dir = dirname(__FILE__).'/tar'; + $out = sys_get_temp_dir().'/dwtartest'.md5(time()); + + foreach(array('tar', 'tgz', 'tbz') as $ext){ + $tar = new Tar(); + $file = "$dir/test.$ext"; + + $tar->open($file); + $tar->extract($out,'','/\/foobar\//'); + + clearstatcache(); + + $this->assertFileExists($out.'/tar/testdata1.txt', "Extracted $file"); + $this->assertEquals(13, filesize($out.'/tar/testdata1.txt'), "Extracted $file"); + + $this->assertFileNotExists($out.'/tar/foobar/testdata2.txt', "Extracted $file"); + + TestUtils::rdelete($out); + } + } + + /** * Check the extension to compression guesser */ -- cgit v1.2.3 From fba11f64c26a8dde5f64c57233b0da84fae35959 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 3 Nov 2012 18:42:57 +0100 Subject: removed old TarLib and changed plugin manager to use new one --- inc/TarLib.class.php | 921 ----------------------- inc/load.php | 1 - lib/plugins/plugin/classes/ap_download.class.php | 25 +- 3 files changed, 10 insertions(+), 937 deletions(-) delete mode 100644 inc/TarLib.class.php diff --git a/inc/TarLib.class.php b/inc/TarLib.class.php deleted file mode 100644 index e04c47cb8..000000000 --- a/inc/TarLib.class.php +++ /dev/null @@ -1,921 +0,0 @@ - (Maxg) - * @author Christopher Smith - */ - -/** - * Those constants represent the compression method to use. - * COMPRESS_GZIP is used for the GZIP compression; COMPRESS_BZIP for - * BZIP2 and COMPRESS_NONE for no compression. - * - * On the other hand, COMPRESS_AUTO is a bit harder. It will first check - * if the zlib extensions are loaded. - * If it is, GZIP will be used. Else it will check if the bz2 extensions - * are loaded. If it is, BZIP2 will be used. Else no compression will be - * performed. - * - * You can then use getCompression() to know the compression chosen. - * - * If you selected a compression which can't be used (i.e extension not - * present), it will be just disabled, and won't produce any error ! - * As a consequence, getCompression() will return COMPRESS_NONE - * - * ARCHIVE_DYNAMIC can be passed as the first argument of the constructor, to - * create an archive in memory instead of a file. See also: MaxgTar(), - * getDynamicArchive() and writeArchive() - * - * ARCHIVE_RENAMECOMP is a flag that can be multiplied by the compression method - * (i.e COMPRESS_AUTO * ARCHIVE_RENAMECOMP). This will add the correct extension - * to the archive name, which is useful with COMPRESS_AUTO, ie .bz2 if you gave - * COMPRESS_BZIP. See also getCompression(TRUE) which does exactly the - * same - * - * COMPRESS_DETECT does exactly the opposite and try to detect the - * compression to use to read the archive depending on its extension. (i.e if - * the archive ends with .tar.gz TarLib will try to decompress it with - * GZIP). See also setCompression() - * - * FULL_ARCHIVE is a -1 constant that means "the complete archive" when - * extracting. This is explained in Extract() - */ -#define('COMPRESS_GZIP',1); -#define('COMPRESS_BZIP',2); -#define('COMPRESS_AUTO',3); -#define('COMPRESS_NONE',0); -#define('TARLIB_VERSION','1.2'); -#define('FULL_ARCHIVE',-1); -#define('ARCHIVE_DYNAMIC',0); -#define('ARCHIVE_RENAMECOMP',5); -#define('COMPRESS_DETECT',-1); - -class TarLib { - var $_comptype; - var $_compzlevel; - var $_fp; - var $_memdat; - var $_nomf; - var $_result; - var $_initerror; - - const COMPRESS_GZIP = 1; - const COMPRESS_BZIP = 2; - const COMPRESS_AUTO = 3; - const COMPRESS_NONE = 0; - const TARLIB_VERSION = '1.2'; - const FULL_ARCHIVE = -1; - const ARCHIVE_DYNAMIC = 0; - const ARCHIVE_RENAMECOMP = 5; - const COMPRESS_DETECT = -1; - - /** - * constructor, initialize the class - * - * The constructor initialize the variables and prepare the class for the - * archive, and return the object created. Note that you can use multiple - * instances of the MaxgTar class, if you call this function another time and - * store the object in an other variable. - * - * In fact, MaxgTar accepts the following arguments (all are optional) : - * - * filename can be either a file name (absolute or relative). In this - * case, it can be used both for reading and writing. You can also open - * remote archive if you add a protocole name at the beginning of the file - * (ie https://host.dom/archive.tar.gz), but for reading only and if the - * directive allow_url_fopen is enabled in PHP.INI (this can be checked with - * TarInfo()). If you pass a file that doesn't exist, the script - * will try to create it. If the archive already exists and contains files, - * you can use Add() to append files.But by default this parameter - * is ARCHIVE_DYNAMIC (write only) so the archive is created in memory and - * can be sent to a file [writeArchive()] or to the client - * [sendClient()] - * - * compression_type should be a constant that represents a type of - * compression, or its integer value. The different values are described in - * the constants. - * - * compression_level is an integer between 1 and 9 (by default) an - * represent the GZIP or BZIP compression level. 1 produce fast compression, - * and 9 produce smaller files. See the RFC 1952 for more infos. - */ - function __construct($p_filen = TarLib::ARCHIVE_DYNAMIC, $p_comptype = TarLib::COMPRESS_AUTO, $p_complevel = 9) { - $this->_initerror = 0; - $this->_nomf = $p_filen; - $flag = 0; - if($p_comptype && $p_comptype % 5 == 0) { - $p_comptype /= TarLib::ARCHIVE_RENAMECOMP; - $flag = 1; - } - - if($p_complevel > 0 && $p_complevel <= 9) $this->_compzlevel = $p_complevel; - else $this->_compzlevel = 9; - - if($p_comptype == TarLib::COMPRESS_DETECT) { - if(strtolower(substr($p_filen, -3)) == '.gz') $p_comptype = TarLib::COMPRESS_GZIP; - elseif(strtolower(substr($p_filen, -4)) == '.bz2') $p_comptype = TarLib::COMPRESS_BZIP; - else $p_comptype = TarLib::COMPRESS_NONE; - } - - switch($p_comptype) { - case TarLib::COMPRESS_GZIP: - if(!extension_loaded('zlib')) $this->_initerror = -1; - $this->_comptype = TarLib::COMPRESS_GZIP; - break; - - case TarLib::COMPRESS_BZIP: - if(!extension_loaded('bz2')) $this->_initerror = -2; - $this->_comptype = TarLib::COMPRESS_BZIP; - break; - - case TarLib::COMPRESS_AUTO: - if(extension_loaded('zlib')) - $this->_comptype = TarLib::COMPRESS_GZIP; - elseif(extension_loaded('bz2')) - $this->_comptype = TarLib::COMPRESS_BZIP; - else - $this->_comptype = TarLib::COMPRESS_NONE; - break; - - default: - $this->_comptype = TarLib::COMPRESS_NONE; - } - - if($this->_initerror < 0) $this->_comptype = TarLib::COMPRESS_NONE; - - if($flag) $this->_nomf .= '.'.$this->getCompression(1); - $this->_result = true; - } - - /** - * Recycle a TAR object. - * - * This function does exactly the same as TarLib (constructor), except it - * returns a status code. - */ - function setArchive($p_name = '', $p_comp = TarLib::COMPRESS_AUTO, $p_level = 9) { - $this->_CompTar(); - $this->__construct($p_name, $p_comp, $p_level); - return $this->_result; - } - - /** - * Get the compression used to generate the archive - * - * This is a very useful function when you're using dynamical archives. - * Besides, if you let the script chose which compression to use, you'll have - * a problem when you'll want to send it to the client if you don't know - * which compression was used. - * - * There are two ways to call this function : if you call it without argument - * or with FALSE, it will return the compression constants, explained on the - * MaxgTar Constants. If you call it with GetExtension on TRUE it will - * return the extension without starting dot (ie "tar" or "tar.bz2" or - * "tar.gz") - * - * NOTE: This can be done with the flag ARCHIVE_RENAMECOMP, see the - * MaxgTar Constants - */ - function getCompression($ext = false) { - $exts = Array('tar', 'tar.gz', 'tar.bz2'); - if($ext) return $exts[$this->_comptype]; - return $this->_comptype; - } - - /** - * Change the compression mode. - * - * This function will change the compression methode to read or write - * the archive. See the MaxgTar Constants to see which constants you can use. - * It may look strange, but it returns the GZIP compression level. - */ - function setCompression($p_comp = TarLib::COMPRESS_AUTO) { - $this->setArchive($this->_nomf, $p_comp, $this->_compzlevel); - return $this->_compzlevel; - } - - /** - * Returns the compressed dynamic archive. - * - * When you're working with dynamic archives, use this function to grab - * the final compressed archive in a string ready to be put in a SQL table or - * in a file. - */ - function getDynamicArchive() { - return $this->_encode($this->_memdat); - } - - /** - * Write a dynamical archive into a file - * - * This function attempts to write a dynamicaly-genrated archive into - * TargetFile on the webserver. It returns a TarErrorStr() status - * code. - * - * To know the extension to add to the file if you're using AUTO_DETECT - * compression, you can use getCompression(). - */ - function writeArchive($p_archive) { - if(!$this->_memdat) return -7; - $fp = @fopen($p_archive, 'wb'); - if(!$fp) return -6; - - fwrite($fp, $this->_memdat); - fclose($fp); - - return true; - } - - /** - * Send a TAR archive to the client browser. - * - * This function will send an archive to the client, and return a status - * code, but can behave differently depending on the arguments you give. All - * arguments are optional. - * - * ClientName is used to specify the archive name to give to the browser. If - * you don't give one, it will send the constructor filename or return an - * error code in case of dynamical archive. - * - * FileName is optional and used to send a specific archive. Leave it blank - * to send dynamical archives or the current working archive. - * - * If SendHeaders is enabled (by default), the library will send the HTTP - * headers itself before it sends the contents. This headers are : - * Content-Type, Content-Disposition, Content-Length and Accept-Range. - * - * Please note that this function DOES NOT stops the script so don't forget - * to exit() to avoid your script sending other data and corrupt the archive. - * Another note : for AUTO_DETECT dynamical archives you can know the - * extension to add to the name with getCompression() - */ - function sendClient($name = '', $archive = '', $headers = true) { - if(!$name && !$this->_nomf) return -9; - if(!$archive && !$this->_memdat) return -10; - if(!$name) $name = utf8_basename($this->_nomf); - - if($archive) { - if(!file_exists($archive)) return -11; - } - $decoded = $this->getDynamicArchive(); - - if($headers) { - header('Content-Type: application/x-gtar'); - header('Content-Disposition: attachment; filename='.utf8_basename($name)); - header('Accept-Ranges: bytes'); - header('Content-Length: '.($archive ? filesize($archive) : strlen($decoded))); - } - - if($archive) { - $fp = @fopen($archive, 'rb'); - if(!$fp) return -4; - - while(!feof($fp)) echo fread($fp, 2048); - } else { - echo $decoded; - } - - return true; - } - - /** - * Extract part or totality of the archive. - * - * This function can extract files from an archive, and returns then a - * status codes that can be converted with TarErrorStr() into a - * human readable message. - * - * Only the first argument is required, What and it can be either the - * constant FULL_ARCHIVE or an indexed array containing each file you want to - * extract. - * - * To contains the target folder to extract the archive. It is optional and - * the default value is '.' which means the current folder. If the target - * folder doesn't exist, the script attempts to create it and give it - * permissions 0777 by default. - * - * RemovePath is very usefull when you want to extract files from a subfoler - * in the archive to a root folder. For instance, if you have a file in the - * archive called some/sub/folder/test.txt and you want to extract it to the - * script folder, you can call Extract with To = '.' and RemovePath = - * 'some/sub/folder/' - * - * FileMode is optional and its default value is 0755. It is in fact the UNIX - * permission in octal mode (prefixed with a 0) that will be given on each - * extracted file. - */ - function Extract($p_what = TarLib::FULL_ARCHIVE, $p_to = '.', $p_remdir = '', $p_mode = 0755) { - if(!$this->_OpenRead()) return -4; - // if(!@is_dir($p_to)) if(!@mkdir($p_to, 0777)) return -8; --CS - if(!@is_dir($p_to)) if(!$this->_dirApp($p_to)) return -8; //--CS (route through correct dir fn) - - $ok = $this->_extractList($p_to, $p_what, $p_remdir, $p_mode); - $this->_CompTar(); - - return $ok; - } - - /** - * Create a new package with the given files - * - * This function will attempt to create a new archive with global headers - * then add the given files into. If the archive is a real file, the - * contents are written directly into the file. If it is a dynamic archive, - * contents are only stored in memory. This function should not be used to - * add files to an existing archive, you should use Add() instead. - * - * The FileList actually supports three different modes: - * - * - You can pass a string containing filenames separated by pipes '|'. - * In this case thes file are read from the filesystem and the root folder - * is the folder running script located. NOT RECOMMENDED - * - * - You can also give an indexed array containing the filenames. The - * behaviour for the content reading is the same as above. - * - * - You can pass an array of arrays. For each file use an array where the - * first element contains the filename and the second contains the file - * contents. You can even add empty folders to the package if the filename - * has a leading '/'. Once again, have a look at the exemples to understand - * better. - * - * Note you can also give arrays with both dynamic contents and static files. - * - * The optional parameter RemovePath can be used to delete a part of the tree - * of the filename you're adding, for instance if you're adding in the root - * of a package a file that is stored somewhere in the server tree. - * - * On the contrary the parameter AddPath can be used to add a prefix folder - * to the file you store. Note also that the RemovePath is applied before the - * AddPath is added, so it HAS a sense to use both parameters together. - */ - function Create($p_filelist, $p_add = '', $p_rem = '') { - if(!$fl = $this->_fetchFilelist($p_filelist)) return -5; - if(!$this->_OpenWrite()) return -6; - - $ok = $this->_addFileList($fl, $p_add, $p_rem); - - if($ok) { - $this->_writeFooter(); - } else { - $this->_CompTar(); - @unlink($this->_nomf); - } - - return $ok; - } - - /** - * Add files to an existing package. - * - * This function does exactly the same as Create() exept it - * will append the given files at the end of the archive. - * - * Note: This is only supported for dynamic in memory files and uncompressed - * tar files - * - * This function returns a status code, you can use TarErrorStr() on - * it to get the human-readable description of the error. - */ - function Add($p_filelist, $p_add = '', $p_rem = '') { - if($this->_nomf !== TarLib::ARCHIVE_DYNAMIC && - $this->_comptype !== TarLib::COMPRESS_NONE - ) { - return -12; - } - - if(($this->_nomf !== TarLib::ARCHIVE_DYNAMIC && !$this->_fp) || - ($this->_nomf === TarLib::ARCHIVE_DYNAMIC && !$this->_memdat) - ) { - return $this->Create($p_filelist, $p_add, $p_rem); - } - - if(!$fl = $this->_fetchFilelist($p_filelist)) return -5; - return $this->_append($fl, $p_add, $p_rem); - } - - /** - * Read the contents of a TAR archive - * - * This function attempts to get the list of the files stored in the - * archive, and return either an error code or an indexed array of - * associative array containing for each file the following information : - * - * checksum Tar Checksum of the file - * filename The full name of the stored file (up to 100 c.) - * mode UNIX permissions in DECIMAL, not octal - * uid The Owner ID - * gid The Group ID - * size Uncompressed filesize - * mtime Timestamp of last modification - * typeflag Empty for files, set for folders - * link For the links, did you guess it ? - * uname Owner name - * gname Group name - */ - function ListContents() { - if(!$this->_nomf) return -3; - if(!$this->_OpenRead()) return -4; - - $result = Array(); - - while($dat = $this->_read(512)) { - $dat = $this->_readHeader($dat); - if(!is_array($dat)) continue; - - $this->_seek(ceil($dat['size'] / 512) * 512, 1); - $result[] = $dat; - } - - return $result; - } - - /** - * Convert a status code into a human readable message - * - * Some MaxgTar functions like Create(), Add() ... return numerical - * status code. You can pass them to this function to grab their english - * equivalent. - */ - function TarErrorStr($i) { - $ecodes = Array( - 1 => true, - 0 => "Undocumented error", - -1 => "Can't use COMPRESS_GZIP compression : ZLIB extensions are not loaded !", - -2 => "Can't use COMPRESS_BZIP compression : BZ2 extensions are not loaded !", - -3 => "You must set a archive file to read the contents !", - -4 => "Can't open the archive file for read !", - -5 => "Invalide file list !", - -6 => "Can't open the archive in write mode !", - -7 => "There is no ARCHIVE_DYNAMIC to write !", - -8 => "Can't create the directory to extract files !", - -9 => "Please pass a archive name to send if you made created an ARCHIVE_DYNAMIC !", - -10 => "You didn't pass an archive filename and there is no stored ARCHIVE_DYNAMIC !", - -11 => "Given archive doesn't exist !", - -12 => "Appending not supported for compressed files" - ); - - return isset($ecodes[$i]) ? $ecodes[$i] : $ecodes[0]; - } - - /** - * Seek in the data stream - * - * @todo probably broken for bzip tars - * @param int $p_flen seek to this position - * @param bool $tell seek from current position? - */ - function _seek($p_flen, $tell = false) { - if($this->_nomf === TarLib::ARCHIVE_DYNAMIC) - $this->_memdat = substr($this->_memdat, 0, ($tell ? strlen($this->_memdat) : 0) + $p_flen); - elseif($this->_comptype == TarLib::COMPRESS_GZIP) - @gzseek($this->_fp, ($tell ? @gztell($this->_fp) : 0) + $p_flen); - elseif($this->_comptype == TarLib::COMPRESS_BZIP) - @fseek($this->_fp, ($tell ? @ftell($this->_fp) : 0) + $p_flen); - else - @fseek($this->_fp, ($tell ? @ftell($this->_fp) : 0) + $p_flen); - } - - /** - * Open the archive for reading - * - * @return bool true if succesfull - */ - function _OpenRead() { - if($this->_comptype == TarLib::COMPRESS_GZIP) - $this->_fp = @gzopen($this->_nomf, 'rb'); - elseif($this->_comptype == TarLib::COMPRESS_BZIP) - $this->_fp = @bzopen($this->_nomf, 'rb'); - else - $this->_fp = @fopen($this->_nomf, 'rb'); - - return ($this->_fp ? true : false); - } - - /** - * Open the archive for writing - * - * @param string $add filemode - * @return bool true on success - */ - function _OpenWrite($add = 'w') { - if($this->_nomf === TarLib::ARCHIVE_DYNAMIC) return true; - - if($this->_comptype == TarLib::COMPRESS_GZIP) - $this->_fp = @gzopen($this->_nomf, $add.'b'.$this->_compzlevel); - elseif($this->_comptype == TarLib::COMPRESS_BZIP) - $this->_fp = @bzopen($this->_nomf, $add.'b'); - else - $this->_fp = @fopen($this->_nomf, $add.'b'); - - return ($this->_fp ? true : false); - } - - /** - * Closes the open file pointer - */ - function _CompTar() { - if($this->_nomf === TarLib::ARCHIVE_DYNAMIC || !$this->_fp) return; - - if($this->_comptype == TarLib::COMPRESS_GZIP) @gzclose($this->_fp); - elseif($this->_comptype == TarLib::COMPRESS_BZIP) @bzclose($this->_fp); - else @fclose($this->_fp); - } - - /** - * Read from the open file pointer - * - * @param int $p_len bytes to read - * @return string - */ - function _read($p_len) { - if($this->_comptype == TarLib::COMPRESS_GZIP) - return @gzread($this->_fp, $p_len); - elseif($this->_comptype == TarLib::COMPRESS_BZIP) - return @bzread($this->_fp, $p_len); - else - return @fread($this->_fp, $p_len); - } - - /** - * Write to the open filepointer or memory - * - * @param string $p_data - * @return int - */ - function _write($p_data) { - if($this->_nomf === TarLib::ARCHIVE_DYNAMIC) { - $this->_memdat .= $p_data; - return strlen($p_data); - } elseif($this->_comptype == TarLib::COMPRESS_GZIP) { - return @gzwrite($this->_fp, $p_data); - } elseif($this->_comptype == TarLib::COMPRESS_BZIP) { - return @bzwrite($this->_fp, $p_data); - } else { - return @fwrite($this->_fp, $p_data); - } - } - - /** - * Compress given data according to the set compression method - * - * @param $p_dat - * @return string - */ - function _encode($p_dat) { - if($this->_comptype == TarLib::COMPRESS_GZIP) - return gzencode($p_dat, $this->_compzlevel); - elseif($this->_comptype == TarLib::COMPRESS_BZIP) - return bzcompress($p_dat, $this->_compzlevel); - else return $p_dat; - } - - /** - * Decode the given tar file header - * - * @param $p_dat - * @return array|bool - */ - function _readHeader($p_dat) { - if(!$p_dat || strlen($p_dat) != 512) return false; - - for($i = 0, $chks = 0; $i < 148; $i++) - $chks += ord($p_dat[$i]); - - for($i = 156, $chks += 256; $i < 512; $i++) - $chks += ord($p_dat[$i]); - - $headers = @unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $p_dat); - if(!$headers) return false; - - $return['checksum'] = OctDec(trim($headers['checksum'])); - if($return['checksum'] != $chks) return false; - - $return['filename'] = trim($headers['filename']); - $return['mode'] = OctDec(trim($headers['mode'])); - $return['uid'] = OctDec(trim($headers['uid'])); - $return['gid'] = OctDec(trim($headers['gid'])); - $return['size'] = OctDec(trim($headers['size'])); - $return['mtime'] = OctDec(trim($headers['mtime'])); - $return['typeflag'] = $headers['typeflag']; - $return['link'] = trim($headers['link']); - $return['uname'] = trim($headers['uname']); - $return['gname'] = trim($headers['gname']); - - return $return; - } - - /** - * Builds a normalized file list - * - * @todo remove string support, use saner format - * - * @param $p_filelist - * @return array|bool - */ - function _fetchFilelist($p_filelist) { - if(!$p_filelist || (is_array($p_filelist) && !@count($p_filelist))) return false; - - if(is_string($p_filelist)) { - $p_filelist = explode('|', $p_filelist); - if(!is_array($p_filelist)) $p_filelist = Array($p_filelist); - } - - return $p_filelist; - } - - /** - * Adds files given as file list - * - * @param array $p_fl - * @param string $p_addir - * @param string $p_remdir - * @return bool - */ - function _addFileList($p_fl, $p_addir, $p_remdir) { - foreach($p_fl as $file) { - if(($file == $this->_nomf && $this->_nomf !== TarLib::ARCHIVE_DYNAMIC) || !$file || (!is_array($file) && !file_exists($file))) - continue; - - if(!$this->_addFile($file, $p_addir, $p_remdir)) - continue; - - if(@is_dir($file)) { - $d = @opendir($file); - - if(!$d) continue; - readdir($d); - readdir($d); - - while($f = readdir($d)) { - if($file != ".") $tmplist[0] = "$file/$f"; - else $tmplist[0] = $d; - - $this->_addFileList($tmplist, $p_addir, $p_remdir); - } - - closedir($d); - unset($tmplist, $f); - } - } - return true; - } - - /** - * Adds a single file - * - * @param array|string $p_fn - * @param string $p_addir - * @param string $p_remdir - * @return bool - */ - function _addFile($p_fn, $p_addir = '', $p_remdir = '') { - $data = false; - if(is_array($p_fn)) list($p_fn, $data) = $p_fn; - $sname = $p_fn; - - if($p_remdir) { - if(substr($p_remdir, -1) != '/') $p_remdir .= "/"; - - if(substr($sname, 0, strlen($p_remdir)) == $p_remdir) - $sname = substr($sname, strlen($p_remdir)); - } - - if($p_addir) $sname = $p_addir.(substr($p_addir, -1) == '/' ? '' : "/").$sname; - - // FIXME ustar should support up 256 chars - if(strlen($sname) > 99) return false; - - if(@is_dir($p_fn)) { - if(!$this->_writeFileHeader($p_fn, $sname)) return false; - } else { - if(!$data) { - $fp = fopen($p_fn, 'rb'); - if(!$fp) return false; - } - - if(!$this->_writeFileHeader($p_fn, $sname, ($data ? strlen($data) : false))) return false; - - if(!$data) { - while(!feof($fp)) { - $packed = pack("a512", fread($fp, 512)); - $this->_write($packed); - } - fclose($fp); - } else { - $len = strlen($data); - for($s = 0; $s < $len; $s += 512) { - $this->_write(pack("a512", substr($data, $s, 512))); - } - } - } - - return true; - } - - /** - * Write the header for a file in the TAR archive - * - * @param string $p_file - * @param string $p_sname - * @param bool $p_data - * @return bool - */ - function _writeFileHeader($p_file, $p_sname, $p_data = false) { - if(!$p_data) { - if(!$p_sname) $p_sname = $p_file; - $p_sname = $this->_pathTrans($p_sname); - - $h_info = stat($p_file); - $h[0] = sprintf("%6s ", DecOct($h_info[4])); - $h[] = sprintf("%6s ", DecOct($h_info[5])); - $h[] = sprintf("%6s ", DecOct(fileperms($p_file))); - clearstatcache(); - $h[] = sprintf("%11s ", DecOct(filesize($p_file))); - $h[] = sprintf("%11s", DecOct(filemtime($p_file))); - - $dir = @is_dir($p_file) ? '5' : ''; - } else { - $dir = ''; - $p_data = sprintf("%11s ", DecOct($p_data)); - $time = sprintf("%11s ", DecOct(time())); - $h = Array(" 0 ", " 0 ", " 40777 ", $p_data, $time); - } - - $data_first = pack("a100a8a8a8a12A12", $p_sname, $h[2], $h[0], $h[1], $h[3], $h[4]); - $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $dir, '', '', '', '', '', '', '', '', ""); - - for($i = 0, $chks = 0; $i < 148; $i++) - $chks += ord($data_first[$i]); - - for($i = 156, $chks += 256, $j = 0; $i < 512; $i++, $j++) - $chks += ord($data_last[$j]); - - $this->_write($data_first); - - $chks = pack("a8", sprintf("%6s ", DecOct($chks))); - $this->_write($chks.$data_last); - - return true; - } - - /** - * Append the given files to the already open archive - * - * @param array $p_filelist - * @param string $p_addir - * @param string $p_remdir - * @return bool|int - */ - function _append($p_filelist, $p_addir = "", $p_remdir = "") { - if(!$this->_fp) if(!$this->_OpenWrite('a')) return -6; - - if($this->_nomf === TarLib::ARCHIVE_DYNAMIC) { - $this->_memdat = substr($this->_memdat, 0, -512 * 2); // remove footer - } else { - clearstatcache(); - $s = filesize($this->_nomf); - - $this->_seek($s - (512 * 2)); // remove footer - } - - $ok = $this->_addFileList($p_filelist, $p_addir, $p_remdir); - $this->_writeFooter(); - - return $ok; - } - - /** - * Cleans up a path and removes relative parts - * - * @param string $p_dir - * @return string - */ - function _pathTrans($p_dir) { - $r = ''; - if($p_dir) { - $subf = explode("/", $p_dir); - - for($i = count($subf) - 1; $i >= 0; $i--) { - if($subf[$i] == ".") { - # do nothing - } elseif($subf[$i] == "..") { - $i--; - } elseif(!$subf[$i] && $i != count($subf) - 1 && $i) { - # do nothing - } else { - $r = $subf[$i].($i != (count($subf) - 1) ? "/".$r : ""); - } - } - } - return $r; - } - - /** - * Add the closing footer to the archive - * - * Physically, an archive consists of a series of file entries terminated by an end-of-archive entry, which - * consists of two 512 blocks of zero bytes - * - * @link http://www.gnu.org/software/tar/manual/html_chapter/tar_8.html#SEC134 - */ - function _writeFooter() { - $this->_write(pack("a512", "")); - $this->_write(pack("a512", "")); - } - - /** - * @param $p_to - * @param $p_files - * @param $p_remdir - * @param int $p_mode - * @return array|bool|int|string - */ - function _extractList($p_to, $p_files, $p_remdir, $p_mode = 0755) { - if(!$p_to || ($p_to[0] != "/" && substr($p_to, 0, 3) != "../" && substr($p_to, 1, 3) != ":\\" && substr($p_to, 1, 2) != ":/")) /*" // <- PHP Coder bug */ - $p_to = "./$p_to"; - - if($p_remdir && substr($p_remdir, -1) != '/') $p_remdir .= '/'; - $p_remdirs = strlen($p_remdir); - while($dat = $this->_read(512)) { - $headers = $this->_readHeader($dat); - if(!$headers['filename']) continue; - - if($p_files == -1 || $p_files[0] == -1) { - $extract = true; - } else { - $extract = false; - - foreach($p_files as $f) { - if(substr($f, -1) == "/") { - if((strlen($headers['filename']) > strlen($f)) && (substr($headers['filename'], 0, strlen($f)) == $f)) { - $extract = true; - break; - } - } elseif($f == $headers['filename']) { - $extract = true; - break; - } - } - } - - if($extract) { - $det[] = $headers; - if($p_remdir && substr($headers['filename'], 0, $p_remdirs) == $p_remdir) - $headers['filename'] = substr($headers['filename'], $p_remdirs); - - if($headers['filename'].'/' == $p_remdir && $headers['typeflag'] == '5') continue; - - if($p_to != "./" && $p_to != "/") { - while($p_to{-1} == "/") $p_to = substr($p_to, 0, -1); - - if($headers['filename']{0} == "/") - $headers['filename'] = $p_to.$headers['filename']; - else - $headers['filename'] = $p_to."/".$headers['filename']; - } - - $ok = $this->_dirApp($headers['typeflag'] == "5" ? $headers['filename'] : dirname($headers['filename'])); - if($ok < 0) return $ok; - - if(!$headers['typeflag']) { - if(!$fp = @fopen($headers['filename'], "wb")) return -6; - $n = floor($headers['size'] / 512); - - for($i = 0; $i < $n; $i++) { - fwrite($fp, $this->_read(512), 512); - } - if(($headers['size'] % 512) != 0) fwrite($fp, $this->_read(512), $headers['size'] % 512); - - fclose($fp); - touch($headers['filename'], $headers['mtime']); - chmod($headers['filename'], $p_mode); - } else { - $this->_seek(ceil($headers['size'] / 512) * 512, 1); - } - } else $this->_seek(ceil($headers['size'] / 512) * 512, 1); - } - return $det; - } - - /** - * Create a directory hierarchy in filesystem - * - * @param string $d - * @return bool - */ - function _dirApp($d) { - // map to dokuwiki function (its more robust) - return io_mkdir_p($d); - } - -} - diff --git a/inc/load.php b/inc/load.php index 49c307054..2ea0d8efd 100644 --- a/inc/load.php +++ b/inc/load.php @@ -72,7 +72,6 @@ function load_autoload($name){ 'Doku_Plugin_Controller'=> DOKU_INC.'inc/plugincontroller.class.php', 'GeSHi' => DOKU_INC.'inc/geshi.php', 'Tar' => DOKU_INC.'inc/Tar.class.php', - 'TarLib' => DOKU_INC.'inc/TarLib.class.php', 'ZipLib' => DOKU_INC.'inc/ZipLib.class.php', 'DokuWikiFeedCreator' => DOKU_INC.'inc/feedcreator.class.php', 'Doku_Parser_Mode' => DOKU_INC.'inc/parser/parser.php', diff --git a/lib/plugins/plugin/classes/ap_download.class.php b/lib/plugins/plugin/classes/ap_download.class.php index d1b518d9d..0eb567c80 100644 --- a/lib/plugins/plugin/classes/ap_download.class.php +++ b/lib/plugins/plugin/classes/ap_download.class.php @@ -200,31 +200,26 @@ class ap_download extends ap_manage { if (in_array($ext, array('tar','bz','gz'))) { switch($ext){ case 'bz': - $compress_type = TarLib::COMPRESS_BZIP; + $compress_type = Tar::COMPRESS_BZIP; break; case 'gz': - $compress_type = TarLib::COMPRESS_GZIP; + $compress_type = Tar::COMPRESS_GZIP; break; default: - $compress_type = TarLib::COMPRESS_NONE; + $compress_type = Tar::COMPRESS_NONE; } - $tar = new TarLib($file, $compress_type); - if($tar->_initerror < 0){ + $tar = new Tar(); + try { + $tar->open($file, $compress_type); + $tar->extract($target); + return true; + }catch(Exception $e){ if($conf['allowdebug']){ - msg('TarLib Error: '.$tar->TarErrorStr($tar->_initerror),-1); + msg('Tar Error: '.$e->getMessage().' ['.$e->getFile().':'.$e->getLine().']',-1); } return false; } - $ok = $tar->Extract(TarLib::FULL_ARCHIVE, $target, '', 0777); - - if($ok<1){ - if($conf['allowdebug']){ - msg('TarLib Error: '.$tar->TarErrorStr($ok),-1); - } - return false; - } - return true; } else if ($ext == 'zip') { $zip = new ZipLib(); -- cgit v1.2.3 From 421a2704022cbc8fa07ab673c2d503199f460b8e Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Nov 2012 10:36:58 +0100 Subject: Tar: Added extraction support for long file names Supports POSIX ustar prefixes and GNU longlink entries --- _test/tests/inc/tar.test.php | 17 ++++++++++++- _test/tests/inc/tar/longpath-gnu.tgz | Bin 0 -> 413 bytes _test/tests/inc/tar/longpath-ustar.tgz | Bin 0 -> 311 bytes inc/Tar.class.php | 43 +++++++++++++++++++++------------ 4 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 _test/tests/inc/tar/longpath-gnu.tgz create mode 100644 _test/tests/inc/tar/longpath-ustar.tgz diff --git a/_test/tests/inc/tar.test.php b/_test/tests/inc/tar.test.php index 4de9e668d..9abd27612 100644 --- a/_test/tests/inc/tar.test.php +++ b/_test/tests/inc/tar.test.php @@ -218,7 +218,6 @@ class Tar_TestCase extends DokuWikiTest { } } - /** * Check the extension to compression guesser */ @@ -234,4 +233,20 @@ class Tar_TestCase extends DokuWikiTest { $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tar.BZ2')); $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tar.bz2')); } + + public function test_longpathextract(){ + $dir = dirname(__FILE__).'/tar'; + $out = sys_get_temp_dir().'/dwtartest'.md5(time()); + + foreach(array('ustar','gnu') as $format){ + $tar = new Tar(); + $tar->open("$dir/longpath-$format.tgz"); + $tar->extract($out); + + $this->assertFileExists($out.'/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/test.txt'); + + TestUtils::rdelete($out); + } + } + } \ No newline at end of file diff --git a/_test/tests/inc/tar/longpath-gnu.tgz b/_test/tests/inc/tar/longpath-gnu.tgz new file mode 100644 index 000000000..6c937c8fe Binary files /dev/null and b/_test/tests/inc/tar/longpath-gnu.tgz differ diff --git a/_test/tests/inc/tar/longpath-ustar.tgz b/_test/tests/inc/tar/longpath-ustar.tgz new file mode 100644 index 000000000..59efbff66 Binary files /dev/null and b/_test/tests/inc/tar/longpath-ustar.tgz differ diff --git a/inc/Tar.class.php b/inc/Tar.class.php index 7f5e5af4a..8da30e736 100644 --- a/inc/Tar.class.php +++ b/inc/Tar.class.php @@ -204,7 +204,7 @@ class Tar { // is this a file? if(!$header['typeflag']){ - $fp = @fopen($output, "wb"); + $fp = fopen($output, "wb"); if(!$fp) throw(new TarIOException('Could not open file for writing: '.$output)); $size = floor($header['size'] / 512); @@ -508,7 +508,6 @@ class Tar { /** * Decode the given tar file header * - * @todo how to handle filenames >100 chars? * @param string $block a 512 byte block containign the header data * @return array|bool */ @@ -521,22 +520,36 @@ class Tar { for($i = 156, $chks += 256; $i < 512; $i++) $chks += ord($block[$i]); - $headers = @unpack("a100filename/a8perm/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $block); - if(!$headers) return false; + $header = @unpack("a100filename/a8perm/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix", $block); + if(!$header) return false; - $return['checksum'] = OctDec(trim($headers['checksum'])); + $return['checksum'] = OctDec(trim($header['checksum'])); if($return['checksum'] != $chks) return false; - $return['filename'] = trim($headers['filename']); - $return['perm'] = OctDec(trim($headers['perm'])); - $return['uid'] = OctDec(trim($headers['uid'])); - $return['gid'] = OctDec(trim($headers['gid'])); - $return['size'] = OctDec(trim($headers['size'])); - $return['mtime'] = OctDec(trim($headers['mtime'])); - $return['typeflag'] = $headers['typeflag']; - $return['link'] = trim($headers['link']); - $return['uname'] = trim($headers['uname']); - $return['gname'] = trim($headers['gname']); + $return['filename'] = trim($header['filename']); + $return['perm'] = OctDec(trim($header['perm'])); + $return['uid'] = OctDec(trim($header['uid'])); + $return['gid'] = OctDec(trim($header['gid'])); + $return['size'] = OctDec(trim($header['size'])); + $return['mtime'] = OctDec(trim($header['mtime'])); + $return['typeflag'] = $header['typeflag']; + $return['link'] = trim($header['link']); + $return['uname'] = trim($header['uname']); + $return['gname'] = trim($header['gname']); + + // Handle ustar Posix compliant path prefixes + if(trim($header['prefix'])) $return['filename'] = trim($header['prefix']).'/'.$return['filename']; + + // Handle Long-Link entries from GNU Tar + if($return['typeflag'] == 'L'){ + // following data block(s) is the filename + $filename = trim($this->readbytes(ceil($header['size'] / 512) * 512)); + // next block is the real header + $block = $this->readbytes(512); + $return = $this->parseHeader($block); + // overwrite the filename + $return['filename'] = $filename; + } return $return; } -- cgit v1.2.3 From 90a1db709d3590e849a5a4966fbdf8fb58ae75cd Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Nov 2012 11:31:20 +0100 Subject: Tar: support for creating archives with long filenames The library now creates either a POSIX ustar prefix or a GNU longlink entry for files which have a name longer than 100 bytes --- _test/tests/inc/tar.test.php | 97 +++++++++++++++++++++++++--------- inc/Tar.class.php | 121 +++++++++++++++++++++++-------------------- 2 files changed, 137 insertions(+), 81 deletions(-) diff --git a/_test/tests/inc/tar.test.php b/_test/tests/inc/tar.test.php index 9abd27612..47851fd4c 100644 --- a/_test/tests/inc/tar.test.php +++ b/_test/tests/inc/tar.test.php @@ -8,7 +8,7 @@ class Tar_TestCase extends DokuWikiTest { * * No check for format correctness */ - public function test_createdynamic(){ + public function test_createdynamic() { $tar = new Tar(); $dir = dirname(__FILE__).'/tar'; @@ -38,7 +38,7 @@ class Tar_TestCase extends DokuWikiTest { * * No check for format correctness */ - public function test_createfile(){ + public function test_createfile() { $tar = new Tar(); $dir = dirname(__FILE__).'/tar'; @@ -70,10 +70,10 @@ class Tar_TestCase extends DokuWikiTest { /** * List the contents of the prebuilt TAR files */ - public function test_tarcontent(){ + public function test_tarcontent() { $dir = dirname(__FILE__).'/tar'; - foreach(array('tar','tgz','tbz') as $ext){ + foreach(array('tar', 'tgz', 'tbz') as $ext) { $tar = new Tar(); $file = "$dir/test.$ext"; @@ -92,11 +92,11 @@ class Tar_TestCase extends DokuWikiTest { /** * Extract the prebuilt tar files */ - public function test_tarextract(){ + public function test_tarextract() { $dir = dirname(__FILE__).'/tar'; $out = sys_get_temp_dir().'/dwtartest'.md5(time()); - foreach(array('tar', 'tgz', 'tbz') as $ext){ + foreach(array('tar', 'tgz', 'tbz') as $ext) { $tar = new Tar(); $file = "$dir/test.$ext"; @@ -118,16 +118,16 @@ class Tar_TestCase extends DokuWikiTest { /** * Extract the prebuilt tar files with component stripping */ - public function test_compstripextract(){ + public function test_compstripextract() { $dir = dirname(__FILE__).'/tar'; $out = sys_get_temp_dir().'/dwtartest'.md5(time()); - foreach(array('tar', 'tgz', 'tbz') as $ext){ + foreach(array('tar', 'tgz', 'tbz') as $ext) { $tar = new Tar(); $file = "$dir/test.$ext"; $tar->open($file); - $tar->extract($out,1); + $tar->extract($out, 1); clearstatcache(); @@ -144,16 +144,16 @@ class Tar_TestCase extends DokuWikiTest { /** * Extract the prebuilt tar files with prefix stripping */ - public function test_prefixstripextract(){ + public function test_prefixstripextract() { $dir = dirname(__FILE__).'/tar'; $out = sys_get_temp_dir().'/dwtartest'.md5(time()); - foreach(array('tar', 'tgz', 'tbz') as $ext){ + foreach(array('tar', 'tgz', 'tbz') as $ext) { $tar = new Tar(); $file = "$dir/test.$ext"; $tar->open($file); - $tar->extract($out,'tar/foobar/'); + $tar->extract($out, 'tar/foobar/'); clearstatcache(); @@ -170,22 +170,21 @@ class Tar_TestCase extends DokuWikiTest { /** * Extract the prebuilt tar files with include regex */ - public function test_includeextract(){ + public function test_includeextract() { $dir = dirname(__FILE__).'/tar'; $out = sys_get_temp_dir().'/dwtartest'.md5(time()); - foreach(array('tar', 'tgz', 'tbz') as $ext){ + foreach(array('tar', 'tgz', 'tbz') as $ext) { $tar = new Tar(); $file = "$dir/test.$ext"; $tar->open($file); - $tar->extract($out,'','','/\/foobar\//'); + $tar->extract($out, '', '', '/\/foobar\//'); clearstatcache(); $this->assertFileNotExists($out.'/tar/testdata1.txt', "Extracted $file"); - $this->assertFileExists($out.'/tar/foobar/testdata2.txt', "Extracted $file"); $this->assertEquals(13, filesize($out.'/tar/foobar/testdata2.txt'), "Extracted $file"); @@ -196,16 +195,16 @@ class Tar_TestCase extends DokuWikiTest { /** * Extract the prebuilt tar files with exclude regex */ - public function test_excludeextract(){ + public function test_excludeextract() { $dir = dirname(__FILE__).'/tar'; $out = sys_get_temp_dir().'/dwtartest'.md5(time()); - foreach(array('tar', 'tgz', 'tbz') as $ext){ + foreach(array('tar', 'tgz', 'tbz') as $ext) { $tar = new Tar(); $file = "$dir/test.$ext"; $tar->open($file); - $tar->extract($out,'','/\/foobar\//'); + $tar->extract($out, '', '/\/foobar\//'); clearstatcache(); @@ -221,8 +220,8 @@ class Tar_TestCase extends DokuWikiTest { /** * Check the extension to compression guesser */ - public function test_filetype(){ - $tar = new Tar(); + public function test_filetype() { + $tar = new Tar(); $this->assertEquals(Tar::COMPRESS_NONE, $tar->filetype('foo')); $this->assertEquals(Tar::COMPRESS_GZIP, $tar->filetype('foo.tgz')); $this->assertEquals(Tar::COMPRESS_GZIP, $tar->filetype('foo.tGZ')); @@ -234,12 +233,12 @@ class Tar_TestCase extends DokuWikiTest { $this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tar.bz2')); } - public function test_longpathextract(){ + public function test_longpathextract() { $dir = dirname(__FILE__).'/tar'; $out = sys_get_temp_dir().'/dwtartest'.md5(time()); - foreach(array('ustar','gnu') as $format){ - $tar = new Tar(); + foreach(array('ustar', 'gnu') as $format) { + $tar = new Tar(); $tar->open("$dir/longpath-$format.tgz"); $tar->extract($out); @@ -249,4 +248,54 @@ class Tar_TestCase extends DokuWikiTest { } } + public function test_createlongpathustar() { + $tar = new Tar(); + $tmp = tempnam(sys_get_temp_dir(), 'dwtartest'); + + $path = ''; + for($i=0; $i<11; $i++) $path .= '1234567890/'; + $path = rtrim($path,'/'); + + $tar->create($tmp, Tar::COMPRESS_NONE); + $tar->addData("$path/test.txt", 'testcontent1'); + $tar->close(); + + $this->assertTrue(filesize($tmp) > 30); //arbitrary non-zero number + $data = file_get_contents($tmp); + + // We should find the path and filename separated, no longlink entry + $this->assertTrue(strpos($data, 'testcontent1') !== false, 'content in TAR'); + $this->assertTrue(strpos($data, 'test.txt') !== false, 'filename in TAR'); + $this->assertTrue(strpos($data, $path) !== false, 'path in TAR'); + $this->assertFalse(strpos($data, "$path/test.txt") !== false, 'full filename in TAR'); + $this->assertFalse(strpos($data, '@LongLink') !== false, '@LongLink in TAR'); + + @unlink($tmp); + } + + public function test_createlongpathgnu() { + $tar = new Tar(); + $tmp = tempnam(sys_get_temp_dir(), 'dwtartest'); + + $path = ''; + for($i=0; $i<20; $i++) $path .= '1234567890/'; + $path = rtrim($path,'/'); + + $tar->create($tmp, Tar::COMPRESS_NONE); + $tar->addData("$path/test.txt", 'testcontent1'); + $tar->close(); + + $this->assertTrue(filesize($tmp) > 30); //arbitrary non-zero number + $data = file_get_contents($tmp); + + // We should find the complete path/filename and a longlink entry + $this->assertTrue(strpos($data, 'testcontent1') !== false, 'content in TAR'); + $this->assertTrue(strpos($data, 'test.txt') !== false, 'filename in TAR'); + $this->assertTrue(strpos($data, $path) !== false, 'path in TAR'); + $this->assertTrue(strpos($data, "$path/test.txt") !== false, 'full filename in TAR'); + $this->assertTrue(strpos($data, '@LongLink') !== false, '@LongLink in TAR'); + + @unlink($tmp); + } + } \ No newline at end of file diff --git a/inc/Tar.class.php b/inc/Tar.class.php index 8da30e736..59e14c705 100644 --- a/inc/Tar.class.php +++ b/inc/Tar.class.php @@ -4,6 +4,8 @@ * To keep things simple, the modification of existing archives is not supported. It handles * uncompressed, gzip and bzip2 compressed tar files. * + * Long pathnames (>100 chars) are supported in POSIX ustar and GNU longlink formats. + * * To list the contents of an existing TAR archive, open() it and use contents() on it: * * $tar = new Tar(); @@ -145,10 +147,10 @@ class Tar { * @throws TarIOException * @return array */ - function extract($outdir, $strip='', $exclude='', $include='') { + function extract($outdir, $strip = '', $exclude = '', $include = '') { if($this->closed || !$this->file) throw(new TarIOException('Can not read from a closed archive')); - $outdir = rtrim($outdir,'/'); + $outdir = rtrim($outdir, '/'); io_mkdir_p($outdir); $striplen = strlen($strip); @@ -164,32 +166,32 @@ class Tar { $filename = $this->cleanPath($header['filename']); if(is_int($strip)) { // if $strip is an integer we strip this many path components - $parts = explode('/',$filename); - if(!$header['typeflag']){ + $parts = explode('/', $filename); + if(!$header['typeflag']) { $base = array_pop($parts); // keep filename itself - }else{ + } else { $base = ''; } - $filename = join('/',array_slice($parts,$strip)); + $filename = join('/', array_slice($parts, $strip)); if($base) $filename .= "/$base"; - }else{ + } else { // ifstrip is a string, we strip a prefix here - if(substr($filename,0,$striplen) == $strip) $filename = substr($filename,$striplen); + if(substr($filename, 0, $striplen) == $strip) $filename = substr($filename, $striplen); } // check if this should be extracted $extract = true; - if(!$filename){ + if(!$filename) { $extract = false; - }else{ - if($include){ - if(preg_match($include, $filename)){ + } else { + if($include) { + if(preg_match($include, $filename)) { $extract = true; - }else{ + } else { $extract = false; } } - if($exclude && preg_match($exclude, $filename)){ + if($exclude && preg_match($exclude, $filename)) { $extract = false; } } @@ -203,7 +205,7 @@ class Tar { io_mkdir_p($directory); // is this a file? - if(!$header['typeflag']){ + if(!$header['typeflag']) { $fp = fopen($output, "wb"); if(!$fp) throw(new TarIOException('Could not open file for writing: '.$output)); @@ -216,10 +218,10 @@ class Tar { fclose($fp); touch($output, $header['mtime']); chmod($output, $header['perm']); - }else{ + } else { $this->skipbytes(ceil($header['size'] / 512) * 512); // the size is usually 0 for directories } - }else{ + } else { $this->skipbytes(ceil($header['size'] / 512) * 512); } } @@ -261,7 +263,7 @@ class Tar { if(!$this->fh) throw(new TarIOException('Could not open file for writing: '.$this->file)); } $this->writeaccess = false; - $this->closed = false; + $this->closed = false; } /** @@ -270,7 +272,6 @@ class Tar { * @todo handle directory adding * @param string $file the original file * @param string $name the name to use for the file in the archive - * @throws TarBadFilename * @throws TarIOException */ public function addFile($file, $name = '') { @@ -279,9 +280,6 @@ class Tar { if(!$name) $name = $file; $name = $this->cleanPath($name); - // FIXME ustar should support up 256 chars - if(strlen($name) > 99) throw(new TarBadFilename('Filenames may not exceed 99 bytes: '.$name)); - $fp = fopen($file, 'rb'); if(!$fp) throw(new TarIOException('Could not open file for reading: '.$file)); @@ -294,8 +292,7 @@ class Tar { $stat[5], fileperms($file), filesize($file), - filemtime($file), - false + filemtime($file) ); while(!feof($fp)) { @@ -306,26 +303,21 @@ class Tar { } /** - * Add a file to the current TAR archive using in memory data + * Add a file to the current TAR archive using the given $data as content * - * @param $name - * @param $data - * @param int $uid - * @param int $gid - * @param int $perm - * @param int $mtime + * @param string $name + * @param string $data + * @param int $uid + * @param int $gid + * @param int $perm + * @param int $mtime * @throws TarIOException - * @throws TarBadFilename */ public function addData($name, $data, $uid = 0, $gid = 0, $perm = 0666, $mtime = 0) { if($this->closed) throw(new TarIOException('Archive has been closed, files can no longer be added')); $name = $this->cleanPath($name); - - // FIXME ustar should support up 256 chars - if(strlen($name) > 99) throw(new TarBadFilename('Filenames may not exceed 99 bytes: '.$name)); - - $len = strlen($data); + $len = strlen($data); $this->writeFileHeader( $name, @@ -333,8 +325,7 @@ class Tar { $gid, $perm, $len, - ($mtime) ? $mtime : time(), - false + ($mtime) ? $mtime : time() ); for($s = 0; $s < $len; $s += 512) { @@ -357,23 +348,23 @@ class Tar { if($this->closed) return; // we did this already // write footer - if($this->writeaccess){ + if($this->writeaccess) { $this->writebytes(pack("a512", "")); $this->writebytes(pack("a512", "")); } // close file handles - if($this->file){ - if($this->comptype === Tar::COMPRESS_GZIP){ + if($this->file) { + if($this->comptype === Tar::COMPRESS_GZIP) { gzclose($this->fh); - }elseif($this->comptype === Tar::COMPRESS_BZIP){ + } elseif($this->comptype === Tar::COMPRESS_BZIP) { bzclose($this->fh); - }else{ + } else { fclose($this->fh); } $this->file = ''; - $this->fh = 0; + $this->fh = 0; } $this->closed = true; @@ -460,12 +451,12 @@ class Tar { * @param int $bytes seek to this position */ function skipbytes($bytes) { - if($this->comptype === Tar::COMPRESS_GZIP){ + if($this->comptype === Tar::COMPRESS_GZIP) { @gzseek($this->fh, $bytes, SEEK_CUR); - }elseif($this->comptype === Tar::COMPRESS_BZIP){ + } elseif($this->comptype === Tar::COMPRESS_BZIP) { // there is no seek in bzip2, we simply read on @bzread($this->fh, $bytes); - }else{ + } else { @fseek($this->fh, $bytes, SEEK_CUR); } } @@ -479,19 +470,38 @@ class Tar { * @param int $perm * @param int $size * @param int $mtime - * @param bool $isdir + * @param string $typeflag Set to '5' for directories */ - protected function writeFileHeader($name, $uid, $gid, $perm, $size, $mtime, $isdir = false) { + protected function writeFileHeader($name, $uid, $gid, $perm, $size, $mtime, $typeflag = '') { + // handle filename length restrictions + $prefix = ''; + $namelen = strlen($name); + if($namelen > 100) { + $file = basename($name); + $dir = dirname($name); + if(strlen($file) > 100 || strlen($dir) > 155) { + // we're still too large, let's use GNU longlink + $this->writeFileHeader('././@LongLink', 0, 0, 0, $namelen, 0, 'L'); + for($s = 0; $s < $namelen; $s += 512) { + $this->writebytes(pack("a512", substr($name, $s, 512))); + } + $name = substr($name, 0, 100); // cut off name + } else { + // we're fine when splitting, use POSIX ustar + $prefix = $dir; + $name = $file; + } + } + // values are needed in octal $uid = sprintf("%6s ", DecOct($uid)); $gid = sprintf("%6s ", DecOct($gid)); $perm = sprintf("%6s ", DecOct($perm)); $size = sprintf("%11s ", DecOct($size)); $mtime = sprintf("%11s", DecOct($mtime)); - $dir = ($isdir) ? '5' : ''; $data_first = pack("a100a8a8a8a12A12", $name, $perm, $uid, $gid, $size, $mtime); - $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $dir, '', '', '', '', '', '', '', '', ""); + $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $typeflag, '', 'ustar', '', '', '', '', '', $prefix, ""); for($i = 0, $chks = 0; $i < 148; $i++) $chks += ord($data_first[$i]); @@ -541,11 +551,11 @@ class Tar { if(trim($header['prefix'])) $return['filename'] = trim($header['prefix']).'/'.$return['filename']; // Handle Long-Link entries from GNU Tar - if($return['typeflag'] == 'L'){ + if($return['typeflag'] == 'L') { // following data block(s) is the filename $filename = trim($this->readbytes(ceil($header['size'] / 512) * 512)); // next block is the real header - $block = $this->readbytes(512); + $block = $this->readbytes(512); $return = $this->parseHeader($block); // overwrite the filename $return['filename'] = $filename; @@ -617,9 +627,6 @@ class Tar { } } -class TarBadFilename extends Exception { -} - class TarIOException extends Exception { } -- cgit v1.2.3 From 2949ece61602372cf55fba6be4522fa8899fb70d Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Nov 2012 12:21:47 +0100 Subject: unit test for tar bombs --- _test/tests/inc/tar.test.php | 18 ++++++++++++++++++ _test/tests/inc/tar/tarbomb.tgz | Bin 0 -> 183 bytes 2 files changed, 18 insertions(+) create mode 100644 _test/tests/inc/tar/tarbomb.tgz diff --git a/_test/tests/inc/tar.test.php b/_test/tests/inc/tar.test.php index 47851fd4c..e8805a75d 100644 --- a/_test/tests/inc/tar.test.php +++ b/_test/tests/inc/tar.test.php @@ -298,4 +298,22 @@ class Tar_TestCase extends DokuWikiTest { @unlink($tmp); } + /** + * Extract a tarbomomb + */ + public function test_tarbomb() { + $dir = dirname(__FILE__).'/tar'; + $out = sys_get_temp_dir().'/dwtartest'.md5(time()); + + $tar = new Tar(); + + $tar->open("$dir/tarbomb.tgz"); + $tar->extract($out); + + clearstatcache(); + + $this->assertFileExists($out.'/AAAAAAAAAAAAAAAAA/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB.txt'); + + TestUtils::rdelete($out); + } } \ No newline at end of file diff --git a/_test/tests/inc/tar/tarbomb.tgz b/_test/tests/inc/tar/tarbomb.tgz new file mode 100644 index 000000000..8418d4073 Binary files /dev/null and b/_test/tests/inc/tar/tarbomb.tgz differ -- cgit v1.2.3 From 35349ab097171f0f9cb6114cffd780abb69c56a6 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 6 Nov 2012 20:57:25 +0100 Subject: added simple compatibility wrapper for old TarLib --- inc/TarLib.class.php | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ inc/load.php | 1 + 2 files changed, 88 insertions(+) create mode 100644 inc/TarLib.class.php diff --git a/inc/TarLib.class.php b/inc/TarLib.class.php new file mode 100644 index 000000000..ae08039ec --- /dev/null +++ b/inc/TarLib.class.php @@ -0,0 +1,87 @@ +error('__construct', '$file'); + + $this->file = $file; + switch($comptype) { + case TarLib::COMPRESS_AUTO: + case TarLib::COMPRESS_DETECT: + $comptype = Tar::COMPRESS_AUTO; + break; + case TarLib::COMPRESS_GZIP: + $comptype = Tar::COMPRESS_GZIP; + break; + case TarLib::COMPRESS_BZIP: + $comptype = Tar::COMPRESS_BZIP; + break; + default: + $comptype = Tar::COMPRESS_NONE; + } + + $this->complevel = $complevel; + + try { + $this->tar = new Tar(); + $this->tar->open($file, $comptype); + } catch(Exception $e) { + $this->_result = false; + } + } + + function Extract($p_what = TarLib::FULL_ARCHIVE, $p_to = '.', $p_remdir = '', $p_mode = 0755) { + if($p_what != TarLib::FULL_ARCHIVE) { + $this->error('Extract', 'Ep_what'); + return 0; + } + + try { + $this->tar->extract($p_to, $p_remdir); + } catch(Exception $e) { + return 0; + } + return 1; + } + + function error($func, $param = '') { + $error = 'TarLib is deprecated and should no longer be used.'; + + if($param) { + $error .= "In this compatibility wrapper, the function '$func' does not accept your value for". + "the parameter '$param' anymore."; + } else { + $error .= "The function '$func' no longer exists in this compatibility wrapper."; + } + + msg($error, -1); + } + + function __call($name, $arguments) { + $this->error($name); + } +} \ No newline at end of file diff --git a/inc/load.php b/inc/load.php index 2ea0d8efd..49c307054 100644 --- a/inc/load.php +++ b/inc/load.php @@ -72,6 +72,7 @@ function load_autoload($name){ 'Doku_Plugin_Controller'=> DOKU_INC.'inc/plugincontroller.class.php', 'GeSHi' => DOKU_INC.'inc/geshi.php', 'Tar' => DOKU_INC.'inc/Tar.class.php', + 'TarLib' => DOKU_INC.'inc/TarLib.class.php', 'ZipLib' => DOKU_INC.'inc/ZipLib.class.php', 'DokuWikiFeedCreator' => DOKU_INC.'inc/feedcreator.class.php', 'Doku_Parser_Mode' => DOKU_INC.'inc/parser/parser.php', -- cgit v1.2.3 From a20ce704cbd26eccbca8bf01dadac23a1432e1a5 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 8 Nov 2012 23:24:57 +0100 Subject: changed proxy in test case --- _test/tests/inc/httpclient_http_proxy.test.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_test/tests/inc/httpclient_http_proxy.test.php b/_test/tests/inc/httpclient_http_proxy.test.php index 81abdbca0..faa7a4280 100644 --- a/_test/tests/inc/httpclient_http_proxy.test.php +++ b/_test/tests/inc/httpclient_http_proxy.test.php @@ -8,8 +8,9 @@ class httpclient_http_proxy_test extends DokuWikiTest { */ function test_simpleget(){ $http = new HTTPClient(); - $http->proxy_host = 'localhost'; //FIXME we need a public server - $http->proxy_port = 3128; + // proxy provided by Andrwe Lord Weber + $http->proxy_host = 'proxy.andrwe.org'; + $http->proxy_port = 8080; $data = $http->get($this->url); $this->assertFalse($data === false, 'HTTP response'); -- cgit v1.2.3 From a21383af58203bf0e6dc36a07ea78fae0b58c1ef Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 12 Nov 2012 20:57:27 +0100 Subject: crossbrowser fixes for quicksearch shortening FS#2660 fixes the problem with missing innerText in Firefox (and other browsers) and corrects shortening in regard to paddings and the use of the text-overflow attribute --- lib/scripts/qsearch.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/scripts/qsearch.js b/lib/scripts/qsearch.js index a309f9e29..c3d0d94fb 100644 --- a/lib/scripts/qsearch.js +++ b/lib/scripts/qsearch.js @@ -92,12 +92,18 @@ var dw_qsearch = { .show() .css('white-space', 'nowrap'); - // shorten namespaces if too long - max = dw_qsearch.$outObj[0].clientWidth; + // disable overflow during shortening + dw_qsearch.$outObj.find('li').css('overflow', 'visible'); + $links = dw_qsearch.$outObj.find('a'); - too_big = (document.documentElement.dir === 'rtl') - ? function (l) { return l.offsetLeft < 0; } - : function (l) { return l.offsetWidth + l.offsetLeft > max; }; + max = dw_qsearch.$outObj[0].clientWidth; // maximum width allowed (but take away paddings below) + if(document.documentElement.dir === 'rtl'){ + max -= parseInt(dw_qsearch.$outObj.css('padding-left')); + too_big = function (l) { return l.offsetLeft < 0; }; + }else{ + max -= parseInt(dw_qsearch.$outObj.css('padding-right')); + too_big = function (l) { return l.offsetWidth + l.offsetLeft > max; }; + } $links.each(function () { var start, length, replace, nsL, nsR, eli, runaway; @@ -106,6 +112,12 @@ var dw_qsearch = { return; } + // make IE's innerText available to W3C conform browsers + if(this.textContent){ + this.__defineGetter__('innerText', function(){ return this.textContent }); + this.__defineSetter__('innerText', function(val){ this.textContent = val }); + } + nsL = this.innerText.indexOf('('); nsR = this.innerText.indexOf(')'); eli = 0; @@ -138,6 +150,9 @@ var dw_qsearch = { nsR = this.innerText.indexOf(')'); } }); + + // reenable overflow + dw_qsearch.$outObj.find('li').css('overflow', 'hidden').css('text-overflow','ellipsis'); } }; -- cgit v1.2.3 From 3161005d07beb46bb8a866ec56a768938571ec9d Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 12 Nov 2012 21:22:26 +0100 Subject: check for unicode preg capabilities in UTF-8 lib FS#2636 We now have two defines for checking for UTF-8 and Unicode property support in PREG and use them to work around FS#2636 on older systems. --- inc/fulltext.php | 15 +++++++++++---- inc/infoutils.php | 4 ++-- inc/utf8.php | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/inc/fulltext.php b/inc/fulltext.php index eab8850dc..7ee386063 100644 --- a/inc/fulltext.php +++ b/inc/fulltext.php @@ -394,10 +394,17 @@ function ft_snippet_re_preprocess($term) { return $term; } - // unicode word boundaries - // see http://stackoverflow.com/a/2449017/172068 - $BL = '(? Date: Sun, 11 Nov 2012 11:18:47 +0100 Subject: compat js findPosX/y more closely mimic historical function --- lib/scripts/compatibility.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/scripts/compatibility.js b/lib/scripts/compatibility.js index 385e45854..76b135b23 100644 --- a/lib/scripts/compatibility.js +++ b/lib/scripts/compatibility.js @@ -165,13 +165,13 @@ toggleWrap = DEPRECATED_WRAP(dw_editor.toggleWrap); setWrap = DEPRECATED_WRAP(dw_editor.setWrap); function findPosX(object){ - DEPRECATED('Use jQuery.position() instead'); - return jQuery(object).position().left; + DEPRECATED('Use jQuery.offset() instead'); + return jQuery(object).offset().left; } function findPosY(object){ - DEPRECATED('Use jQuery.position() instead'); - return jQuery(object).position().top; + DEPRECATED('Use jQuery.offset() instead'); + return jQuery(object).offset().top; } function getElementsByClass(searchClass,node,tag){ -- cgit v1.2.3 From 649ee76f050057709402fd3d70243ea537d72b27 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 12 Nov 2012 21:29:23 +0100 Subject: Czech language update --- inc/lang/cs/lang.php | 2 ++ lib/plugins/acl/lang/cs/lang.php | 1 + lib/plugins/config/lang/cs/lang.php | 14 ++++++++++++-- lib/plugins/plugin/lang/cs/lang.php | 1 + lib/plugins/popularity/lang/cs/lang.php | 1 + lib/plugins/revert/lang/cs/lang.php | 1 + lib/plugins/usermanager/lang/cs/lang.php | 1 + 7 files changed, 19 insertions(+), 2 deletions(-) diff --git a/inc/lang/cs/lang.php b/inc/lang/cs/lang.php index a53da327a..cfb8e8eb3 100644 --- a/inc/lang/cs/lang.php +++ b/inc/lang/cs/lang.php @@ -12,6 +12,7 @@ * @author Vojta Beran * @author zbynek.krivka@seznam.cz * @author Bohumir Zamecnik + * @author Jakub A. Těšínský (j@kub.cz) */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -197,6 +198,7 @@ $lang['user_tools'] = 'Uživatelské nástroje'; $lang['site_tools'] = 'Nástroje pro tento web'; $lang['page_tools'] = 'Nástroje pro stránku'; $lang['skip_to_content'] = 'jít k obsahu'; +$lang['sidebar'] = 'Postranní lišta'; $lang['mail_newpage'] = 'nová stránka:'; $lang['mail_changed'] = 'změna stránky:'; $lang['mail_subscribe_list'] = 'stránky změněné ve jmenném prostoru:'; diff --git a/lib/plugins/acl/lang/cs/lang.php b/lib/plugins/acl/lang/cs/lang.php index a1dce0369..feb160a02 100644 --- a/lib/plugins/acl/lang/cs/lang.php +++ b/lib/plugins/acl/lang/cs/lang.php @@ -11,6 +11,7 @@ * @author Vojta Beran * @author zbynek.krivka@seznam.cz * @author Bohumir Zamecnik + * @author Jakub A. Těšínský (j@kub.cz) */ $lang['admin_acl'] = 'Správa přístupových práv'; $lang['acl_group'] = 'Skupina'; diff --git a/lib/plugins/config/lang/cs/lang.php b/lib/plugins/config/lang/cs/lang.php index d2ec5035a..383afebb4 100644 --- a/lib/plugins/config/lang/cs/lang.php +++ b/lib/plugins/config/lang/cs/lang.php @@ -11,6 +11,7 @@ * @author Vojta Beran * @author zbynek.krivka@seznam.cz * @author Bohumir Zamecnik + * @author Jakub A. Těšínský (j@kub.cz) */ $lang['menu'] = 'Správa nastavení'; $lang['error'] = 'Nastavení nebyla změněna kvůli alespoň jedné neplatné položce, @@ -36,6 +37,8 @@ $lang['_anti_spam'] = 'Protispamová nastavení'; $lang['_editing'] = 'Nastavení editace'; $lang['_links'] = 'Nastavení odkazů'; $lang['_media'] = 'Nastavení médií'; +$lang['_notifications'] = 'Nastavení upozornění'; +$lang['_syndication'] = 'Nastavení syndikace'; $lang['_advanced'] = 'Pokročilá nastavení'; $lang['_network'] = 'Nastavení sítě'; $lang['_plugin_sufix'] = 'Nastavení pluginů '; @@ -47,6 +50,8 @@ $lang['title'] = 'Název celé wiki'; $lang['start'] = 'Název úvodní stránky'; $lang['lang'] = 'Jazyk'; $lang['template'] = 'Šablona'; +$lang['tagline'] = 'Slogan (pokud ho šablona podporuje)'; +$lang['sidebar'] = 'Jméno stránky s obsahem postranní lišty (pokud ho šablona podporuje). Prázdné pole postranní lištu deaktivuje.'; $lang['license'] = 'Pod jakou licencí má být tento obsah publikován?'; $lang['savedir'] = 'Adresář pro ukládání dat'; $lang['basedir'] = 'Kořenový adresář (např. /dokuwiki/). Pro autodetekci nechte prázdné.'; @@ -55,8 +60,8 @@ $lang['cookiedir'] = 'Cesta pro cookie. Není-li vyplněno, použije $lang['dmode'] = 'Přístupová práva pro vytváření adresářů'; $lang['fmode'] = 'Přístupová práva pro vytváření souborů'; $lang['allowdebug'] = 'Povolit debugování. Vypněte, pokud to nepotřebujete!'; -$lang['recent'] = 'Nedávné změny'; -$lang['recent_days'] = 'Jak staré nedávných změny uchovávat (ve dnech)'; +$lang['recent'] = 'Počet položek v nedávných změnách'; +$lang['recent_days'] = 'Jak staré nedávné změny zobrazovat (ve dnech)'; $lang['breadcrumbs'] = 'Počet odkazů na navštívené stránky'; $lang['youarehere'] = 'Hierarchická "drobečková" navigace'; $lang['fullpath'] = 'Ukazovat plnou cestu ke stránkám v patičce'; @@ -94,6 +99,8 @@ $lang['disableactions_wikicode'] = 'Prohlížet zdrojové kódy/Export wiki text $lang['disableactions_other'] = 'Další akce (oddělené čárkou)'; $lang['auth_security_timeout'] = 'Časový limit pro autentikaci (v sekundách)'; $lang['securecookie'] = 'Má prohlížeč posílat cookies nastavené přes HTTPS opět jen přes HTTPS? Vypněte tuto volbu, pokud chcete, aby bylo pomocí SSL zabezpečeno pouze přihlašování do wiki, ale obsah budete prohlížet nezabezpečeně.'; +$lang['remote'] = 'Zapne API systému, umožňující jiným aplikacím vzdálený přístup k wiki pomoci XML-RPC nebo jiných mechanizmů.'; +$lang['remoteuser'] = 'Omezit přístup k API na tyto uživatelské skupiny či uživatele (seznam oddělený čárkami). Prázdné pole povolí přístup všem.'; $lang['usewordblock'] = 'Blokovat spam za použití seznamu známých spamových slov'; $lang['relnofollow'] = 'Používat rel="nofollow" na externí odkazy'; $lang['indexdelay'] = 'Časová prodleva před indexací (v sekundách)'; @@ -109,6 +116,7 @@ $lang['target____interwiki'] = 'Cílové okno pro interwiki odkazy'; $lang['target____extern'] = 'Cílové okno pro externí odkazy'; $lang['target____media'] = 'Cílové okno pro odkazy na média'; $lang['target____windows'] = 'Cílové okno pro odkazy na windows sdílení'; +$lang['mediarevisions'] = 'Aktivovat revize souborů'; $lang['refcheck'] = 'Kontrolovat odkazy na média (před vymazáním)'; $lang['refshow'] = 'Počet zobrazených odkazů na média'; $lang['gdlib'] = 'Verze GD knihovny'; @@ -121,12 +129,14 @@ $lang['notify'] = 'Posílat oznámení o změnách na následují $lang['registernotify'] = 'Posílat informace o nově registrovaných uživatelích na tuto mailovou adresu'; $lang['mailfrom'] = 'E-mailová adresa, která se bude používat pro automatické maily'; $lang['mailprefix'] = 'Předpona předmětu e-mailu, která se bude používat pro automatické maily'; +$lang['htmlmail'] = 'Posílat emaily v HTML (hezčí ale větší). Při vypnutí budou posílány jen textové emaily.'; $lang['sitemap'] = 'Generovat Google sitemap (interval ve dnech)'; $lang['rss_type'] = 'Typ XML kanálu'; $lang['rss_linkto'] = 'XML kanál odkazuje na'; $lang['rss_content'] = 'Co zobrazovat v položkách XML kanálu?'; $lang['rss_update'] = 'Interval aktualizace XML kanálu (v sekundách)'; $lang['rss_show_summary'] = 'XML kanál ukazuje souhrn v titulku'; +$lang['rss_media'] = 'Jaký typ změn má být uveden v kanálu XML'; $lang['updatecheck'] = 'Kontrolovat aktualizace a bezpečnostní varování? DokuWiki potřebuje pro tuto funkci přístup k update.dokuwiki.org'; $lang['userewrite'] = 'Používat "pěkná" URL'; $lang['useslash'] = 'Používat lomítko jako oddělovač jmenných prostorů v URL'; diff --git a/lib/plugins/plugin/lang/cs/lang.php b/lib/plugins/plugin/lang/cs/lang.php index 1fd360dca..20a015cd4 100644 --- a/lib/plugins/plugin/lang/cs/lang.php +++ b/lib/plugins/plugin/lang/cs/lang.php @@ -12,6 +12,7 @@ * @author Vojta Beran * @author zbynek.krivka@seznam.cz * @author Bohumir Zamecnik + * @author Jakub A. Těšínský (j@kub.cz) */ $lang['menu'] = 'Správa pluginů'; $lang['download'] = 'Stáhnout a instalovat plugin'; diff --git a/lib/plugins/popularity/lang/cs/lang.php b/lib/plugins/popularity/lang/cs/lang.php index d7c58af2e..0b0dbae7f 100644 --- a/lib/plugins/popularity/lang/cs/lang.php +++ b/lib/plugins/popularity/lang/cs/lang.php @@ -9,6 +9,7 @@ * @author Vojta Beran * @author zbynek.krivka@seznam.cz * @author Bohumir Zamecnik + * @author Jakub A. Těšínský (j@kub.cz) */ $lang['name'] = 'Průzkum používání (může chviličku trvat, než se natáhne)'; $lang['submit'] = 'Odeslat data'; diff --git a/lib/plugins/revert/lang/cs/lang.php b/lib/plugins/revert/lang/cs/lang.php index 5414ea1e5..dd8d7845c 100644 --- a/lib/plugins/revert/lang/cs/lang.php +++ b/lib/plugins/revert/lang/cs/lang.php @@ -12,6 +12,7 @@ * @author Vojta Beran * @author zbynek.krivka@seznam.cz * @author Bohumir Zamecnik + * @author Jakub A. Těšínský (j@kub.cz) */ $lang['menu'] = 'Obnova zaspamovaných stránek'; $lang['filter'] = 'Hledat zaspamované stránky'; diff --git a/lib/plugins/usermanager/lang/cs/lang.php b/lib/plugins/usermanager/lang/cs/lang.php index 8351c190b..6de408e14 100644 --- a/lib/plugins/usermanager/lang/cs/lang.php +++ b/lib/plugins/usermanager/lang/cs/lang.php @@ -11,6 +11,7 @@ * @author Vojta Beran * @author zbynek.krivka@seznam.cz * @author Bohumir Zamecnik + * @author Jakub A. Těšínský (j@kub.cz) */ $lang['menu'] = 'Správa uživatelů'; $lang['noauth'] = '(autentizace uživatelů není k dispozici)'; -- cgit v1.2.3 From de78e4ef14515e4248d5f637558ec451e018799c Mon Sep 17 00:00:00 2001 From: Anael Mobilia Date: Mon, 12 Nov 2012 21:43:53 +0100 Subject: French language update --- inc/lang/fr/admin.txt | 3 +- inc/lang/fr/adminplugins.txt | 2 +- inc/lang/fr/backlinks.txt | 2 +- inc/lang/fr/conflict.txt | 4 +- inc/lang/fr/diff.txt | 2 +- inc/lang/fr/draft.txt | 4 +- inc/lang/fr/edit.txt | 2 +- inc/lang/fr/index.txt | 4 +- inc/lang/fr/install.html | 10 +- inc/lang/fr/lang.php | 172 +++++++++++++------------- inc/lang/fr/locked.txt | 2 +- inc/lang/fr/mailtext.txt | 2 +- inc/lang/fr/mailwrap.html | 2 +- inc/lang/fr/newpage.txt | 2 +- inc/lang/fr/norev.txt | 2 +- inc/lang/fr/password.txt | 2 +- inc/lang/fr/preview.txt | 2 +- inc/lang/fr/pwconfirm.txt | 8 +- inc/lang/fr/read.txt | 2 +- inc/lang/fr/register.txt | 2 +- inc/lang/fr/registermail.txt | 6 +- inc/lang/fr/resendpwd.txt | 2 +- inc/lang/fr/stopwords.txt | 4 +- inc/lang/fr/subscr_digest.txt | 4 +- inc/lang/fr/subscr_form.txt | 2 +- inc/lang/fr/subscr_list.txt | 2 +- inc/lang/fr/subscr_single.txt | 4 +- inc/lang/fr/uploadmail.txt | 4 +- lib/plugins/acl/lang/fr/help.txt | 10 +- lib/plugins/acl/lang/fr/lang.php | 27 +++-- lib/plugins/config/lang/fr/intro.txt | 6 +- lib/plugins/config/lang/fr/lang.php | 175 ++++++++++++++------------- lib/plugins/plugin/lang/fr/admin_plugin.txt | 4 +- lib/plugins/plugin/lang/fr/lang.php | 45 +++---- lib/plugins/popularity/lang/fr/intro.txt | 6 +- lib/plugins/popularity/lang/fr/lang.php | 9 +- lib/plugins/popularity/lang/fr/submitted.txt | 3 +- lib/plugins/revert/lang/fr/intro.txt | 4 +- lib/plugins/revert/lang/fr/lang.php | 9 +- lib/plugins/usermanager/lang/fr/edit.txt | 2 +- lib/plugins/usermanager/lang/fr/lang.php | 21 ++-- 41 files changed, 297 insertions(+), 283 deletions(-) diff --git a/inc/lang/fr/admin.txt b/inc/lang/fr/admin.txt index 4477a512b..eeeb2317a 100644 --- a/inc/lang/fr/admin.txt +++ b/inc/lang/fr/admin.txt @@ -1,4 +1,3 @@ ====== Administration ====== -Ci-dessous, vous trouverez une liste des tâches administratives disponibles dans DokuWiki. - +Ci-dessous, vous trouverez une liste des tâches d'administration disponibles dans DokuWiki. diff --git a/inc/lang/fr/adminplugins.txt b/inc/lang/fr/adminplugins.txt index 42a3538ab..0b2bf18db 100644 --- a/inc/lang/fr/adminplugins.txt +++ b/inc/lang/fr/adminplugins.txt @@ -1 +1 @@ -===== Modules supplémentaires ===== \ No newline at end of file +===== Extensions ===== \ No newline at end of file diff --git a/inc/lang/fr/backlinks.txt b/inc/lang/fr/backlinks.txt index 6902b43e3..8e6d27d95 100644 --- a/inc/lang/fr/backlinks.txt +++ b/inc/lang/fr/backlinks.txt @@ -1,4 +1,4 @@ ====== Pages pointant sur la page en cours ====== -Ceci est la liste des pages qui pointent sur la page en cours. +Ceci est la liste des pages qui semblent pointer sur la page actuelle. diff --git a/inc/lang/fr/conflict.txt b/inc/lang/fr/conflict.txt index 8f527ee21..e34ec9743 100644 --- a/inc/lang/fr/conflict.txt +++ b/inc/lang/fr/conflict.txt @@ -1,6 +1,6 @@ -====== Une version plus récente existe déjà ====== +====== Une version plus récente existe ====== -Une version plus récente du document que vous avez modifié existe déjà. Cela se produit lorsqu'un autre utilisateur enregistre le document pendant que vous le modifiez. +Une version plus récente du document que vous avez modifié existe. Cela se produit lorsqu'un autre utilisateur enregistre une nouvelle version du document alors que vous le modifiez. Examinez attentivement les différences ci-dessous et décidez quelle version conserver. Si vous choisissez « Enregistrer », votre version sera enregistrée. Cliquez sur « Annuler » pour conserver la version actuelle. diff --git a/inc/lang/fr/diff.txt b/inc/lang/fr/diff.txt index 773695d6d..8569f3497 100644 --- a/inc/lang/fr/diff.txt +++ b/inc/lang/fr/diff.txt @@ -1,4 +1,4 @@ ====== Différences ====== -Cette page vous donne les différences entre la révision choisie et la version actuelle de la page. +Cette page vous affiche les différences entre la révision choisie et la version actuelle de la page. diff --git a/inc/lang/fr/draft.txt b/inc/lang/fr/draft.txt index a48554298..ab383ee2c 100644 --- a/inc/lang/fr/draft.txt +++ b/inc/lang/fr/draft.txt @@ -1,6 +1,6 @@ ====== Un fichier brouillon a été trouvé ====== -La dernière modification de cette page ne s'est pas terminée proprement. Dokuwiki a enregistré automatiquement un brouillon de votre travail que vous pouvez utiliser pour votre modification. Ci-dessous figurent les données enregistrées lors de votre dernière session. +La dernière modification de cette page ne s'est pas terminée correctement. DokuWiki a enregistré automatiquement un brouillon de votre travail que vous pouvez utiliser pour votre modification. Ci-dessous figurent les données enregistrées lors de votre dernière session. -À vous de décider si vous souhaitez //récupérer// votre session de modification passée, //supprimer// le brouillon enregistré automatiquement ou //annuler// le processus d'édition. +À vous de décider si vous souhaitez //récupérer// votre session de modification précédente, //supprimer// le brouillon enregistré automatiquement ou //annuler// le processus d'édition. diff --git a/inc/lang/fr/edit.txt b/inc/lang/fr/edit.txt index e30f1b78b..df8c9fc9e 100644 --- a/inc/lang/fr/edit.txt +++ b/inc/lang/fr/edit.txt @@ -1,2 +1,2 @@ -Modifiez cette page et cliquez sur « Enregistrer ». Voyez le [[:wiki:syntax|guide de la mise en page]] pour une aide à propos du formatage. Veuillez ne modifier cette page que si vous pouvez l'**améliorer**. Si vous souhaitez faire des tests, faites vos premiers pas dans le [[:playground:playground|bac à sable]]. +Modifiez cette page et cliquez sur « Enregistrer ». Voyez le [[:wiki:syntax|guide de mise en page]] pour une aide à propos du formatage. Veuillez ne modifier cette page que si vous pouvez l'**améliorer**. Si vous souhaitez faire des tests, faites vos premiers pas dans le [[:playground:playground|bac à sable]]. diff --git a/inc/lang/fr/index.txt b/inc/lang/fr/index.txt index c66c656ab..15e16734c 100644 --- a/inc/lang/fr/index.txt +++ b/inc/lang/fr/index.txt @@ -1,4 +1,4 @@ -====== Index ====== +====== Plan du site ====== -Voici un index de toutes les pages disponibles, triées par [[doku>fr:namespaces|catégorie]]. +Voici un plan du site de toutes les pages disponibles, triées par [[doku>fr:namespaces|catégories]]. diff --git a/inc/lang/fr/install.html b/inc/lang/fr/install.html index 91c9f2edf..6dcba25dc 100644 --- a/inc/lang/fr/install.html +++ b/inc/lang/fr/install.html @@ -1,13 +1,13 @@ -

Cette page vous assiste dans la première installation et la +

Cette page vous assiste dans l'installation et la configuration de DokuWiki. -Pour plus d'information sur cet installeur, reportez-vous à sa +Pour plus d'informations sur cet installateur, reportez-vous à sa page de documentation.

DokuWiki utilise des fichiers textes ordinaires pour stocker les pages du wiki et les autres informations associées à ces pages -(tel que images, index de recherche, anciennes révisions, etc.). Pour fonctionner correctement, DokuWiki doit avoir accès en écriture aux différents répertoires qui contiennent ces fichiers. L'installeur n'est pas capable de modifier les permissions sur les répertoires. Ceci doit être effectué directement sur la ligne de commande de votre shell, ou, si vous êtes hébergé, via FTP ou votre panneau de contrôle (tel que cPanel).

+(par exemple, les images, les index de recherche, les anciennes révisions, ...). Pour fonctionner correctement, DokuWiki doit avoir accès en écriture aux différents répertoires qui contiennent ces fichiers. Cet installateur n'est pas capable de modifier les autorisations sur les répertoires. Cette opération doit-être effectué directement depuis votre ligne de commande shell, ou, si vous êtes hébergé, via FTP ou votre panneau de contrôle (par exemple cPanel, Plesk, ...).

-

Cet installeur va paramétrer votre configuration de DokuWiki pour des ACL, qui permettront l'accès à un identifiant administrateur et l'accès au menu d'administration de DokuWiki pour l'ajout de modules externes (greffons), la gestion d'utilisateurs, la gestion de l'accès aux pages du wiki et les modifications des paramètres de configuration. Il n'est pas nécessaire au fonctionnement de DokuWiki, néanmoins il facilite l'administration de DokuWiki.

+

Cet installateur va paramétrer votre configuration de DokuWiki pour des contrôle d'accès (ACL), qui permettront l'accès à un identifiant administrateur et l'accès au menu d'administration de DokuWiki pour l'ajout d'extensions, la gestion d'utilisateurs, la gestion de l'accès aux pages du wiki et les modifications des paramètres de configuration. Les contrôle d'accès ne sont pas nécessaires au fonctionnement de DokuWiki, néanmoins elles facilitent l'administration de DokuWiki.

-

Les utilisateurs expérimentés ou ceux nécessitant des paramétrages particuliers devraient se reporter aux liens suivants pour les détails concernant les instructions d'installation et les paramètres de configuration.

+

Les utilisateurs expérimentés ou les utilisateurs possédants des besoins de configurations spécifiques devraient se reporter aux liens suivants pour les détails concernant les instructions d'installation et les paramètres de configuration.

diff --git a/inc/lang/fr/lang.php b/inc/lang/fr/lang.php index c4080bc50..44cf04e04 100644 --- a/inc/lang/fr/lang.php +++ b/inc/lang/fr/lang.php @@ -25,6 +25,7 @@ * @author skimpax@gmail.com * @author Yannick Aure * @author Olivier DUVAL + * @author Anael Mobilia */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -73,17 +74,17 @@ $lang['user'] = 'Utilisateur'; $lang['pass'] = 'Mot de passe'; $lang['newpass'] = 'Nouveau mot de passe'; $lang['oldpass'] = 'Mot de passe actuel'; -$lang['passchk'] = 'Répéter nouveau mot de passe'; +$lang['passchk'] = 'Répétez le mot de passe'; $lang['remember'] = 'Mémoriser'; $lang['fullname'] = 'Nom'; $lang['email'] = 'Adresse de courriel'; $lang['profile'] = 'Profil utilisateur'; $lang['badlogin'] = 'L\'utilisateur ou le mot de passe est incorrect.'; $lang['minoredit'] = 'Modification mineure'; -$lang['draftdate'] = 'Brouillon auto-enregistré le'; +$lang['draftdate'] = 'Brouillon enregistré de manière automatique le'; $lang['nosecedit'] = 'La page a changé entre temps, les informations de la section sont obsolètes ; la page complète a été chargée à la place.'; $lang['regmissing'] = 'Désolé, vous devez remplir tous les champs.'; -$lang['reguexists'] = 'Désolé, ce nom d\'utilisateur est déjà pris.'; +$lang['reguexists'] = 'Désolé, ce nom d\'utilisateur est déjà utilisé.'; $lang['regsuccess'] = 'L\'utilisateur a été créé. Le mot de passe a été expédié par courriel.'; $lang['regsuccess2'] = 'L\'utilisateur a été créé.'; $lang['regmailfail'] = 'Il semble y avoir un problème à l\'envoi du courriel. Contactez l\'administrateur.'; @@ -92,94 +93,94 @@ $lang['regbadpass'] = 'Les deux mots de passe fournis sont différent $lang['regpwmail'] = 'Votre mot de passe DokuWiki'; $lang['reghere'] = 'Vous n\'avez pas encore de compte ? Enregistrez-vous ici '; $lang['profna'] = 'Ce wiki ne permet pas de modifier les profils'; -$lang['profnochange'] = 'Pas de changement, rien à faire.'; +$lang['profnochange'] = 'Pas de modification, rien à faire.'; $lang['profnoempty'] = 'Un nom ou une adresse de courriel vide n\'est pas permis.'; $lang['profchanged'] = 'Mise à jour du profil réussie.'; -$lang['pwdforget'] = 'Mot de passe oublié ? Faites-vous envoyer votre mot de passe '; +$lang['pwdforget'] = 'Mot de passe oublié ? Obtenez-en un nouveau'; $lang['resendna'] = 'Ce wiki ne permet pas le renvoi de mot de passe.'; $lang['resendpwd'] = 'Définir un nouveau mot de passe pour'; $lang['resendpwdmissing'] = 'Désolé, vous devez remplir tous les champs.'; -$lang['resendpwdnouser'] = 'Désolé, cet utilisateur est introuvable dans notre base.'; -$lang['resendpwdbadauth'] = 'Désolé, ce code d\'authentification est invalide. Assurez-vous d\'avoir utilisé le lien de confirmation.'; -$lang['resendpwdconfirm'] = 'Un lien de confirmation vous a été envoyé par courriel.'; +$lang['resendpwdnouser'] = 'Désolé, cet utilisateur n\'existe pas dans notre base de données.'; +$lang['resendpwdbadauth'] = 'Désolé, ce code d\'authentification est invalide. Assurez-vous d\'avoir utilisé le lien de confirmation intégral.'; +$lang['resendpwdconfirm'] = 'Un lien de confirmation vous a été expédié par courriel.'; $lang['resendpwdsuccess'] = 'Votre nouveau mot de passe vous a été expédié par courriel.'; -$lang['license'] = 'Sauf mention contraire, le contenu de ce wiki est placé sous la licence suivante :'; +$lang['license'] = 'Sauf mention contraire, le contenu de ce wiki est placé sous les termes de la licence suivante :'; $lang['licenseok'] = 'Note : En modifiant cette page, vous acceptez que le contenu soit placé sous les termes de la licence suivante :'; $lang['searchmedia'] = 'Chercher le nom de fichier :'; $lang['searchmedia_in'] = 'Chercher dans %s'; $lang['txt_upload'] = 'Sélectionnez un fichier à envoyer '; -$lang['txt_filename'] = 'Donnez un « wikiname » (optionnel) '; -$lang['txt_overwrt'] = 'Écraser le fichier cible'; -$lang['maxuploadsize'] = 'Téléverser max. %s par fichier'; +$lang['txt_filename'] = 'Envoyer en tant que (optionnel) '; +$lang['txt_overwrt'] = 'Écraser le fichier cible (s\'il existe)'; +$lang['maxuploadsize'] = 'Taille d\'envoi maximale : %s par fichier'; $lang['lockedby'] = 'Actuellement bloqué par'; $lang['lockexpire'] = 'Le blocage expire à'; -$lang['js']['willexpire'] = 'Votre verrouillage pour la modification de cette page expire dans une minute.\nPour éviter les conflits, utilisez le bouton « Aperçu » pour réinitialiser le minuteur.'; +$lang['js']['willexpire'] = 'Votre blocage pour la modification de cette page expire dans une minute.\nPour éviter les conflits, utilisez le bouton « Aperçu » pour réinitialiser le minuteur.'; $lang['js']['notsavedyet'] = 'Les modifications non enregistrées seront perdues. Voulez-vous vraiment continuer ?'; $lang['js']['searchmedia'] = 'Chercher des fichiers'; -$lang['js']['keepopen'] = 'Gardez cette fenêtre toujours ouverte'; -$lang['js']['hidedetails'] = 'Masquer détails'; +$lang['js']['keepopen'] = 'Toujours conserver cette fenêtre ouverte'; +$lang['js']['hidedetails'] = 'Masquer les détails'; $lang['js']['mediatitle'] = 'Paramètres de lien'; $lang['js']['mediadisplay'] = 'Type de lien'; $lang['js']['mediaalign'] = 'Alignement'; -$lang['js']['mediasize'] = 'Taille d\'image'; +$lang['js']['mediasize'] = 'Taille de l\'image'; $lang['js']['mediatarget'] = 'Cible du lien'; $lang['js']['mediaclose'] = 'Fermer'; $lang['js']['mediainsert'] = 'Insérer'; $lang['js']['mediadisplayimg'] = 'Afficher l\'image.'; $lang['js']['mediadisplaylnk'] = 'N\'afficher que le lien.'; $lang['js']['mediasmall'] = 'Petite taille'; -$lang['js']['mediamedium'] = 'taille moyenne'; +$lang['js']['mediamedium'] = 'Taille moyenne'; $lang['js']['medialarge'] = 'Grande taille'; -$lang['js']['mediaoriginal'] = 'taille d\'origine'; +$lang['js']['mediaoriginal'] = 'Taille originelle'; $lang['js']['medialnk'] = 'Lien vers la page de détail'; $lang['js']['mediadirect'] = 'Lien direct vers l\'original'; $lang['js']['medianolnk'] = 'Aucun lien'; $lang['js']['medianolink'] = 'Ne pas lier l\'image'; -$lang['js']['medialeft'] = 'Aligner l\'image sur la gauche.'; -$lang['js']['mediaright'] = 'Aligner l\'image sur la droite.'; -$lang['js']['mediacenter'] = 'Centrer l\'image'; +$lang['js']['medialeft'] = 'Aligner l\'image à gauche.'; +$lang['js']['mediaright'] = 'Aligner l\'image à droite.'; +$lang['js']['mediacenter'] = 'Centrer l\'image.'; $lang['js']['medianoalign'] = 'Ne pas aligner.'; $lang['js']['nosmblinks'] = 'Les liens vers les partages Windows ne fonctionnent qu\'avec Microsoft Internet Explorer.\nVous pouvez toujours copier puis coller le lien.'; $lang['js']['linkwiz'] = 'Assistant Lien'; $lang['js']['linkto'] = 'Lien vers :'; -$lang['js']['del_confirm'] = 'Effacer cette entrée ?'; -$lang['js']['restore_confirm'] = 'Voulez vous vraiment restaurer cette version ?'; -$lang['js']['media_diff'] = 'Voir les différences:'; +$lang['js']['del_confirm'] = 'Voulez-vous vraiment effacer ce(s) élément(s) ?'; +$lang['js']['restore_confirm'] = 'Voulez-vous vraiment restaurer cette version ?'; +$lang['js']['media_diff'] = 'Voir les différences :'; $lang['js']['media_diff_both'] = 'Côte à côte'; $lang['js']['media_diff_opacity'] = 'Calque'; $lang['js']['media_diff_portions'] = 'Curseur'; $lang['js']['media_select'] = 'Sélection de fichiers…'; -$lang['js']['media_upload_btn'] = 'Télécharger'; +$lang['js']['media_upload_btn'] = 'Envoyer'; $lang['js']['media_done_btn'] = 'Terminé'; -$lang['js']['media_drop'] = 'Déposez des fichiers ici pour les télécharger'; +$lang['js']['media_drop'] = 'Déposez des fichiers ici pour les envoyer'; $lang['js']['media_cancel'] = 'supprimer'; $lang['js']['media_overwrt'] = 'Écraser les fichiers existants'; $lang['rssfailed'] = 'Une erreur s\'est produite en récupérant ce flux : '; $lang['nothingfound'] = 'Pas de réponse.'; -$lang['mediaselect'] = 'Sélection de fichier'; +$lang['mediaselect'] = 'Sélection de fichiers'; $lang['fileupload'] = 'Envoi de fichier'; -$lang['uploadsucc'] = 'Téléversement réussi'; -$lang['uploadfail'] = 'Le téléversement n\'a pas réussi. Les permissions sont-elles correctes ?'; -$lang['uploadwrong'] = 'Téléversement refusé. Cette extension de fichier est interdite !'; -$lang['uploadexist'] = 'Le fichier existe. Téléversement avorté.'; -$lang['uploadbadcontent'] = 'Le contenu envoyé ne correspond pas à l\'extension du fichier %s.'; -$lang['uploadspam'] = 'Le téléversement a été bloqué par la liste noire antispam.'; -$lang['uploadxss'] = 'Le téléversement a été bloqué car son contenu est peut-être malveillant.'; -$lang['uploadsize'] = 'Le fichier téléversé était trop gros. (max. %s)'; +$lang['uploadsucc'] = 'Envoi réussi'; +$lang['uploadfail'] = 'L\'envoi a échoué. Les autorisations sont-elles correctes ?'; +$lang['uploadwrong'] = 'Envoi refusé. Cette extension de fichier est interdite !'; +$lang['uploadexist'] = 'Le fichier existe déjà. L\'envoi a été annulé.'; +$lang['uploadbadcontent'] = 'Le contenu envoyé ne correspond pas à l\'extension du fichier (%s).'; +$lang['uploadspam'] = 'L\'envoi a été bloqué par la liste noire de l\'anti-spam.'; +$lang['uploadxss'] = 'L\'envoi a été bloqué car son contenu est peut-être malveillant.'; +$lang['uploadsize'] = 'Le fichier envoyé était trop gros. (max. : %s)'; $lang['deletesucc'] = 'Le fichier « %s » a été effacé.'; -$lang['deletefail'] = 'Le fichier « %s » n\'a pu être effacé, vérifier les permissions.'; -$lang['mediainuse'] = 'Le fichier « %s » n\'a pas été effacé, il est en cours d\'utilisation.'; +$lang['deletefail'] = 'Le fichier « %s » n\'a pas pu être effacé. Vérifiez les autorisations.'; +$lang['mediainuse'] = 'Le fichier « %s » n\'a pas été effacé : il est en toujours utilisé.'; $lang['namespaces'] = 'Catégories'; $lang['mediafiles'] = 'Fichiers disponibles dans'; $lang['accessdenied'] = 'Vous n\'êtes pas autorisé à voir cette page.'; $lang['mediausage'] = 'Utilisez la syntaxe suivante pour faire référence à ce fichier :'; $lang['mediaview'] = 'Afficher le fichier original'; $lang['mediaroot'] = 'racine'; -$lang['mediaupload'] = 'Téléverser un fichier dans la catégorie actuelle. Pour créer des sous-catégories, préfixez le nom du fichier par le nom de la sous-catégorie séparée par un double-point.'; -$lang['mediaextchange'] = 'Extension du fichier changée de .%s en .%s !'; +$lang['mediaupload'] = 'Envoyez un fichier dans la catégorie actuelle. Pour créer des sous-catégories, préfixez en le nom du fichier séparées par un double-point, après avoir choisis le(s) fichier(s). Le(s) fichier(s) peuvent également être envoyé(s) par glisser-déposer (drag & drop)'; +$lang['mediaextchange'] = 'Extension du fichier modifiée de .%s en .%s !'; $lang['reference'] = 'Références pour'; -$lang['ref_inuse'] = 'Le fichier ne peut être effacé car il est utilisé par les pages suivantes :'; -$lang['ref_hidden'] = 'Des références existent dans des pages que vous n\'avez pas la permission de lire'; +$lang['ref_inuse'] = 'Le fichier ne peut être effacé car il est toujours utilisé par les pages suivantes :'; +$lang['ref_hidden'] = 'Des références sont présentes dans des pages que vous ne pouvez pas voir (autorisations insuffisantes)'; $lang['hits'] = 'Occurrences trouvées'; $lang['quickhits'] = 'Pages trouvées '; $lang['toc'] = 'Table des matières'; @@ -187,7 +188,7 @@ $lang['current'] = 'Version actuelle'; $lang['yours'] = 'Votre version'; $lang['diff'] = 'Différences avec la version actuelle'; $lang['diff2'] = 'Différences entre les versions sélectionnées'; -$lang['difflink'] = 'Lien vers cette vue'; +$lang['difflink'] = 'Lien vers cette vue comparative'; $lang['diff_type'] = 'Voir les différences :'; $lang['diff_inline'] = 'Sur une seule ligne'; $lang['diff_side'] = 'Côte à côte'; @@ -196,18 +197,19 @@ $lang['breadcrumb'] = 'Piste'; $lang['youarehere'] = 'Vous êtes ici'; $lang['lastmod'] = 'Dernière modification'; $lang['by'] = 'par'; -$lang['deleted'] = 'effacée'; +$lang['deleted'] = 'supprimée'; $lang['created'] = 'créée'; -$lang['restored'] = 'ancienne révision restaurée'; +$lang['restored'] = 'ancienne révision (%s) restaurée'; $lang['external_edit'] = 'modification externe'; $lang['summary'] = 'Résumé'; -$lang['noflash'] = 'Le greffon Adobe Flash est nécessaire pour afficher ce contenu.'; +$lang['noflash'] = 'L\'extension Adobe Flash est nécessaire pour afficher ce contenu.'; $lang['download'] = 'Télécharger un extrait'; $lang['tools'] = 'Outils'; -$lang['user_tools'] = 'Outils d\'utilisateurs'; -$lang['site_tools'] = 'Outils du Site'; -$lang['page_tools'] = 'Outils de la Page'; +$lang['user_tools'] = 'Outils pour utilisateurs'; +$lang['site_tools'] = 'Outils du site'; +$lang['page_tools'] = 'Outils de la page'; $lang['skip_to_content'] = 'Aller au contenu'; +$lang['sidebar'] = 'Panneau latéral'; $lang['mail_newpage'] = 'page ajoutée :'; $lang['mail_changed'] = 'page modifiée :'; $lang['mail_subscribe_list'] = 'pages modifiées dans la catégorie :'; @@ -215,13 +217,13 @@ $lang['mail_new_user'] = 'nouvel utilisateur :'; $lang['mail_upload'] = 'fichier envoyé :'; $lang['changes_type'] = 'Voir les changements'; $lang['pages_changes'] = 'Pages'; -$lang['media_changes'] = 'Fichier multimédias'; +$lang['media_changes'] = 'Fichiers multimédias'; $lang['both_changes'] = 'Pages et fichiers multimédias'; -$lang['qb_bold'] = 'Emphase forte (gras)'; -$lang['qb_italic'] = 'Emphase (italique)'; -$lang['qb_underl'] = 'Souligné'; +$lang['qb_bold'] = 'Gras'; +$lang['qb_italic'] = 'Italique'; +$lang['qb_underl'] = 'Soulignage'; $lang['qb_code'] = 'Code « machine à écrire »'; -$lang['qb_strike'] = 'Texte barré'; +$lang['qb_strike'] = 'Barré'; $lang['qb_h1'] = 'Titre de niveau 1'; $lang['qb_h2'] = 'Titre de niveau 2'; $lang['qb_h3'] = 'Titre de niveau 3'; @@ -237,14 +239,14 @@ $lang['qb_extlink'] = 'Lien externe'; $lang['qb_hr'] = 'Ligne horizontale'; $lang['qb_ol'] = 'Liste numérotée'; $lang['qb_ul'] = 'Liste à puce'; -$lang['qb_media'] = 'Ajouter des images ou d\'autres fichiers'; +$lang['qb_media'] = 'Ajouter des images ou autres fichiers'; $lang['qb_sig'] = 'Insérer une signature'; $lang['qb_smileys'] = 'Émoticones'; $lang['qb_chars'] = 'Caractères spéciaux'; $lang['upperns'] = 'Aller à la catégorie parente'; $lang['admin_register'] = 'Ajouter un nouvel utilisateur'; $lang['metaedit'] = 'Modifier les métadonnées'; -$lang['metasaveerr'] = 'Erreur lors de l\'écriture des métadonnées'; +$lang['metasaveerr'] = 'Erreur lors de l\'enregistrement des métadonnées'; $lang['metasaveok'] = 'Métadonnées enregistrées'; $lang['img_backto'] = 'Retour à'; $lang['img_title'] = 'Titre'; @@ -252,7 +254,7 @@ $lang['img_caption'] = 'Légende'; $lang['img_date'] = 'Date'; $lang['img_fname'] = 'Nom de fichier'; $lang['img_fsize'] = 'Taille'; -$lang['img_artist'] = 'Auteur'; +$lang['img_artist'] = 'Photographe'; $lang['img_copyr'] = 'Copyright'; $lang['img_format'] = 'Format'; $lang['img_camera'] = 'Appareil photo'; @@ -261,47 +263,47 @@ $lang['img_width'] = 'Largeur'; $lang['img_height'] = 'Hauteur'; $lang['img_manager'] = 'Voir dans le gestionnaire de médias'; $lang['subscr_subscribe_success'] = '%s a été ajouté à la liste de souscription de %s'; -$lang['subscr_subscribe_error'] = 'Erreur en ajoutant %s à la liste de souscription de %s'; +$lang['subscr_subscribe_error'] = 'Erreur à l\'ajout de %s à la liste de souscription de %s'; $lang['subscr_subscribe_noaddress'] = 'Il n\'y a pas d\'adresse associée à votre identifiant, vous ne pouvez pas être ajouté à la liste de souscription'; -$lang['subscr_unsubscribe_success'] = '%s a été retiré de la liste de souscription de %s'; -$lang['subscr_unsubscribe_error'] = 'Erreur en retirant %s de la liste de souscription de %s'; +$lang['subscr_unsubscribe_success'] = '%s a été supprimé de la liste de souscription de %s'; +$lang['subscr_unsubscribe_error'] = 'Erreur au retrait de %s de la liste de souscription de %s'; $lang['subscr_already_subscribed'] = '%s est déjà souscrit à %s'; $lang['subscr_not_subscribed'] = '%s n\'est pas souscrit à %s'; -$lang['subscr_m_not_subscribed'] = 'Vous n\'avez pas souscrit pour l\'instant à la page actuelle ou la catégorie'; +$lang['subscr_m_not_subscribed'] = 'Vous n\'avez pas souscrit pour l\'instant à la page actuelle ou à la catégorie'; $lang['subscr_m_new_header'] = 'Ajouter une souscription'; $lang['subscr_m_current_header'] = 'Souscriptions actives'; $lang['subscr_m_unsubscribe'] = 'Annuler la souscription'; $lang['subscr_m_subscribe'] = 'Souscrire'; $lang['subscr_m_receive'] = 'Recevoir'; -$lang['subscr_style_every'] = 'Envoyer un courriel à chaque modification'; +$lang['subscr_style_every'] = 'Recevoir un courriel à chaque modification'; $lang['subscr_style_digest'] = 'Courriel, tous les %.2f jours, résumant les modifications de chaque page'; $lang['subscr_style_list'] = 'Liste des pages modifiées depuis le dernier courriel (tous les %.2f jours)'; -$lang['authmodfailed'] = 'Mauvais paramétrage de l\'authentification. Merci d\'informer l\'administrateur du Wiki.'; -$lang['authtempfail'] = 'L\'authentification est temporairement indisponible. Si cela perdure, merci d\'informer l\'administrateur du Wiki.'; +$lang['authmodfailed'] = 'Mauvais paramétrage de l\'authentification. Merci d\'en informer l\'administrateur du wiki.'; +$lang['authtempfail'] = 'L\'authentification est temporairement indisponible. Si cela perdure, merci d\'en informer l\'administrateur du wiki.'; $lang['authpwdexpire'] = 'Votre mot de passe expirera dans %d jours, vous devriez le changer bientôt.'; $lang['i_chooselang'] = 'Choisissez votre langue'; -$lang['i_installer'] = 'Installeur DokuWiki'; +$lang['i_installer'] = 'Installateur DokuWiki'; $lang['i_wikiname'] = 'Nom du wiki'; -$lang['i_enableacl'] = 'Activer les ACL (recommandé)'; +$lang['i_enableacl'] = 'Activer le contrôle d\'accès (recommandé)'; $lang['i_superuser'] = 'Super-utilisateur'; -$lang['i_problems'] = 'L\'installeur a détecté les problèmes indiqués ci-dessous. Vous ne pouvez poursuivre tant qu\'ils n\'auront pas été corrigés.'; -$lang['i_modified'] = 'Pour des raisons de sécurité ce script ne fonctionne qu\'avec une installation neuve et non modifiée de DokuWiki. Vous devriez ré-extraire les fichiers depuis le paquet téléchargé ou consulter les instructions d\'installation de DokuWiki'; -$lang['i_funcna'] = 'La fonction PHP %s n\'est pas disponible. Peut-être que votre hébergeur l\'a désactivée ?'; +$lang['i_problems'] = 'L\'installateur a détecté les problèmes indiqués ci-dessous. Vous ne pouvez pas poursuivre l\'installation tant qu\'ils n\'auront pas été corrigés.'; +$lang['i_modified'] = 'Pour des raisons de sécurité, ce script ne fonctionne qu\'avec une installation neuve et non modifiée de DokuWiki. Vous devriez ré-extraire les fichiers depuis le paquet téléchargé ou consulter les instructions d\'installation de DokuWiki'; +$lang['i_funcna'] = 'La fonction PHP %s n\'est pas disponible. Peut-être que votre hébergeur web l\'a désactivée ?'; $lang['i_phpver'] = 'Votre version de PHP (%s) est antérieure à la version requise (%s). Vous devez mettre à jour votre installation de PHP.'; -$lang['i_permfail'] = '%s n\'est pas accessible en écriture pour DokuWiki. Vous devez corriger les permissions de ce répertoire !'; +$lang['i_permfail'] = '%s n\'est pas accessible en écriture pour DokuWiki. Vous devez corriger les autorisations de ce répertoire !'; $lang['i_confexists'] = '%s existe déjà'; -$lang['i_writeerr'] = 'Impossible de créer %s. Vous devez vérifier les permissions des répertoires/fichiers et créer le fichier manuellement.'; +$lang['i_writeerr'] = 'Impossible de créer %s. Vous devez vérifier les autorisations des répertoires/fichiers et créer le fichier manuellement.'; $lang['i_badhash'] = 'dokuwiki.php non reconnu ou modifié (hash=%s)'; $lang['i_badval'] = '%s - valeur interdite ou vide'; $lang['i_success'] = 'L\'installation s\'est terminée avec succès. Vous pouvez maintenant supprimer le fichier « install.php ». Continuer avec votre nouveau DokuWiki.'; $lang['i_failure'] = 'Des erreurs sont survenues lors de l\'écriture des fichiers de configuration. Il vous faudra les corriger manuellement avant de pouvoir utiliser votre nouveau DokuWiki.'; -$lang['i_policy'] = 'Politique d\'ACL initiale'; +$lang['i_policy'] = 'Politique de contrôle d\'accès initiale'; $lang['i_pol0'] = 'Wiki ouvert (lecture, écriture, envoi de fichiers pour tout le monde)'; $lang['i_pol1'] = 'Wiki public (lecture pour tout le monde, écriture et envoi de fichiers pour les utilisateurs enregistrés)'; $lang['i_pol2'] = 'Wiki fermé (lecture, écriture, envoi de fichiers pour les utilisateurs enregistrés uniquement)'; $lang['i_retry'] = 'Réessayer'; -$lang['i_license'] = 'Veuillez choisir la licence sous laquelle placer votre contenu :'; -$lang['recent_global'] = 'Vous êtes actuellement en train de regarder les modifications au sein de la catégorie %s. Vous pouvez aussi voir les récentes modifications sur tout le wiki.'; +$lang['i_license'] = 'Veuillez choisir la licence sous laquelle vous souhaitez placer votre contenu :'; +$lang['recent_global'] = 'Vous êtes actuellement en train de regarder les modifications au sein de la catégorie %s. Vous pouvez également afficher les derniers changements sur l\'ensemble du wiki.'; $lang['years'] = 'il y a %d ans'; $lang['months'] = 'il y a %d mois'; $lang['weeks'] = 'il y a %d semaines'; @@ -309,27 +311,27 @@ $lang['days'] = 'il y a %d jours'; $lang['hours'] = 'il y a %d heures'; $lang['minutes'] = 'il y a %d minutes'; $lang['seconds'] = 'il y a %d secondes'; -$lang['wordblock'] = 'Vos modifications n\'ont pas été sauvegardées parce qu\'elles contiennent des textes non autorisé (spam).'; -$lang['media_uploadtab'] = 'Télécharger'; +$lang['wordblock'] = 'Vos modifications n\'ont pas été enregistrées car elles contiennent du texte non autorisé (spam).'; +$lang['media_uploadtab'] = 'Envoyer'; $lang['media_searchtab'] = 'Rechercher'; $lang['media_file'] = 'Fichier'; $lang['media_viewtab'] = 'Voir'; $lang['media_edittab'] = 'Éditer'; $lang['media_historytab'] = 'Historique'; -$lang['media_list_thumbs'] = 'Aperçus'; +$lang['media_list_thumbs'] = 'Miniatures'; $lang['media_list_rows'] = 'Lignes'; -$lang['media_sort_name'] = 'Tri par nom'; -$lang['media_sort_date'] = 'Tri par date'; -$lang['media_namespaces'] = 'Choisissez un espace de nom'; -$lang['media_files'] = 'Fichiers de %s'; -$lang['media_upload'] = 'Télécharger dans %s.'; -$lang['media_search'] = 'Chercher dans %s.'; +$lang['media_sort_name'] = 'Nom'; +$lang['media_sort_date'] = 'Date'; +$lang['media_namespaces'] = 'Choisissez une catégorie'; +$lang['media_files'] = 'Fichiers dans %s'; +$lang['media_upload'] = 'Envoyer vers %s.'; +$lang['media_search'] = 'Rechercher dans %s.'; $lang['media_view'] = '%s'; $lang['media_viewold'] = '%s dans %s'; $lang['media_edit'] = 'Éditer %s'; $lang['media_history'] = 'Historique de %s'; $lang['media_meta_edited'] = 'métadonnées éditées'; -$lang['media_perm_read'] = 'Désolé, vous n\'avez pas les droits pour lire les fichiers.'; -$lang['media_perm_upload'] = 'Désolé, vous n\'avez pas les droits pour télécharger des fichiers.'; -$lang['media_update'] = 'Télécharger une nouvelle version'; +$lang['media_perm_read'] = 'Désolé, vous n\'avez pas l\'autorisation de voir les fichiers.'; +$lang['media_perm_upload'] = 'Désolé, vous n\'avez pas l\'autorisation d\'envoyer des fichiers.'; +$lang['media_update'] = 'Envoyer une nouvelle version'; $lang['media_restore'] = 'Restaurer cette version'; diff --git a/inc/lang/fr/locked.txt b/inc/lang/fr/locked.txt index 82cdd7373..fe88b57c8 100644 --- a/inc/lang/fr/locked.txt +++ b/inc/lang/fr/locked.txt @@ -1,3 +1,3 @@ ====== Page bloquée ====== -Cette page est actuellement bloquée pour modification par un autre utilisateur. Vous devez attendre que l'autre utilisateur ait terminé ou que le blocage de la page expire. +Cette page est actuellement bloquée pour modification par un autre utilisateur. Vous devez attendre que cet utilisateur ait terminé ou que le blocage de la page expire. diff --git a/inc/lang/fr/mailtext.txt b/inc/lang/fr/mailtext.txt index 3c2d53292..3f191756a 100644 --- a/inc/lang/fr/mailtext.txt +++ b/inc/lang/fr/mailtext.txt @@ -14,5 +14,5 @@ Utilisateur : @USER@ -- -Ce courriel a été généré par DokuWiki +Ce courriel a été généré par DokuWiki depuis @DOKUWIKIURL@ diff --git a/inc/lang/fr/mailwrap.html b/inc/lang/fr/mailwrap.html index 2b674196b..aa5011021 100644 --- a/inc/lang/fr/mailwrap.html +++ b/inc/lang/fr/mailwrap.html @@ -8,6 +8,6 @@ @HTMLBODY@

-Ce courriel a été automatiquement généré par DokuWiki à l'adresse @DOKUWIKIURL@. +Ce courriel a été automatiquement généré par DokuWiki depuis @DOKUWIKIURL@. \ No newline at end of file diff --git a/inc/lang/fr/newpage.txt b/inc/lang/fr/newpage.txt index 0ed2b25af..b23bf4fe4 100644 --- a/inc/lang/fr/newpage.txt +++ b/inc/lang/fr/newpage.txt @@ -1,4 +1,4 @@ ====== Cette page n'existe pas encore ====== -Vous avez suivi un lien vers une page qui n'existe pas encore. Si vos droits sont suffisants, vous pouvez utiliser le bouton ou le lien « Créer cette page ». +Vous avez suivi un lien vers une page qui n'existe pas encore. Si vos autorisations sont suffisants, vous pouvez la créer en cliquant sur « Créer cette page ». diff --git a/inc/lang/fr/norev.txt b/inc/lang/fr/norev.txt index 3f96b6aff..0d40dbe05 100644 --- a/inc/lang/fr/norev.txt +++ b/inc/lang/fr/norev.txt @@ -1,4 +1,4 @@ ====== Révision non trouvée ====== -La révision demandée n'existe pas. Utilisez le bouton ou le lien « Anciennes révisions » pour une liste des révisions de ce document. +La révision demandée n'existe pas. Cliquez sur « Anciennes révisions » pour obtenir une liste des révisions de ce document. diff --git a/inc/lang/fr/password.txt b/inc/lang/fr/password.txt index f4500fc85..47cb391d2 100644 --- a/inc/lang/fr/password.txt +++ b/inc/lang/fr/password.txt @@ -6,5 +6,5 @@ Utilisateur : @LOGIN@ Mot de passe : @PASSWORD@ -- -Ce courriel a été envoyé par DokuWiki de +Ce courriel a été envoyé par DokuWiki depuis @DOKUWIKIURL@ diff --git a/inc/lang/fr/preview.txt b/inc/lang/fr/preview.txt index 26fbcd9c2..00f09e218 100644 --- a/inc/lang/fr/preview.txt +++ b/inc/lang/fr/preview.txt @@ -1,4 +1,4 @@ ====== Aperçu ====== -Ceci est un aperçu de votre document. Attention ! Il n'est **pas encore enregistré** ! +Ceci est un aperçu de votre document. Attention : il n'est **pas encore enregistré** ! diff --git a/inc/lang/fr/pwconfirm.txt b/inc/lang/fr/pwconfirm.txt index af84833df..5cbfb2241 100644 --- a/inc/lang/fr/pwconfirm.txt +++ b/inc/lang/fr/pwconfirm.txt @@ -1,15 +1,15 @@ Bonjour @FULLNAME@ ! Quelqu'un a demandé un nouveau mot de passe pour votre identifiant -@TITLE@ sur @DOKUWIKIURL@ +@TITLE@ depuis @DOKUWIKIURL@ Si vous n'êtes pas à l'origine de cette requête d'un nouveau mot de -passe, ignorez ce message. +passe, ignorez simplement ce message. -Pour confirmer que cette requête émane bien de vous, merci de suivre le lien ci-dessous. +Pour confirmer que cette requête émane bien de vous, merci de cliquer sur le lien ci-dessous. @CONFIRM@ -- -Ce courriel a été généré par DokuWiki +Ce courriel a été généré par DokuWiki depuis @DOKUWIKIURL@ diff --git a/inc/lang/fr/read.txt b/inc/lang/fr/read.txt index faa756e8b..6afb864a8 100644 --- a/inc/lang/fr/read.txt +++ b/inc/lang/fr/read.txt @@ -1,2 +1,2 @@ -Cette page est en lecture seule. Vous pouvez afficher le texte source, mais pas le modifier. Contactez votre administrateur si vous pensez qu'il s'agit d'une erreur. +Cette page est en lecture seule. Vous pouvez afficher le texte source, mais ne pourrez pas le modifier. Contactez votre administrateur si vous pensez qu'il s'agit d'une erreur. diff --git a/inc/lang/fr/register.txt b/inc/lang/fr/register.txt index e2d02f55c..f98383454 100644 --- a/inc/lang/fr/register.txt +++ b/inc/lang/fr/register.txt @@ -1,3 +1,3 @@ ====== S'enregistrer comme nouvel utilisateur ====== -Remplissez toutes les informations ci-dessous pour vous créer un compte sur ce Wiki. Assurez-vous de fournir une **adresse de courriel valide** car votre mot de passe sera envoyé à cette adresse. Le nom d'utilisateur doit être un [[doku>pagename|nom de page]] valide. +Remplissez toutes les informations ci-dessous pour vous créer un compte sur ce wiki. Assurez-vous de fournir une **adresse de courriel valide** - s'il ne vous est pas demandé de saisir un mot de passe ici, il vous sera expédié par courriel à cette adresse. Le nom d'utilisateur doit être un [[doku>pagename|nom de page]] valide. diff --git a/inc/lang/fr/registermail.txt b/inc/lang/fr/registermail.txt index 1beae8522..43d72dba9 100644 --- a/inc/lang/fr/registermail.txt +++ b/inc/lang/fr/registermail.txt @@ -2,13 +2,13 @@ Un nouvel utilisateur s'est enregistré. Voici les détails : Utilisateur : @NEWUSER@ Nom : @NEWNAME@ -Adresse de courriel : @NEWEMAIL@ +Courriel : @NEWEMAIL@ Date : @DATE@ -Navigateur : @BROWSER@ +Navigateur internet : @BROWSER@ Adresse IP : @IPADDRESS@ Nom d'hôte : @HOSTNAME@ -- -Ce courriel a été généré par DokuWiki +Ce courriel a été généré par DokuWiki depuis @DOKUWIKIURL@ diff --git a/inc/lang/fr/resendpwd.txt b/inc/lang/fr/resendpwd.txt index 44fbeef03..91dd92482 100644 --- a/inc/lang/fr/resendpwd.txt +++ b/inc/lang/fr/resendpwd.txt @@ -1,4 +1,4 @@ ====== Envoyer un nouveau mot de passe ====== -Veuillez compléter les champs ci-dessous pour obtenir un nouveau mot de passe pour votre compte dans ce wiki. Un lien de confirmation vous sera envoyé à l'adresse de courriel utilisée lors de votre enregistrement. +Veuillez compléter les champs ci-dessous pour obtenir un nouveau mot de passe pour votre compte dans ce wiki. Un lien de confirmation vous sera expédié à l'adresse de courriel utilisée lors de votre enregistrement. diff --git a/inc/lang/fr/stopwords.txt b/inc/lang/fr/stopwords.txt index 981bae26b..5f187f7e1 100644 --- a/inc/lang/fr/stopwords.txt +++ b/inc/lang/fr/stopwords.txt @@ -1,5 +1,5 @@ -# Cette liste regroupe des mots ignorés par l'indexeur -# Chaque ligne comporte un mot +# Cette liste regroupe les mots ignorés par l'indexeur +# Un seul mot par ligne # Les fins de ligne de ce fichier doivent être de type UNIX # Les mots de moins de 3 lettres sont ignorés par défaut. # Cette liste est basée sur http://www.ranks.nl/stopwords/ diff --git a/inc/lang/fr/subscr_digest.txt b/inc/lang/fr/subscr_digest.txt index 1803407fa..7ec75ca76 100644 --- a/inc/lang/fr/subscr_digest.txt +++ b/inc/lang/fr/subscr_digest.txt @@ -1,6 +1,6 @@ Bonjour, -La page « @PAGE@ » dans le wiki « @TITLE@ » a été modifiée. Voici ces modifications : +La page « @PAGE@ » dans le wiki « @TITLE@ » a été modifiée. Voici les modifications : -------------------------------------------------------- @DIFF@ @@ -15,5 +15,5 @@ Pour annuler les notifications de page, connectez-vous au wiki à l'adresse et désabonnez-vous de la page ou de la catégorie. -- -Ce courriel a été généré par Dokuwiki : +Ce courriel a été généré par DokuWiki depuis @DOKUWIKIURL@ \ No newline at end of file diff --git a/inc/lang/fr/subscr_form.txt b/inc/lang/fr/subscr_form.txt index 528f77475..49c0cf443 100644 --- a/inc/lang/fr/subscr_form.txt +++ b/inc/lang/fr/subscr_form.txt @@ -1,3 +1,3 @@ ====== Gestion de l'abonnement ====== -Cette page vous permet de gérer vos abonnements à la page ou à la catégorie courantes \ No newline at end of file +Cette page vous permet de gérer vos abonnements à la page et à la catégorie courantes \ No newline at end of file diff --git a/inc/lang/fr/subscr_list.txt b/inc/lang/fr/subscr_list.txt index 3387b11ee..d8c6b68e4 100644 --- a/inc/lang/fr/subscr_list.txt +++ b/inc/lang/fr/subscr_list.txt @@ -1,6 +1,6 @@ Bonjour, -Des pages dans la catégorie « @PAGE@ » du wiki « @TITLE@ » ont été modifiées. Voici ces modifications : +Des pages de la catégorie « @PAGE@ » du wiki « @TITLE@ » ont été modifiées. Voici les modifications : -------------------------------------------------------- @DIFF@ diff --git a/inc/lang/fr/subscr_single.txt b/inc/lang/fr/subscr_single.txt index 1b9d5e1b5..236d45e8f 100644 --- a/inc/lang/fr/subscr_single.txt +++ b/inc/lang/fr/subscr_single.txt @@ -1,6 +1,6 @@ Bonjour, -La page « @PAGE@ » dans le wiki « @TITLE@ » a été modifiée. Voici ces modifications : +La page « @PAGE@ » dans le wiki « @TITLE@ » a été modifiée. Voici les modifications : -------------------------------------------------------- @DIFF@ @@ -18,5 +18,5 @@ Pour annuler les notifications de page, connectez-vous au wiki à l'adresse et désabonnez-vous de la page ou de la catégorie. -- -Ce courriel a été généré par Dokuwiki : +Ce courriel a été généré par Dokuwiki depuis @DOKUWIKIURL@ \ No newline at end of file diff --git a/inc/lang/fr/uploadmail.txt b/inc/lang/fr/uploadmail.txt index 05b3205d7..80be0de8c 100644 --- a/inc/lang/fr/uploadmail.txt +++ b/inc/lang/fr/uploadmail.txt @@ -1,4 +1,4 @@ -Un fichier a été téléversé dans votre wiki. En voici les détails : +Un fichier a été envoyé dans votre wiki. Voici les détails : Fichier : @MEDIA@ Date : @DATE@ @@ -10,5 +10,5 @@ Type MIME : @MIME@ Utilisateur : @USER@ -- -Ce message a été généré par DokuWiki +Ce message a été généré par DokuWiki depuis @DOKUWIKIURL@ diff --git a/lib/plugins/acl/lang/fr/help.txt b/lib/plugins/acl/lang/fr/help.txt index 158ec92ed..081978488 100644 --- a/lib/plugins/acl/lang/fr/help.txt +++ b/lib/plugins/acl/lang/fr/help.txt @@ -1,9 +1,11 @@ === Aide rapide === -Cette page vous permet d'ajouter ou de supprimer des permissions pour les catégories et les pages de votre wiki. Le panneau de gauche liste toutes les catégories et les pages disponibles. +Cette page vous permet d'ajouter ou de supprimer des autorisations pour les catégories et les pages de votre wiki. -Le formulaire ci-dessus permet d'afficher et de modifier les permissions d'un utilisateur ou d'un groupe sélectionné. +Le panneau de gauche liste toutes les catégories et les pages disponibles. -Dans le tableau ci-dessous, toutes les listes de contrôle d'accès actuelles sont affichées. Vous pouvez l'utiliser pour supprimer ou modifier rapidement plusieurs ACL. +Le formulaire ci-dessus permet d'afficher et de modifier les autorisations d'un utilisateur ou d'un groupe sélectionné. -La lecture de [[doku>fr:acl|la documentation officielle des ACL]] pourra vous permettre de bien comprendre le fonctionnement du contrôle d'accès dans DokuWiki. +Dans le tableau ci-dessous, toutes les listes de contrôle d'accès (ACL) actuelles sont affichées. Vous pouvez l'utiliser pour supprimer ou modifier rapidement plusieurs contrôles d'accès. + +La lecture de [[doku>fr:acl|la documentation officielle des contrôles d'accès]] pourra vous permettre de mieux comprendre le fonctionnement du contrôle d'accès dans DokuWiki. diff --git a/lib/plugins/acl/lang/fr/lang.php b/lib/plugins/acl/lang/fr/lang.php index b1b3188be..e52bf51a0 100644 --- a/lib/plugins/acl/lang/fr/lang.php +++ b/lib/plugins/acl/lang/fr/lang.php @@ -24,32 +24,33 @@ * @author skimpax@gmail.com * @author Yannick Aure * @author Olivier DUVAL + * @author Anael Mobilia */ $lang['admin_acl'] = 'Gestion de la liste des contrôles d\'accès (ACL)'; $lang['acl_group'] = 'Groupe'; $lang['acl_user'] = 'Utilisateur'; -$lang['acl_perms'] = 'Permission pour'; +$lang['acl_perms'] = 'Autorisations pour'; $lang['page'] = 'Page'; $lang['namespace'] = 'Catégorie'; $lang['btn_select'] = 'Sélectionner'; -$lang['p_user_id'] = 'Permissions actuelles de l\'utilisateur %s sur la page %s: %s.'; -$lang['p_user_ns'] = 'Permissions actuelles de l\'utilisateur %s sur la catégorie %s: %s.'; -$lang['p_group_id'] = 'Permissions actuelles des membres du groupe %s sur la page %s: %s.'; -$lang['p_group_ns'] = 'Permissions actuelles des membres du groupe %s sur la catégorie %s: %s.'; -$lang['p_choose_id'] = 'Saisissez un nom d\'utilisateur ou de groupe dans le formulaire ci-dessus pour afficher ou éditer les permissions relatives à la page %s.'; -$lang['p_choose_ns'] = 'Saisissez un nom d\'utilisateur ou de groupe dans le formulaire ci-dessous pour afficher ou éditer les permissions relatives à la catégorie %s.'; -$lang['p_inherited'] = 'Note : Ces permissions n\'ont pas été explicitement fixées mais sont héritées d\'autres groupes ou catégories supérieures.'; -$lang['p_isadmin'] = 'Note : Le groupe ou l\'utilisateur sélectionné dispose de toutes les permissions car il est paramétré en tant que superutilisateur.'; -$lang['p_include'] = 'Les permissions les plus élevées induisent les plus faibles. Création, Télécharger et Effacer ne s\'appliquent qu\'aux catégories, pas aux pages.'; -$lang['current'] = 'ACL actuelles'; +$lang['p_user_id'] = 'Autorisations actuelles de l\'utilisateur %s sur la page %s : %s.'; +$lang['p_user_ns'] = 'Autorisations actuelles de l\'utilisateur %s sur la catégorie %s : %s.'; +$lang['p_group_id'] = 'Autorisations actuelles des membres du groupe %s sur la page %s : %s.'; +$lang['p_group_ns'] = 'Autorisations actuelles des membres du groupe %s sur la catégorie %s : %s.'; +$lang['p_choose_id'] = 'Saisissez un nom d\'utilisateur ou de groupe dans le formulaire ci-dessous pour afficher ou éditer les autorisations relatives à la page %s.'; +$lang['p_choose_ns'] = 'Saisissez un nom d\'utilisateur ou de groupe dans le formulaire ci-dessous pour afficher ou éditer les autorisations relatives à la catégorie %s.'; +$lang['p_inherited'] = 'Note : ces autorisations n\'ont pas été explicitement définies mais sont héritées de groupes ou catégories supérieurs.'; +$lang['p_isadmin'] = 'Note : le groupe ou l\'utilisateur sélectionné dispose toujours de toutes les autorisations car il est paramétré en tant que super-utilisateur.'; +$lang['p_include'] = 'Les autorisations les plus élevées incluent les plus faibles. Création, Envoyer et Effacer ne s\'appliquent qu\'aux catégories, pas aux pages.'; +$lang['current'] = 'Contrôles d\'accès actuels'; $lang['where'] = 'Page/Catégorie'; $lang['who'] = 'Utilisateur/Groupe'; -$lang['perm'] = 'Permissions'; +$lang['perm'] = 'Autorisations'; $lang['acl_perm0'] = 'Aucune'; $lang['acl_perm1'] = 'Lecture'; $lang['acl_perm2'] = 'Écriture'; $lang['acl_perm4'] = 'Création'; -$lang['acl_perm8'] = 'Téléverser'; +$lang['acl_perm8'] = 'Envoyer'; $lang['acl_perm16'] = 'Effacer'; $lang['acl_new'] = 'Ajouter une nouvelle entrée'; $lang['acl_mod'] = 'Modifier l\'entrée'; diff --git a/lib/plugins/config/lang/fr/intro.txt b/lib/plugins/config/lang/fr/intro.txt index 2a59b34d1..3d71f6184 100644 --- a/lib/plugins/config/lang/fr/intro.txt +++ b/lib/plugins/config/lang/fr/intro.txt @@ -1,9 +1,9 @@ ====== Gestionnaire de configuration ====== -Utilisez cette page pour contrôler les paramètres de votre installation de DokuWiki. Pour de l'aide sur chaque paramètre, reportez vous à [[doku>fr:config]]. Pour d'autres détails concernant ce module, reportez vous à [[doku>fr:plugin:config]]. +Utilisez cette page pour contrôler les paramètres de votre installation de DokuWiki. Pour de l'aide sur chaque paramètre, reportez vous à [[doku>fr:config]]. Pour plus de détails concernant cette extension, reportez vous à [[doku>fr:plugin:config]]. -Les paramètres affichés sur un fond rouge sont protégés et ne peuvent être modifiés avec ce module. Les paramètres affichés sur un fond bleu sont les valeurs par défaut et les valeurs affectées à votre installation sont affichées sur un fond blanc. Les paramètres bleus et blancs peuvent être modifiés. +Les paramètres affichés sur un fond rouge sont protégés et ne peuvent être modifiés avec cette extension. Les paramètres affichés sur un fond bleu sont les valeurs par défaut et les valeurs spécifiquement définies pour votre installation sont affichées sur un fond blanc. Seuls les paramètres sur fond bleu ou blanc peuvent être modifiés. -N'oubliez pas d'utiliser le bouton **Enregistrer** avant de quitter cette page, sinon vos modifications seront perdues. +N'oubliez pas d'utiliser le bouton **ENREGISTRER** avant de quitter cette page, sinon vos modifications ne seront pas prises en compte ! diff --git a/lib/plugins/config/lang/fr/lang.php b/lib/plugins/config/lang/fr/lang.php index af2217af5..c4b521497 100644 --- a/lib/plugins/config/lang/fr/lang.php +++ b/lib/plugins/config/lang/fr/lang.php @@ -19,18 +19,19 @@ * @author skimpax@gmail.com * @author Yannick Aure * @author Olivier DUVAL + * @author Anael Mobilia */ $lang['menu'] = 'Paramètres de configuration'; -$lang['error'] = 'Paramètres non modifiés en raison d\'une valeur non valide, vérifiez vos réglages et réessayez.
Les valeurs erronées sont entourées d\'une bordure rouge.'; +$lang['error'] = 'Paramètres non modifiés en raison d\'une valeur invalide, vérifiez vos réglages puis réessayez.
Les valeurs erronées sont entourées d\'une bordure rouge.'; $lang['updated'] = 'Paramètres mis à jour avec succès.'; $lang['nochoice'] = '(aucun autre choix possible)'; -$lang['locked'] = 'Le fichier des paramètres ne peut être modifié, si ceci n\'est pas intentionnel,
vérifiez que le nom et les droits du fichier sont corrects.'; -$lang['danger'] = 'Danger : Modifier cette option pourrait rendre inaccessible votre wiki et son menu de configuration.'; -$lang['warning'] = 'Attention : Modifier cette option pourrait engendrer un comportement indésirable.'; -$lang['security'] = 'Avertissement de sécurité : Modifier cette option pourrait induire un risque de sécurité.'; +$lang['locked'] = 'Le fichier des paramètres ne peut être modifié, si ceci n\'est pas intentionnel,
vérifiez que le nom et les autorisations du fichier sont correctes.'; +$lang['danger'] = 'Danger : modifier cette option pourrait rendre inaccessibles votre wiki et son menu de configuration.'; +$lang['warning'] = 'Attention : modifier cette option pourrait engendrer un comportement indésirable.'; +$lang['security'] = 'Avertissement de sécurité : modifier cette option pourrait induire un risque de sécurité.'; $lang['_configuration_manager'] = 'Gestionnaire de configuration'; $lang['_header_dokuwiki'] = 'Paramètres de DokuWiki'; -$lang['_header_plugin'] = 'Paramètres des modules externes'; +$lang['_header_plugin'] = 'Paramètres des extensions'; $lang['_header_template'] = 'Paramètres des modèles'; $lang['_header_undefined'] = 'Paramètres indéfinis'; $lang['_basic'] = 'Paramètres de base'; @@ -39,54 +40,56 @@ $lang['_authentication'] = 'Paramètres d\'authentification'; $lang['_anti_spam'] = 'Paramètres anti-spam'; $lang['_editing'] = 'Paramètres d\'édition'; $lang['_links'] = 'Paramètres des liens'; -$lang['_media'] = 'Paramètres média'; -$lang['_notifications'] = 'Paramètres de Notification'; -$lang['_syndication'] = 'Paramètres de Syndication'; +$lang['_media'] = 'Paramètres des médias'; +$lang['_notifications'] = 'Paramètres de notification'; +$lang['_syndication'] = 'Paramètres de syndication'; $lang['_advanced'] = 'Paramètres avancés'; $lang['_network'] = 'Paramètres réseaux'; -$lang['_plugin_sufix'] = 'Paramètres de module'; +$lang['_plugin_sufix'] = 'Paramètres d\'extension'; $lang['_template_sufix'] = 'Paramètres de modèle'; -$lang['_msg_setting_undefined'] = 'Pas de métadonnée de paramètres.'; -$lang['_msg_setting_no_class'] = 'Pas de classe de paramètres.'; +$lang['_msg_setting_undefined'] = 'Pas de définition de métadonnées'; +$lang['_msg_setting_no_class'] = 'Pas de définition de paramètres.'; $lang['_msg_setting_no_default'] = 'Pas de valeur par défaut.'; -$lang['title'] = 'Titre du wiki'; -$lang['start'] = 'Nom de la page d\'accueil'; -$lang['lang'] = 'Langue'; -$lang['template'] = 'Modèle'; -$lang['license'] = 'Sous quelle licence doit être placé le contenu ?'; -$lang['savedir'] = 'Répertoire de stockage'; -$lang['basedir'] = 'Répertoire de base (ex. : /dokuwiki/). Laisser vide pour une détection automatique.'; -$lang['baseurl'] = 'URL de base. Laisser vide pour une détection automatique.'; +$lang['title'] = 'Titre du wiki (nom du wiki)'; +$lang['start'] = 'Nom de la page d\'accueil à utiliser pour toutes les catégories'; +$lang['lang'] = 'Langue de l\'interface'; +$lang['template'] = 'Modèle (rendu visuel du wiki)'; +$lang['tagline'] = 'Descriptif du site (si le modèle supporte cette fonctionnalité)'; +$lang['sidebar'] = 'Nom du panneau latéral (si le modèle supporte cette fonctionnalité). Laisser le champ vide désactive le panneau latéral.'; +$lang['license'] = 'Sous quelle licence doit-être placé le contenu ?'; +$lang['savedir'] = 'Répertoire d\'enregistrement des données'; +$lang['basedir'] = 'Répertoire de base du serveur (par exemple : /dokuwiki/). Laisser vide pour une détection automatique.'; +$lang['baseurl'] = 'URL de base du site (par exemple http://www.example.com). Laisser vide pour une détection automatique.'; $lang['cookiedir'] = 'Chemin des cookies. Laissez vide pour utiliser l\'URL de base.'; $lang['dmode'] = 'Mode de création des répertoires'; $lang['fmode'] = 'Mode de création des fichiers'; $lang['allowdebug'] = 'Debug (Ne l\'activez que si vous en avez besoin !)'; -$lang['recent'] = 'Nombre de derniers changements à afficher'; +$lang['recent'] = 'Nombre de lignes à afficher - par page - pour les derniers changements'; $lang['recent_days'] = 'Signaler les pages modifiées depuis (en jours)'; -$lang['breadcrumbs'] = 'Nombre de traces à afficher'; -$lang['youarehere'] = 'Traces hiérarchiques'; -$lang['fullpath'] = 'Utiliser le chemin complet dans le pied de page'; +$lang['breadcrumbs'] = 'Nombre de traces à afficher. 0 désactive cette fonctionnalité.'; +$lang['youarehere'] = 'Utiliser des traces hiérarchiques (vous voulez probablement désactiver l\'option ci-dessus)'; +$lang['fullpath'] = 'Afficher le chemin complet des pages dans le pied de page'; $lang['typography'] = 'Effectuer des améliorations typographiques'; $lang['dformat'] = 'Format de date (cf. fonction strftime de PHP)'; -$lang['signature'] = 'Signature'; -$lang['showuseras'] = 'Qu\'afficher en montrant les utilisateurs qui ont récemment modifié la page'; +$lang['signature'] = 'Données à insérer lors de l\'utilisation du bouton « signature » dans l\'éditeur'; +$lang['showuseras'] = 'Données à afficher concernant le dernier utilisateur ayant modifié une page'; $lang['toptoclevel'] = 'Niveau le plus haut à afficher dans la table des matières'; -$lang['tocminheads'] = 'Nombre minimum de titres pour qu\'une table des matières soit construite'; +$lang['tocminheads'] = 'Nombre minimum de titres pour qu\'une table des matières soit affichée'; $lang['maxtoclevel'] = 'Niveau maximum pour figurer dans la table des matières'; $lang['maxseclevel'] = 'Niveau maximum pour modifier des sections'; -$lang['camelcase'] = 'Utiliser CamelCase pour les liens'; +$lang['camelcase'] = 'Utiliser l\'affichage «CamelCase » pour les liens'; $lang['deaccent'] = 'Retirer les accents dans les noms de pages'; -$lang['useheading'] = 'Utiliser le titre de premier niveau'; -$lang['sneaky_index'] = 'Par défaut, DokuWiki affichera toutes les catégories dans la vue par index. Activer cette option permet de cacher celles pour lesquelles l\'utilisateur n\'a pas la permission de lecture. Il peut en résulter le masquage de sous-catégories accessibles. Ceci peut rendre l\'index inutilisable avec certaines ACL.'; +$lang['useheading'] = 'Utiliser le titre de premier niveau pour le nom de la page'; +$lang['sneaky_index'] = 'Par défaut, DokuWiki affichera toutes les catégories dans la vue par index. Activer cette option permet de cacher les catégories pour lesquelles l\'utilisateur n\'a pas l\'autorisation de lecture. Il peut en résulter le masquage de sous-catégories accessibles. Ceci peut rendre l\'index inutilisable avec certains contrôles d\'accès.'; $lang['hidepages'] = 'Cacher les pages correspondant à (expression régulière)'; $lang['useacl'] = 'Utiliser les listes de contrôle d\'accès (ACL)'; $lang['autopasswd'] = 'Auto-générer les mots de passe'; $lang['authtype'] = 'Mécanisme d\'authentification'; $lang['passcrypt'] = 'Méthode de chiffrement des mots de passe'; -$lang['defaultgroup'] = 'Groupe par défaut'; -$lang['superuser'] = 'Superuser - groupe, utilisateur ou liste séparée par des virgules user1,@group1,user2 ayant un accès complet à toutes les pages quelque soit le paramétrage des ACL'; -$lang['manager'] = 'Manager - groupe, utilisateur ou liste séparée par des virgules user1,@group1,user2 ayant accès à certaines fonctions de gestion'; -$lang['profileconfirm'] = 'Confirmer par mot de passe les modifications de profil'; +$lang['defaultgroup'] = 'Groupe par défaut : tous les nouveaux utilisateurs y seront affectés'; +$lang['superuser'] = 'Super-utilisateur : groupe, utilisateur ou liste séparée par des virgules utilisateur1,@groupe1,utilisateur2 ayant un accès complet à toutes les pages quelque soit le paramétrage des contrôle d\'accès'; +$lang['manager'] = 'Manager:- groupe, utilisateur ou liste séparée par des virgules utilisateur1,@groupe1,utilisateur2 ayant accès à certaines fonctionnalités de gestion'; +$lang['profileconfirm'] = 'Confirmer les modifications de profil par la saisie du mot de passe '; $lang['rememberme'] = 'Permettre de conserver de manière permanente les cookies de connexion (mémoriser)'; $lang['disableactions'] = 'Actions à désactiver dans DokuWiki'; $lang['disableactions_check'] = 'Vérifier'; @@ -94,74 +97,76 @@ $lang['disableactions_subscription'] = 'Abonnement aux pages'; $lang['disableactions_wikicode'] = 'Afficher le texte source'; $lang['disableactions_other'] = 'Autres actions (séparées par des virgules)'; $lang['auth_security_timeout'] = 'Délai d\'expiration de sécurité (secondes)'; -$lang['securecookie'] = 'Les cookies mis via HTTPS doivent-ils n\'être envoyé par le navigateur que via HTTPS ? Ne désactivez cette option que si la connexion à votre wiki est sécurisée avec SSL mais que la navigation sur le wiki n\'est pas sécurisée.'; -$lang['remote'] = 'Active l\'API système distante. Ceci autorise d\'autres applications à accéder au wiki via XML-RPC ou d\'autres mécanismes.'; -$lang['remoteuser'] = 'Restreindre l\'accès à l\'API par une liste de groupes ou d\'utilisateurs séparés par une virgule. Laisser vide pour donner l\'accès à n\'importe qui.'; +$lang['securecookie'] = 'Les cookies définis via HTTPS doivent-ils n\'être envoyé par le navigateur que via HTTPS ? Désactivez cette option lorsque seule la connexion à votre wiki est sécurisée avec SSL et que la navigation sur le wiki est effectuée de manière non sécurisée.'; +$lang['remote'] = 'Active l\'API système distante. Ceci permet à d\'autres applications d\'accéder au wiki via XML-RPC ou d\'autres mécanismes.'; +$lang['remoteuser'] = 'Restreindre l\'accès à l\'API à une liste de groupes ou d\'utilisateurs (séparés par une virgule). Laisser vide pour donner l\'accès tout le monde.'; $lang['usewordblock'] = 'Bloquer le spam selon les mots utilisés'; -$lang['relnofollow'] = 'Utiliser rel="nofollow" sur les liens extérieurs'; -$lang['indexdelay'] = 'Délai avant l\'indexation (en secondes)'; -$lang['mailguard'] = 'Brouiller les adresses de courriel'; -$lang['iexssprotect'] = 'Vérifier la présence de code JavaScript ou HTML malveillant dans les fichiers envoyés'; +$lang['relnofollow'] = 'Utiliser l\'attribut « rel="nofollow" » sur les liens extérieurs'; +$lang['indexdelay'] = 'Délai avant l\'indexation (secondes)'; +$lang['mailguard'] = 'Cacher les adresses de courriel'; +$lang['iexssprotect'] = 'Vérifier, dans les fichiers envoyés, la présence de code JavaScript ou HTML malveillant'; $lang['usedraft'] = 'Enregistrer automatiquement un brouillon pendant l\'édition'; -$lang['htmlok'] = 'Permettre HTML dans les pages'; -$lang['phpok'] = 'Permettre PHP dans les pages'; -$lang['locktime'] = 'Âge maximum des fichiers verrous (en secondes)'; -$lang['cachetime'] = 'Âge maximum d\'un fichier en cache (en secondes)'; +$lang['htmlok'] = 'Permettre l\'utilisation de code HTML dans les pages'; +$lang['phpok'] = 'Permettre l\'utilisation de code PHP dans les pages'; +$lang['locktime'] = 'Âge maximum des fichiers de blocage (secondes)'; +$lang['cachetime'] = 'Âge maximum d\'un fichier en cache (secondes)'; $lang['target____wiki'] = 'Cible pour liens internes'; $lang['target____interwiki'] = 'Cible pour liens interwiki'; $lang['target____extern'] = 'Cible pour liens externes'; $lang['target____media'] = 'Cible pour liens média'; $lang['target____windows'] = 'Cible pour liens vers partages Windows'; $lang['mediarevisions'] = 'Activer les révisions (gestion de versions) des médias'; -$lang['refcheck'] = 'Vérifier les références de média'; -$lang['refshow'] = 'Nombre de références de média à montrer'; -$lang['gdlib'] = 'Version de GD Lib'; -$lang['im_convert'] = 'Chemin vers l\'outil de conversion d\'ImageMagick'; +$lang['refcheck'] = 'Vérifier si un média est toujours utilisé avant de le supprimer'; +$lang['refshow'] = 'Nombre de références de média à montrer lorsque le paramètre précédent est actif'; +$lang['gdlib'] = 'Version de la librairie GD'; +$lang['im_convert'] = 'Chemin vers l\'outil de conversion ImageMagick'; $lang['jpg_quality'] = 'Qualité de la compression JPEG (0-100)'; -$lang['fetchsize'] = 'Taille maximale (en octets) du fichier que fetch.php peut télécharger'; +$lang['fetchsize'] = 'Taille maximale (en octets) que fetch.php peut télécharger depuis une URL tierce (par exemple pour conserver en cache et redimensionner une image tierce)'; $lang['subscribers'] = 'Activer l\'abonnement aux pages'; -$lang['subscribe_time'] = 'Délai après lequel les listes d\'abonnement et résumés sont envoyés (en secondes). Devrait être plus petit que le délai précisé dans recent_days.'; -$lang['notify'] = 'Notifier les modifications à cette adresse de courriel'; -$lang['registernotify'] = 'Envoyer un courriel annonçant les nouveaux utilisateurs enregistrés à cette adresse'; -$lang['mailfrom'] = 'Expéditeur des notifications par courriel du wiki'; -$lang['mailprefix'] = 'Préfixe à utiliser dans les objets des courriels automatiques'; -$lang['sitemap'] = 'Fréquence de génération une carte Google du site (en jours)'; -$lang['rss_type'] = 'Type de flux RSS'; -$lang['rss_linkto'] = 'Lien du flux RSS vers'; -$lang['rss_content'] = 'Quel contenu afficher dans le flux RSS ?'; -$lang['rss_update'] = 'Fréquence de mise à jour du flux RSS (en secondes)'; +$lang['subscribe_time'] = 'Délai après lequel les listes d\'abonnement et résumés sont expédiés (en secondes). Devrait être plus petit que le délai précisé dans recent_days.'; +$lang['notify'] = 'Notifier systématiquement les modifications à cette adresse de courriel'; +$lang['registernotify'] = 'Notifier systématiquement les nouveaux utilisateurs enregistrés à cette adresse de courriel'; +$lang['mailfrom'] = 'Adresse de courriel de l\'expéditeur des notifications par courriel du wiki'; +$lang['mailprefix'] = 'Préfixe à utiliser dans les objets des courriels automatiques. Laisser vide pour utiliser le titre du wiki'; +$lang['htmlmail'] = 'Envoyer des courriel HTML multipart (visuellement plus agréable, mais plus lourd). Désactiver pour utiliser uniquement des courriel plain text'; +$lang['sitemap'] = 'Fréquence de génération du sitemap Google (jours). 0 pour désactiver'; +$lang['rss_type'] = 'Type de flux XML (RSS)'; +$lang['rss_linkto'] = 'Lien du flux XML vers'; +$lang['rss_content'] = 'Quel contenu afficher dans le flux XML?'; +$lang['rss_update'] = 'Fréquence de mise à jour du flux XML (secondes)'; $lang['rss_show_summary'] = 'Le flux XML affiche le résumé dans le titre'; -$lang['rss_media'] = 'Quels types de changements devraient être listés dans le flux XML?'; -$lang['updatecheck'] = 'Vérifier les mises à jour ? DokuWiki doit pouvoir contacter update.dokuwiki.org.'; -$lang['userewrite'] = 'URL esthétiques'; -$lang['useslash'] = 'Utiliser « / » comme séparateur de catégorie dans les URL'; +$lang['rss_media'] = 'Quels types de changements doivent être listés dans le flux XML?'; +$lang['updatecheck'] = 'Vérifier les mises à jour et alertes de sécurité? DokuWiki doit pouvoir contacter update.dokuwiki.org'; +$lang['userewrite'] = 'Utiliser des URL esthétiques'; +$lang['useslash'] = 'Utiliser « / » comme séparateur de catégories dans les URL'; $lang['sepchar'] = 'Séparateur de mots dans les noms de page'; $lang['canonical'] = 'Utiliser des URL canoniques'; $lang['fnencode'] = 'Méthode pour l\'encodage des fichiers non-ASCII'; $lang['autoplural'] = 'Rechercher les formes plurielles dans les liens'; -$lang['compression'] = 'Méthode de compression pour les fichiers dans attic'; -$lang['gzip_output'] = 'Utiliser Content-Encoding gzip pour XHTML'; -$lang['compress'] = 'Compresser CSS et JavaScript'; -$lang['cssdatauri'] = 'Taille maximale en octets pour inclure dans les feuilles de styles CSS, les images qui y sont référencées. Cette technique minimise les requêtes HTTP. Pour IE, ceci ne fonctionne qu\'à partir de la version 8 ! Valeurs correctes entre 400 et 600. 0 pour désactiver.'; -$lang['send404'] = 'Renvoyer "HTTP 404/Page Non Trouvée" pour les pages introuvables'; +$lang['compression'] = 'Méthode de compression pour les fichiers attic'; +$lang['gzip_output'] = 'Utiliser gzip pour le Content-Encoding du XHTML'; +$lang['compress'] = 'Compresser les flux CSS et JavaScript'; +$lang['cssdatauri'] = 'Taille maximale en octets pour inclure dans les feuilles de styles CSS les images qui y sont référencées. Cette technique réduit le nombre de requêtes HTTP. Cette fonctionnalité ne fonctionne qu\'à partir de la version 8 d\'Internet Explorer! Nous recommandons une valeur entre 400 et 600. 0 pour désactiver.'; +$lang['send404'] = 'Renvoyer « HTTP 404/Page Not Found » pour les pages inexistantes'; $lang['broken_iua'] = 'La fonction ignore_user_abort est-elle opérationnelle sur votre système ? Ceci peut empêcher le fonctionnement de l\'index de recherche. IIS+PHP/ -CGI dysfonctionne. Voir le bug 852 pour plus d\'info.'; -$lang['xsendfile'] = 'Utiliser l\'en-tête X-Sendfile pour permettre au serveur Web de délivrer des fichiers statiques ? Votre serveur Web doit supporter cette fonctionnalité.'; +CGI dysfonctionne. Voir le bug 852 pour plus d\'informations.'; +$lang['xsendfile'] = 'Utiliser l\'en-tête X-Sendfile pour permettre au serveur web de délivrer les fichiers statiques ? Votre serveur web doit supporter cette fonctionnalité.'; $lang['renderer_xhtml'] = 'Moteur de rendu du format de sortie principal (XHTML)'; -$lang['renderer__core'] = '%s (cœur de dokuwiki)'; -$lang['renderer__plugin'] = '%s (module externe)'; -$lang['proxy____host'] = 'Proxy - Serveur hôte'; -$lang['proxy____port'] = 'Proxy - Numéro de port'; -$lang['proxy____user'] = 'Proxy - Identifiant'; -$lang['proxy____pass'] = 'Proxy - Mot de passe'; -$lang['proxy____ssl'] = 'Proxy - Utilisation de SSL'; -$lang['proxy____except'] = 'Expression régulière de test des URLs pour lesquelles le proxy ne devrait pas être utilisé.'; +$lang['renderer__core'] = '%s (cœur de DokuWiki)'; +$lang['renderer__plugin'] = '%s (extension)'; +$lang['dnslookups'] = 'DokuWiki effectuera une résolution du nom d\'hôte sur les adresses IP des utilisateurs modifiant des pages. Si vous ne possédez pas de serveur DNS, que ce dernier est lent ou que vous ne souhaitez pas utiliser cette fonctionnalité : désactivez-la.'; +$lang['proxy____host'] = 'Mandataire (proxy) - Hôte'; +$lang['proxy____port'] = 'Mandataire - Port'; +$lang['proxy____user'] = 'Mandataire - Identifiant'; +$lang['proxy____pass'] = 'Mandataire - Mot de passe'; +$lang['proxy____ssl'] = 'Mandataire - Utilisation de SSL'; +$lang['proxy____except'] = 'Mandataire - Expression régulière de test des URLs pour lesquelles le mandataire (proxy) ne doit pas être utilisé.'; $lang['safemodehack'] = 'Activer l\'option Mode sans échec'; -$lang['ftp____host'] = 'FTP - Serveur hôte pour Mode sans échec'; -$lang['ftp____port'] = 'FTP - Numéro de port pour Mode sans échec'; -$lang['ftp____user'] = 'FTP - Identifiant pour Mode sans échec'; -$lang['ftp____pass'] = 'FTP - Mot de passe pour Mode sans échec'; -$lang['ftp____root'] = 'FTP - Répertoire racine pour Mode sans échec'; +$lang['ftp____host'] = 'FTP / Mode sans échec - Serveur hôte'; +$lang['ftp____port'] = 'FTP / Mode sans échec - Port'; +$lang['ftp____user'] = 'FTP / Mode sans échec - Identifiant'; +$lang['ftp____pass'] = 'FTP / Mode sans échec - Mot de passe'; +$lang['ftp____root'] = 'FTP / Mode sans échec - Répertoire racine'; $lang['license_o_'] = 'Aucune choisie'; $lang['typography_o_0'] = 'aucun'; $lang['typography_o_1'] = 'guillemets uniquement'; @@ -171,7 +176,7 @@ $lang['userewrite_o_1'] = 'Fichier .htaccess'; $lang['userewrite_o_2'] = 'Interne à DokuWiki'; $lang['deaccent_o_0'] = 'off'; $lang['deaccent_o_1'] = 'supprimer les accents'; -$lang['deaccent_o_2'] = 'convertir en roman'; +$lang['deaccent_o_2'] = 'convertir en caractères latins'; $lang['gdlib_o_0'] = 'Librairie GD non disponible'; $lang['gdlib_o_1'] = 'version 1.x'; $lang['gdlib_o_2'] = 'auto-détectée'; diff --git a/lib/plugins/plugin/lang/fr/admin_plugin.txt b/lib/plugins/plugin/lang/fr/admin_plugin.txt index f90b627f3..b7beba25a 100644 --- a/lib/plugins/plugin/lang/fr/admin_plugin.txt +++ b/lib/plugins/plugin/lang/fr/admin_plugin.txt @@ -1,4 +1,4 @@ -====== Gestion des modules externes ====== +====== Gestion des extensions ====== -Cette page vous permet de gérer tout ce qui a trait aux [[doku>fr:plugins|modules externes]] de DokuWiki. Pour télécharger et installer un module, le répertoire « ''plugin'' » doit être accessible en écriture pour le serveur Web. +Cette page vous permet de gérer tout ce qui a trait aux [[doku>fr:plugins|extensions]] de DokuWiki. Pour pouvoir télécharger et installer un module, le répertoire « ''plugin'' » doit être accessible en écriture pour le serveur web. diff --git a/lib/plugins/plugin/lang/fr/lang.php b/lib/plugins/plugin/lang/fr/lang.php index 31d524cc6..06cd1ab8d 100644 --- a/lib/plugins/plugin/lang/fr/lang.php +++ b/lib/plugins/plugin/lang/fr/lang.php @@ -19,10 +19,11 @@ * @author skimpax@gmail.com * @author Yannick Aure * @author Olivier DUVAL + * @author Anael Mobilia */ -$lang['menu'] = 'Gestion des modules externes'; -$lang['download'] = 'Télécharger et installer un nouveau module'; -$lang['manage'] = 'Modules installés'; +$lang['menu'] = 'Gestion des extensions'; +$lang['download'] = 'Télécharger et installer une nouvelle extension'; +$lang['manage'] = 'Extensions installées'; $lang['btn_info'] = 'Info'; $lang['btn_update'] = 'Mettre à jour'; $lang['btn_delete'] = 'Supprimer'; @@ -35,18 +36,18 @@ $lang['lastupdate'] = 'Dernière mise à jour :'; $lang['source'] = 'Source :'; $lang['unknown'] = 'inconnu'; $lang['updating'] = 'Mise à jour…'; -$lang['updated'] = 'Modules %s mis à jour avec succès'; -$lang['updates'] = 'Les modules suivants ont été mis à jour avec succès'; +$lang['updated'] = 'Extension %s mise à jour avec succès'; +$lang['updates'] = 'Les extensions suivantes ont été mises à jour avec succès'; $lang['update_none'] = 'Aucune mise à jour n\'a été trouvée.'; $lang['deleting'] = 'Suppression…'; -$lang['deleted'] = 'Module %s supprimé.'; +$lang['deleted'] = 'Extension %s supprimée.'; $lang['downloading'] = 'Téléchargement…'; -$lang['downloaded'] = 'Module %s installé avec succès'; -$lang['downloads'] = 'Les modules suivants ont été installés avec succès :'; -$lang['download_none'] = 'Aucun module n\'était trouvé, ou un problème inconnu est survenu durant le téléchargement et l\'installation.'; -$lang['plugin'] = 'Module :'; +$lang['downloaded'] = 'Extension %s installée avec succès'; +$lang['downloads'] = 'Les extensions suivantes ont été installées avec succès :'; +$lang['download_none'] = 'Aucune extension n\'a été trouvée, ou un problème inconnu est survenu durant le téléchargement et l\'installation.'; +$lang['plugin'] = 'Extension :'; $lang['components'] = 'Composants'; -$lang['noinfo'] = 'Ce module externe n\'a transmis aucune information, il pourrait être invalide.'; +$lang['noinfo'] = 'Cette extension n\'a transmis aucune information, elle pourrait être invalide.'; $lang['name'] = 'Nom :'; $lang['date'] = 'Date :'; $lang['type'] = 'Type :'; @@ -54,14 +55,14 @@ $lang['desc'] = 'Description :'; $lang['author'] = 'Auteur :'; $lang['www'] = 'Site web :'; $lang['error'] = 'Une erreur inconnue est survenue.'; -$lang['error_download'] = 'Impossible de télécharger le fichier du module : %s'; -$lang['error_badurl'] = 'URL suspecte. Impossible de déterminer le nom du fichier à partir de l\'URL'; -$lang['error_dircreate'] = 'Impossible de créer le répertoire temporaire pour réceptionner le téléchargement'; -$lang['error_decompress'] = 'Le gestionnaire de modules externes a été incapable de décompresser le fichier téléchargé. Ceci peut être le résultat d\'un mauvais téléchargement, auquel cas vous devriez réessayer ; ou bien le format de compression est inconnu, auquel cas vous devez télécharger et installer le module manuellement.'; -$lang['error_copy'] = 'Une erreur de copie est survenue lors de l\'installation des fichiers du module %s : votre disque est peut-être plein ou les droits d\'accès au fichier sont incorrects. Il a pu en résulter une installation partielle du module rendant votre installation du wiki instable.'; -$lang['error_delete'] = 'Une erreur est survenue à la suppression du module %s. La raison la plus probable est l\'insuffisance des droits sur les fichiers ou le répertoire.'; -$lang['enabled'] = 'Module %s activé.'; -$lang['notenabled'] = 'Le module %s n\'a pas pu être activé, vérifiez le fichier des permissions.'; -$lang['disabled'] = 'Module %s désactivé.'; -$lang['notdisabled'] = 'Le module %s n\'a pas pu être désactivé, vérifiez le fichier des permissions.'; -$lang['packageinstalled'] = 'Ensemble de modules (%d module(s): %s) installé avec succès.'; +$lang['error_download'] = 'Impossible de télécharger le fichier de l\'extension : %s'; +$lang['error_badurl'] = 'URL suspecte : impossible de déterminer le nom du fichier à partir de l\'URL'; +$lang['error_dircreate'] = 'Impossible de créer le répertoire temporaire pour effectuer le téléchargement'; +$lang['error_decompress'] = 'Le gestionnaire d\'extensions a été incapable de décompresser le fichier téléchargé. Ceci peut être le résultat d\'un mauvais téléchargement, auquel cas vous devriez réessayer ; ou bien le format de compression est inconnu, auquel cas vous devez télécharger et installer l\'extension manuellement.'; +$lang['error_copy'] = 'Une erreur de copie est survenue lors de l\'installation des fichiers de l\'extension %s : le disque est peut-être plein ou les autorisations d\'accès sont incorrects. Il a pu en résulter une installation partielle de l\'extension et laisser votre installation du wiki instable.'; +$lang['error_delete'] = 'Une erreur est survenue lors de la suppression de l\'extension %s. La raison la plus probable est l\'insuffisance des autorisations sur les fichiers ou les répertoires.'; +$lang['enabled'] = 'Extension %s activée.'; +$lang['notenabled'] = 'L\'extension %s n\'a pas pu être activée, vérifiez les autorisations des fichiers.'; +$lang['disabled'] = 'Extension %s désactivée.'; +$lang['notdisabled'] = 'L\'extension %s n\'a pas pu être désactivée, vérifiez les autorisations des fichiers.'; +$lang['packageinstalled'] = 'Ensemble d\'extensions (%d extension(s): %s) installé avec succès.'; diff --git a/lib/plugins/popularity/lang/fr/intro.txt b/lib/plugins/popularity/lang/fr/intro.txt index 041e65d69..598523492 100644 --- a/lib/plugins/popularity/lang/fr/intro.txt +++ b/lib/plugins/popularity/lang/fr/intro.txt @@ -1,10 +1,10 @@ ====== Enquête de popularité ====== -Cet [[doku>popularity|outil]] collecte des données anonymes concernant votre wiki et vous permet de les expédier aux développeurs de DokuWiki. Ceci leur permet de mieux comprendre comment DokuWiki est employé par ses utilisateurs et d'orienter les décisions sur les développements futurs en tenant compte des statistiques d'usage réel. +Cet [[doku>popularity|outil]] collecte des données anonymes concernant votre wiki et vous permet de les expédier aux développeurs de DokuWiki. Ceci leur permet de mieux comprendre comment DokuWiki est utilisé par ses utilisateurs et d'orienter les décisions sur les développements futurs en tenant compte des statistiques d'usage réel. -Vous êtes encouragé à répéter l'opération de collecte et d'envoi des données anonymes de temps en temps afin d'informer les développeurs de la croissance de votre wiki. +Vous êtes encouragé à répéter cette opération de temps à autres afin de tenir informés les développeurs de l'évolution de votre wiki. L'ensemble de vos contributions seront recensées via un identifiant anonyme. -Les données collectées contiennent des informations telle que votre version de DokuWiki, le nombre et la taille de vos pages et fichiers, les modules installés ainsi que des informations sur la version de PHP installée. +Les données collectées contiennent des informations telles votre version de DokuWiki, le nombre et la taille de vos pages et fichiers, les extensions installées ainsi que des informations sur la version de PHP installée. Les données brutes qui sont envoyées sont affichées ci dessous. Merci d'utiliser le bouton « Envoyer les données » pour expédier l'information. diff --git a/lib/plugins/popularity/lang/fr/lang.php b/lib/plugins/popularity/lang/fr/lang.php index 904987079..d5bc92081 100644 --- a/lib/plugins/popularity/lang/fr/lang.php +++ b/lib/plugins/popularity/lang/fr/lang.php @@ -16,11 +16,12 @@ * @author skimpax@gmail.com * @author Yannick Aure * @author Olivier DUVAL + * @author Anael Mobilia */ $lang['name'] = 'Enquête de popularité (peut nécessiter un certain temps pour être chargée)'; $lang['submit'] = 'Envoyer les données'; -$lang['autosubmit'] = 'Envoyer les données automatiquement chaque mois'; -$lang['submissionFailed'] = 'Les données ne peuvent pas être envoyées à cause des erreurs suivantes :'; -$lang['submitDirectly'] = 'Vous pouvez envoyer le données manuellement en soumettant ce formulaire.'; +$lang['autosubmit'] = 'Envoyer les données automatiquement une fois par mois'; +$lang['submissionFailed'] = 'Les données ne peuvent pas être expédiées à cause des erreurs suivantes :'; +$lang['submitDirectly'] = 'Vous pouvez envoyer les données manuellement en soumettant ce formulaire.'; $lang['autosubmitError'] = 'La dernière soumission automatique a échoué pour les raisons suivantes :'; -$lang['lastSent'] = 'Les données ont été envoyées '; +$lang['lastSent'] = 'Les données ont été expédiées'; diff --git a/lib/plugins/popularity/lang/fr/submitted.txt b/lib/plugins/popularity/lang/fr/submitted.txt index 0bc4cfe71..edb5e21f6 100644 --- a/lib/plugins/popularity/lang/fr/submitted.txt +++ b/lib/plugins/popularity/lang/fr/submitted.txt @@ -1,2 +1,3 @@ ====== Enquête de popularité ====== -Les données ont été envoyées avec succès. \ No newline at end of file + +Les données ont été expédiées avec succès. \ No newline at end of file diff --git a/lib/plugins/revert/lang/fr/intro.txt b/lib/plugins/revert/lang/fr/intro.txt index 6dcbe74b9..30e6d8a51 100644 --- a/lib/plugins/revert/lang/fr/intro.txt +++ b/lib/plugins/revert/lang/fr/intro.txt @@ -1,3 +1,3 @@ -====== Gestionnaire de réversions ====== +====== Gestionnaire des réversions ====== -Cette page peut vous aider à restaurer des pages après une attaque de spam. Pour trouver la liste des pages vandalisées, entrez un motif de recherche (p. ex. une URL de spam), puis confirmez que les pages trouvées contiennent du spam et annulez leurs éditions. +Cette page vous aide à restaurer des pages après une attaque de spam. Pour trouver la liste des pages vandalisées, entrez un motif de recherche (par exemple : une URL de spam), puis confirmez que les pages trouvées contiennent du spam et annulez leur modifications. diff --git a/lib/plugins/revert/lang/fr/lang.php b/lib/plugins/revert/lang/fr/lang.php index 253e0c96e..07b012e38 100644 --- a/lib/plugins/revert/lang/fr/lang.php +++ b/lib/plugins/revert/lang/fr/lang.php @@ -17,13 +17,14 @@ * @author skimpax@gmail.com * @author Yannick Aure * @author Olivier DUVAL + * @author Anael Mobilia */ -$lang['menu'] = 'Gestionnaire de réversions'; +$lang['menu'] = 'Gestionnaire des réversions'; $lang['filter'] = 'Trouver les pages spammées '; $lang['revert'] = 'Annuler les modifications sélectionnées'; $lang['reverted'] = '%s restauré à la révision %s'; $lang['removed'] = '%s supprimé'; -$lang['revstart'] = 'Processus de réversion démarré. Ceci peut prendre longtemps. Si le script dépasse le délai avant de terminer, vous devrez restaurer de plus petits groupes de pages.'; +$lang['revstart'] = 'Processus de réversion démarré. Ceci peut durer longtemps. Si le script dépasse le délai d\'exécution avant de finir, vous devrez restaurer de plus petits groupes de pages.'; $lang['revstop'] = 'Processus de réversion terminé avec succès.'; -$lang['note1'] = 'Note : cette recherche est insensible à la casse'; -$lang['note2'] = 'Note : cette page sera révisée à la version précédente ne contenant pas le terme spammeur %s.'; +$lang['note1'] = 'Note : cette recherche est sensible à la casse'; +$lang['note2'] = 'Note : cette page sera restaurée à la dernière version ne contenant pas le terme « spam » %s.'; diff --git a/lib/plugins/usermanager/lang/fr/edit.txt b/lib/plugins/usermanager/lang/fr/edit.txt index ec193eb5a..e667989b4 100644 --- a/lib/plugins/usermanager/lang/fr/edit.txt +++ b/lib/plugins/usermanager/lang/fr/edit.txt @@ -1 +1 @@ -===== Modifier les informations d'un utilisateur ===== +===== Modifier l'utilisateur ===== diff --git a/lib/plugins/usermanager/lang/fr/lang.php b/lib/plugins/usermanager/lang/fr/lang.php index d84ff65c3..7e602d0ce 100644 --- a/lib/plugins/usermanager/lang/fr/lang.php +++ b/lib/plugins/usermanager/lang/fr/lang.php @@ -18,10 +18,11 @@ * @author skimpax@gmail.com * @author Yannick Aure * @author Olivier DUVAL + * @author Anael Mobilia */ $lang['menu'] = 'Gestion des utilisateurs'; -$lang['noauth'] = '(authentification utilisateur non disponible)'; -$lang['nosupport'] = '(gestion utilisateur non supportée)'; +$lang['noauth'] = '(authentification de l\'utilisateur non disponible)'; +$lang['nosupport'] = '(gestion de l\'utilisateur non supportée)'; $lang['badauth'] = 'mécanisme d\'authentification invalide'; $lang['user_id'] = 'Identifiant '; $lang['user_pass'] = 'Mot de passe '; @@ -40,20 +41,20 @@ $lang['search'] = 'Rechercher'; $lang['search_prompt'] = 'Effectuer la recherche'; $lang['clear'] = 'Réinitialiser la recherche'; $lang['filter'] = 'Filtre'; -$lang['summary'] = 'Affichage des utilisateurs %1$d-%2$d parmi %3$d trouvé(s). %4$d utilisateur(s) au total.'; -$lang['nonefound'] = 'Aucun utilisateur trouvé. %d utilisateur(s) au total.'; +$lang['summary'] = 'Affichage des utilisateurs %1$d-%2$d parmi %3$d trouvés. %4$d utilisateurs au total.'; +$lang['nonefound'] = 'Aucun utilisateur trouvé. %d utilisateurs au total.'; $lang['delete_ok'] = '%d utilisateurs effacés'; -$lang['delete_fail'] = '%d effacement échoué.'; +$lang['delete_fail'] = '%d effacements échoués.'; $lang['update_ok'] = 'Utilisateur mis à jour avec succès'; -$lang['update_fail'] = 'Échec de la mise à jour utilisateur'; -$lang['update_exists'] = 'Échec du changement de nom d\'utilisateur, le nom spécifié (%s) existe déjà (toutes les autres modifications seront effectuées).'; -$lang['start'] = 'Démarrage'; +$lang['update_fail'] = 'Échec lors de la mise à jour de l\'utilisateur'; +$lang['update_exists'] = 'Échec lors du changement du nom d\'utilisateur : le nom spécifié (%s) existe déjà (toutes les autres modifications seront effectuées).'; +$lang['start'] = 'Début'; $lang['prev'] = 'Précédent'; $lang['next'] = 'Suivant'; -$lang['last'] = 'Dernier'; +$lang['last'] = 'Fin'; $lang['edit_usermissing'] = 'Utilisateur sélectionné non trouvé, cet utilisateur a peut-être été supprimé ou modifié ailleurs.'; $lang['user_notify'] = 'Notifier l\'utilisateur '; -$lang['note_notify'] = 'Envoi de notification par courriel uniquement lorsqu\'un nouveau mot de passe est attribué à l\'utilisateur.'; +$lang['note_notify'] = 'Expédition de notification par courriel uniquement lorsque l\'utilisateur fourni un nouveau mot de passe.'; $lang['note_group'] = 'Les nouveaux utilisateurs seront ajoutés au groupe par défaut (%s) si aucun groupe n\'est spécifié.'; $lang['note_pass'] = 'Le mot de passe sera généré automatiquement si le champ est laissé vide et si la notification de l\'utilisateur est activée.'; $lang['add_ok'] = 'Utilisateur ajouté avec succès'; -- cgit v1.2.3 From 8ca91870d51c8a06a61e4ea7be859abbe6ba00e5 Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Wed, 14 Nov 2012 00:31:22 +0000 Subject: added another place to look for logo to make it more consistent (FS#2656) --- lib/tpl/dokuwiki/tpl_header.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tpl/dokuwiki/tpl_header.php b/lib/tpl/dokuwiki/tpl_header.php index 0704aa271..19d165059 100644 --- a/lib/tpl/dokuwiki/tpl_header.php +++ b/lib/tpl/dokuwiki/tpl_header.php @@ -20,7 +20,7 @@ if (!defined('DOKU_INC')) die();

Date: Fri, 16 Nov 2012 10:57:01 +0100 Subject: removed a bunch of outdated and irrelevant networking acronyms --- conf/acronyms.conf | 84 +----------------------------------------------------- 1 file changed, 1 insertion(+), 83 deletions(-) diff --git a/conf/acronyms.conf b/conf/acronyms.conf index 66f563bd2..072deb324 100644 --- a/conf/acronyms.conf +++ b/conf/acronyms.conf @@ -4,140 +4,58 @@ ACL Access Control List AFAICS As far as I can see AFAIK As far as I know AFAIR As far as I remember -AJAX Asynchronous JavaScript and XML -AIM AOL (America Online) Instant Messenger -AOL America Online API Application Programming Interface ASAP As soon as possible ASCII American Standard Code for Information Interchange -ASP Active Server Pages BTW By the way -CGI Common Gateway Interface CMS Content Management System CSS Cascading Style Sheets -CVS Concurrent Versions System -DBA Database Administrator -DHCP Dynamic Host Configuration Protocol -DHTML Dynamic HyperText Markup Language -DMCA Digital Millenium Copyright Act DNS Domain Name System -DOM Document Object Model -DTD Document Type Definition EOF End of file EOL End of line EOM End of message EOT End of text -ESMTP Extended Simple Mail Transfer Protocol FAQ Frequently Asked Questions -FDL GNU Free Documentation License FTP File Transfer Protocol FOSS Free & Open-Source Software FLOSS Free/Libre and Open Source Software FUD Fear, Uncertainty, and Doubt GB Gigabyte GHz Gigahertz -GIF Graphics Interchange Format GPL GNU General Public License GUI Graphical User Interface HTML HyperText Markup Language -HTTP Hyper Text Transfer Protocol IANAL I am not a lawyer (but) -ICANN Internet Corporation for Assigned Names and Numbers -ICQ I seek you (Instant Messenger) -IE5 Internet Explorer 5 -IE6 Internet Explorer 6 IE Internet Explorer IIRC If I remember correctly -IIS Internet Information Services -IMAP Internet Message Access Protocol IMHO In my humble opinion IMO In my opinion IOW In other words IRC Internet Relay Chat IRL In real life -ISO International Organization for Standardization -ISP Internet Service Provider -JDK Java Development Kit -JPEG Joint Photographics Experts Group -JPG Joint Photographics Experts Group -JS JavaScript KISS Keep it simple stupid LAN Local Area Network -LDAP Lightweight Directory Access Protocol LGPL GNU Lesser General Public License LOL Laughing out loud MathML Mathematical Markup Language MB Megabyte MHz Megahertz -MIME Multipurpose Internet Mail Extension -MIT Massachusetts Institute of Technology -MML Mathematical Markup Language -MP3 Moving Picture Experts Group Layer 3 -MPEG Moving Picture Experts Group -MSDN Microsoft Developer Network -MS Microsoft MSIE Microsoft Internet Explorer -NIS Network Information Service -NS4.7 Netscape 4.7 -NS4 Netscape 4 -NS6 Netscape 6 -NS7 Netscape 7 OMG Oh my God -OPML Outline Processor Markup Language OS Operating System OSS Open Source Software OTOH On the other hand -P2P Peer to Peer -PDA Personal Digital Assistant -PDF Portable Document Format -PHP Hypertext Preprocessor -PICS Platform for Internet Content Selection -PIN Personal Identification Number PITA Pain in the Ass -PNG Portable Network Graphics -POP3 Post Office Protocol 3 -POP Post Office Protocol -QoS Quality of Service -RAID Redundant Array of Inexpensive Disks -RDF Resource Description Framework RFC Request for Comments ROTFL Rolling on the floor laughing -RPC Remote Procedure Call -RSS Rich Site Summary RTFM Read The Fine Manual -RTF Rich Text File -SCSI Small Computer System Interface -SDK Software Development Kit -SGML Standard General Markup Language -SMIL Synchronized Multimedia Integration Language -SMTP Simple Mail Transfer Protocol -SOAP Simple Object Access Protocol spec specification -SQL Structured Query Language -SSH Secure Shell -SSI Server Side Includes -SSL Secure Sockets Layer -SVG Scalable Vector Graphics TIA Thanks in advance -TIFF Tagged Image File Format -TLD Top Level Domain +TL;DR Too long; din't read TOC Table of Contents URI Uniform Resource Identifier URL Uniform Resource Locator -URN Uniform Resource Name -VBA Visual Basic for Applications -VB Visual Basic W3C World Wide Web Consortium -WAN Wide Area Network -WAP Wireless Access Protocol -WML Wireless Markup Language WTF? What the f*** -WWW World Wide Web WYSIWYG What You See Is What You Get -XHTML Extensible HyperText Markup Language -XML Extensible Markup Language -XSD XML (Extensible Markup Language) Schema Definition -XSL Extensible Stylesheet Language -XSLT Extensible Stylesheet Language Transformations -XUL XML User Interface Language YMMV Your mileage may vary -- cgit v1.2.3 From 054a11302ce0722a1ac71d38e5408a8e2299ca41 Mon Sep 17 00:00:00 2001 From: Antoine Turmel Date: Fri, 16 Nov 2012 12:06:47 +0100 Subject: Typo fix for TL;DR --- conf/acronyms.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/acronyms.conf b/conf/acronyms.conf index 072deb324..9363f947e 100644 --- a/conf/acronyms.conf +++ b/conf/acronyms.conf @@ -51,7 +51,7 @@ ROTFL Rolling on the floor laughing RTFM Read The Fine Manual spec specification TIA Thanks in advance -TL;DR Too long; din't read +TL;DR Too long; didn't read TOC Table of Contents URI Uniform Resource Identifier URL Uniform Resource Locator -- cgit v1.2.3 From c786a1b6200b051466db67a1791f46bbd375bb3b Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Sun, 18 Nov 2012 12:02:20 +0000 Subject: fixed wrong sidebar showing in namespaces when sidebar is disabled --- inc/pageutils.php | 1 + inc/template.php | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/inc/pageutils.php b/inc/pageutils.php index 3bb10883f..ef82eebcd 100644 --- a/inc/pageutils.php +++ b/inc/pageutils.php @@ -645,6 +645,7 @@ function utf8_decodeFN($file){ * @return string|false the full page id of the found page, false if any */ function page_findnearest($page){ + if (!$page) return false; global $ID; $ns = $ID; diff --git a/inc/template.php b/inc/template.php index 0d96be214..4af35cc2b 100644 --- a/inc/template.php +++ b/inc/template.php @@ -1471,11 +1471,10 @@ function tpl_license($img = 'badge', $imgonly = false, $return = false, $wrap = * template */ function tpl_include_page($pageid, $print = true, $propagate = false) { - global $ID; - global $TOC; - + if (!$pageid) return false; if ($propagate) $pageid = page_findnearest($pageid); + global $TOC; $oldtoc = $TOC; $html = p_wiki_xhtml($pageid, '', false); $TOC = $oldtoc; -- cgit v1.2.3 From 2c2ee174e46096ce890518061ca8e2e0866cf67c Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Sun, 18 Nov 2012 18:52:13 +0000 Subject: changed semicolon to colon in link to welcome page to make it less confusing --- inc/lang/ar/lang.php | 4 ++-- inc/lang/az/lang.php | 4 ++-- inc/lang/bg/lang.php | 6 +++--- inc/lang/ca-valencia/lang.php | 4 ++-- inc/lang/ca/lang.php | 4 ++-- inc/lang/cs/lang.php | 4 ++-- inc/lang/da/lang.php | 4 ++-- inc/lang/de-informal/lang.php | 4 ++-- inc/lang/de/lang.php | 4 ++-- inc/lang/el/lang.php | 4 ++-- inc/lang/en/lang.php | 4 ++-- inc/lang/eo/lang.php | 4 ++-- inc/lang/es/lang.php | 4 ++-- inc/lang/et/lang.php | 4 ++-- inc/lang/eu/lang.php | 4 ++-- inc/lang/fa/lang.php | 4 ++-- inc/lang/fi/lang.php | 4 ++-- inc/lang/fr/lang.php | 4 ++-- inc/lang/gl/lang.php | 4 ++-- inc/lang/he/lang.php | 4 ++-- inc/lang/hr/lang.php | 4 ++-- inc/lang/hu/lang.php | 4 ++-- inc/lang/ia/lang.php | 4 ++-- inc/lang/id/lang.php | 4 ++-- inc/lang/it/lang.php | 4 ++-- inc/lang/ja/lang.php | 4 ++-- inc/lang/ko/lang.php | 4 ++-- inc/lang/la/lang.php | 4 ++-- inc/lang/lv/lang.php | 4 ++-- inc/lang/mk/lang.php | 4 ++-- inc/lang/mr/lang.php | 4 ++-- inc/lang/ne/lang.php | 4 ++-- inc/lang/nl/lang.php | 4 ++-- inc/lang/no/lang.php | 4 ++-- inc/lang/pl/lang.php | 4 ++-- inc/lang/pt-br/lang.php | 4 ++-- inc/lang/pt/lang.php | 4 ++-- inc/lang/ro/lang.php | 4 ++-- inc/lang/ru/lang.php | 4 ++-- inc/lang/sk/lang.php | 4 ++-- inc/lang/sl/lang.php | 4 ++-- inc/lang/sq/lang.php | 4 ++-- inc/lang/sr/lang.php | 4 ++-- inc/lang/sv/lang.php | 4 ++-- inc/lang/tr/lang.php | 4 ++-- inc/lang/uk/lang.php | 4 ++-- inc/lang/zh-tw/lang.php | 4 ++-- inc/lang/zh/lang.php | 4 ++-- 48 files changed, 97 insertions(+), 97 deletions(-) diff --git a/inc/lang/ar/lang.php b/inc/lang/ar/lang.php index 0f5566471..85c88d10f 100644 --- a/inc/lang/ar/lang.php +++ b/inc/lang/ar/lang.php @@ -284,8 +284,8 @@ $lang['i_badhash'] = 'الملف dokuwiki.php غير مصنف أو (hash=%s)'; $lang['i_badval'] = 'القيمة %s غير شرعية أو فارغة'; $lang['i_success'] = 'الإعدادات تمت بنجاح، يرجى حذف الملف install.php الآن. -ثم تابع إلى دوكو ويكي الجديدة'; -$lang['i_failure'] = 'بعض الأخطاء حدثت أثنا كتابة ملفات الإعدادات، عليك تعديلها يدوياً قبل أن تستطيع استخدام دوكو ويكي الجديدة'; +ثم تابع إلى دوكو ويكي الجديدة'; +$lang['i_failure'] = 'بعض الأخطاء حدثت أثنا كتابة ملفات الإعدادات، عليك تعديلها يدوياً قبل أن تستطيع استخدام دوكو ويكي الجديدة'; $lang['i_policy'] = 'تصريح ACL مبدئي'; $lang['i_pol0'] = 'ويكي مفتوحة؛ أي القراءة والكتابة والتحميل مسموحة للجميع'; $lang['i_pol1'] = 'ويكي عامة؛ أي القراءة للجميع ولكن الكتابة والتحميل للمشتركين المسجلين فقط'; diff --git a/inc/lang/az/lang.php b/inc/lang/az/lang.php index 384a347b7..6df15a83e 100644 --- a/inc/lang/az/lang.php +++ b/inc/lang/az/lang.php @@ -208,8 +208,8 @@ $lang['i_writeerr'] = '%s yaradıla bilmədi. Faylın/qo $lang['i_badhash'] = 'dokuwiki.php tanıla bilmir və ya dəyişdirilmişdir (hash=%s)'; $lang['i_badval'] = '%s - səhv ya boş qiymətdir'; $lang['i_success'] = 'Konfiqurasiya uğurla başa çatdı. İndi siz install.php faylını silə bilərsiniz. - Yeni DokuWiki-nizə xoş gəlmişsiniz!'; -$lang['i_failure'] = 'Konfiqurasiya fayllarına məlumat yazan zaman səhvlər tapıldı. Yəgin ki, yeni DokuWiki-nizi istifadə etmədən öncə, Siz o xətaları əl ilə düzəltməli olacaqsınız.'; + Yeni DokuWiki-nizə xoş gəlmişsiniz!'; +$lang['i_failure'] = 'Konfiqurasiya fayllarına məlumat yazan zaman səhvlər tapıldı. Yəgin ki, yeni DokuWiki-nizi istifadə etmədən öncə, Siz o xətaları əl ilə düzəltməli olacaqsınız.'; $lang['i_policy'] = 'İlkin giriş haqları siyasəti'; $lang['i_pol0'] = 'Tam açıq wiki (oxumaq, yazmaq, fayl yükləmək hamıya olar)'; $lang['i_pol1'] = 'Acıq wiki (oxumaq hamıya olar, yazmaq və fayl yükləmək ancaq üzv olan istifadəçilərə olar)'; diff --git a/inc/lang/bg/lang.php b/inc/lang/bg/lang.php index 7a9a20469..04b0edd08 100644 --- a/inc/lang/bg/lang.php +++ b/inc/lang/bg/lang.php @@ -298,10 +298,10 @@ $lang['i_confexists'] = '%s вече съществува' $lang['i_writeerr'] = '%s не можа да бъде създаден. Трябва да проверите правата за достъп до директорията/файла и да създадете файла ръчно.'; $lang['i_badhash'] = 'Файлът dokuwiki.php не може да бъде разпознат или е променен (hash=%s)'; $lang['i_badval'] = '%s - непозволена или празна стойност'; -$lang['i_success'] = 'Настройването приключи успешно. Вече можете да изтриете файла install.php. Продължете към Вашето ново DokuWiki.'; +$lang['i_success'] = 'Настройването приключи успешно. Вече можете да изтриете файла install.php. Продължете към Вашето ново DokuWiki.'; -$lang['i_failure'] = 'Възникнаха грешки при записването на файловете с настройки. Вероятно ще се наложи да ги поправите ръчно, - за да можете да ползвате Вашето ново DokuWiki.'; +$lang['i_failure'] = 'Възникнаха грешки при записването на файловете с настройки. Вероятно ще се наложи да ги поправите ръчно, + за да можете да ползвате Вашето ново DokuWiki.'; $lang['i_policy'] = 'Първоначална политика за достъп'; $lang['i_pol0'] = 'Отворено Wiki (всеки може да чете, пише и качва)'; $lang['i_pol1'] = 'Публично Wiki (всеки може да чете, само регистрирани пишат и качват)'; diff --git a/inc/lang/ca-valencia/lang.php b/inc/lang/ca-valencia/lang.php index e62010418..532f6c73d 100644 --- a/inc/lang/ca-valencia/lang.php +++ b/inc/lang/ca-valencia/lang.php @@ -211,9 +211,9 @@ $lang['i_writeerr'] = 'No es pot crear %s. Haurà de com $lang['i_badhash'] = 'dokuwiki.php substituït o modificat (hash=%s)'; $lang['i_badval'] = '%s - valor illegal o buit'; $lang['i_success'] = 'La configuració ha finalisat correctament. Ya pot borrar l\'archiu install.php. Passe al -nou DokuWiki.'; +nou DokuWiki.'; $lang['i_failure'] = 'Han aparegut alguns erros escrivint els archius de configuració. Deurà arreglar-los manualment abans de que -puga utilisar el nou DokuWiki.'; +puga utilisar el nou DokuWiki.'; $lang['i_policy'] = 'Política inicial ACL'; $lang['i_pol0'] = 'Wiki obert (llegir, escriure i enviar tots)'; $lang['i_pol1'] = 'Wiki públic (llegir tots, escriure i enviar només usuaris registrats)'; diff --git a/inc/lang/ca/lang.php b/inc/lang/ca/lang.php index 7fc078419..0fd88ec39 100644 --- a/inc/lang/ca/lang.php +++ b/inc/lang/ca/lang.php @@ -208,8 +208,8 @@ $lang['i_confexists'] = '%s ja existeix'; $lang['i_writeerr'] = 'No es pot crear %s. Comproveu els permisos del directori i/o del fitxer i creeu el fitxer manualment.'; $lang['i_badhash'] = 'dokuwiki.php no reconegut o modificat (hash=%s)'; $lang['i_badval'] = '%s - valor il·legal o buit'; -$lang['i_success'] = 'La configuració s\'ha acabat amb èxit. Ara podeu suprimir el fitxer install.php. Aneu al vostre nou DokuWiki.'; -$lang['i_failure'] = 'S\'han produït alguns errors en escriure els fitxers de configuració. Potser caldrà que els arregleu manualment abans d\'utilitzar el vostre nou DokuWiki.'; +$lang['i_success'] = 'La configuració s\'ha acabat amb èxit. Ara podeu suprimir el fitxer install.php. Aneu al vostre nou DokuWiki.'; +$lang['i_failure'] = 'S\'han produït alguns errors en escriure els fitxers de configuració. Potser caldrà que els arregleu manualment abans d\'utilitzar el vostre nou DokuWiki.'; $lang['i_policy'] = 'Política ACL inicial'; $lang['i_pol0'] = 'Wiki obert (tothom pot llegir, escriure i penjar fitxers)'; $lang['i_pol1'] = 'Wiki públic (tothom pot llegir, els usuaris registrats poden escriure i penjar fitxers)'; diff --git a/inc/lang/cs/lang.php b/inc/lang/cs/lang.php index 11033ff68..b5ed76bf5 100644 --- a/inc/lang/cs/lang.php +++ b/inc/lang/cs/lang.php @@ -278,8 +278,8 @@ $lang['i_confexists'] = '%s již existuje'; $lang['i_writeerr'] = 'Nelze vytvořit %s. Budete muset zkontrolovat práva k souborům či adresářům a vytvořit tento soubor ručně.'; $lang['i_badhash'] = 'soubor dokuwiki.php (hash=%s) nebyl rozpoznán nebo byl upraven'; $lang['i_badval'] = '%s - neplatná nebo prázdná hodnota'; -$lang['i_success'] = 'Konfigurace byla úspěšně dokončena. Nyní můžete smazat soubor install.php. Pokračujte do své nové DokuWiki.'; -$lang['i_failure'] = 'Vyskytly se nějaké chyby při zápisu do konfiguračních souborů. Budete je nejspíš muset upravit ručně před použitím své nové DokuWiki.'; +$lang['i_success'] = 'Konfigurace byla úspěšně dokončena. Nyní můžete smazat soubor install.php. Pokračujte do své nové DokuWiki.'; +$lang['i_failure'] = 'Vyskytly se nějaké chyby při zápisu do konfiguračních souborů. Budete je nejspíš muset upravit ručně před použitím své nové DokuWiki.'; $lang['i_policy'] = 'Úvodní politika ACL'; $lang['i_pol0'] = 'Otevřená wiki (čtení, zápis a upload pro všechny)'; $lang['i_pol1'] = 'Veřejná wiki (čtení pro všechny, zápis a upload pro registrované uživatele)'; diff --git a/inc/lang/da/lang.php b/inc/lang/da/lang.php index 2c26cd3da..88cbb6871 100644 --- a/inc/lang/da/lang.php +++ b/inc/lang/da/lang.php @@ -285,8 +285,8 @@ $lang['i_confexists'] = '%s eksisterer allerede'; $lang['i_writeerr'] = 'Kunne ikke oprette %s. Du bliver nød til at tjekke mappe/fil- tilladelserne og oprette filen manuelt.'; $lang['i_badhash'] = 'uigenkendelig eller modificeret dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - ulovlig eller tom værdi'; -$lang['i_success'] = 'Konfigurationen fulførtedes med success. Du kan nu slette install.php filen. Fortsætte til din nye DokuWiki.'; -$lang['i_failure'] = 'Nogle fejl forekom mens konfigurations filerne skulle skrives. Du er mulighvis nød til at fixe dem manuelt før du kan bruge din nye DokuWiki.'; +$lang['i_success'] = 'Konfigurationen fulførtedes med success. Du kan nu slette install.php filen. Fortsætte til din nye DokuWiki.'; +$lang['i_failure'] = 'Nogle fejl forekom mens konfigurations filerne skulle skrives. Du er mulighvis nød til at fixe dem manuelt før du kan bruge din nye DokuWiki.'; $lang['i_policy'] = 'Begyndende ACL politik'; $lang['i_pol0'] = 'Åben Wiki (alle kan læse, skrive og uploade)'; $lang['i_pol1'] = 'Offentlig Wiki (alle kan læse, kun registrerede brugere kan skrive og overføre)'; diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php index cce898b15..bedda77ae 100644 --- a/inc/lang/de-informal/lang.php +++ b/inc/lang/de-informal/lang.php @@ -287,8 +287,8 @@ $lang['i_confexists'] = '%s existiert bereits'; $lang['i_writeerr'] = '%s konnte nicht erzeugt werden. Du solltest die Verzeichnis-/Datei-Rechte überprüfen und die Datei manuell anlegen.'; $lang['i_badhash'] = 'Unbekannte oder modifizierte dokuwiki.php (Hash=%s)'; $lang['i_badval'] = '%s - unerlaubter oder leerer Wert'; -$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Du kannst jetzt die install.php löschen. Dein neues DokuWiki ist jetzt für dich bereit.'; -$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Du musst diese vermutlich von Hand beheben, bevor du dein neues DokuWiki nutzen kannst.'; +$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Du kannst jetzt die install.php löschen. Dein neues DokuWiki ist jetzt für dich bereit.'; +$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Du musst diese vermutlich von Hand beheben, bevor du dein neues DokuWiki nutzen kannst.'; $lang['i_policy'] = 'Anfangseinstellung für Zugangskontrolle (ACL)'; $lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben, hochladen für alle)'; $lang['i_pol1'] = 'Öffentliches Wiki (lesen für alle, schreiben und hochladen für registrierte Nutzer)'; diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php index 07052fb3d..3810d4378 100644 --- a/inc/lang/de/lang.php +++ b/inc/lang/de/lang.php @@ -289,8 +289,8 @@ $lang['i_confexists'] = '%s existiert bereits'; $lang['i_writeerr'] = '%s konnte nicht erzeugt werden. Sie sollten die Verzeichnis-/Datei-Rechte überprüfen und die Datei manuell anlegen.'; $lang['i_badhash'] = 'Unbekannte oder modifizierte dokuwiki.php (Hash=%s)'; $lang['i_badval'] = '%s - unerlaubter oder leerer Wert'; -$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Sie können jetzt die install.php löschen. Ihr neues DokuWiki ist jetzt für Sie bereit.'; -$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Sie müssen diese vermutlich von Hand beheben, bevor Sie Ihr neues DokuWiki nutzen können.'; +$lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Sie können jetzt die install.php löschen. Ihr neues DokuWiki ist jetzt für Sie bereit.'; +$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Sie müssen diese vermutlich von Hand beheben, bevor Sie Ihr neues DokuWiki nutzen können.'; $lang['i_policy'] = 'Anfangseinstellung für Zugangskontrolle (ACL)'; $lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben, hochladen für alle)'; $lang['i_pol1'] = 'Öffentliches Wiki (lesen für alle, schreiben und hochladen für registrierte Nutzer)'; diff --git a/inc/lang/el/lang.php b/inc/lang/el/lang.php index d5bde6929..3220988ef 100644 --- a/inc/lang/el/lang.php +++ b/inc/lang/el/lang.php @@ -270,8 +270,8 @@ $lang['i_confexists'] = '%s υπάρχει ήδη'; $lang['i_writeerr'] = 'Δεν είναι δυνατή η δημιουργία του %s. Πρέπει να διορθώσετε τα δικαιώματα πρόσβασης αυτού του φακέλου/αρχείου και να δημιουργήσετε το αρχείο χειροκίνητα!'; $lang['i_badhash'] = 'Μη αναγνωρίσιμο ή τροποποιημένο αρχείο dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - λάθος ή ανύπαρκτη τιμή'; -$lang['i_success'] = 'Η εγκατάσταση ολοκληρώθηκε επιτυχώς. Μπορείτε πλέον να διαγράψετε το αρχείο install.php. Συνεχίστε στο νέο σας DokuWiki.'; -$lang['i_failure'] = 'Εμφανίστηκαν κάποια προβλήματα στη διαδικασία ανανέωσης των αρχείων ρυθμίσεων. Πιθανόν να χρειάζεται να τα τροποποιήσετε χειροκίνητα ώστε να μπορείτε να χρησιμοποιήσετε το νέο σας DokuWiki.'; +$lang['i_success'] = 'Η εγκατάσταση ολοκληρώθηκε επιτυχώς. Μπορείτε πλέον να διαγράψετε το αρχείο install.php. Συνεχίστε στο νέο σας DokuWiki.'; +$lang['i_failure'] = 'Εμφανίστηκαν κάποια προβλήματα στη διαδικασία ανανέωσης των αρχείων ρυθμίσεων. Πιθανόν να χρειάζεται να τα τροποποιήσετε χειροκίνητα ώστε να μπορείτε να χρησιμοποιήσετε το νέο σας DokuWiki.'; $lang['i_policy'] = 'Αρχική πολιτική Λίστας Δικαιωμάτων Πρόσβασης - ACL'; $lang['i_pol0'] = 'Ανοιχτό Wiki (όλοι μπορούν να διαβάσουν ή να δημιουργήσουν/τροποποιήσουν σελίδες και να μεταφορτώσουν αρχεία)'; $lang['i_pol1'] = 'Δημόσιο Wiki (όλοι μπορούν να διαβάσουν σελίδες αλλά μόνο οι εγγεγραμμένοι χρήστες μπορούν να δημιουργήσουν/τροποποιήσουν σελίδες και να μεταφορτώσουν αρχεία)'; diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 73c3522fd..99877320f 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -302,9 +302,9 @@ $lang['i_writeerr'] = 'Unable to create %s. You will nee $lang['i_badhash'] = 'unrecognised or modified dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - illegal or empty value'; $lang['i_success'] = 'The configuration was finished successfully. You may delete the install.php file now. Continue to - your new DokuWiki.'; + your new DokuWiki.'; $lang['i_failure'] = 'Some errors occurred while writing the configuration files. You may need to fix them manually before - you can use your new DokuWiki.'; + you can use your new DokuWiki.'; $lang['i_policy'] = 'Initial ACL policy'; $lang['i_pol0'] = 'Open Wiki (read, write, upload for everyone)'; $lang['i_pol1'] = 'Public Wiki (read for everyone, write and upload for registered users)'; diff --git a/inc/lang/eo/lang.php b/inc/lang/eo/lang.php index 3e0d86386..ccfc85fc8 100644 --- a/inc/lang/eo/lang.php +++ b/inc/lang/eo/lang.php @@ -278,8 +278,8 @@ $lang['i_confexists'] = '%s jam ekzistas'; $lang['i_writeerr'] = 'Ne eblas krei "%s". Vi bezonas kontroli la permesojn de la dosier(uj)oj kaj mem krej la dosieron.'; $lang['i_badhash'] = 'dokuwiki.php ne estas rekonebla aŭ ĝi estas modifita (hash=%s)'; $lang['i_badval'] = '%s - malvalida aŭ malplena valoro'; -$lang['i_success'] = 'La agordado sukcese kompletiĝis. Vi povas forigi la dosieron nun. Pluiru al via nova DokuWiki.'; -$lang['i_failure'] = 'Kelkaj eraroj okazis dum la konservo de la agordaj dosieroj. Vi devas senpere korekti ilin antaŭ ol vi povos uzi vian novan DokuWiki-on. '; +$lang['i_success'] = 'La agordado sukcese kompletiĝis. Vi povas forigi la dosieron nun. Pluiru al via nova DokuWiki.'; +$lang['i_failure'] = 'Kelkaj eraroj okazis dum la konservo de la agordaj dosieroj. Vi devas senpere korekti ilin antaŭ ol vi povos uzi vian novan DokuWiki-on. '; $lang['i_policy'] = 'Komenca ACL-a agordo'; $lang['i_pol0'] = 'Malferma Vikio (legi, skribi, alŝuti povas ĉiuj)'; $lang['i_pol1'] = 'Publika Vikio (legi povas ĉiuj, skribi kaj alŝuti povas registritaj uzantoj)'; diff --git a/inc/lang/es/lang.php b/inc/lang/es/lang.php index c09b12121..59a68fec4 100644 --- a/inc/lang/es/lang.php +++ b/inc/lang/es/lang.php @@ -287,8 +287,8 @@ $lang['i_confexists'] = '%s ya existe'; $lang['i_writeerr'] = 'Imposible crear %s. Se necesita que usted controle los permisos del fichero/directorio y que cree el fichero manualmente.'; $lang['i_badhash'] = 'dokuwiki.php no reconocido o modificado (hash=%s)'; $lang['i_badval'] = '%s - valor ilegal o vacío'; -$lang['i_success'] = 'La configuración ha concluido correctamente. Ahora puede eliminar el archivo install.php. Visite su nuevo DokuWiki.'; -$lang['i_failure'] = 'Han ocurrido algunos errores durante la escritura de los ficheros de configuración. Puede ser que necesite corregirlos manualmente antes de poder usar su nuevo DokuWiki.'; +$lang['i_success'] = 'La configuración ha concluido correctamente. Ahora puede eliminar el archivo install.php. Visite su nuevo DokuWiki.'; +$lang['i_failure'] = 'Han ocurrido algunos errores durante la escritura de los ficheros de configuración. Puede ser que necesite corregirlos manualmente antes de poder usar su nuevo DokuWiki.'; $lang['i_policy'] = 'Política de ACL inicial'; $lang['i_pol0'] = 'Wiki abierto (leer, escribir y subir archivos para todos)'; $lang['i_pol1'] = 'Wiki público (leer para todos, escribir y subir archivos para usuarios registrados únicamente)'; diff --git a/inc/lang/et/lang.php b/inc/lang/et/lang.php index 37d4538ec..8ae61558a 100644 --- a/inc/lang/et/lang.php +++ b/inc/lang/et/lang.php @@ -223,8 +223,8 @@ $lang['i_permfail'] = 'Dokuwiki ei saa kirjutada faili %svotre nouveau DokuWiki.'; -$lang['i_failure'] = 'Des erreurs sont survenues lors de l\'écriture des fichiers de configuration. Il vous faudra les corriger manuellement avant de pouvoir utiliser votre nouveau DokuWiki.'; +$lang['i_success'] = 'L\'installation s\'est terminée avec succès. Vous pouvez maintenant supprimer le fichier « install.php ». Continuer avec votre nouveau DokuWiki.'; +$lang['i_failure'] = 'Des erreurs sont survenues lors de l\'écriture des fichiers de configuration. Il vous faudra les corriger manuellement avant de pouvoir utiliser votre nouveau DokuWiki.'; $lang['i_policy'] = 'Politique d\'ACL initiale'; $lang['i_pol0'] = 'Wiki ouvert (lecture, écriture, envoi de fichiers pour tout le monde)'; $lang['i_pol1'] = 'Wiki public (lecture pour tout le monde, écriture et envoi de fichiers pour les utilisateurs enregistrés)'; diff --git a/inc/lang/gl/lang.php b/inc/lang/gl/lang.php index 466f0fb8c..7c8b82691 100644 --- a/inc/lang/gl/lang.php +++ b/inc/lang/gl/lang.php @@ -269,9 +269,9 @@ $lang['i_writeerr'] = 'Non se puido crear %s. Terás de $lang['i_badhash'] = 'dokuwiki.php irrecoñecíbel ou modificado (hash=%s)'; $lang['i_badval'] = '%s - ilegal ou valor baleiro'; $lang['i_success'] = 'A configuración rematou correctamente. Agora podes eliminar o arquivo install.php. Continúa deica o - teu novo DokuWiki.'; + teu novo DokuWiki.'; $lang['i_failure'] = 'Houbo algúns erros ao tentar escribir os arquivos de configuración. Pode que precises solucionalos de xeito manual antes - de poderes empregar o teu novo DokuWiki.'; + de poderes empregar o teu novo DokuWiki.'; $lang['i_policy'] = 'Regras iniciais da ACL'; $lang['i_pol0'] = 'Wiki Aberto (lectura, escritura, subida de arquivos para todas as persoas)'; $lang['i_pol1'] = 'Wiki Público (lectura para todas as persoas, escritura e subida de arquivos para usuarios rexistrados)'; diff --git a/inc/lang/he/lang.php b/inc/lang/he/lang.php index 9cbcc3c4f..e474501ae 100644 --- a/inc/lang/he/lang.php +++ b/inc/lang/he/lang.php @@ -249,8 +249,8 @@ $lang['i_confexists'] = '%s כבר קיים'; $lang['i_writeerr'] = 'אין אפשרות ליצור את %s. נא לבדוק את הרשאות הקובץ/תיקייה וליצור את הקובץ ידנית.'; $lang['i_badhash'] = 'הקובץ Dokuwiki.php אינו מזוהה או שעבר שינויים (hash=%s)'; $lang['i_badval'] = '%s - הערך אינו חוקי או ריק'; -$lang['i_success'] = 'תהליך ההגדרה הסתיים בהצלחה. כעת ניתן למחוק את הקובץ install.php ולהמשיך אל ה־DokuWiki החדש שלך.'; -$lang['i_failure'] = 'מספר שגיאות אירעו בעת כתיבת קובצי התצורה. יתכן כי יהיה צורך לתקנם ידנית לפני שניתן יהיה להשתמש ב־DokuWiki החדש שלך.'; +$lang['i_success'] = 'תהליך ההגדרה הסתיים בהצלחה. כעת ניתן למחוק את הקובץ install.php ולהמשיך אל ה־DokuWiki החדש שלך.'; +$lang['i_failure'] = 'מספר שגיאות אירעו בעת כתיבת קובצי התצורה. יתכן כי יהיה צורך לתקנם ידנית לפני שניתן יהיה להשתמש ב־DokuWiki החדש שלך.'; $lang['i_policy'] = 'מדיניות ACL התחלתית'; $lang['i_pol0'] = 'ויקי פתוח (קריאה, כתיבה והעלאה לכולם)'; $lang['i_pol1'] = ' ויקי ציבורי (קריאה לכולם, כתיבה והעלאה למשתמשים רשומים)'; diff --git a/inc/lang/hr/lang.php b/inc/lang/hr/lang.php index ac2a740ef..97f4cf0c2 100644 --- a/inc/lang/hr/lang.php +++ b/inc/lang/hr/lang.php @@ -247,8 +247,8 @@ $lang['i_confexists'] = '%s već postoji'; $lang['i_writeerr'] = 'Ne može se kreirati %s. Trebate provjeriti dozvole direktorija/datoteke i kreirati dokument ručno.'; $lang['i_badhash'] = 'neprepoznat ili promijenjen dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - nedozvoljena ili prazna vrijednost'; -$lang['i_success'] = 'Konfiguracija je uspješno završena. Sada možete obrisati install.php datoteku. Nastavite na vaš novi DokuWiki.'; -$lang['i_failure'] = 'Pojavile su se neke greške prilikom pisanja konfiguracijskih datoteka. Morati ćete ih ručno ispraviti da bi mogli koristiti vaš novi DokuWiki.'; +$lang['i_success'] = 'Konfiguracija je uspješno završena. Sada možete obrisati install.php datoteku. Nastavite na vaš novi DokuWiki.'; +$lang['i_failure'] = 'Pojavile su se neke greške prilikom pisanja konfiguracijskih datoteka. Morati ćete ih ručno ispraviti da bi mogli koristiti vaš novi DokuWiki.'; $lang['i_policy'] = 'Inicijalna ACL politika'; $lang['i_pol0'] = 'Otvoreni Wiki (čitanje, pisanje, učitavanje za sve)'; $lang['i_pol1'] = 'Javni Wiki (čitanje za sve, pisanje i učitavanje za registrirane korisnike)'; diff --git a/inc/lang/hu/lang.php b/inc/lang/hu/lang.php index 43b79b41b..c59cace77 100644 --- a/inc/lang/hu/lang.php +++ b/inc/lang/hu/lang.php @@ -252,8 +252,8 @@ $lang['i_confexists'] = '%s már létezik.'; $lang['i_writeerr'] = 'Nem tudom ezt létrehozni: %s. Ellenőrizd a könyvtár/fájl jogosultságokat, és hozd létre az állományt kézzel.'; $lang['i_badhash'] = 'A dokuwiki.php nem felismerhető vagy módosított (hash=%s)'; $lang['i_badval'] = '%s - nem helyes vagy üres érték'; -$lang['i_success'] = 'A beállítás sikeresen befejeződött. Most már letörölhető az install.php fájl. Látogasd meg az új DokuWikidet!'; -$lang['i_failure'] = 'Hiba lépett fel a konfigurációs állományok írásakor. Ki kell javítanod kézzel, mielőtt használni kezded az új DokuWikidet.'; +$lang['i_success'] = 'A beállítás sikeresen befejeződött. Most már letörölhető az install.php fájl. Látogasd meg az új DokuWikidet!'; +$lang['i_failure'] = 'Hiba lépett fel a konfigurációs állományok írásakor. Ki kell javítanod kézzel, mielőtt használni kezded az új DokuWikidet.'; $lang['i_policy'] = 'Kezdeti hozzáférési politika'; $lang['i_pol0'] = 'Nyitott Wiki (mindenki olvashatja, írhatja, és fájlokat tölthet fel)'; $lang['i_pol1'] = 'Publikus Wiki (mindenki olvashatja, de csak regisztrált felhasználók írhatják, és tölthetnek fel fájlokat)'; diff --git a/inc/lang/ia/lang.php b/inc/lang/ia/lang.php index aff133698..a9d5c376c 100644 --- a/inc/lang/ia/lang.php +++ b/inc/lang/ia/lang.php @@ -247,9 +247,9 @@ $lang['i_writeerr'] = 'Impossibile crear %s. Tu debe ver $lang['i_badhash'] = 'dokuwiki.php non recognoscite o modificate (hash=%s)'; $lang['i_badval'] = '%s - valor vacue o invalide'; $lang['i_success'] = 'Le configuration ha succedite. Tu pote ora deler le file install.php. Continua a -tu nove DokuWiki.'; +tu nove DokuWiki.'; $lang['i_failure'] = 'Alcun errores occurreva durante le scriptura del files de configuration. Es possibile que tu debe remediar iste errores manualmente ante que -tu pote usar tu nove DokuWiki.'; +tu pote usar tu nove DokuWiki.'; $lang['i_policy'] = 'Politica de ACL interne'; $lang['i_pol0'] = 'Wiki aperte (lectura, scriptura, incargamento pro omnes)'; $lang['i_pol1'] = 'Wiki public (lectura pro omnes, scriptura e incargamento pro usatores registrate)'; diff --git a/inc/lang/id/lang.php b/inc/lang/id/lang.php index 566e8dcb0..91ed38e31 100644 --- a/inc/lang/id/lang.php +++ b/inc/lang/id/lang.php @@ -188,8 +188,8 @@ $lang['i_confexists'] = '%s sudah ada'; $lang['i_writeerr'] = 'Tidak dapat membuat %s. Anda harus memeriksa konfigurasi hak akses direktori/berkas dan membuatnya secara manual.'; $lang['i_badhash'] = 'dokuwiki.php tidak dikenal atau sudah diubah (hash=%s)'; $lang['i_badval'] = '%s - tidak valid atau belum diisi'; -$lang['i_success'] = 'Konfigurasi telah berhasil. Anda boleh menghapus berkas install.php sekarang. Lanjutkan ke DokuWiki baru Anda.'; -$lang['i_failure'] = 'Terdapat beberapa kesalahan dalam menulis berkas konfigurasi. Anda harus memperbaikinnya sendiri sebelum dapat menggunakan DokuWiki baru Anda.'; +$lang['i_success'] = 'Konfigurasi telah berhasil. Anda boleh menghapus berkas install.php sekarang. Lanjutkan ke DokuWiki baru Anda.'; +$lang['i_failure'] = 'Terdapat beberapa kesalahan dalam menulis berkas konfigurasi. Anda harus memperbaikinnya sendiri sebelum dapat menggunakan DokuWiki baru Anda.'; $lang['i_policy'] = 'Policy ACL awal'; $lang['i_pol0'] = 'Wiki Terbuka (baca, tulis, upload untuk semua orang)'; $lang['i_pol1'] = 'Wiki Publik (baca untuk semua orang, tulis dan upload untuk pengguna terdaftar)'; diff --git a/inc/lang/it/lang.php b/inc/lang/it/lang.php index 6ae864f8b..3d84c7bbb 100644 --- a/inc/lang/it/lang.php +++ b/inc/lang/it/lang.php @@ -281,8 +281,8 @@ $lang['i_confexists'] = '%s esiste già'; $lang['i_writeerr'] = 'Impossibile creare %s. E\' necessario verificare i permessi della directory o del file oppure creare il file manualmente.'; $lang['i_badhash'] = 'dokuwiki.php (hash=%s) non riconosciuto o modificato'; $lang['i_badval'] = '%s - valore vuoto o non valido'; -$lang['i_success'] = 'La configurazione è stata completata correttamente. Ora è possibile eliminare il file install.php. Poi, visita il tuo nuovo DokuWiki.'; -$lang['i_failure'] = 'Si sono verificati errori durante la scrittura dei file di configurazione. Potrebbe essere necessario correggerli manualmente prima di poter utilizzare il tuo nuovo DokuWiki.'; +$lang['i_success'] = 'La configurazione è stata completata correttamente. Ora è possibile eliminare il file install.php. Poi, visita il tuo nuovo DokuWiki.'; +$lang['i_failure'] = 'Si sono verificati errori durante la scrittura dei file di configurazione. Potrebbe essere necessario correggerli manualmente prima di poter utilizzare il tuo nuovo DokuWiki.'; $lang['i_policy'] = 'Regole di accesso iniziali'; $lang['i_pol0'] = 'Wiki Aperto (lettura, scrittura, caricamento file per tutti)'; $lang['i_pol1'] = 'Wiki Pubblico (lettura per tutti, scrittura e caricamento file per gli utenti registrati)'; diff --git a/inc/lang/ja/lang.php b/inc/lang/ja/lang.php index 93300e20e..dc6146468 100644 --- a/inc/lang/ja/lang.php +++ b/inc/lang/ja/lang.php @@ -278,8 +278,8 @@ $lang['i_confexists'] = '%s は既に存在します'; $lang['i_writeerr'] = '%s を作成できません。ディレクトリとファイルの権限を確認し、それらを手動で作成する必要があります。'; $lang['i_badhash'] = 'dokuwiki.php が認識できないか、編集されています(hash=%s)'; $lang['i_badval'] = '%s - 正しくない、もしくは値が空です'; -$lang['i_success'] = '設定ファイルは正しく作成されました。作成した DokuWikiを使用するには install.php を削除してください。'; -$lang['i_failure'] = '設定ファイルの作成中にエラーが発生しました。作成した DokuWikiを使用する前に、それらの問題を手動で修正する必要があります。'; +$lang['i_success'] = '設定ファイルは正しく作成されました。作成した DokuWikiを使用するには install.php を削除してください。'; +$lang['i_failure'] = '設定ファイルの作成中にエラーが発生しました。作成した DokuWikiを使用する前に、それらの問題を手動で修正する必要があります。'; $lang['i_policy'] = 'ACL初期設定'; $lang['i_pol0'] = 'オープン Wiki(全ての人に、閲覧・書き込み・アップロードを許可)'; $lang['i_pol1'] = 'パブリック Wiki(閲覧は全ての人が可能、書き込み・アップロードは登録ユーザーのみ)'; diff --git a/inc/lang/ko/lang.php b/inc/lang/ko/lang.php index 1a618f1a7..53d3cf58e 100644 --- a/inc/lang/ko/lang.php +++ b/inc/lang/ko/lang.php @@ -279,8 +279,8 @@ $lang['i_confexists'] = '%s(은)는 이미 존재합니다 $lang['i_writeerr'] = '%s(을)를 만들 수 없습니다. 먼저 디렉토리/파일 권한을 확인하고 파일을 수동으로 만들기 바랍니다.'; $lang['i_badhash'] = 'dokuwiki.php를 인식할 수 없거나 원본 파일이 아닙니다. (해시=%s)'; $lang['i_badval'] = '%s - 유효하지 않거나 빈 값입니다.'; -$lang['i_success'] = '환경 설정이 성공적으로 끝났습니다. 지금 install.php를 지워도 상관없습니다. 새 DokuWiki로 들어갑니다.'; -$lang['i_failure'] = '환경 설정 파일에 쓰는 도중에 오류가 발생했습니다. 새 DokuWiki를 사용하기 전에 수동으로 문제를 해결할 필요가 있습니다.'; +$lang['i_success'] = '환경 설정이 성공적으로 끝났습니다. 지금 install.php를 지워도 상관없습니다. 새 DokuWiki로 들어갑니다.'; +$lang['i_failure'] = '환경 설정 파일에 쓰는 도중에 오류가 발생했습니다. 새 DokuWiki를 사용하기 전에 수동으로 문제를 해결할 필요가 있습니다.'; $lang['i_policy'] = '초기 ACL 정책'; $lang['i_pol0'] = '열린 위키 (누구나 읽기, 쓰기, 올리기가 가능합니다.)'; $lang['i_pol1'] = '공개 위키 (누구나 읽을 수 있지만, 등록된 사용자만 쓰기와 올리기가 가능합니다.)'; diff --git a/inc/lang/la/lang.php b/inc/lang/la/lang.php index c7d654e96..77fec8362 100644 --- a/inc/lang/la/lang.php +++ b/inc/lang/la/lang.php @@ -246,8 +246,8 @@ $lang['i_confexists'] = '%s iam est.'; $lang['i_writeerr'] = '%s non creari potest. Manu illum creas.'; $lang['i_badhash'] = 'Ignotum uel mutatum dokuwiki.php (%s)'; $lang['i_badval'] = '%s non legitimum uel uacuom'; -$lang['i_success'] = 'Administratio feliciter perficitur. Delere install.php documentum potes. I ad hanc paginam ut continues.'; -$lang['i_failure'] = 'Aliqui errores dum documenta administrantur sunt. Manu onerare omnes potes priusquam tuo nouo uice uteris.'; +$lang['i_success'] = 'Administratio feliciter perficitur. Delere install.php documentum potes. I ad hanc paginam ut continues.'; +$lang['i_failure'] = 'Aliqui errores dum documenta administrantur sunt. Manu onerare omnes potes priusquam tuo nouo uice uteris.'; $lang['i_policy'] = 'ICA ratio prima'; $lang['i_pol0'] = 'Vicem aperire (omnes legere, scribere, onerare possunt)'; $lang['i_pol1'] = 'Publicus uicis (omnes legere, Sodales scribere et onerare possunt)'; diff --git a/inc/lang/lv/lang.php b/inc/lang/lv/lang.php index 67480abfc..6bdec03f3 100644 --- a/inc/lang/lv/lang.php +++ b/inc/lang/lv/lang.php @@ -264,8 +264,8 @@ $lang['i_confexists'] = '%s jau ir'; $lang['i_writeerr'] = 'Nevar izveidot %s. Jāpārbauda direktorijas/faila tiesības un fails jāizveido pašam.'; $lang['i_badhash'] = 'nepazīstams vai izmainīts dokuwiki.php fails (hash=%s)'; $lang['i_badval'] = '%s - neatļauta vai tukša vērtība'; -$lang['i_success'] = 'Konfigurēšana veiksmīgi pabeigta. Tagad vari nodzēst failu install.php. Tālāk turpini savā jaunajā DokuWiki.'; -$lang['i_failure'] = 'Rakstot konfigurācijas failu, gadījās dažas kļūmes. Pirms lieto savu jauno DokuWiki, tās varbūt jāizlabo.'; +$lang['i_success'] = 'Konfigurēšana veiksmīgi pabeigta. Tagad vari nodzēst failu install.php. Tālāk turpini savā jaunajā DokuWiki.'; +$lang['i_failure'] = 'Rakstot konfigurācijas failu, gadījās dažas kļūmes. Pirms lieto savu jauno DokuWiki, tās varbūt jāizlabo.'; $lang['i_policy'] = 'Sākotnējā ACL politika'; $lang['i_pol0'] = 'Atvērts Wiki (raksta, lasa un augšupielādē ikviens)'; $lang['i_pol1'] = 'Publisks Wiki (lasa ikviens, raksta un augšupielādē reģistrēti lietotāji)'; diff --git a/inc/lang/mk/lang.php b/inc/lang/mk/lang.php index f04c51e37..7482f2512 100644 --- a/inc/lang/mk/lang.php +++ b/inc/lang/mk/lang.php @@ -214,8 +214,8 @@ $lang['i_confexists'] = '%s веќе постои'; $lang['i_writeerr'] = 'Не може да се креира %s. Треба да ги проверите пермисиите на директориумот/датотеката и рачно да ја креирате датотеката.'; $lang['i_badhash'] = 'непозната или изменете dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - нелегална или празна вредност'; -$lang['i_success'] = 'Конфигурацијата успешно заврши. Сега можете да ја избришете датотеката install.php. Продолжете до вашето ново DokuWiki.'; -$lang['i_failure'] = 'Се појавија некои грешки при запишувањето на конфигурациските датотеки. Можеби треба да ги поравите рачно пред да можете да го користите вашето ново DokuWiki.'; +$lang['i_success'] = 'Конфигурацијата успешно заврши. Сега можете да ја избришете датотеката install.php. Продолжете до вашето ново DokuWiki.'; +$lang['i_failure'] = 'Се појавија некои грешки при запишувањето на конфигурациските датотеки. Можеби треба да ги поравите рачно пред да можете да го користите вашето ново DokuWiki.'; $lang['i_policy'] = 'Почетна ACL политика'; $lang['i_pol0'] = 'Отвори вики (читај, запиши, качи за сите)'; $lang['i_pol1'] = 'Јавно вики (читај за сите, запиши и качи за регистрирани корисници)'; diff --git a/inc/lang/mr/lang.php b/inc/lang/mr/lang.php index c6064a610..b754a3f1c 100644 --- a/inc/lang/mr/lang.php +++ b/inc/lang/mr/lang.php @@ -258,8 +258,8 @@ $lang['i_confexists'] = '%s आधीच अस्ति $lang['i_writeerr'] = '%s निर्माण करू शकलो नाही. तुम्हाला डिरेक्टरी / फाइल च्या परवानग्या तपासून स्वतःच ही फाइल बनवावी लागेल.'; $lang['i_badhash'] = 'अनाकलनीय किंवा बदललेले dokuwiki.php (hash=%s)'; $lang['i_badval'] = 'code>%s - अवैध किंवा रिकामा मजकूर.'; -$lang['i_success'] = 'व्यवस्था लावण्याचे काम यशस्वीरीत्या पार पडले. आता तुम्ही install.php डिलीट करू शकता. तुमच्या नविन डॉक्युविकि वर जा.'; -$lang['i_failure'] = 'कॉन्फिगुरेशनच्या फाइल सुरक्षित करताना काही अडचणी आल्या आहेत. तुमची नवीन डॉक्युविकि वापरण्याआधी तुम्हाला ह्या फाइल स्वतः ठीक कराव्या लागतील.'; +$lang['i_success'] = 'व्यवस्था लावण्याचे काम यशस्वीरीत्या पार पडले. आता तुम्ही install.php डिलीट करू शकता. तुमच्या नविन डॉक्युविकि वर जा.'; +$lang['i_failure'] = 'कॉन्फिगुरेशनच्या फाइल सुरक्षित करताना काही अडचणी आल्या आहेत. तुमची नवीन डॉक्युविकि वापरण्याआधी तुम्हाला ह्या फाइल स्वतः ठीक कराव्या लागतील.'; $lang['i_policy'] = 'आरंभीची ACL पॉलिसी'; $lang['i_pol0'] = 'मुक्त विकी ( सर्वांना वाचन, लेखन व अपलोड करण्याची परवानगी )'; $lang['i_pol1'] = 'सार्वजनिक विकी ( सर्वांना वाचण्याची मुभा , लेखन व अपलोडची परवानगी फक्त नोंदणीकृत सदस्यांना )'; diff --git a/inc/lang/ne/lang.php b/inc/lang/ne/lang.php index bde40a670..fa6d2f705 100644 --- a/inc/lang/ne/lang.php +++ b/inc/lang/ne/lang.php @@ -191,8 +191,8 @@ $lang['i_confexists'] = '%s पहिले देखि $lang['i_writeerr'] = '%s बनाउन असमर्थ । तपाईले डाइरेक्टरी / फाइल अनुमति जाच्नु पर्छ र फाइल आफैले बनाउनु पर्छ ।'; $lang['i_badhash'] = 'पहिचान हुन नसकेको वा परिवर्तित okuwiki.php (hash=code>%s)'; $lang['i_badval'] = '%s - अवैध वा रित्तो मान '; -$lang['i_success'] = 'स्थापना सफलरुपमा समाप्त भयो ।तपाई install.php मेट्न सक्नुहु्न्छ । तपाईको नयाँ DokuWiki निरन्तर गर्न सक्नुहुन्छ ।'; -$lang['i_failure'] = 'स्थापना समयमा केहि त्रुटि फेला पर्यो ।तपाईले आफैले यसलाई तपाईको नयाँ DokuWiki प्रयोग गर्नु अगि सच्याउनुपर्ने हुन्छ ।'; +$lang['i_success'] = 'स्थापना सफलरुपमा समाप्त भयो ।तपाई install.php मेट्न सक्नुहु्न्छ । तपाईको नयाँ DokuWiki निरन्तर गर्न सक्नुहुन्छ ।'; +$lang['i_failure'] = 'स्थापना समयमा केहि त्रुटि फेला पर्यो ।तपाईले आफैले यसलाई तपाईको नयाँ DokuWiki प्रयोग गर्नु अगि सच्याउनुपर्ने हुन्छ ।'; $lang['i_policy'] = 'सुरुको ACL निति'; $lang['i_pol0'] = 'खुल्ला विकि (पठन, लेखन , अपलोड ) सबैका लागि'; $lang['i_pol1'] = 'Public विकि (पठन सवैका लागि,लेखन र अपलोड दर्ता गरिएका प्रयपगकर्ताका लागि ) '; diff --git a/inc/lang/nl/lang.php b/inc/lang/nl/lang.php index 6d14a0e4b..44feda846 100644 --- a/inc/lang/nl/lang.php +++ b/inc/lang/nl/lang.php @@ -286,8 +286,8 @@ $lang['i_confexists'] = '%s bestaat reeds'; $lang['i_writeerr'] = 'Niet mogelijk om %s aan te maken. Controleer de directory/bestandspermissies en maak het bestand handmatig aan.'; $lang['i_badhash'] = 'Onbekende of aangepaste dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - onjuiste of lege waarde'; -$lang['i_success'] = 'De configuratie is succesvol afgerond. Je kunt nu het bestand install.php verwijderen. Ga naar je nieuwe DokuWiki.'; -$lang['i_failure'] = 'Fouten deden zich voor tijdens het schrijven naar de configuratiebestanden. Pas deze aan voor je gebruik kunt maken van je nieuwe DokuWiki.'; +$lang['i_success'] = 'De configuratie is succesvol afgerond. Je kunt nu het bestand install.php verwijderen. Ga naar je nieuwe DokuWiki.'; +$lang['i_failure'] = 'Fouten deden zich voor tijdens het schrijven naar de configuratiebestanden. Pas deze aan voor je gebruik kunt maken van je nieuwe DokuWiki.'; $lang['i_policy'] = 'Initieel ACL-beleid'; $lang['i_pol0'] = 'Open wiki (lezen, schrijven, uploaden voor iedereen)'; $lang['i_pol1'] = 'Publieke wiki (lezen voor iedereen, schrijven en uploaden voor geregistreerde gebruikers)'; diff --git a/inc/lang/no/lang.php b/inc/lang/no/lang.php index 81aa39612..92c840274 100644 --- a/inc/lang/no/lang.php +++ b/inc/lang/no/lang.php @@ -282,9 +282,9 @@ $lang['i_writeerr'] = 'Kunne ikke opprette %s. Du må sj $lang['i_badhash'] = 'ikke gjenkjent eller modifisert dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - ugyldig eller tom verdi'; $lang['i_success'] = 'Konfigurasjonen ble vellykket fullført. Du kan slette install.php filen nå. Fortsett til - din nye DokuWiki.'; + din nye DokuWiki.'; $lang['i_failure'] = 'En eller flere feil oppstod ved skriving til konfigurasjonsfilene. Du må kanskje fikse dem manuelt før - du kan bruke din nye DokuWiki.'; + du kan bruke din nye DokuWiki.'; $lang['i_policy'] = 'Innledende ACL-politikk'; $lang['i_pol0'] = 'Åpen Wiki (les, skriv og opplasting for alle)'; $lang['i_pol1'] = 'Offentlig Wiki (les for alle, skriving og opplasting bare for registrerte brukere)'; diff --git a/inc/lang/pl/lang.php b/inc/lang/pl/lang.php index 0f0381e8f..7c89a611a 100644 --- a/inc/lang/pl/lang.php +++ b/inc/lang/pl/lang.php @@ -285,8 +285,8 @@ $lang['i_confexists'] = '%s już istnieje'; $lang['i_writeerr'] = 'Nie można utworzyć %s. Sprawdź uprawnienia do katalogu lub pliku i stwórz plik ręcznie.'; $lang['i_badhash'] = 'nierozpoznany lub zmodyfikowany plik dokuwiki.php (skrót=%s)'; $lang['i_badval'] = '%s - nieprawidłowa wartość lub jej brak'; -$lang['i_success'] = 'Konfiguracja pomyślnie zakończona. Możesz teraz usunąć plik install.php. Przejdź do Twojego nowego DokuWiki.'; -$lang['i_failure'] = 'Podczas zapisu plików konfiguracyjnych wystąpiły błędy. Musisz usunąć wszystkie problemy, zanim zaczniesz korzystać z Twojego nowego DokuWiki.'; +$lang['i_success'] = 'Konfiguracja pomyślnie zakończona. Możesz teraz usunąć plik install.php. Przejdź do Twojego nowego DokuWiki.'; +$lang['i_failure'] = 'Podczas zapisu plików konfiguracyjnych wystąpiły błędy. Musisz usunąć wszystkie problemy, zanim zaczniesz korzystać z Twojego nowego DokuWiki.'; $lang['i_policy'] = 'Wstępna polityka uprawnień ACL'; $lang['i_pol0'] = 'Otwarte Wiki (odczyt, zapis i dodawanie plików dla wszystkich)'; $lang['i_pol1'] = 'Publiczne Wiki (odczyt dla wszystkich, zapis i dodawanie plików tylko dla zarejestrowanych użytkowników)'; diff --git a/inc/lang/pt-br/lang.php b/inc/lang/pt-br/lang.php index 26a73bfae..3da7e9f45 100644 --- a/inc/lang/pt-br/lang.php +++ b/inc/lang/pt-br/lang.php @@ -261,8 +261,8 @@ $lang['i_confexists'] = '%s já existe'; $lang['i_writeerr'] = 'Não foi possível criar %s. É necessário checar as permissões de arquivos/diretórios e criar o arquivo manualmente.'; $lang['i_badhash'] = 'dokuwiki.php não reconhecido ou modificado (hash=%s)'; $lang['i_badval'] = '%s - valor ilegal ou em branco'; -$lang['i_success'] = 'A configuração terminou com sucesso. Agora você deve excluir o arquivo install.php. Conheça o seu novo DokuWiki!'; -$lang['i_failure'] = 'Ocorreram alguns erros durante a escrita dos arquivos de configuração. É necessário corrigi-los manualmente antes de usar seu novo DokuWiki'; +$lang['i_success'] = 'A configuração terminou com sucesso. Agora você deve excluir o arquivo install.php. Conheça o seu novo DokuWiki!'; +$lang['i_failure'] = 'Ocorreram alguns erros durante a escrita dos arquivos de configuração. É necessário corrigi-los manualmente antes de usar seu novo DokuWiki'; $lang['i_policy'] = 'Política inicial de permissões'; $lang['i_pol0'] = 'Wiki aberto (leitura, escrita e envio de arquivos por todos)'; $lang['i_pol1'] = 'Wiki público (leitura por todos, escrita e envio de arquivos por usuários registrados)'; diff --git a/inc/lang/pt/lang.php b/inc/lang/pt/lang.php index 37b3fba8c..7fec71aa2 100644 --- a/inc/lang/pt/lang.php +++ b/inc/lang/pt/lang.php @@ -268,8 +268,8 @@ $lang['i_confexists'] = '%s já existe'; $lang['i_writeerr'] = 'Não foi possível criar %s. É preciso verificar as permissões e criar o ficheiro manualmente.'; $lang['i_badhash'] = 'dokuwiki.php não é o original ou não é reconhecido (hash=%s)'; $lang['i_badval'] = '%s - valor ilegal ou vazio'; -$lang['i_success'] = 'A instalação e configuração inicial foram bem sucedidas. Pode remover o install.php. Aceda ao seu novo Wiki a correr o DokuWiki.'; -$lang['i_failure'] = 'Ocorreram alguns erros durante a escrita nos ficheiros de configuração. Poderá ser preciso corrigi-los manualmente antes de poder aceder ao seu novo Wiki a correr o DokuWiki.'; +$lang['i_success'] = 'A instalação e configuração inicial foram bem sucedidas. Pode remover o install.php. Aceda ao seu novo Wiki a correr o DokuWiki.'; +$lang['i_failure'] = 'Ocorreram alguns erros durante a escrita nos ficheiros de configuração. Poderá ser preciso corrigi-los manualmente antes de poder aceder ao seu novo Wiki a correr o DokuWiki.'; $lang['i_policy'] = 'Politica ACL inicial'; $lang['i_pol0'] = 'Wiki Aberto (ler, escrever e carregar para todos)'; $lang['i_pol1'] = 'Wiki Público (ler para todos, escrever e carregar para utilizadores inscritos)'; diff --git a/inc/lang/ro/lang.php b/inc/lang/ro/lang.php index cb8e2ed0c..94c9d87ce 100644 --- a/inc/lang/ro/lang.php +++ b/inc/lang/ro/lang.php @@ -280,8 +280,8 @@ $lang['i_confexists'] = '%s există deja'; $lang['i_writeerr'] = 'Nu s-a putut crea %s. Trebuie să verificaţi drepturile directorului/fişierului şi să creaţi fişierul manual.'; $lang['i_badhash'] = 'dokuwiki.php nu a fost recunoscut sau a fost modificat (hash=%s)'; $lang['i_badval'] = '%s - valoare nepemisă sau neintrodusă'; -$lang['i_success'] = 'Configurarea a fost finalizată cu succes. Acum puteţi sterge fişierul install.php. Continuaţi cu your new DokuWiki.'; -$lang['i_failure'] = 'Au apărut erori la scrierea fişierelor de configurare. Va trebui să le corectaţi manual înainte de a putea folosi your new DokuWiki.'; +$lang['i_success'] = 'Configurarea a fost finalizată cu succes. Acum puteţi sterge fişierul install.php. Continuaţi cu your new DokuWiki.'; +$lang['i_failure'] = 'Au apărut erori la scrierea fişierelor de configurare. Va trebui să le corectaţi manual înainte de a putea folosi your new DokuWiki.'; $lang['i_policy'] = 'Politica ACL iniţială'; $lang['i_pol0'] = 'Wiki Deschisă (citeşte, scrie şi încarcă oricine)'; $lang['i_pol1'] = 'Wiki Deschisă (citeste oricine, scrie şi încarcă doar utilizatorul înregistrat)'; diff --git a/inc/lang/ru/lang.php b/inc/lang/ru/lang.php index 920bc907f..76dcc8428 100644 --- a/inc/lang/ru/lang.php +++ b/inc/lang/ru/lang.php @@ -291,8 +291,8 @@ $lang['i_writeerr'] = 'Не удалось создать %sсвоей новой «ДокуВики».'; +$lang['i_failure'] = 'При записи в файлы конфигурации были обнаружены ошибки. Возможно, вам придётся исправить их вручную, прежде чем вы сможете использовать свою новую «ДокуВики».'; $lang['i_policy'] = 'Исходная политика прав доступа'; $lang['i_pol0'] = 'Открытая вики (чтение, запись, закачка файлов для всех)'; $lang['i_pol1'] = 'Общедоступная вики (чтение для всех, запись и загрузка файлов для зарегистрированных пользователей)'; diff --git a/inc/lang/sk/lang.php b/inc/lang/sk/lang.php index 79a13ac35..4eddc199a 100644 --- a/inc/lang/sk/lang.php +++ b/inc/lang/sk/lang.php @@ -268,8 +268,8 @@ $lang['i_confexists'] = '%s už existuje'; $lang['i_writeerr'] = 'Nie je možné vytvoriť %s. Potrebujete skontrolovať prístupové práva pre adresár/súbor a vytvoriť ho manuálne.'; $lang['i_badhash'] = 'neznámy alebo zmenený súbor dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - nesprávna alebo žiadna hodnota'; -$lang['i_success'] = 'Konfigurácia bola úspešne ukončená. Teraz môžete zmazať súbor install.php. Pokračujte vo vašej novej DokuWiki.'; -$lang['i_failure'] = 'Pri zápise konfiguračného súboru nastali nejaké chyby. Potrebujete ich opraviť manuálne pred tým, ako budete môcť používať vašu novú DokuWiki.'; +$lang['i_success'] = 'Konfigurácia bola úspešne ukončená. Teraz môžete zmazať súbor install.php. Pokračujte vo vašej novej DokuWiki.'; +$lang['i_failure'] = 'Pri zápise konfiguračného súboru nastali nejaké chyby. Potrebujete ich opraviť manuálne pred tým, ako budete môcť používať vašu novú DokuWiki.'; $lang['i_policy'] = 'Počiatočná ACL politika'; $lang['i_pol0'] = 'Otvorená Wiki (čítanie, zápis a nahrávanie pre každého)'; $lang['i_pol1'] = 'Verejná Wiki (čítanie pre každého, zápis a nahrávanie pre registrovaných užívateľov)'; diff --git a/inc/lang/sl/lang.php b/inc/lang/sl/lang.php index 7cd16f7ed..d2a8287a1 100644 --- a/inc/lang/sl/lang.php +++ b/inc/lang/sl/lang.php @@ -271,8 +271,8 @@ $lang['i_confexists'] = 'Predmet %s že obstaja.'; $lang['i_writeerr'] = 'Ni mogoče ustvariti predmeta %s. Preveriti je treba dovoljenja datotek in map in nato ustvariti datoteko ročno.'; $lang['i_badhash'] = 'nepoznana ali spremenjena datoteka dokuwiki.php (razpršilo=%s)'; $lang['i_badval'] = '%s - neveljavna ali prazna vrednost'; -$lang['i_success'] = 'Nastavitev je uspešno končana. Datoteko install.php lahko sedaj izbrišete. Nadaljujte v novi DokuWiki.'; -$lang['i_failure'] = 'Med zapisovanjem nastavitvenih datotek je prišlo do napak. Preden lahko uporabite vaš DokuWiki, jih je treba odpraviti.'; +$lang['i_success'] = 'Nastavitev je uspešno končana. Datoteko install.php lahko sedaj izbrišete. Nadaljujte v novi DokuWiki.'; +$lang['i_failure'] = 'Med zapisovanjem nastavitvenih datotek je prišlo do napak. Preden lahko uporabite vaš DokuWiki, jih je treba odpraviti.'; $lang['i_policy'] = 'Začetna določila ACL'; $lang['i_pol0'] = 'Odprt Wiki (branje, zapis, nalaganje datotek je javno za vse)'; $lang['i_pol1'] = 'Javni Wiki (branje za vse, zapis in nalaganje datotek za prijavljene uporabnike)'; diff --git a/inc/lang/sq/lang.php b/inc/lang/sq/lang.php index 3c58d708d..e190d8404 100644 --- a/inc/lang/sq/lang.php +++ b/inc/lang/sq/lang.php @@ -223,8 +223,8 @@ $lang['i_confexists'] = '%s ekziston njëherë'; $lang['i_writeerr'] = '%s nuk mundi të krijohej. Duhet të kontrolloni lejet e dirkektorisë/skedarit dhe ta krijoni skedarin manualisht.'; $lang['i_badhash'] = 'dokuwiki.php e panjohur ose e ndryshuar (hash=code>%s)'; $lang['i_badval'] = '%s - vlerë e palejuar ose boshe'; -$lang['i_success'] = 'Konfigurimi u mbarua me sukses. Tani mund ta fshini skedarin install.php. Vazhdoni tek DokuWiki juaj i ri..'; -$lang['i_failure'] = 'Ndodhën disa gabime gjatë shkrimit të skedarit të konfigurimit. Do t\'ju duhet t\'i rregulloni manualisht para se të përdorni DokuWiki-in tuaj të ri..'; +$lang['i_success'] = 'Konfigurimi u mbarua me sukses. Tani mund ta fshini skedarin install.php. Vazhdoni tek DokuWiki juaj i ri..'; +$lang['i_failure'] = 'Ndodhën disa gabime gjatë shkrimit të skedarit të konfigurimit. Do t\'ju duhet t\'i rregulloni manualisht para se të përdorni DokuWiki-in tuaj të ri..'; $lang['i_policy'] = 'Veprimi fillestar ACL'; $lang['i_pol0'] = 'Wiki i Hapur (lexim, shkrim, ngarkim për këdo)'; $lang['i_pol1'] = 'Wiki Publike (lexim për këdo, shkrim dhe ngarkim për përdoruesit e regjistruar)'; diff --git a/inc/lang/sr/lang.php b/inc/lang/sr/lang.php index 875b1d695..d7f594511 100644 --- a/inc/lang/sr/lang.php +++ b/inc/lang/sr/lang.php @@ -244,8 +244,8 @@ $lang['i_confexists'] = '%s већ постоји'; $lang['i_writeerr'] = 'Не могу да направим %s. Проверите дозволе а затим ручно направите ову датотеку.'; $lang['i_badhash'] = 'dokuwiki.php није препознат или је измењен (hash=%s)'; $lang['i_badval'] = '%s - недозвољена или празна вредност'; -$lang['i_success'] = 'Подешавања су завршена. Сада можете обрисати датотеку install.php. Наставите у Ваш нови DokuWiki.'; -$lang['i_failure'] = 'Појавили су се проблеми при писању датотеке са подешавањима. Требало би да их ручно исправите пре него што ћете моћи да користите Ваш нови DokuWiki.'; +$lang['i_success'] = 'Подешавања су завршена. Сада можете обрисати датотеку install.php. Наставите у Ваш нови DokuWiki.'; +$lang['i_failure'] = 'Појавили су се проблеми при писању датотеке са подешавањима. Требало би да их ручно исправите пре него што ћете моћи да користите Ваш нови DokuWiki.'; $lang['i_policy'] = 'Иницијалне корисничке дозволе'; $lang['i_pol0'] = 'Отворени вики (читање, писање, слање датотека за све)'; $lang['i_pol1'] = 'Јавни вики (читање за све, писање и слање датотека само за регистроване кориснике)'; diff --git a/inc/lang/sv/lang.php b/inc/lang/sv/lang.php index 4cc97e8c6..1c3141da7 100644 --- a/inc/lang/sv/lang.php +++ b/inc/lang/sv/lang.php @@ -246,9 +246,9 @@ $lang['i_writeerr'] = 'Kan inte skapa %s. Kontrollera fi $lang['i_badhash'] = 'okänd eller ändrad dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - felaktig eller blank'; $lang['i_success'] = 'Konfigurationen avslutades utan fel. Du kan radera filen install.php nu. Fortsätt till - din nya DokuWiki.'; + din nya DokuWiki.'; $lang['i_failure'] = 'Fel uppstod vid skrivning av konfigurationsfilerna. Du kan behöva ordna till dem manuellt innan - du kan använda din nya DokuWiki.'; + du kan använda din nya DokuWiki.'; $lang['i_policy'] = 'Initial ACL-policy'; $lang['i_pol0'] = 'Öppen wiki (alla får läsa, skriva och ladda upp filer)'; $lang['i_pol1'] = 'Publik wiki (alla får läsa, registrerade användare för skriva och ladda upp filer)'; diff --git a/inc/lang/tr/lang.php b/inc/lang/tr/lang.php index cf75aac9d..a8d8c5ac9 100644 --- a/inc/lang/tr/lang.php +++ b/inc/lang/tr/lang.php @@ -225,8 +225,8 @@ $lang['i_confexists'] = '%s zaten var'; $lang['i_writeerr'] = '%s oluşturulamadı. Dosya/Klasör izin ayarlarını gözden geçirip dosyayı elle oluşturmalısınız.'; $lang['i_badhash'] = 'dokuwiki.php tanınamadı ya da değiştirilmiş (hash=%s)'; $lang['i_badval'] = '%s - Yanlış veya boş değer'; -$lang['i_success'] = 'Kurulum başarıyla tamamlandı. Şimdi install.php dosyasını silebilirsiniz. Yeni DokuWikinizi kullanabilirsiniz.'; -$lang['i_failure'] = 'Ayar dosyalarını yazarken bazı hatalar oluştu. Yeni DokuWikinizi kullanmadan önce bu hatalarınızı elle düzeltmeniz gerekebilir.'; +$lang['i_success'] = 'Kurulum başarıyla tamamlandı. Şimdi install.php dosyasını silebilirsiniz. Yeni DokuWikinizi kullanabilirsiniz.'; +$lang['i_failure'] = 'Ayar dosyalarını yazarken bazı hatalar oluştu. Yeni DokuWikinizi kullanmadan önce bu hatalarınızı elle düzeltmeniz gerekebilir.'; $lang['i_policy'] = 'İlk ACL ayarı'; $lang['i_pol0'] = 'Tamamen Açık Wiki (herkes okuyabilir, yazabilir ve dosya yükleyebilir)'; $lang['i_pol1'] = 'Açık Wiki (herkes okuyabilir, ancak sadece üye olanlar yazabilir ve dosya yükleyebilir)'; diff --git a/inc/lang/uk/lang.php b/inc/lang/uk/lang.php index e38db2300..5274a4210 100644 --- a/inc/lang/uk/lang.php +++ b/inc/lang/uk/lang.php @@ -253,9 +253,9 @@ $lang['i_writeerr'] = 'Неможливо створити %s%s)'; $lang['i_badval'] = '%s - невірне або пусте значення.'; $lang['i_success'] = 'Налаштування завершено. Ви можете знищити файл install.php. -Перейдіть до вашої нової ДокуВікі'; +Перейдіть до вашої нової ДокуВікі'; $lang['i_failure'] = 'При збереженні файлу конфігурації виникли помилки. Можливо вам доведеться виправити їх самостійно -до початку використання вашої нової ДокуВікі.'; +до початку використання вашої нової ДокуВікі.'; $lang['i_policy'] = 'Початкова політика ACL'; $lang['i_pol0'] = 'Відкрита Вікі (читання, запис та завантаження файлів для всіх)'; $lang['i_pol1'] = 'Публічна Вікі (читання для всіх, запис та завантаження для зареєстрованих користувачів)'; diff --git a/inc/lang/zh-tw/lang.php b/inc/lang/zh-tw/lang.php index 41c79f57c..1304759f7 100644 --- a/inc/lang/zh-tw/lang.php +++ b/inc/lang/zh-tw/lang.php @@ -272,8 +272,8 @@ $lang['i_writeerr'] = '無法建立 %s。您必須檢查 $lang['i_badhash'] = '無法辨識或被變更的 dokuwiki.php (hash=%s)'; $lang['i_badval'] = '%s - 非法或空白的值'; $lang['i_success'] = '設定已成功完成。您現在可以刪除 install.php 檔案。繼續到 -您的新 DokuWiki.'; -$lang['i_failure'] = '寫入設定檔時發生了一些錯誤。您必須在使用您的新 Dokuwiki 之前手動修正它們。'; +您的新 DokuWiki.'; +$lang['i_failure'] = '寫入設定檔時發生了一些錯誤。您必須在使用您的新 Dokuwiki 之前手動修正它們。'; $lang['i_policy'] = '初步的 ACL 政策'; $lang['i_pol0'] = '開放的維基 (任何人可讀取、寫入、上傳)'; $lang['i_pol1'] = '公開的維基 (任何人可讀取,註冊使用者可寫入與上傳)'; diff --git a/inc/lang/zh/lang.php b/inc/lang/zh/lang.php index 8b9644262..4315f780b 100644 --- a/inc/lang/zh/lang.php +++ b/inc/lang/zh/lang.php @@ -288,8 +288,8 @@ $lang['i_writeerr'] = '无法创建 %s。您需要检查 $lang['i_badhash'] = '无法识别的或被修改的 dokuwiki.php(值=%s)'; $lang['i_badval'] = '%s - 非法或空值'; $lang['i_success'] = '配置成功完成。您现在可以删除 install.php 了。继续进入 - 您全新的 DokuWiki。'; -$lang['i_failure'] = '写入配置文件的时候产生一些错误。在使用 您全新安装的 DokuWiki 前 + 您全新的 DokuWiki。'; +$lang['i_failure'] = '写入配置文件的时候产生一些错误。在使用 您全新安装的 DokuWiki 前 您需要手动修复它们。'; $lang['i_policy'] = '初始的 ACL 政策'; $lang['i_pol0'] = '开放的维基(任何人都有读、写、上传的权限)'; -- cgit v1.2.3 From 3755fc25fd2934f8d887f713a48b342ef252cfee Mon Sep 17 00:00:00 2001 From: Tom N Harris Date: Mon, 14 Mar 2011 20:39:30 -0400 Subject: Combine subsequent calls to strtr into a single transformation --- inc/pageutils.php | 5 ++--- inc/parser/renderer.php | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/inc/pageutils.php b/inc/pageutils.php index ef82eebcd..ca4936a82 100644 --- a/inc/pageutils.php +++ b/inc/pageutils.php @@ -115,11 +115,10 @@ function cleanID($raw_id,$ascii=false,$media=false){ $id = utf8_strtolower($id); //alternative namespace seperator - $id = strtr($id,';',':'); if($conf['useslash']){ - $id = strtr($id,'/',':'); + $id = strtr($id,';/','::'); }else{ - $id = strtr($id,'/',$sepchar); + $id = strtr($id,';/',':'.$sepchar); } if($conf['deaccent'] == 2 || $ascii) $id = utf8_romanize($id); diff --git a/inc/parser/renderer.php b/inc/parser/renderer.php index 2c78f220a..7df369478 100644 --- a/inc/parser/renderer.php +++ b/inc/parser/renderer.php @@ -274,9 +274,10 @@ class Doku_Renderer extends DokuWiki_Plugin { list($name,$hash) = explode('#',$name,2); if($hash) return $hash; - $name = strtr($name,';',':'); if($conf['useslash']){ - $name = strtr($name,'/',':'); + $name = strtr($name,';/',';:'); + }else{ + $name = strtr($name,';',':'); } return noNSorNS($name); -- cgit v1.2.3 From 7d9a3395980475d110593562432eeba4fa102691 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 18 Nov 2012 21:04:48 +0100 Subject: some welcome page changes --- data/pages/wiki/welcome.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/pages/wiki/welcome.txt b/data/pages/wiki/welcome.txt index 472e2cabc..6978f1b14 100644 --- a/data/pages/wiki/welcome.txt +++ b/data/pages/wiki/welcome.txt @@ -11,7 +11,8 @@ Your wiki needs to have a start page. As long as it doesn't exist, this link wil Go on, follow that link and create the page. If you need help with using the syntax you can always refer to the [[wiki:syntax|syntax page]]. -You might also want to use a sidebar. To create it, just edit the [[:sidebar]] page. Everything in that page will be shown in a margin column on the side. A sidebar is a good place for a navigation, just place a list of links in it or install and use one of the [[http://www.dokuwiki.org/plugins?plugintag=navigation#extension__table|navigation plugins]]. +You might also want to use a sidebar. To create it, just edit the [[:sidebar]] page. Everything in that page will be shown in a margin column on the side. Read our [[doku>faq:sidebar|FAQ on sidebars]] to learn more. + Please be aware that not all templates support sidebars. ===== Customize your Wiki ===== @@ -26,4 +27,4 @@ DokuWiki is an Open Source project that thrives through user contributions. A go The [[http://forum.dokuwiki.org|DokuWiki User Forum]] is an excellent way to get in contact with other DokuWiki users and is just one of the many ways to get [[doku>faq:support|support]]. -Of course we'd be more than happy to have you [[doku>devel:getting_involved|getting involved]] with DokuWiki. +Of course we'd be more than happy to have you [[doku>teams:getting_involved|getting involved]] with DokuWiki. -- cgit v1.2.3 From 78f0e83246184ff6cb8679d086b0fa17ab508057 Mon Sep 17 00:00:00 2001 From: Leandro Regueiro Date: Fri, 23 Nov 2012 09:23:29 +0100 Subject: Galician language update --- inc/lang/gl/lang.php | 15 ++++- inc/lang/gl/mailwrap.html | 13 ++++ inc/lang/gl/resetpwd.txt | 3 + lib/plugins/acl/lang/gl/lang.php | 1 + lib/plugins/config/lang/gl/lang.php | 107 +++++++++++++++++-------------- lib/plugins/plugin/lang/gl/lang.php | 1 + lib/plugins/popularity/lang/gl/lang.php | 1 + lib/plugins/revert/lang/gl/lang.php | 1 + lib/plugins/usermanager/lang/gl/lang.php | 1 + 9 files changed, 93 insertions(+), 50 deletions(-) create mode 100644 inc/lang/gl/mailwrap.html create mode 100644 inc/lang/gl/resetpwd.txt diff --git a/inc/lang/gl/lang.php b/inc/lang/gl/lang.php index 45fd444d9..a33aba72e 100644 --- a/inc/lang/gl/lang.php +++ b/inc/lang/gl/lang.php @@ -5,6 +5,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Medúlio * @author Oscar M. Lage + * @author Leandro Regueiro */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -40,6 +41,7 @@ $lang['btn_backtomedia'] = 'Volver á Selección de Arquivos-Media'; $lang['btn_subscribe'] = 'Avísame dos trocos na páxina'; $lang['btn_profile'] = 'Actualizar Perfil'; $lang['btn_reset'] = 'Reiniciar'; +$lang['btn_resendpwd'] = 'Definir novo contrasinal'; $lang['btn_draft'] = 'Editar borrador'; $lang['btn_recover'] = 'Recuperar borrador'; $lang['btn_draftdel'] = 'Eliminar borrador'; @@ -76,6 +78,7 @@ $lang['profnoempty'] = 'Non se permite un nome ou un enderezo de corre $lang['profchanged'] = 'Perfil de usuario actualizado correctamente.'; $lang['pwdforget'] = 'Esqueceches o teu contrasinal? Consegue un novo'; $lang['resendna'] = 'Este wiki non permite o reenvío de contrasinais.'; +$lang['resendpwd'] = 'Definir novo contrasinal para'; $lang['resendpwdmissing'] = 'Sentímolo, tes que cubrir todos os campos.'; $lang['resendpwdnouser'] = 'Sentímolo, non atopamos este usuario no noso banco de datos.'; $lang['resendpwdbadauth'] = 'Sentímolo, mais este código de autorización non é válido. Asegúrate de que usaches a ligazón completa de confirmación.'; @@ -88,6 +91,7 @@ $lang['searchmedia_in'] = 'Procurar en %s'; $lang['txt_upload'] = 'Escolle o arquivo para subir'; $lang['txt_filename'] = 'Subir como (opcional)'; $lang['txt_overwrt'] = 'Sobrescribir arquivo existente'; +$lang['maxuploadsize'] = 'Envío máx. de %s por ficheiro.'; $lang['lockedby'] = 'Bloqueado actualmente por'; $lang['lockexpire'] = 'O bloqueo remata o'; $lang['js']['willexpire'] = 'O teu bloqueo para editares esta páxina vai caducar nun minuto.\nPara de evitar conflitos, emprega o botón de previsualización para reiniciares o contador do tempo de bloqueo.'; @@ -182,6 +186,12 @@ $lang['external_edit'] = 'edición externa'; $lang['summary'] = 'Resumo da edición'; $lang['noflash'] = 'Precísase o Extensión Adobe Flash para amosar este contido.'; $lang['download'] = 'Descargar Retallo (Snippet)'; +$lang['tools'] = 'Ferramentas'; +$lang['user_tools'] = 'Ferramentas de usuario'; +$lang['site_tools'] = 'Ferramentas do sitio'; +$lang['page_tools'] = 'Ferramentas de páxina'; +$lang['skip_to_content'] = 'saltar ao contido'; +$lang['sidebar'] = 'Barra lateral'; $lang['mail_newpage'] = 'páxina engadida:'; $lang['mail_changed'] = 'páxina mudada:'; $lang['mail_subscribe_list'] = 'páxinas mudadas en nome de espazo:'; @@ -252,6 +262,7 @@ $lang['subscr_style_digest'] = 'correo-e con resumo de trocos para cada páxin $lang['subscr_style_list'] = 'lista de páxinas mudadas dende o último correo-e'; $lang['authmodfailed'] = 'Configuración de autenticación de usuario incorrecta. Por favor, informa ao Administrador do teu Wiki.'; $lang['authtempfail'] = 'A autenticación de usuario non está dispoñible de xeito temporal. De persistir esta situación, por favor, informa ao Administrador do teu Wiki.'; +$lang['authpwdexpire'] = 'O seu contrasinal vai caducar en %d días, razón pola cal debería cambialo axiña.'; $lang['i_chooselang'] = 'Escolle o teu idioma'; $lang['i_installer'] = 'Instalador do DokuWiki'; $lang['i_wikiname'] = 'Nome do Wiki'; @@ -269,9 +280,9 @@ $lang['i_writeerr'] = 'Non se puido crear %s. Terás de $lang['i_badhash'] = 'dokuwiki.php irrecoñecíbel ou modificado (hash=%s)'; $lang['i_badval'] = '%s - ilegal ou valor baleiro'; $lang['i_success'] = 'A configuración rematou correctamente. Agora podes eliminar o arquivo install.php. Continúa deica o - teu novo DokuWiki.'; + teu novo DokuWiki.'; $lang['i_failure'] = 'Houbo algúns erros ao tentar escribir os arquivos de configuración. Pode que precises solucionalos de xeito manual antes - de poderes empregar o teu novo DokuWiki.'; + de poderes empregar o teu novo DokuWiki.'; $lang['i_policy'] = 'Regras iniciais da ACL'; $lang['i_pol0'] = 'Wiki Aberto (lectura, escritura, subida de arquivos para todas as persoas)'; $lang['i_pol1'] = 'Wiki Público (lectura para todas as persoas, escritura e subida de arquivos para usuarios rexistrados)'; diff --git a/inc/lang/gl/mailwrap.html b/inc/lang/gl/mailwrap.html new file mode 100644 index 000000000..05ef4175a --- /dev/null +++ b/inc/lang/gl/mailwrap.html @@ -0,0 +1,13 @@ + + +@TITLE@ + + + + +@HTMLBODY@ + +

+Esta mensaxe foi xerada por DokuWiki en @DOKUWIKIURL@. + + \ No newline at end of file diff --git a/inc/lang/gl/resetpwd.txt b/inc/lang/gl/resetpwd.txt new file mode 100644 index 000000000..7b662d8f5 --- /dev/null +++ b/inc/lang/gl/resetpwd.txt @@ -0,0 +1,3 @@ +====== Definir novo contrasinal ====== + +Introduza un novo contrasinal para a súa conta neste wiki. \ No newline at end of file diff --git a/lib/plugins/acl/lang/gl/lang.php b/lib/plugins/acl/lang/gl/lang.php index db57598e6..537e03eef 100644 --- a/lib/plugins/acl/lang/gl/lang.php +++ b/lib/plugins/acl/lang/gl/lang.php @@ -4,6 +4,7 @@ * * @author Medúlio * @author Oscar M. Lage + * @author Leandro Regueiro */ $lang['admin_acl'] = 'Xestión da Lista de Control de Acceso (ACL)'; $lang['acl_group'] = 'Grupo'; diff --git a/lib/plugins/config/lang/gl/lang.php b/lib/plugins/config/lang/gl/lang.php index 97b7ecdc8..5ba3be2ec 100644 --- a/lib/plugins/config/lang/gl/lang.php +++ b/lib/plugins/config/lang/gl/lang.php @@ -4,6 +4,7 @@ * * @author Medúlio * @author Oscar M. Lage + * @author Leandro Regueiro */ $lang['menu'] = 'Opcións de Configuración'; $lang['error'] = 'Configuración non actualizada debido a un valor inválido, por favor revisa os teus trocos e volta envialos de novo. @@ -27,6 +28,8 @@ $lang['_anti_spam'] = 'Configuración de Anti-Correo-lixo'; $lang['_editing'] = 'Configuración de Edición'; $lang['_links'] = 'Configuración de Ligazóns'; $lang['_media'] = 'Configuración de Media'; +$lang['_notifications'] = 'Configuración de notificación'; +$lang['_syndication'] = 'Configuración de afiliación'; $lang['_advanced'] = 'Configuración Avanzada'; $lang['_network'] = 'Configuración de Rede'; $lang['_plugin_sufix'] = 'Configuración de Extensións'; @@ -34,26 +37,29 @@ $lang['_template_sufix'] = 'Configuración de Sobreplanta'; $lang['_msg_setting_undefined'] = 'Non hai configuración de metadatos.'; $lang['_msg_setting_no_class'] = 'Non hai configuración de clase.'; $lang['_msg_setting_no_default'] = 'Non hai valor predeterminado.'; -$lang['fmode'] = 'Modo de creación de arquivos'; -$lang['dmode'] = 'Modo de creación de directorios'; +$lang['title'] = 'Título do Wiki'; +$lang['start'] = 'Nome da páxina inicial'; $lang['lang'] = 'Idioma'; +$lang['template'] = 'Sobreplanta'; +$lang['tagline'] = 'Slogan (se o modelo o admite)'; +$lang['sidebar'] = 'Nome da páxina de barra lateral (se o modelo o admite), se o campo está baleiro desactívase a barra lateral'; +$lang['license'] = 'Baixo de que licenza será ceibado o teu contido?'; +$lang['savedir'] = 'Directorio no que se gardarán os datos'; $lang['basedir'] = 'Directorio base'; $lang['baseurl'] = 'URL base'; -$lang['savedir'] = 'Directorio no que se gardarán os datos'; $lang['cookiedir'] = 'Ruta das cookies. Deixar en blanco para usar a url de base.'; -$lang['start'] = 'Nome da páxina inicial'; -$lang['title'] = 'Título do Wiki'; -$lang['template'] = 'Sobreplanta'; -$lang['license'] = 'Baixo de que licenza será ceibado o teu contido?'; -$lang['fullpath'] = 'Amosar a ruta completa das páxinas no pé das mesmas'; +$lang['dmode'] = 'Modo de creación de directorios'; +$lang['fmode'] = 'Modo de creación de arquivos'; +$lang['allowdebug'] = 'Permitir o depurado desactívao se non o precisas!'; $lang['recent'] = 'Trocos recentes'; +$lang['recent_days'] = 'Número de trocos recentes a manter (días)'; $lang['breadcrumbs'] = 'Número de niveis da estrutura de navegación'; $lang['youarehere'] = 'Niveis xerárquicos da estrutura de navegación'; +$lang['fullpath'] = 'Amosar a ruta completa das páxinas no pé das mesmas'; $lang['typography'] = 'Facer substitucións tipográficas'; -$lang['htmlok'] = 'Permitir a inserción de HTML'; -$lang['phpok'] = 'Permitir a inserción de PHP'; $lang['dformat'] = 'Formato de Data (bótalle un ollo á función strftime do PHP)'; $lang['signature'] = 'Sinatura'; +$lang['showuseras'] = 'Que amosar cando se informe do usuario que fixo a última modificación dunha páxina'; $lang['toptoclevel'] = 'Nivel superior para a táboa de contidos'; $lang['tocminheads'] = 'Cantidade mínima de liñas de cabeceira que determinará se a TDC vai ser xerada'; $lang['maxtoclevel'] = 'Nivel máximo para a táboa de contidos'; @@ -61,16 +67,8 @@ $lang['maxseclevel'] = 'Nivel máximo de edición da sección'; $lang['camelcase'] = 'Utilizar CamelCase para as ligazóns'; $lang['deaccent'] = 'Limpar nomes de páxina'; $lang['useheading'] = 'Utilizar a primeira cabeceira para os nomes de páxina'; -$lang['refcheck'] = 'Comprobar a referencia media'; -$lang['refshow'] = 'Número de referencias media a amosar'; -$lang['allowdebug'] = 'Permitir o depurado desactívao se non o precisas!'; -$lang['mediarevisions'] = 'Habilitar revisións dos arquivos-media?'; -$lang['usewordblock'] = 'Bloquear correo-lixo segundo unha lista de verbas'; -$lang['indexdelay'] = 'Retardo denantes de indexar (seg)'; -$lang['relnofollow'] = 'Utilizar rel="nofollow" nas ligazóns externas'; -$lang['mailguard'] = 'Ofuscar enderezos de correo-e'; -$lang['iexssprotect'] = 'Comprobar arquivos subidos na procura de posíbel código JavaScript ou HTML malicioso'; -$lang['showuseras'] = 'Que amosar cando se informe do usuario que fixo a última modificación dunha páxina'; +$lang['sneaky_index'] = 'O DokuWiki amosará por defecto todos os nomes de espazo na vista de índice. Se activas isto agocharanse aqueles onde o usuario non teña permisos de lectura.'; +$lang['hidepages'] = 'Agochar páxinas que coincidan (expresións regulares)'; $lang['useacl'] = 'Utilizar lista de control de acceso'; $lang['autopasswd'] = 'Xerar contrasinais automaticamente'; $lang['authtype'] = 'Backend de autenticación'; @@ -79,57 +77,70 @@ $lang['defaultgroup'] = 'Grupo por defecto'; $lang['superuser'] = 'Super-usuario - un grupo ou usuario con acceso completo a todas as páxinas e funcións independentemente da configuración da ACL'; $lang['manager'] = 'Xestor - un grupo ou usuario con acceso a certas funcións de xestión'; $lang['profileconfirm'] = 'Confirmar trocos de perfil mediante contrasinal'; +$lang['rememberme'] = 'Permitir cookies permanentes de inicio de sesión (lembrarme)'; $lang['disableactions'] = 'Desactivar accións do DokuWiki'; $lang['disableactions_check'] = 'Comprobar'; $lang['disableactions_subscription'] = 'Subscribir/Desubscribir'; $lang['disableactions_wikicode'] = 'Ver fonte/Exportar Datos Raw'; $lang['disableactions_other'] = 'Outras accións (separadas por comas)'; -$lang['sneaky_index'] = 'O DokuWiki amosará por defecto todos os nomes de espazo na vista de índice. Se activas isto agocharanse aqueles onde o usuario non teña permisos de lectura.'; $lang['auth_security_timeout'] = 'Tempo Límite de Seguridade de Autenticación (segundos)'; $lang['securecookie'] = 'Deben enviarse só vía HTTPS polo navegador as cookies configuradas vía HTTPS? Desactiva esta opción cando só o inicio de sesión do teu wiki estea asegurado con SSL pero a navegación do mesmo se faga de xeito inseguro.'; +$lang['remote'] = 'Activar o sistema de API remota. Isto permítelle a outras aplicacións acceder ao wiki a través de XML-RPC ou outros mecanismos.'; +$lang['remoteuser'] = 'Restrinxir o acceso remoto á API aos grupos ou usuarios separados por comas especificados aquí. Déixeo baleiro para concederlle acceso a todos.'; +$lang['usewordblock'] = 'Bloquear correo-lixo segundo unha lista de verbas'; +$lang['relnofollow'] = 'Utilizar rel="nofollow" nas ligazóns externas'; +$lang['indexdelay'] = 'Retardo denantes de indexar (seg)'; +$lang['mailguard'] = 'Ofuscar enderezos de correo-e'; +$lang['iexssprotect'] = 'Comprobar arquivos subidos na procura de posíbel código JavaScript ou HTML malicioso'; +$lang['usedraft'] = 'Gardar un borrador automaticamente no tempo da edición'; +$lang['htmlok'] = 'Permitir a inserción de HTML'; +$lang['phpok'] = 'Permitir a inserción de PHP'; +$lang['locktime'] = 'Tempo máximo para o bloqueo de arquivos (seg.)'; +$lang['cachetime'] = 'Tempo máximo para a caché (seg.)'; +$lang['target____wiki'] = 'Fiestra de destino para as ligazóns internas'; +$lang['target____interwiki'] = 'Fiestra de destino para as ligazóns interwiki'; +$lang['target____extern'] = 'Fiestra de destino para as ligazóns externas'; +$lang['target____media'] = 'Fiestra de destino para as ligazóns de media'; +$lang['target____windows'] = 'Fiestra de destino para as ligazóns de fiestras'; +$lang['mediarevisions'] = 'Habilitar revisións dos arquivos-media?'; +$lang['refcheck'] = 'Comprobar a referencia media'; +$lang['refshow'] = 'Número de referencias media a amosar'; +$lang['gdlib'] = 'Versión da Libraría GD'; +$lang['im_convert'] = 'Ruta deica a ferramenta de conversión ImageMagick'; +$lang['jpg_quality'] = 'Calidade de compresión dos JPG (0-100)'; +$lang['fetchsize'] = 'Tamaño máximo (en bytes) que pode descargar fetch.php dende fontes externas'; +$lang['subscribers'] = 'Activar posibilidade de subscrición á páxina'; +$lang['subscribe_time'] = 'Tempo despois do cal se enviarán os resumos e listas de subscrición (seg.): isto debe ser inferior ao tempo especificado en recent_days.'; +$lang['notify'] = 'Enviar notificacións de trocos a este enderezo de correo-e'; +$lang['registernotify'] = 'Enviar información de novos usuarios rexistrados a este enderezo de correo-e'; +$lang['mailfrom'] = 'Enderezo de correo-e a usar para as mensaxes automáticas'; +$lang['mailprefix'] = 'Prefixo de asunto de correo-e para as mensaxes automáticas'; +$lang['htmlmail'] = 'Enviar mensaxes de e-mail HTML multiparte con mellor aspecto, pero de tamaño maior. Desactivar para as mensaxes de só texto plano.'; +$lang['sitemap'] = 'Xerar mapa do sitio co Google (días)'; +$lang['rss_type'] = 'Tipo de corrente RSS XML'; +$lang['rss_linkto'] = 'A corrente XML liga para'; +$lang['rss_content'] = 'Que queres amosar nos elementos da corrente XML?'; +$lang['rss_update'] = 'Intervalo de actualización da corrente XML (seg.)'; +$lang['rss_show_summary'] = 'Amosar sumario no título da corrente XML'; +$lang['rss_media'] = 'Que tipo de cambios se deben mostrar na fonte XML?'; $lang['updatecheck'] = 'Comprobar se hai actualizacións e avisos de seguridade? O DokuWiki precisa contactar con update.dokuwiki.org para executar esta característica.'; $lang['userewrite'] = 'Utilizar URLs amigábeis'; $lang['useslash'] = 'Utilizar a barra inclinada (/) como separador de nome de espazo nos URLs'; -$lang['usedraft'] = 'Gardar un borrador automaticamente no tempo da edición'; $lang['sepchar'] = 'Verba separadora do nome de páxina'; $lang['canonical'] = 'Utilizar URLs completamente canónicos'; $lang['fnencode'] = 'Método para codificar os nomes de arquivo non-ASCII.'; $lang['autoplural'] = 'Comprobar formas plurais nas ligazóns'; $lang['compression'] = 'Método de compresión para arquivos attic'; -$lang['cachetime'] = 'Tempo máximo para a caché (seg.)'; -$lang['locktime'] = 'Tempo máximo para o bloqueo de arquivos (seg.)'; -$lang['fetchsize'] = 'Tamaño máximo (en bytes) que pode descargar fetch.php dende fontes externas'; -$lang['notify'] = 'Enviar notificacións de trocos a este enderezo de correo-e'; -$lang['registernotify'] = 'Enviar información de novos usuarios rexistrados a este enderezo de correo-e'; -$lang['mailfrom'] = 'Enderezo de correo-e a usar para as mensaxes automáticas'; -$lang['mailprefix'] = 'Prefixo de asunto de correo-e para as mensaxes automáticas'; $lang['gzip_output'] = 'Utilizar Contido-Codificación gzip para o xhtml'; -$lang['gdlib'] = 'Versión da Libraría GD'; -$lang['im_convert'] = 'Ruta deica a ferramenta de conversión ImageMagick'; -$lang['jpg_quality'] = 'Calidade de compresión dos JPG (0-100)'; -$lang['subscribers'] = 'Activar posibilidade de subscrición á páxina'; -$lang['subscribe_time'] = 'Tempo despois do cal se enviarán os resumos e listas de subscrición (seg.): isto debe ser inferior ao tempo especificado en recent_days.'; $lang['compress'] = 'Saída compacta de CSS e Javascript'; -$lang['hidepages'] = 'Agochar páxinas que coincidan (expresións regulares)'; +$lang['cssdatauri'] = 'Tamaño en bytes ata o cal as imaxes referenciadas nos ficheiros CSS se deben incorporar directamente na folla de estilos para reducir o exceso de cabeceiras de solicitudes HTTP. Esta técnica non funciona con IE 7 ou inferior! Valores entre 400 e 600 son axeitados. Defina 0 para desactivar.'; $lang['send404'] = 'Enviar "HTTP 404/Páxina non atopada" para as páxinas inexistentes'; -$lang['sitemap'] = 'Xerar mapa do sitio co Google (días)'; $lang['broken_iua'] = 'Rachou a función ignore_user_abort no teu sistema? Isto podería causar que o índice de procura non funcione. Coñécese que o IIS+PHP/CGI ráchaa. Bótalle un ollo ao Bug 852 para obter máis información.'; $lang['xsendfile'] = 'Empregar a cabeceira X-Sendfile para que o servidor web envie arquivos estáticos? O teu servidor web precisa soportar isto.'; $lang['renderer_xhtml'] = 'Intérprete a empregar para a saída principal (XHTML) do Wiki'; $lang['renderer__core'] = '%s (núcleo do Dokuwiki)'; $lang['renderer__plugin'] = '%s (extensión)'; -$lang['rememberme'] = 'Permitir cookies permanentes de inicio de sesión (lembrarme)'; -$lang['rss_type'] = 'Tipo de corrente RSS XML'; -$lang['rss_linkto'] = 'A corrente XML liga para'; -$lang['rss_content'] = 'Que queres amosar nos elementos da corrente XML?'; -$lang['rss_update'] = 'Intervalo de actualización da corrente XML (seg.)'; -$lang['recent_days'] = 'Número de trocos recentes a manter (días)'; -$lang['rss_show_summary'] = 'Amosar sumario no título da corrente XML'; -$lang['target____wiki'] = 'Fiestra de destino para as ligazóns internas'; -$lang['target____interwiki'] = 'Fiestra de destino para as ligazóns interwiki'; -$lang['target____extern'] = 'Fiestra de destino para as ligazóns externas'; -$lang['target____media'] = 'Fiestra de destino para as ligazóns de media'; -$lang['target____windows'] = 'Fiestra de destino para as ligazóns de fiestras'; +$lang['dnslookups'] = 'DokuWiki buscará os nomes de máquina ou enderezos IP remotos dos usuarios que editen páxinas. Se ten un servidor DNS lento ou que non funciona ou en caso de non querer esta característica, desactive esta opción.'; $lang['proxy____host'] = 'Nome do servidor Proxy'; $lang['proxy____port'] = 'Porto do Proxy'; $lang['proxy____user'] = 'Nome de usuario do Proxy'; diff --git a/lib/plugins/plugin/lang/gl/lang.php b/lib/plugins/plugin/lang/gl/lang.php index a314b71b9..fecdf9425 100644 --- a/lib/plugins/plugin/lang/gl/lang.php +++ b/lib/plugins/plugin/lang/gl/lang.php @@ -4,6 +4,7 @@ * * @author Medúlio * @author Oscar M. Lage + * @author Leandro Regueiro */ $lang['menu'] = 'Xestionar Extensións'; $lang['download'] = 'Descargar e instalar unha nova extensión'; diff --git a/lib/plugins/popularity/lang/gl/lang.php b/lib/plugins/popularity/lang/gl/lang.php index 34bd3935f..8032fccb0 100644 --- a/lib/plugins/popularity/lang/gl/lang.php +++ b/lib/plugins/popularity/lang/gl/lang.php @@ -4,6 +4,7 @@ * * @author Medúlio * @author Oscar M. Lage + * @author Leandro Regueiro */ $lang['name'] = 'Resposta de Popularidade (pode demorar un tempo a cargar)'; $lang['submit'] = 'Enviar Datos'; diff --git a/lib/plugins/revert/lang/gl/lang.php b/lib/plugins/revert/lang/gl/lang.php index a0c5a9785..ad4fe4045 100644 --- a/lib/plugins/revert/lang/gl/lang.php +++ b/lib/plugins/revert/lang/gl/lang.php @@ -4,6 +4,7 @@ * * @author Medúlio * @author Oscar M. Lage + * @author Leandro Regueiro */ $lang['menu'] = 'Xestor de Reversión'; $lang['filter'] = 'Procurar páxinas con correo-lixo'; diff --git a/lib/plugins/usermanager/lang/gl/lang.php b/lib/plugins/usermanager/lang/gl/lang.php index c9c633b39..fb965985f 100644 --- a/lib/plugins/usermanager/lang/gl/lang.php +++ b/lib/plugins/usermanager/lang/gl/lang.php @@ -4,6 +4,7 @@ * * @author Medúlio * @author Oscar M. Lage + * @author Leandro Regueiro */ $lang['menu'] = 'Xestor de Usuarios'; $lang['noauth'] = '(autenticación de usuarios non dispoñible)'; -- cgit v1.2.3 From 1f61f312a78e212aaa4a4bc3f60961036ec07fd7 Mon Sep 17 00:00:00 2001 From: Dominik Eckelmann Date: Fri, 23 Nov 2012 18:48:09 +0100 Subject: remove empty BCC/CC mail headers Empty BCC/CC headers may cause errors on IIS. --- _test/tests/inc/mailer.test.php | 17 +++++++++++++++++ inc/Mailer.class.php | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/_test/tests/inc/mailer.test.php b/_test/tests/inc/mailer.test.php index b2c74a257..91c4a999d 100644 --- a/_test/tests/inc/mailer.test.php +++ b/_test/tests/inc/mailer.test.php @@ -7,6 +7,14 @@ class TestMailer extends Mailer { public function prop($name){ return $this->$name; } + + public function &propRef($name) { + return $this->$name; + } + + public function prepareHeaders() { + return parent::prepareHeaders(); + } } class mailer_test extends DokuWikiTest { @@ -90,5 +98,14 @@ class mailer_test extends DokuWikiTest { } } + function test_emptyBCCorCC() { + $mail = new TestMailer(); + $headers = &$mail->propRef('headers'); + $headers['Bcc'] = ''; + $headers['Cc'] = ''; + $header = $mail->prepareHeaders(); + $this->assertEquals(0, preg_match('/(^|\n)Bcc: (\n|$)/', $header), 'Bcc found in headers.'); + $this->assertEquals(0, preg_match('/(^|\n)Cc: (\n|$)/', $header), 'Bcc found in headers.'); + } } //Setup VIM: ex: et ts=4 : diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index cbd1eb0a9..256a76d22 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -553,6 +553,7 @@ class Mailer { * @returns string the headers */ protected function prepareHeaders() { + $this->removeEmptyBccOrCcHeader(); $headers = ''; foreach($this->headers as $key => $val) { $headers .= "$key: $val".MAILHEADER_EOL; @@ -560,6 +561,16 @@ class Mailer { return $headers; } + /** + * Removes empty BCC and CC Header. + * + * Empty BCC/CC Header can cause an error with Microsoft IIS. + */ + protected function removeEmptyBccOrCcHeader() { + if (isset($this->headers['Bcc']) && empty($this->headers['Bcc'])) unset($this->headers['Bcc']); + if (isset($this->headers['Cc']) && empty($this->headers['Cc'])) unset($this->headers['Cc']); + } + /** * return a full email with all headers * -- cgit v1.2.3 From 91effd8de07e4afc59b6763ac72b268f58cfc941 Mon Sep 17 00:00:00 2001 From: Dominik Eckelmann Date: Fri, 23 Nov 2012 19:55:44 +0100 Subject: ignore empty header on mail sending --- _test/tests/inc/mailer.test.php | 3 +++ inc/Mailer.class.php | 12 +----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/_test/tests/inc/mailer.test.php b/_test/tests/inc/mailer.test.php index 91c4a999d..053e216b8 100644 --- a/_test/tests/inc/mailer.test.php +++ b/_test/tests/inc/mailer.test.php @@ -98,6 +98,9 @@ class mailer_test extends DokuWikiTest { } } + /** + * @see https://forum.dokuwiki.org/post/35822 + */ function test_emptyBCCorCC() { $mail = new TestMailer(); $headers = &$mail->propRef('headers'); diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 256a76d22..f1492be9b 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -553,24 +553,14 @@ class Mailer { * @returns string the headers */ protected function prepareHeaders() { - $this->removeEmptyBccOrCcHeader(); $headers = ''; foreach($this->headers as $key => $val) { + if ($val === '') continue; $headers .= "$key: $val".MAILHEADER_EOL; } return $headers; } - /** - * Removes empty BCC and CC Header. - * - * Empty BCC/CC Header can cause an error with Microsoft IIS. - */ - protected function removeEmptyBccOrCcHeader() { - if (isset($this->headers['Bcc']) && empty($this->headers['Bcc'])) unset($this->headers['Bcc']); - if (isset($this->headers['Cc']) && empty($this->headers['Cc'])) unset($this->headers['Cc']); - } - /** * return a full email with all headers * -- cgit v1.2.3 From b7183bb542c52e0826a76346fd9005da965a9ac5 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 24 Nov 2012 08:23:32 +0100 Subject: GeSHi update to 1.0.8.11 --- inc/geshi.php | 68 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/inc/geshi.php b/inc/geshi.php index aedc64f84..c6ff9ef77 100644 --- a/inc/geshi.php +++ b/inc/geshi.php @@ -41,7 +41,7 @@ // /** The version of this GeSHi file */ -define('GESHI_VERSION', '1.0.8.10'); +define('GESHI_VERSION', '1.0.8.11'); // Define the root directory for the GeSHi code tree if (!defined('GESHI_ROOT')) { @@ -604,6 +604,17 @@ class GeSHi { $this->set_language_path($path); } + /** + * Returns the version of GeSHi + * + * @return string + * @since 1 0.8.11 + */ + function get_version() + { + return GESHI_VERSION; + } + /** * Returns an error message associated with the last GeSHi operation, * or false if no error has occured @@ -808,7 +819,7 @@ class GeSHi { } // match the langname - if (!preg_match('/\'LANG_NAME\'\s*=>\s*\'((?:[^\']|\\\')+)\'/', $data, $matches)) { + if (!preg_match('/\'LANG_NAME\'\s*=>\s*\'((?:[^\']|\\\')+?)\'/', $data, $matches)) { $this->error = sprintf('Geshi::get_lang_fullname(%s): Regex can not detect language', $language); return false; } @@ -1437,6 +1448,8 @@ class GeSHi { * @todo static? */ function get_language_name_from_extension( $extension, $lookup = array() ) { + $extension = strtolower($extension); + if ( !is_array($lookup) || empty($lookup)) { $lookup = array( '6502acme' => array( 'a', 's', 'asm', 'inc' ), @@ -1470,6 +1483,7 @@ class GeSHi { 'gnuplot' => array('plt'), 'groovy' => array('groovy'), 'haskell' => array('hs'), + 'haxe' => array('hx'), 'html4strict' => array('html', 'htm'), 'ini' => array('ini', 'desktop'), 'java' => array('java'), @@ -1504,6 +1518,7 @@ class GeSHi { 'smalltalk' => array('st'), 'smarty' => array(), 'tcl' => array('tcl'), + 'text' => array('txt'), 'vb' => array('bas'), 'vbnet' => array(), 'visualfoxpro' => array(), @@ -1518,7 +1533,8 @@ class GeSHi { return $lang; } } - return ''; + + return 'text'; } /** @@ -1555,6 +1571,9 @@ class GeSHi { * @since 1.0.0 */ function add_keyword($key, $word) { + if (!is_array($this->language_data['KEYWORDS'][$key])) { + $this->language_data['KEYWORDS'][$key] = array(); + } if (!in_array($word, $this->language_data['KEYWORDS'][$key])) { $this->language_data['KEYWORDS'][$key][] = $word; @@ -1816,7 +1835,7 @@ class GeSHi { //Decide on which style to use if ($style === null) { //Check if we should use default style unset($this->highlight_extra_lines_styles[$lines]); - } else if ($style === false) { //Check if to remove this line + } elseif ($style === false) { //Check if to remove this line unset($this->highlight_extra_lines[$lines]); unset($this->highlight_extra_lines_styles[$lines]); } else { @@ -1988,7 +2007,7 @@ class GeSHi { $this->language_data['SYMBOL_DATA'][$symbols] = 0; if (isset($symbols[1])) { // multiple chars $symbol_preg_multi[] = preg_quote($symbols, '/'); - } else if ($symbols == '-') { + } elseif ($symbols == '-') { // don't trigger range out of order error $symbol_preg_single[] = '\-'; } else { // single char @@ -2392,7 +2411,7 @@ class GeSHi { foreach ($this->language_data['QUOTEMARKS'] as $quotemark) { if (!isset($is_string_starter[$quotemark[0]])) { $is_string_starter[$quotemark[0]] = (string)$quotemark; - } else if (is_string($is_string_starter[$quotemark[0]])) { + } elseif (is_string($is_string_starter[$quotemark[0]])) { $is_string_starter[$quotemark[0]] = array( $is_string_starter[$quotemark[0]], $quotemark); @@ -2478,7 +2497,7 @@ class GeSHi { continue; } $match_i = $comment_regexp_cache_per_key[$comment_key]['pos']; - } else if ( + } elseif ( //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $i), $match, PREG_OFFSET_CAPTURE)) || (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $i)) @@ -2586,7 +2605,7 @@ class GeSHi { continue; } $match_i = $escape_regexp_cache_per_key[$escape_key]['pos']; - } else if ( + } elseif ( //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $start), $match, PREG_OFFSET_CAPTURE)) || (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $start)) @@ -2656,13 +2675,13 @@ class GeSHi { // don't put a newline around newlines $string .= "\n"; $start = $es_pos + 2; - } else if (ord($es_char) >= 128) { + } elseif (ord($es_char) >= 128) { //This is an non-ASCII char (UTF8 or single byte) //This code tries to work around SF#2037598 ... if(function_exists('mb_substr')) { $es_char_m = mb_substr(substr($part, $es_pos+1, 16), 0, 1, $this->encoding); $string .= $es_char_m . ''; - } else if (!GESHI_PHP_PRE_433 && 'utf-8' == $this->encoding) { + } elseif (!GESHI_PHP_PRE_433 && 'utf-8' == $this->encoding) { if(preg_match("/[\xC2-\xDF][\x80-\xBF]". "|\xE0[\xA0-\xBF][\x80-\xBF]". "|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}". @@ -2684,7 +2703,7 @@ class GeSHi { $string .= $this->hsc($es_char) . ''; $start = $es_pos + 2; } - } else if ($next_escape_regexp_pos < $length && + } elseif ($next_escape_regexp_pos < $length && $next_escape_regexp_pos < $close_pos) { $es_pos = $next_escape_regexp_pos; //Add the stuff not in the string yet ... @@ -2728,7 +2747,7 @@ class GeSHi { $string = ''; $i = $start - 1; continue; - } else if ($this->lexic_permissions['STRINGS'] && $hq && $hq[0] == $char && + } elseif ($this->lexic_permissions['STRINGS'] && $hq && $hq[0] == $char && substr($part, $i, $hq_strlen) == $hq && ($i != $next_comment_regexp_pos)) { // The start of a hard quoted string if (!$this->use_classes) { @@ -2886,7 +2905,7 @@ class GeSHi { continue; } $match_i = $comment_multi_cache_per_key[$open]; - } else if (($match_i = stripos($part, $open, $i)) !== false) { + } elseif (($match_i = stripos($part, $open, $i)) !== false) { $comment_multi_cache_per_key[$open] = $match_i; } else { $comment_multi_cache_per_key[$open] = false; @@ -2983,7 +3002,7 @@ class GeSHi { continue; } $match_i = $comment_single_cache_per_key[$comment_key]; - } else if ( + } elseif ( // case sensitive comments ($this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] && ($match_i = stripos($part, $comment_mark, $i)) !== false) || @@ -3140,10 +3159,10 @@ class GeSHi { $IN_TAG = false; } $lines[$key] .= $char; - } else if ('<' == $char) { + } elseif ('<' == $char) { $IN_TAG = true; $lines[$key] .= '<'; - } else if ('&' == $char) { + } elseif ('&' == $char) { $substr = substr($line, $i + 3, 5); $posi = strpos($substr, ';'); if (false === $posi) { @@ -3152,7 +3171,7 @@ class GeSHi { $pos -= $posi+2; } $lines[$key] .= $char; - } else if ("\t" == $char) { + } elseif ("\t" == $char) { $str = ''; // OPTIMISE - move $strs out. Make an array: // $tabs = array( @@ -3173,7 +3192,7 @@ class GeSHi { $lines[$key] .= substr($line, $i + 1); break; } - } else if (0 == $pos && ' ' == $char) { + } elseif (0 == $pos && ' ' == $char) { $lines[$key] .= ' '; ++$pos; } else { @@ -3231,6 +3250,7 @@ class GeSHi { function handle_keyword_replace($match) { $k = $this->_kw_replace_group; $keyword = $match[0]; + $keyword_match = $match[1]; $before = ''; $after = ''; @@ -3248,12 +3268,12 @@ class GeSHi { if (!$this->language_data['CASE_SENSITIVE'][$k] && strpos($this->language_data['URLS'][$k], '{FNAME}') !== false) { foreach ($this->language_data['KEYWORDS'][$k] as $word) { - if (strcasecmp($word, $keyword) == 0) { + if (strcasecmp($word, $keyword_match) == 0) { break; } } } else { - $word = $keyword; + $word = $keyword_match; } $before = '<|UR1|"' . @@ -3367,7 +3387,7 @@ class GeSHi { foreach (array_keys($this->language_data['KEYWORDS']) as $k) { if (!isset($this->lexic_permissions['KEYWORDS'][$k]) || - $this->lexic_permissions['KEYWORDS'][$k]) { + $this->lexic_permissions['KEYWORDS'][$k]) { $case_sensitive = $this->language_data['CASE_SENSITIVE'][$k]; $modifiers = $case_sensitive ? '' : 'i'; @@ -3991,7 +4011,7 @@ class GeSHi { $parsed_code .= $this->line_numbers_start + $i; if ($close) { $parsed_code .= str_repeat('', $close); - } else if ($i != $n) { + } elseif ($i != $n) { $parsed_code .= "\n"; } } @@ -4123,10 +4143,10 @@ class GeSHi { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { if ($this->header_type == GESHI_HEADER_PRE) { return "$header"; - } else if ($this->header_type == GESHI_HEADER_DIV || + } elseif ($this->header_type == GESHI_HEADER_DIV || $this->header_type == GESHI_HEADER_PRE_VALID) { return "$header"; - } else if ($this->header_type == GESHI_HEADER_PRE_TABLE) { + } elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) { return "$header"; } } else { -- cgit v1.2.3 From eb3ce0d55290dd4a60193e680aa50b46571350bd Mon Sep 17 00:00:00 2001 From: Kazutaka Miyasaka Date: Sun, 25 Nov 2012 21:02:32 +0900 Subject: Fix case-insensitive match in ACL checking ACL checking of DokuWiki is currently always case-sensitive regardless of auth backend setting ($auth->isCaseSensitive). This commit enables case-insensitive match in the same way of auth_isMember(). --- .../inc/auth_aclcheck_caseinsensitive.test.php | 131 +++++++++++++++++++++ inc/auth.php | 17 ++- 2 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 _test/tests/inc/auth_aclcheck_caseinsensitive.test.php diff --git a/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php b/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php new file mode 100644 index 000000000..9f1fb6aa0 --- /dev/null +++ b/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php @@ -0,0 +1,131 @@ +oldConf = $conf; + $this->oldAuth = $auth; + $this->oldAuthAcl = $AUTH_ACL; + + $auth = new auth_acl_caseinsensitive_auth(); + } + + function teardown() { + global $conf; + global $AUTH_ACL; + global $auth; + + $conf = $this->oldConf; + $auth = $this->oldAuth; + $AUTH_ACL = $this->oldAuthAcl; + } + + function test_multiadmin_restricted_ropage() { + global $conf; + global $AUTH_ACL; + + $conf['superuser'] = 'John,doe,@Admin1,@admin2'; + $conf['useacl'] = 1; + + $AUTH_ACL = array( + '* @ALL 0', + '* @Group1 8', + '* @group2 8', + 'namespace:page @Group1 1', + 'namespace:page @group2 1', + ); + + // anonymous user + $this->assertEquals(auth_aclcheck('page', '', array()), AUTH_NONE); + $this->assertEquals(auth_aclcheck('namespace:page', '', array()), AUTH_NONE); + $this->assertEquals(auth_aclcheck('namespace:*', '', array()), AUTH_NONE); + + // user with no matching group + $this->assertEquals(auth_aclcheck('page', 'jill', array('foo')), AUTH_NONE); + $this->assertEquals(auth_aclcheck('namespace:page', 'jill', array('foo')), AUTH_NONE); + $this->assertEquals(auth_aclcheck('namespace:*', 'jill', array('foo')), AUTH_NONE); + + // user with matching group 1 + $this->assertEquals(auth_aclcheck('page', 'jill', array('foo', 'group1')), AUTH_UPLOAD); + $this->assertEquals(auth_aclcheck('namespace:page', 'jill', array('foo', 'group1')), AUTH_READ); + $this->assertEquals(auth_aclcheck('namespace:*', 'jill', array('foo', 'group1')), AUTH_UPLOAD); + + // user with matching group 2 + $this->assertEquals(auth_aclcheck('page', 'jill', array('foo', 'Group2')), AUTH_UPLOAD); + $this->assertEquals(auth_aclcheck('namespace:page', 'jill', array('foo', 'Group2')), AUTH_READ); + $this->assertEquals(auth_aclcheck('namespace:*', 'jill', array('foo', 'Group2')), AUTH_UPLOAD); + + // super user John + $this->assertEquals(auth_aclcheck('page', 'john', array('foo')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:page', 'john', array('foo')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:*', 'john', array('foo')), AUTH_ADMIN); + + // super user doe + $this->assertEquals(auth_aclcheck('page', 'Doe', array('foo')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:page', 'Doe', array('foo')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:*', 'Doe', array('foo')), AUTH_ADMIN); + + // user with matching admin group 1 + $this->assertEquals(auth_aclcheck('page', 'jill', array('foo', 'admin1')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:page', 'jill', array('foo', 'admin1')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:*', 'jill', array('foo', 'admin1')), AUTH_ADMIN); + + // user with matching admin group 2 + $this->assertEquals(auth_aclcheck('page', 'jill', array('foo', 'Admin2')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:page', 'jill', array('foo', 'Admin2')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:*', 'jill', array('foo', 'Admin2')), AUTH_ADMIN); + } + + /* + * Test aclcheck on @ALL group + * + * The default permission for @ALL group is AUTH_NONE. So we use an + * ACL entry which grants @ALL group an AUTH_READ permission to see + * whether ACL matching is properly done or not. + */ + function test_restricted_allread() { + global $conf; + global $AUTH_ACL; + + $conf['superuser'] = 'john'; + $conf['useacl'] = 1; + + $AUTH_ACL = array( + '* @ALL 1', + '* @group1 8', + ); + + // anonymous user + $this->assertEquals(auth_aclcheck('page', '', array()), AUTH_READ); + $this->assertEquals(auth_aclcheck('namespace:page', '', array()), AUTH_READ); + $this->assertEquals(auth_aclcheck('namespace:*', '', array()), AUTH_READ); + + // user with no matching group + $this->assertEquals(auth_aclcheck('page', 'jill', array('foo')), AUTH_READ); + $this->assertEquals(auth_aclcheck('namespace:page', 'jill', array('foo')), AUTH_READ); + $this->assertEquals(auth_aclcheck('namespace:*', 'jill', array('foo')), AUTH_READ); + + // user with matching group + $this->assertEquals(auth_aclcheck('page', 'jill', array('foo', 'Group1')), AUTH_UPLOAD); + $this->assertEquals(auth_aclcheck('namespace:page', 'jill', array('foo', 'Group1')), AUTH_UPLOAD); + $this->assertEquals(auth_aclcheck('namespace:*', 'jill', array('foo', 'Group1')), AUTH_UPLOAD); + + // super user + $this->assertEquals(auth_aclcheck('page', 'John', array('foo')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:page', 'John', array('foo')), AUTH_ADMIN); + $this->assertEquals(auth_aclcheck('namespace:*', 'John', array('foo')), AUTH_ADMIN); + } +} diff --git a/inc/auth.php b/inc/auth.php index 1c8a8f5f5..9c458338d 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -535,9 +535,10 @@ function auth_aclcheck($id, $user, $groups) { return AUTH_ADMIN; } - $ci = ''; - if(!$auth->isCaseSensitive()) $ci = 'ui'; - + if(!$auth->isCaseSensitive()) { + $user = utf8_strtolower($user); + $groups = array_map('utf8_strtolower', $groups); + } $user = $auth->cleanUser($user); $groups = array_map(array($auth, 'cleanGroup'), (array) $groups); $user = auth_nameencode($user); @@ -561,11 +562,14 @@ function auth_aclcheck($id, $user, $groups) { } //check exact match first - $matches = preg_grep('/^'.preg_quote($id, '/').'\s+(\S+)\s+/'.$ci, $AUTH_ACL); + $matches = preg_grep('/^'.preg_quote($id, '/').'\s+(\S+)\s+/u', $AUTH_ACL); if(count($matches)) { foreach($matches as $match) { $match = preg_replace('/#.*$/', '', $match); //ignore comments $acl = preg_split('/\s+/', $match); + if(!$auth->isCaseSensitive() && $acl[1] !== '@ALL') { + $acl[1] = utf8_strtolower($acl[1]); + } if(!in_array($acl[1], $groups)) { continue; } @@ -588,11 +592,14 @@ function auth_aclcheck($id, $user, $groups) { } do { - $matches = preg_grep('/^'.preg_quote($path, '/').'\s+(\S+)\s+/'.$ci, $AUTH_ACL); + $matches = preg_grep('/^'.preg_quote($path, '/').'\s+(\S+)\s+/u', $AUTH_ACL); if(count($matches)) { foreach($matches as $match) { $match = preg_replace('/#.*$/', '', $match); //ignore comments $acl = preg_split('/\s+/', $match); + if(!$auth->isCaseSensitive() && $acl[1] !== '@ALL') { + $acl[1] = utf8_strtolower($acl[1]); + } if(!in_array($acl[1], $groups)) { continue; } -- cgit v1.2.3 From 46a853c3756aa4abe582ccb0de6f4e1f4b2035c4 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 27 Nov 2012 17:39:04 +0100 Subject: correct return in sendDigest() the function always returned true, even if no action was taken. This resulted in no further indexer tasks being run. --- lib/exe/indexer.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/exe/indexer.php b/lib/exe/indexer.php index 1ccede923..c336514cd 100644 --- a/lib/exe/indexer.php +++ b/lib/exe/indexer.php @@ -181,6 +181,8 @@ function sendDigest() { global $conf; global $USERINFO; + $sent = false; + // remember current user info $olduinfo = $USERINFO; $olduser = $_SERVER['REMOTE_USER']; @@ -236,9 +238,11 @@ function sendDigest() { foreach($change_ids as $change_id) { subscription_send_digest($USERINFO['mail'], $change_id, $lastupdate); + $sent = true; } } elseif ($style === 'list') { subscription_send_list($USERINFO['mail'], $change_ids, $id); + $sent = true; } // TODO: Handle duplicate subscriptions. @@ -252,7 +256,7 @@ function sendDigest() { $USERINFO = $olduinfo; $_SERVER['REMOTE_USER'] = $olduser; echo 'sendDigest(): finished'.NL; - return true; + return $sent; } /** -- cgit v1.2.3 From 3f6c460c29cccb4fdbbbbd14afbdd29916947221 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Wed, 28 Nov 2012 17:40:42 +0100 Subject: Correct German plugin manager translation (download != install) --- lib/plugins/plugin/lang/de/lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plugins/plugin/lang/de/lang.php b/lib/plugins/plugin/lang/de/lang.php index 8708d7836..9f26a2933 100644 --- a/lib/plugins/plugin/lang/de/lang.php +++ b/lib/plugins/plugin/lang/de/lang.php @@ -53,7 +53,7 @@ $lang['desc'] = 'Beschreibung:'; $lang['author'] = 'Entwickler:'; $lang['www'] = 'Web:'; $lang['error'] = 'Ein unbekannter Fehler ist aufgetreten.'; -$lang['error_download'] = 'Konnte das Plugin %s nicht installieren'; +$lang['error_download'] = 'Konnte das Plugin %s nicht herunterladen'; $lang['error_badurl'] = 'Wahrscheinlich ungültige URL, konnte keinen Dateinamen ausfindig machen'; $lang['error_dircreate'] = 'Konnte keinen temporären Ordner für die Downloads erstellen'; $lang['error_decompress'] = 'Der Plugin Manager konnte das Plugin-Archiv nicht entpacken. Entweder ist der Download fehlerhaft oder das Komprimierungsverfahren wird nicht unterstützt. Bitte versuchen Sie es erneut oder downloaden und installieren Sie das Plugin manuell.'; -- cgit v1.2.3 From ff576d9309a9a8c229caea79f2f8509cc986eee4 Mon Sep 17 00:00:00 2001 From: Dominik Eckelmann Date: Thu, 29 Nov 2012 14:59:46 +0100 Subject: use correct setUp method and parent calls. --- _test/tests/inc/auth_aclcheck.test.php | 10 +++------- _test/tests/inc/auth_aclcheck_caseinsensitive.test.php | 9 +++------ _test/tests/inc/auth_admincheck.test.php | 5 ++--- _test/tests/inc/auth_nameencode.test.php | 2 +- _test/tests/inc/parser/parser.inc.php | 3 ++- _test/tests/inc/parser/parser_footnote.test.php | 4 ++-- _test/tests/inc/parser/parser_quotes.test.php | 4 ++-- _test/tests/inc/remote.test.php | 5 +---- 8 files changed, 16 insertions(+), 26 deletions(-) diff --git a/_test/tests/inc/auth_aclcheck.test.php b/_test/tests/inc/auth_aclcheck.test.php index 991f82da7..8e5a04ff5 100644 --- a/_test/tests/inc/auth_aclcheck.test.php +++ b/_test/tests/inc/auth_aclcheck.test.php @@ -2,22 +2,18 @@ class auth_acl_test extends DokuWikiTest { - var $oldConf; var $oldAuthAcl; - function setup() { - global $conf; + function setUp() { + parent::setUp(); global $AUTH_ACL; global $auth; - $this->oldConf = $conf; $this->oldAuthAcl = $AUTH_ACL; $auth = new auth_basic(); } - function teardown() { - global $conf; + function tearDown() { global $AUTH_ACL; - $conf = $this->oldConf; $AUTH_ACL = $this->oldAuthAcl; } diff --git a/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php b/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php index 9f1fb6aa0..2f4821c2d 100644 --- a/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php +++ b/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php @@ -7,28 +7,25 @@ class auth_acl_caseinsensitive_auth extends auth_basic { } class auth_acl_caseinsensitive_test extends DokuWikiTest { - protected $oldConf; protected $oldAuth; protected $oldAuthAcl; - function setup() { - global $conf; + function setUp() { + parent::setUp(); global $auth; global $AUTH_ACL; - $this->oldConf = $conf; $this->oldAuth = $auth; $this->oldAuthAcl = $AUTH_ACL; $auth = new auth_acl_caseinsensitive_auth(); } - function teardown() { + function tearDown() { global $conf; global $AUTH_ACL; global $auth; - $conf = $this->oldConf; $auth = $this->oldAuth; $AUTH_ACL = $this->oldAuthAcl; } diff --git a/_test/tests/inc/auth_admincheck.test.php b/_test/tests/inc/auth_admincheck.test.php index d88399cbe..17424a08e 100644 --- a/_test/tests/inc/auth_admincheck.test.php +++ b/_test/tests/inc/auth_admincheck.test.php @@ -10,7 +10,8 @@ class auth_admin_test extends DokuWikiTest { private $oldauth; - function setup() { + function setUp() { + parent::setUp(); global $auth; $this->oldauth = $auth; } @@ -27,9 +28,7 @@ class auth_admin_test extends DokuWikiTest { function teardown() { global $auth; - global $conf; global $AUTH_ACL; - unset($conf); unset($AUTH_ACL); $auth = $this->oldauth; } diff --git a/_test/tests/inc/auth_nameencode.test.php b/_test/tests/inc/auth_nameencode.test.php index 21db304e0..da9f31f90 100644 --- a/_test/tests/inc/auth_nameencode.test.php +++ b/_test/tests/inc/auth_nameencode.test.php @@ -2,7 +2,7 @@ class auth_nameencode_test extends DokuWikiTest { - function teardown() { + function tearDown() { global $cache_authname; $cache_authname = array(); } diff --git a/_test/tests/inc/parser/parser.inc.php b/_test/tests/inc/parser/parser.inc.php index e9efef0d3..61f15678b 100644 --- a/_test/tests/inc/parser/parser.inc.php +++ b/_test/tests/inc/parser/parser.inc.php @@ -8,7 +8,8 @@ abstract class TestOfDoku_Parser extends PHPUnit_Framework_TestCase { var $P; var $H; - function setup() { + function setUp() { + parent::setUp(); $this->P = new Doku_Parser(); $this->H = new Doku_Handler(); $this->P->Handler = & $this->H; diff --git a/_test/tests/inc/parser/parser_footnote.test.php b/_test/tests/inc/parser/parser_footnote.test.php index f3b5ddf56..b47a575de 100644 --- a/_test/tests/inc/parser/parser_footnote.test.php +++ b/_test/tests/inc/parser/parser_footnote.test.php @@ -3,8 +3,8 @@ require_once 'parser.inc.php'; class TestOfDoku_Parser_Footnote extends TestOfDoku_Parser { - function setup() { - parent::setup(); + function setUp() { + parent::setUp(); $this->P->addMode('footnote',new Doku_Parser_Mode_Footnote()); } diff --git a/_test/tests/inc/parser/parser_quotes.test.php b/_test/tests/inc/parser/parser_quotes.test.php index b2dae1039..b82328212 100644 --- a/_test/tests/inc/parser/parser_quotes.test.php +++ b/_test/tests/inc/parser/parser_quotes.test.php @@ -3,8 +3,8 @@ require_once 'parser.inc.php'; class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser { - function setup() { - parent::setup(); + function setUp() { + parent::setUp(); global $conf; $conf['typography'] = 2; } diff --git a/_test/tests/inc/remote.test.php b/_test/tests/inc/remote.test.php index 49152d8db..611e1ab0f 100644 --- a/_test/tests/inc/remote.test.php +++ b/_test/tests/inc/remote.test.php @@ -112,12 +112,12 @@ class remote_plugin_testplugin extends DokuWiki_Remote_Plugin { class remote_test extends DokuWikiTest { - var $originalConf; var $userinfo; var $remote; function setUp() { + parent::setUp(); global $plugin_controller; global $conf; global $USERINFO; @@ -131,7 +131,6 @@ class remote_test extends DokuWikiTest { $plugin_controller = $pluginManager; - $this->originalConf = $conf; $conf['remote'] = 1; $conf['remoteuser'] = '!!not set!!'; $conf['useacl'] = 0; @@ -143,9 +142,7 @@ class remote_test extends DokuWikiTest { } function tearDown() { - global $conf; global $USERINFO; - $conf = $this->originalConf; $USERINFO = $this->userinfo; } -- cgit v1.2.3 From 818f6d5179dd55f43e04269bc03e0afd5459c27e Mon Sep 17 00:00:00 2001 From: Dominik Eckelmann Date: Thu, 29 Nov 2012 15:00:44 +0100 Subject: added .idea project folder to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 459f0ea92..11634a598 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ *~ *.DS_Store *.iml +.idea/ /data/attic/* /data/cache/* /data/index/* -- cgit v1.2.3 From 38479cbba628ee76a92ff5f3c974cfa8e6ce9e61 Mon Sep 17 00:00:00 2001 From: Dominik Eckelmann Date: Thu, 29 Nov 2012 16:06:43 +0100 Subject: some coding style improvements - removed some dead/unused code - fixed phpdoc - added typing on methods --- lib/plugins/acl/admin.php | 7 ------- lib/plugins/config/settings/config.class.php | 7 +++---- lib/plugins/info/syntax.php | 20 +++----------------- lib/plugins/plugin/admin.php | 22 ++++------------------ lib/plugins/plugin/classes/ap_download.class.php | 4 +--- lib/plugins/plugin/classes/ap_manage.class.php | 6 +----- lib/plugins/plugin/classes/ap_update.class.php | 2 -- lib/plugins/popularity/action.php | 6 +++++- lib/plugins/popularity/admin.php | 8 ++++++-- lib/plugins/popularity/helper.php | 10 ++++++---- lib/plugins/revert/admin.php | 2 -- lib/plugins/syntax.php | 14 +++++++------- lib/plugins/usermanager/admin.php | 5 +---- 13 files changed, 37 insertions(+), 76 deletions(-) diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php index 1197892f2..0d9cd742a 100644 --- a/lib/plugins/acl/admin.php +++ b/lib/plugins/acl/admin.php @@ -173,8 +173,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * @author Andreas Gohr */ function html() { - global $ID; - echo '
'.NL; echo '

'.$this->getLang('admin_acl').'

'.NL; echo '
'.NL; @@ -208,7 +206,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * @author Andreas Gohr */ function _get_opts($addopts=null){ - global $ID; $opts = array( 'do'=>'admin', 'page'=>'acl', @@ -230,7 +227,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { global $ID; global $lang; - $dir = $conf['datadir']; $ns = $this->ns; if(empty($ns)){ $ns = dirname(str_replace(':','/',$ID)); @@ -326,7 +322,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * @author Andreas Gohr */ function _html_detail(){ - global $conf; global $ID; echo '
'.NL; @@ -493,7 +488,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * @author Andreas Gohr */ function _html_list_acl($item){ - global $ID; $ret = ''; // what to display if($item['label']){ @@ -764,7 +758,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * @author Andreas Gohr */ function _html_select(){ - global $conf; $inlist = false; if($this->who && diff --git a/lib/plugins/config/settings/config.class.php b/lib/plugins/config/settings/config.class.php index 8c48018d7..a30a0605b 100644 --- a/lib/plugins/config/settings/config.class.php +++ b/lib/plugins/config/settings/config.class.php @@ -369,7 +369,7 @@ if (!class_exists('setting')) { * update setting with user provided value $input * if value fails error check, save it * - * @return true if changed, false otherwise (incl. on error) + * @return boolean true if changed, false otherwise (incl. on error) */ function update($input) { if (is_null($input)) return false; @@ -426,7 +426,6 @@ if (!class_exists('setting')) { if ($fmt=='php') { // translation string needs to be improved FIXME - $tr = array("\n"=>'\n', "\r"=>'\r', "\t"=>'\t', "\\" => '\\\\', "'" => '\\\''); $tr = array("\\" => '\\\\', "'" => '\\\''); $out = '$'.$var."['".$this->_out_key()."'] = '".strtr($this->_local, $tr)."';\n"; @@ -538,7 +537,7 @@ if (!class_exists('setting_email')) { * update setting with user provided value $input * if value fails error check, save it * - * @return true if changed, false otherwise (incl. on error) + * @return boolean true if changed, false otherwise (incl. on error) */ function update($input) { if (is_null($input)) return false; @@ -574,7 +573,7 @@ if (!class_exists('setting_richemail')) { * update setting with user provided value $input * if value fails error check, save it * - * @return true if changed, false otherwise (incl. on error) + * @return boolean true if changed, false otherwise (incl. on error) */ function update($input) { if (is_null($input)) return false; diff --git a/lib/plugins/info/syntax.php b/lib/plugins/info/syntax.php index 9aedbf0aa..d813aa23a 100644 --- a/lib/plugins/info/syntax.php +++ b/lib/plugins/info/syntax.php @@ -15,20 +15,6 @@ if(!defined('DOKU_INC')) die(); */ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { - /** - * return some info - */ - function getInfo(){ - return array( - 'author' => 'Andreas Gohr', - 'email' => 'andi@splitbrain.org', - 'date' => '2008-09-12', - 'name' => 'Info Plugin', - 'desc' => 'Displays information about various DokuWiki internals', - 'url' => 'http://dokuwiki.org/plugin:info', - ); - } - /** * What kind of syntax are we? */ @@ -114,7 +100,7 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * * uses some of the original renderer methods */ - function _plugins_xhtml($type, &$renderer){ + function _plugins_xhtml($type, Doku_Renderer &$renderer){ global $lang; $renderer->doc .= '
    '; @@ -152,7 +138,7 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * * uses some of the original renderer methods */ - function _helpermethods_xhtml(&$renderer){ + function _helpermethods_xhtml(Doku_Renderer &$renderer){ global $lang; $plugins = plugin_list('helper'); @@ -237,7 +223,7 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { /** * Adds a TOC item */ - function _addToTOC($text, $level, &$renderer){ + function _addToTOC($text, $level, Doku_Renderer_xhtml &$renderer){ global $conf; if (($level >= $conf['toptoclevel']) && ($level <= $conf['maxtoclevel'])){ diff --git a/lib/plugins/plugin/admin.php b/lib/plugins/plugin/admin.php index b2108f185..8b1ee3c7d 100644 --- a/lib/plugins/plugin/admin.php +++ b/lib/plugins/plugin/admin.php @@ -33,6 +33,10 @@ class admin_plugin_plugin extends DokuWiki_Admin_Plugin { var $disabled = 0; var $plugin = ''; var $cmd = ''; + + /** + * @var ap_manage + */ var $handler = NULL; var $functions = array('delete','update',/*'settings',*/'info'); // require a plugin name @@ -43,27 +47,9 @@ class admin_plugin_plugin extends DokuWiki_Admin_Plugin { var $error = ''; function admin_plugin_plugin() { - global $conf; $this->disabled = plugin_isdisabled('plugin'); } - /** - * return some info - */ - function getInfo(){ - $disabled = ($this->disabled) ? '(disabled)' : ''; - - return array( - 'author' => 'Christopher Smith', - 'email' => 'chris@jalakai.co.uk', - 'date' => '2009-11-11', - 'name' => 'Plugin Manager', - 'desc' => "Manage Plugins, including automated plugin installer $disabled", - 'url' => 'http://www.dokuwiki.org/plugin:plugin', - ); - } - - /** * return sort order for position in admin menu */ diff --git a/lib/plugins/plugin/classes/ap_download.class.php b/lib/plugins/plugin/classes/ap_download.class.php index 0eb567c80..3cc455867 100644 --- a/lib/plugins/plugin/classes/ap_download.class.php +++ b/lib/plugins/plugin/classes/ap_download.class.php @@ -7,7 +7,6 @@ class ap_download extends ap_manage { * Initiate the plugin download */ function process() { - global $lang; global $INPUT; $plugin_url = $INPUT->str('url'); @@ -45,7 +44,6 @@ class ap_download extends ap_manage { * Process the downloaded file */ function download($url, $overwrite=false) { - global $lang; // check the url $matches = array(); if (!preg_match("/[^\/]*$/", $url, $matches) || !$matches[0]) { @@ -241,7 +239,7 @@ class ap_download extends ap_manage { * if neither bz, gz or zip are recognized, tar is assumed. * * @author Andreas Gohr - * @returns false if the file can't be read, otherwise an "extension" + * @returns boolean|string false if the file can't be read, otherwise an "extension" */ function guess_archive($file){ $fh = fopen($file,'rb'); diff --git a/lib/plugins/plugin/classes/ap_manage.class.php b/lib/plugins/plugin/classes/ap_manage.class.php index 28579cbe9..3ec740dae 100644 --- a/lib/plugins/plugin/classes/ap_manage.class.php +++ b/lib/plugins/plugin/classes/ap_manage.class.php @@ -69,7 +69,6 @@ class ap_manage { } function html_pluginlist() { - global $ID; global $plugin_protected; foreach ($this->manager->plugin_list as $plugin) { @@ -195,11 +194,8 @@ class ap_manage { closedir($dh); return @rmdir($path); - } else { - return @unlink($path); } - - return false; + return @unlink($path); } diff --git a/lib/plugins/plugin/classes/ap_update.class.php b/lib/plugins/plugin/classes/ap_update.class.php index c43429a1b..5d7f6cb08 100644 --- a/lib/plugins/plugin/classes/ap_update.class.php +++ b/lib/plugins/plugin/classes/ap_update.class.php @@ -5,8 +5,6 @@ class ap_update extends ap_download { var $overwrite = true; function process() { - global $lang; - $plugin_url = $this->plugin_readlog($this->plugin, 'url'); $this->download($plugin_url, $this->overwrite); return ''; diff --git a/lib/plugins/popularity/action.php b/lib/plugins/popularity/action.php index 1c7a2f65d..f0cbb771b 100644 --- a/lib/plugins/popularity/action.php +++ b/lib/plugins/popularity/action.php @@ -9,6 +9,10 @@ require_once(DOKU_PLUGIN.'action.php'); require_once(DOKU_PLUGIN.'popularity/admin.php'); class action_plugin_popularity extends Dokuwiki_Action_Plugin { + + /** + * @var helper_plugin_popularity + */ var $helper; function action_plugin_popularity(){ @@ -22,7 +26,7 @@ class action_plugin_popularity extends Dokuwiki_Action_Plugin { $controller->register_hook('INDEXER_TASKS_RUN', 'AFTER', $this, '_autosubmit', array()); } - function _autosubmit(&$event, $param){ + function _autosubmit(Doku_Event &$event, $param){ //Do we have to send the data now if ( !$this->helper->isAutosubmitEnabled() || $this->_isTooEarlyToSubmit() ){ return; diff --git a/lib/plugins/popularity/admin.php b/lib/plugins/popularity/admin.php index 474a09ef9..deb8048f4 100644 --- a/lib/plugins/popularity/admin.php +++ b/lib/plugins/popularity/admin.php @@ -14,6 +14,10 @@ if(!defined('DOKU_INC')) die(); */ class admin_plugin_popularity extends DokuWiki_Admin_Plugin { var $version; + + /** + * @var helper_plugin_popularity + */ var $helper; var $sentStatus = null; @@ -118,9 +122,9 @@ class admin_plugin_popularity extends DokuWiki_Admin_Plugin { /** * Build the form which presents the data to be sent - * @param string $submit How is the data supposed to be sent? (may be: 'browser' or 'server') + * @param string $submissionMode How is the data supposed to be sent? (may be: 'browser' or 'server') * @param string $data The popularity data, if it has already been computed. NULL otherwise. - * @return The form, as an html string + * @return string The form, as an html string */ function buildForm($submissionMode, $data = null){ $url = ($submissionMode === 'browser' ? $this->helper->submitUrl : script()); diff --git a/lib/plugins/popularity/helper.php b/lib/plugins/popularity/helper.php index 34521021d..5bbeddba0 100644 --- a/lib/plugins/popularity/helper.php +++ b/lib/plugins/popularity/helper.php @@ -29,6 +29,8 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { */ var $popularityLastSubmitFile; + var $version; + function helper_plugin_popularity(){ global $conf; @@ -69,7 +71,7 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { /** * Check if autosubmit is enabled - * @return TRUE if we should send data once a month, FALSE otherwise + * @return boolean TRUE if we should send data once a month, FALSE otherwise */ function isAutoSubmitEnabled(){ return @file_exists($this->autosubmitFile); @@ -78,7 +80,7 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { /** * Send the data, to the submit url * @param string $data The popularity data - * @return An empty string if everything worked fine, a string describing the error otherwise + * @return string An empty string if everything worked fine, a string describing the error otherwise */ function sendData($data){ $error = ''; @@ -102,7 +104,7 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { /** * Gather all information - * @return The popularity data as a string + * @return string The popularity data as a string */ function gatherAsString(){ $data = $this->_gather(); @@ -119,7 +121,7 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { /** * Gather all information - * @return The popularity data as an array + * @return array The popularity data as an array */ function _gather(){ global $conf; diff --git a/lib/plugins/revert/admin.php b/lib/plugins/revert/admin.php index 958cf5acf..fcdaa230d 100644 --- a/lib/plugins/revert/admin.php +++ b/lib/plugins/revert/admin.php @@ -73,8 +73,6 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { * Start the reversion process */ function _revert($revert,$filter){ - global $conf; - echo '

    '; echo '

    '.$this->getLang('revstart').'

    '; diff --git a/lib/plugins/syntax.php b/lib/plugins/syntax.php index 8b94493e4..552cc747a 100644 --- a/lib/plugins/syntax.php +++ b/lib/plugins/syntax.php @@ -84,13 +84,13 @@ class DokuWiki_Syntax_Plugin extends Doku_Parser_Mode { * * Usually you should only need the $match param. * - * @param $match string The text matched by the patterns - * @param $state int The lexer state for the match - * @param $pos int The character position of the matched text - * @param $handler Doku_Handler Reference to the Doku_Handler object - * @return array Return an array with all data you want to use in render + * @param string $match The text matched by the patterns + * @param int $state The lexer state for the match + * @param int $pos The character position of the matched text + * @param Doku_Handler $handler Reference to the Doku_Handler object + * @return array Return an array with all data you want to use in render */ - function handle($match, $state, $pos, &$handler){ + function handle($match, $state, $pos, Doku_Handler &$handler){ trigger_error('handle() not implemented in '.get_class($this), E_USER_WARNING); } @@ -117,7 +117,7 @@ class DokuWiki_Syntax_Plugin extends Doku_Parser_Mode { * @param $data array data created by handler() * @return boolean rendered correctly? */ - function render($format, &$renderer, $data) { + function render($format, Doku_Renderer &$renderer, $data) { trigger_error('render() not implemented in '.get_class($this), E_USER_WARNING); } diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index 30b65debb..cf8963e64 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -73,8 +73,6 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * handle user request */ function handle() { - global $ID; - if (is_null($this->_auth)) return false; // extract the command and any specific parameters @@ -308,7 +306,6 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { function _htmlInputField($id, $name, $label, $value, $cando, $indent=0) { $class = $cando ? '' : ' class="disabled"'; - $disabled = $cando ? '' : ' disabled="disabled"'; echo str_pad('',$indent); if($name == 'userpass'){ @@ -549,7 +546,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { /** * retrieve & clean user data from the form * - * @return array(user, password, full name, email, array(groups)) + * @return array (user, password, full name, email, array(groups)) */ function _retrieveUser($clean=true) { global $auth; -- cgit v1.2.3 From 10b5c32d6486ab0884deda109b1e5947f7ec7662 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 30 Nov 2012 12:35:46 +0100 Subject: fixed merge error in inc/auth.php merged the wrong change here --- inc/auth.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/inc/auth.php b/inc/auth.php index 54d2cd50a..9c458338d 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -782,21 +782,21 @@ function register() { // create substitutions for use in notification email $substitutions = array( - 'NEWUSER' => $_POST['login'], - 'NEWNAME' => $_POST['fullname'], - 'NEWEMAIL' => $_POST['email'], + 'NEWUSER' => $login, + 'NEWNAME' => $fullname, + 'NEWEMAIL' => $email, ); if(!$conf['autopasswd']) { msg($lang['regsuccess2'], 1); - notify('', 'register', '', $_POST['login'], false, $substitutions); + notify('', 'register', '', $login, false, $substitutions); return true; } // autogenerated password? then send him the password if(auth_sendPassword($login, $pass)) { msg($lang['regsuccess'], 1); - notify('', 'register', '', $_POST['login'], false, $substitutions); + notify('', 'register', '', $login, false, $substitutions); return true; } else { msg($lang['regmailfail'], -1); -- cgit v1.2.3 From 790b77202079261b11d425e0c814608d626eea70 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 30 Nov 2012 13:09:15 +0100 Subject: moved registration notification to subscription class --- inc/auth.php | 14 +++++--------- inc/common.php | 27 ++------------------------- inc/subscription.php | 29 ++++++++++++++++------------- 3 files changed, 23 insertions(+), 47 deletions(-) diff --git a/inc/auth.php b/inc/auth.php index 9c458338d..29a46b37e 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -780,23 +780,19 @@ function register() { return false; } - // create substitutions for use in notification email - $substitutions = array( - 'NEWUSER' => $login, - 'NEWNAME' => $fullname, - 'NEWEMAIL' => $email, - ); + // send notification about the new user + $subscription = new Subscription(); + $subscription->send_register($login, $fullname, $email); + // are we done? if(!$conf['autopasswd']) { msg($lang['regsuccess2'], 1); - notify('', 'register', '', $login, false, $substitutions); return true; } - // autogenerated password? then send him the password + // autogenerated password? then send password to user if(auth_sendPassword($login, $pass)) { msg($lang['regsuccess'], 1); - notify('', 'register', '', $login, false, $substitutions); return true; } else { msg($lang['regmailfail'], -1); diff --git a/inc/common.php b/inc/common.php index d17061a1b..20e0af389 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1126,36 +1126,13 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = $to = $data['addresslist']; if(empty($to)) return false; $tpl = 'subscr_single'; - } elseif($who == 'register') { - if(empty($conf['registernotify'])) return false; - $text = rawLocale('registermail'); - $to = $conf['registernotify']; } else { return false; //just to be safe } // prepare content - if($who == 'register') { - $subject = $lang['mail_new_user'].' '.$summary; - } else { - $subscription = new Subscription(); - return $subscription->send_diff($to, $tpl, $id, $rev, $summary); - } - - - // send mail - $mail = new Mailer(); - $mail->to($to); - $mail->subject($subject); - $mail->setBody($text, $trep, $hrep); - if($who == 'subscribers') { - $mail->setHeader( - 'List-Unsubscribe', - '<'.wl($id, array('do'=> 'subscribe'), true, '&').'>', - false - ); - } - return $mail->send(); + $subscription = new Subscription(); + return $subscription->send_diff($to, $tpl, $id, $rev, $summary); } /** diff --git a/inc/subscription.php b/inc/subscription.php index 4757b216c..bfbd95244 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -429,9 +429,18 @@ class Subscription { ); } + /** + * Send a notify mail on new registration + * + * @author Andreas Gohr + * + * @param string $login login name of the new user + * @param string $fullname full name of the new user + * @param string $email email address of the new user + * @return bool true if a mail was sent + */ public function send_register($login, $fullname, $email) { global $conf; - global $ID; if(empty($conf['registernotify'])) return false; $trep = array( @@ -443,7 +452,7 @@ class Subscription { return $this->send( $conf['registernotify'], 'new_user', - $ID, + $login, 'registermail', $trep ); @@ -486,10 +495,10 @@ class Subscription { * @param string $subscriber_mail The target mail address * @param array $ids Array of ids * @param string $ns_id The id of the namespace - * @return bool + * @return bool true if a mail was sent */ protected function send_list($subscriber_mail, $ids, $ns_id) { - if(count($ids) === 0) return; + if(count($ids) === 0) return false; $tlist = ''; $hlist = '
      '; @@ -526,7 +535,7 @@ class Subscription { * @param string $subscriber_mail The target mail address * @param string $subject The lang id of the mail subject (without the * prefix “mail_”) - * @param string $id The page or namespace id + * @param string $context The context of this mail, eg. page or namespace id * @param string $template The name of the mail template * @param array $trep Predefined parameters used to parse the * template (in text format) @@ -534,17 +543,11 @@ class Subscription { * template (in HTML format), null to default to $trep * @return bool */ - protected function send($subscriber_mail, $subject, $id, $template, $trep, $hrep = null) { + protected function send($subscriber_mail, $subject, $context, $template, $trep, $hrep = null) { global $lang; $text = rawLocale($template); - $trep = array_merge( - $trep, array( - - ) - ); - - $subject = $lang['mail_'.$subject].' '.$id; + $subject = $lang['mail_'.$subject].' '.$context; $mail = new Mailer(); $mail->bcc($subscriber_mail); $mail->subject($subject); -- cgit v1.2.3 From 2e41a0255616465dae4c1883ce295ed4a9cd9a33 Mon Sep 17 00:00:00 2001 From: Hakan Sandell Date: Sun, 2 Dec 2012 20:32:38 +0100 Subject: Re-phrased "no license" installer text --- inc/lang/en/lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index a21db0564..6ea5acec0 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -311,7 +311,7 @@ $lang['i_pol1'] = 'Public Wiki (read for everyone, write and uplo $lang['i_pol2'] = 'Closed Wiki (read, write, upload for registered users only)'; $lang['i_retry'] = 'Retry'; $lang['i_license'] = 'Please choose the license you want to put your content under:'; -$lang['i_license_none'] = 'None of the above'; +$lang['i_license_none'] = 'Do not show any license information'; $lang['recent_global'] = 'You\'re currently watching the changes inside the %s namespace. You can also view the recent changes of the whole wiki.'; $lang['years'] = '%d years ago'; -- cgit v1.2.3 From 8740865b92ffc5ea809dce6ae44f48aa7caf4134 Mon Sep 17 00:00:00 2001 From: Hakan Sandell Date: Sun, 2 Dec 2012 20:33:29 +0100 Subject: Fixed missing %s in Swedish translation --- inc/lang/sv/lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/lang/sv/lang.php b/inc/lang/sv/lang.php index 1c3141da7..4c4e060b4 100644 --- a/inc/lang/sv/lang.php +++ b/inc/lang/sv/lang.php @@ -172,7 +172,7 @@ $lang['lastmod'] = 'Senast uppdaterad'; $lang['by'] = 'av'; $lang['deleted'] = 'raderad'; $lang['created'] = 'skapad'; -$lang['restored'] = 'tidigare version återställd'; +$lang['restored'] = 'tidigare version återställd (%s)'; $lang['external_edit'] = 'extern redigering'; $lang['summary'] = 'Redigeringskommentar'; $lang['noflash'] = 'Adobe Flash Plugin behövs för att visa detta innehåll.'; -- cgit v1.2.3 From b04a190d960a260703e65e9ed4a951cb083e4e61 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sun, 2 Dec 2012 23:58:38 +0100 Subject: XHTML renderer: bind section id counter to the renderer instance This changes the previously static lastsecid into an instance variable, this leads to consistent section edit ids when the xhtml renderer is used more than once in a request. This makes it possible for test cases to know the exact section edit id for an instruction array. --- inc/parser/xhtml.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index b4e78a530..68b92ca43 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -30,6 +30,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { var $toc = array(); // will contain the Table of Contents var $sectionedits = array(); // A stack of section edit data + private $lastsecid = 0; // last section edit id, used by startSectionEdit var $headers = array(); var $footnotes = array(); @@ -50,9 +51,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * @author Adrian Lang */ public function startSectionEdit($start, $type, $title = null) { - static $lastsecid = 0; - $this->sectionedits[] = array(++$lastsecid, $start, $type, $title); - return 'sectionedit' . $lastsecid; + $this->sectionedits[] = array(++$this->lastsecid, $start, $type, $title); + return 'sectionedit' . $this->lastsecid; } /** -- cgit v1.2.3 From 48a1417ef1d153f5c7994aa7ced8da4e710bc70e Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Mon, 3 Dec 2012 00:04:36 +0100 Subject: Correct parameter documentation of DokuWiki_Plugin::loadHelper() --- inc/plugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/plugin.php b/inc/plugin.php index b0518346d..e4bba989d 100644 --- a/inc/plugin.php +++ b/inc/plugin.php @@ -184,8 +184,8 @@ class DokuWiki_Plugin { * * @author Esther Brunner * - * @param $name name of plugin to load - * @param $msg message to display in case the plugin is not available + * @param string $name name of plugin to load + * @param bool $msg if a message should be displayed in case the plugin is not available * * @return object helper plugin object */ -- cgit v1.2.3 From 4f4c6fd5079db8beb50ea9b9aa08351a49a57d21 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Mon, 3 Dec 2012 00:07:36 +0100 Subject: lib/exe/indexer.php: Fix sending of the GIF when it is deferred FS#2646 Before this change the GIF wasn't sent at all when the PHP settings indicate that sending of the GIF needs to be deferred and it was sent when the debug output was on. --- lib/exe/indexer.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/exe/indexer.php b/lib/exe/indexer.php index c336514cd..28ee5331f 100644 --- a/lib/exe/indexer.php +++ b/lib/exe/indexer.php @@ -37,9 +37,12 @@ if ($evt->advise_before()) { runTrimRecentChanges(true) or $evt->advise_after(); } -if($defer) sendGIF(); -if(!$output) ob_end_clean(); +if(!$output) { + ob_end_clean(); + if($defer) sendGIF(); +} + exit; // -------------------------------------------------------------------- -- cgit v1.2.3 From 03aafe1cc677b4b0b0b0ef9ed04d8ab72f3ce583 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Mon, 3 Dec 2012 00:13:01 +0100 Subject: Indexer: add getPID/getPageFromPID functions and PID to INDEXER_PAGE_ADD This allows plugins to get the PID for a page and also to get the page for a certain PID. That way plugins can build their own index that uses numeric ids. --- inc/indexer.php | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/inc/indexer.php b/inc/indexer.php index f22aee3a0..cbb817d78 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -120,7 +120,7 @@ class Doku_Indexer { return "locked"; // load known documents - $pid = $this->addIndexKey('page', '', $page); + $pid = $this->getPIDNoLock($page); if ($pid === false) { $this->unlock(); return false; @@ -256,7 +256,7 @@ class Doku_Indexer { return "locked"; // load known documents - $pid = $this->addIndexKey('page', '', $page); + $pid = $this->getPIDNoLock($page); if ($pid === false) { $this->unlock(); return false; @@ -348,7 +348,7 @@ class Doku_Indexer { return "locked"; // load known documents - $pid = $this->addIndexKey('page', '', $page); + $pid = $this->getPIDNoLock($page); if ($pid === false) { $this->unlock(); return false; @@ -453,6 +453,48 @@ class Doku_Indexer { return array_values($wordlist); } + /** + * Get the numeric PID of a page + * + * @param string $page The page to get the PID for + * @return bool|int The page id on success, false on error + */ + public function getPID($page) { + if (!$this->lock()) + return false; + + // load known documents + $pid = $this->getPIDNoLock($page); + if ($pid === false) { + $this->unlock(); + return false; + } + + $this->unlock(); + return $pid; + } + + /** + * Get the numeric PID of a page without locking the index. + * Only use this function when the index is already locked. + * + * @param string $page The page to get the PID for + * @return bool|int The page id on success, false on error + */ + protected function getPIDNoLock($page) { + return $this->addIndexKey('page', '', $page); + } + + /** + * Get the page id of a numeric PID + * + * @param int $pid The PID to get the page id for + * @return string The page id + */ + public function getPageFromPID($pid) { + return $this->getIndexKey('page', '', $pid); + } + /** * Find pages in the fulltext index containing the words, * @@ -946,7 +988,7 @@ class Doku_Indexer { * @param string $idx name of the index * @param string $suffix subpart identifier * @param string $value line to find in the index - * @return int line number of the value in the index + * @return int|bool line number of the value in the index or false if writing the index failed * @author Tom N Harris */ protected function addIndexKey($idx, $suffix, $value) { @@ -1223,6 +1265,12 @@ function idx_addPage($page, $verbose=false, $force=false) { return $result; } + $Indexer = idx_get_indexer(); + $pid = $Indexer->getPID($page); + if ($pid === false) { + if ($verbose) print("Indexer: getting the PID failed for $page".DOKU_LF); + return false; + } $body = ''; $metadata = array(); $metadata['title'] = p_get_metadata($page, 'title', METADATA_RENDER_UNLIMITED); @@ -1230,14 +1278,13 @@ function idx_addPage($page, $verbose=false, $force=false) { $metadata['relation_references'] = array_keys($references); else $metadata['relation_references'] = array(); - $data = compact('page', 'body', 'metadata'); + $data = compact('page', 'body', 'metadata', 'pid'); $evt = new Doku_Event('INDEXER_PAGE_ADD', $data); if ($evt->advise_before()) $data['body'] = $data['body'] . " " . rawWiki($page); $evt->advise_after(); unset($evt); extract($data); - $Indexer = idx_get_indexer(); $result = $Indexer->addPageWords($page, $body); if ($result === "locked") { if ($verbose) print("Indexer: locked".DOKU_LF); -- cgit v1.2.3 From 0572700e3546546abe8375a0fff7245673f2b02a Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Tue, 4 Dec 2012 15:35:00 +0100 Subject: Indexer: Add test case for the PID functions --- _test/tests/inc/indexer_pid.test.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 _test/tests/inc/indexer_pid.test.php diff --git a/_test/tests/inc/indexer_pid.test.php b/_test/tests/inc/indexer_pid.test.php new file mode 100644 index 000000000..8c58b1abd --- /dev/null +++ b/_test/tests/inc/indexer_pid.test.php @@ -0,0 +1,18 @@ + + */ +class indexer_pid_test extends DokuWikiTest { + function test_pid() { + $indexer = idx_get_indexer(); + $syntaxPID = $indexer->getPID('wiki:syntax'); + $this->assertEquals('wiki:syntax', $indexer->getPageFromPID($syntaxPID), 'getPageFromPID(getPID(\'wiki:syntax\')) != \'wiki:syntax\''); + $dokuwikiPID = $indexer->getPID('wiki:dokuwiki'); + $this->assertEquals('wiki:syntax', $indexer->getPageFromPID($syntaxPID), 'getPageFromPID(getPID(\'wiki:syntax\')) != \'wiki:syntax\' after getting the PID for wiki:dokuwiki'); + $this->assertEquals($syntaxPID, $indexer->getPID('wiki:syntax'), 'getPID(\'wiki:syntax\') didn\'t returned different PIDs when called twice'); + $this->assertNotEquals($syntaxPID, $dokuwikiPID, 'Same PID returned for different pages'); + $this->assertTrue(is_numeric($syntaxPID) && is_numeric($dokuwikiPID), 'PIDs are not numeric'); + } +} -- cgit v1.2.3 From 3d2ce006bd7cffab5cda27f01787d2fd66ab630e Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Tue, 4 Dec 2012 16:13:46 +0100 Subject: Indexer: Add cache for getPID() This avoids re-reading of the page index file for every getPID()-call by using a simple FIFO cache, limited to 10 items. In idx_addPage() and the functions that it calls getPID() is called 3 times for the same PID. --- inc/indexer.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/inc/indexer.php b/inc/indexer.php index cbb817d78..05b082872 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -102,6 +102,10 @@ function wordlen($w){ * @author Tom N Harris */ class Doku_Indexer { + /** + * @var array $pidCache Cache for getPID() + */ + protected $pidCache = array(); /** * Adds the contents of a page to the fulltext index @@ -460,6 +464,9 @@ class Doku_Indexer { * @return bool|int The page id on success, false on error */ public function getPID($page) { + // return PID without locking when it is in the cache + if (isset($this->pidCache[$page])) return $this->pidCache[$page]; + if (!$this->lock()) return false; @@ -482,7 +489,14 @@ class Doku_Indexer { * @return bool|int The page id on success, false on error */ protected function getPIDNoLock($page) { - return $this->addIndexKey('page', '', $page); + // avoid expensive addIndexKey operation for the most recently requested pages by using a cache + if (isset($this->pidCache[$page])) return $this->pidCache[$page]; + $pid = $this->addIndexKey('page', '', $page); + // limit cache to 10 entries by discarding the oldest element as in DokuWiki usually only the most recently + // added item will be requested again + if (count($this->pidCache) > 10) array_shift($this->pidCache); + $this->pidCache[$page] = $pid; + return $pid; } /** -- cgit v1.2.3 From 1421e5483ad1ca8780331077141e0c07b6530bc5 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Tue, 4 Dec 2012 16:15:49 +0100 Subject: Indexer: Make $Indexer in idx_get_indexer() global instead of static This avoids problems with test cases that use the indexer and the PID cache - the index is cleaned between test cases but the PID cache wasn't cleaned. Now PHPUnit can unset the global $Indexer between test cases. --- inc/indexer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/indexer.php b/inc/indexer.php index 05b082872..4dfaa33fb 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -1196,8 +1196,8 @@ class Doku_Indexer { * @author Tom N Harris */ function idx_get_indexer() { - static $Indexer = null; - if (is_null($Indexer)) { + global $Indexer; + if (!isset($Indexer)) { $Indexer = new Doku_Indexer(); } return $Indexer; -- cgit v1.2.3 From e13e01da48b642dcdf3efe6864f0fc2bb5094455 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 7 Dec 2012 10:35:27 +0100 Subject: added compatibility function --- inc/subscription.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/inc/subscription.php b/inc/subscription.php index bfbd95244..df6f1af32 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -604,4 +604,19 @@ class Subscription { } $data['addresslist'] = trim($addresslist.','.implode(',', $result), ','); } +} + +/** + * Compatibility wrapper around Subscription:notifyaddresses + * + * for plugins emitting COMMON_NOTIFY_ADDRESSLIST themselves and relying on on this to + * be the default handler + * + * @param array $data event data for + * + * @deprecated 2012-12-07 + */ +function subscription_addresslist(&$data){ + $sub = new Subscription(); + $sub->notifyaddresses($data); } \ No newline at end of file -- cgit v1.2.3 From b34cf753be6c2c3fc67eac58738acc74a1c1785a Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 7 Dec 2012 10:35:49 +0100 Subject: some reformatting --- inc/subscription.php | 78 ++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/inc/subscription.php b/inc/subscription.php index df6f1af32..44248a39d 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -93,27 +93,27 @@ class Subscription { */ protected function buildregex($user = null, $style = null, $data = null) { // always work with arrays - $user = (array) $user; + $user = (array) $user; $style = (array) $style; - $data = (array) $data; + $data = (array) $data; // clean - $user = array_filter(array_map('trim', $user)); + $user = array_filter(array_map('trim', $user)); $style = array_filter(array_map('trim', $style)); - $data = array_filter(array_map('trim', $data)); + $data = array_filter(array_map('trim', $data)); // user names are encoded $user = array_map('auth_nameencode', $user); // quote - $user = array_map('preg_quote_cb', $user); + $user = array_map('preg_quote_cb', $user); $style = array_map('preg_quote_cb', $style); - $data = array_map('preg_quote_cb', $data); + $data = array_map('preg_quote_cb', $data); // join - $user = join('|', $user); + $user = join('|', $user); $style = join('|', $style); - $data = join('|', $data); + $data = join('|', $data); // any data at all? if($user.$style.$data === '') throw new Exception('no data passed'); @@ -126,7 +126,7 @@ class Subscription { } if($style === '') { $style = '\S+'; - $sopt = '?'; + $sopt = '?'; } if($data === '') { $data = '\S+'; @@ -158,7 +158,7 @@ class Subscription { $files = array(':' => $this->file(':')); do { $files[$page] = $this->file($page); - $page = getNS(rtrim($page, ':')).':'; + $page = getNS(rtrim($page, ':')).':'; } while($page !== ':'); $re = $this->buildregex($user, $style, $data); @@ -204,9 +204,9 @@ class Subscription { // delete any existing subscription $this->remove($id, $user); - $user = auth_nameencode(trim($user)); + $user = auth_nameencode(trim($user)); $style = trim($style); - $data = trim($data); + $data = trim($data); if(!$user) throw new Exception('no subscription user given'); if(!$style) throw new Exception('no subscription style given'); @@ -270,8 +270,8 @@ class Subscription { foreach($subs as $target => $info) { $result[] = array( 'target' => $target, - 'style' => $info[$user][0], - 'data' => $info[$user][1] + 'style' => $info[$user][0], + 'data' => $info[$user][1] ); } @@ -302,7 +302,7 @@ class Subscription { // remember current user info $olduinfo = $USERINFO; - $olduser = $_SERVER['REMOTE_USER']; + $olduser = $_SERVER['REMOTE_USER']; foreach($subscriptions as $target => $users) { if(!$this->lock($target)) continue; @@ -318,7 +318,7 @@ class Subscription { } // Work as the user to make sure ACLs apply correctly - $USERINFO = $auth->getUserData($user); + $USERINFO = $auth->getUserData($user); $_SERVER['REMOTE_USER'] = $user; if($USERINFO === false) continue; if(!$USERINFO['mail']) continue; @@ -329,7 +329,7 @@ class Subscription { } else { // single page subscription, check ACL ourselves if(auth_quickaclcheck($target) < AUTH_READ) continue; - $meta = p_get_metadata($target); + $meta = p_get_metadata($target); $changes = array($meta['last_change']); } @@ -372,7 +372,7 @@ class Subscription { } // restore current user info - $USERINFO = $olduinfo; + $USERINFO = $olduinfo; $_SERVER['REMOTE_USER'] = $olduser; return $count; } @@ -392,32 +392,32 @@ class Subscription { // prepare replacements (keys not set in hrep will be taken from trep) $trep = array( - 'PAGE' => $id, - 'NEWPAGE' => wl($id, '', true, '&'), - 'SUMMARY' => $summary, + 'PAGE' => $id, + 'NEWPAGE' => wl($id, '', true, '&'), + 'SUMMARY' => $summary, 'SUBSCRIBE' => wl($id, array('do' => 'subscribe'), true, '&') ); $hrep = array(); if($rev) { - $subject = 'changed'; + $subject = 'changed'; $trep['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); - $dformat = new UnifiedDiffFormatter(); - $tdiff = $dformat->format($df); + $df = new Diff(explode("\n", rawWiki($id, $rev)), + explode("\n", rawWiki($id))); + $dformat = new UnifiedDiffFormatter(); + $tdiff = $dformat->format($df); $DIFF_INLINESTYLES = true; - $dformat = new InlineDiffFormatter(); - $hdiff = $dformat->format($df); - $hdiff = ''.$hdiff.'
      '; + $dformat = new InlineDiffFormatter(); + $hdiff = $dformat->format($df); + $hdiff = ''.$hdiff.'
      '; $DIFF_INLINESTYLES = false; } else { - $subject = 'newpage'; + $subject = 'newpage'; $trep['OLDPAGE'] = '---'; - $tdiff = rawWiki($id); - $hdiff = nl2br(hsc($tdiff)); + $tdiff = rawWiki($id); + $hdiff = nl2br(hsc($tdiff)); } $trep['DIFF'] = $tdiff; @@ -444,8 +444,8 @@ class Subscription { if(empty($conf['registernotify'])) return false; $trep = array( - 'NEWUSER' => $login, - 'NEWNAME' => $fullname, + 'NEWUSER' => $login, + 'NEWNAME' => $fullname, 'NEWEMAIL' => $email, ); @@ -548,11 +548,11 @@ class Subscription { $text = rawLocale($template); $subject = $lang['mail_'.$subject].' '.$context; - $mail = new Mailer(); + $mail = new Mailer(); $mail->bcc($subscriber_mail); $mail->subject($subject); $mail->setBody($text, $trep, $hrep); - if(isset($trep['SUBSCRIBE'])){ + if(isset($trep['SUBSCRIBE'])) { $mail->setHeader('List-Unsubscribe', '<'.$trep['SUBSCRIBE'].'>', false); } return $mail->send(); @@ -580,8 +580,8 @@ class Subscription { global $auth; global $conf; - $id = $data['id']; - $self = $data['self']; + $id = $data['id']; + $self = $data['self']; $addresslist = $data['addresslist']; $subscriptions = $this->subscribers($id, null, 'every'); @@ -616,7 +616,7 @@ class Subscription { * * @deprecated 2012-12-07 */ -function subscription_addresslist(&$data){ +function subscription_addresslist(&$data) { $sub = new Subscription(); $sub->notifyaddresses($data); } \ No newline at end of file -- cgit v1.2.3 From 3a0852d932a09ba01dcbcf2d371febf451f9f00c Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 7 Dec 2012 17:46:16 +0100 Subject: added option to enable automatic popularity data in installer --- inc/lang/en/lang.php | 2 ++ install.php | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 6ea5acec0..144faf4e1 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -312,6 +312,8 @@ $lang['i_pol2'] = 'Closed Wiki (read, write, upload for registere $lang['i_retry'] = 'Retry'; $lang['i_license'] = 'Please choose the license you want to put your content under:'; $lang['i_license_none'] = 'Do not show any license information'; +$lang['i_pop_field'] = 'Please, help us to improve the DokuWiki experience:'; +$lang['i_pop_label'] = 'Once a month, send anonymous usage data to the DokuWiki developers'; $lang['recent_global'] = 'You\'re currently watching the changes inside the %s namespace. You can also view the recent changes of the whole wiki.'; $lang['years'] = '%d years ago'; diff --git a/install.php b/install.php index f2bc1a26d..8f00d9746 100644 --- a/install.php +++ b/install.php @@ -167,6 +167,7 @@ function print_form($d){ $d = array_map('htmlspecialchars',$d); if(!isset($d['acl'])) $d['acl']=1; + if(!isset($d['pop'])) $d['pop']=1; ?> @@ -223,6 +224,14 @@ function print_form($d){ ?>

+
+

+ +
+
@@ -376,6 +385,12 @@ EOT; } $ok = $ok && fileWrite(DOKU_LOCAL.'acl.auth.php', $output); } + + // enable popularity submission + if($d['pop']){ + @touch(DOKU_INC.'data/cache/autosubmit.txt'); + } + return $ok; } -- cgit v1.2.3 From 740da4c2e05743b1f0823b3be40c44f0fc4810a9 Mon Sep 17 00:00:00 2001 From: lupo49 Date: Wed, 12 Dec 2012 11:28:42 +0100 Subject: de/de-informal: language updates / added "sidebar" --- inc/lang/de-informal/install.html | 8 ++++---- inc/lang/de-informal/lang.php | 37 +++++++++++++++++++------------------ inc/lang/de/install.html | 8 ++++---- inc/lang/de/lang.php | 37 +++++++++++++++++++------------------ 4 files changed, 46 insertions(+), 44 deletions(-) diff --git a/inc/lang/de-informal/install.html b/inc/lang/de-informal/install.html index 55239e6db..f0473772c 100644 --- a/inc/lang/de-informal/install.html +++ b/inc/lang/de-informal/install.html @@ -1,10 +1,10 @@ -

Diese Seite hilft dir bei der Erst-Installation und Konfiguration von -Dokuwiki. Zusätzliche Informationen zu +

Diese Seite hilft dir bei der Erstinstallation und Konfiguration von +DokuWiki. Zusätzliche Informationen zu diesem Installationsskript findest du auf der entsprechenden Hilfe-Seite (en).

DokuWiki verwendet normale Dateien für das Speichern von Wikiseiten und -anderen Informationen (Bilder, Suchindizes, alte Versionen, usw.). +anderen Informationen (Bilder, Suchindizes, alte Versionen usw.). Um DokuWiki betreiben zu können, muss Schreibzugriff auf die Verzeichnisse bestehen, in denen DokuWiki diese Dateien ablegt. Dieses Installationsprogramm kann diese Rechte nicht für dich setzen. Du musst dies @@ -14,7 +14,7 @@ hostest, über FTP oder ein entsprechendes Werkzeug (z.B. cPanel) durchführen.<

Dieses Skript hilft dir beim ersten Einrichten des Zugangsschutzes (ACL) von DokuWiki, welcher eine Administratoranmeldung und damit Zugang zum Administrationsmenü ermöglicht. -Dort kannst du dann weitere Tätigkeiten wie das Installieren von Plugins, das +Dort kannst du dann weitere Tätigkeiten wie das Installieren von Plugins, dass Verwalten von Nutzern und das Ändern von Konfigurationseinstellungen durchführen. Das Nutzen der Zugangskontrolle ist nicht zwingend erforderlich, es erleichtert aber die Administration von DokuWiki.

diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php index 3b6a28040..3b19f749d 100644 --- a/inc/lang/de-informal/lang.php +++ b/inc/lang/de-informal/lang.php @@ -1,6 +1,6 @@ @@ -67,7 +67,7 @@ $lang['user'] = 'Benutzername'; $lang['pass'] = 'Passwort'; $lang['newpass'] = 'Neues Passwort'; $lang['oldpass'] = 'Bestätigen (Altes Passwort)'; -$lang['passchk'] = 'und nochmal'; +$lang['passchk'] = 'Passwort erneut eingeben'; $lang['remember'] = 'Angemeldet bleiben'; $lang['fullname'] = 'Voller Name'; $lang['email'] = 'E-Mail'; @@ -83,7 +83,7 @@ $lang['regsuccess2'] = 'Der neue Nutzer wurde angelegt.'; $lang['regmailfail'] = 'Offenbar ist ein Fehler beim Versenden der Passwortmail aufgetreten. Bitte wende dich an den Wiki-Admin.'; $lang['regbadmail'] = 'Die angegebene Mail-Adresse scheint ungültig zu sein. Falls dies ein Fehler ist, wende dich bitte an den Wiki-Admin.'; $lang['regbadpass'] = 'Die beiden eingegeben Passwörter stimmen nicht überein. Bitte versuche es noch einmal.'; -$lang['regpwmail'] = 'Ihr DokuWiki Passwort'; +$lang['regpwmail'] = 'Ihr DokuWiki-Passwort'; $lang['reghere'] = 'Du hast noch keinen Zugang? Hier registrieren'; $lang['profna'] = 'Änderung des Benutzerprofils in diesem Wiki nicht möglich.'; $lang['profnochange'] = 'Keine Änderungen, nichts zu tun.'; @@ -92,9 +92,9 @@ $lang['profchanged'] = 'Benutzerprofil erfolgreich geändert.'; $lang['pwdforget'] = 'Passwort vergessen? Fordere ein neues an'; $lang['resendna'] = 'Passwörter versenden ist in diesem Wiki nicht möglich.'; $lang['resendpwd'] = 'Neues Passwort setzen für'; -$lang['resendpwdmissing'] = 'Es tut mir Leid, aber du musst alle Felder ausfüllen.'; -$lang['resendpwdnouser'] = 'Es tut mir Leid, aber der Benutzer existiert nicht in unserer Datenbank.'; -$lang['resendpwdbadauth'] = 'Es tut mir Leid, aber dieser Authentifizierungscode ist ungültig. Stelle sicher, dass du den kompletten Bestätigungslink verwendet haben.'; +$lang['resendpwdmissing'] = 'Es tut mir leid, aber du musst alle Felder ausfüllen.'; +$lang['resendpwdnouser'] = 'Es tut mir leid, aber der Benutzer existiert nicht in unserer Datenbank.'; +$lang['resendpwdbadauth'] = 'Es tut mir leid, aber dieser Authentifizierungscode ist ungültig. Stelle sicher, dass du den kompletten Bestätigungslink verwendet haben.'; $lang['resendpwdconfirm'] = 'Ein Bestätigungslink wurde per E-Mail versandt.'; $lang['resendpwdsuccess'] = 'Dein neues Passwort wurde per E-Mail versandt.'; $lang['license'] = 'Falls nicht anders bezeichnet, ist der Inhalt dieses Wikis unter der folgenden Lizenz veröffentlicht:'; @@ -137,7 +137,7 @@ $lang['js']['nosmblinks'] = 'Das Verlinken von Windows-Freigaben funktionie $lang['js']['linkwiz'] = 'Link-Assistent'; $lang['js']['linkto'] = 'Link zu:'; $lang['js']['del_confirm'] = 'Die ausgewählten Dateien wirklich löschen?'; -$lang['js']['restore_confirm'] = 'Wirkliich diese Version wieder herstellen?'; +$lang['js']['restore_confirm'] = 'Wirklich diese Version wiederherstellen?'; $lang['js']['media_diff'] = 'Unterschiede anzeigen:'; $lang['js']['media_diff_both'] = 'Seite für Seite'; $lang['js']['media_diff_opacity'] = 'Überblenden'; @@ -161,7 +161,7 @@ $lang['uploadspam'] = 'Hochladen verweigert: Treffer auf der Spamlist $lang['uploadxss'] = 'Hochladen verweigert: Daten scheinen Schadcode zu enthalten.'; $lang['uploadsize'] = 'Die hochgeladene Datei war zu groß. (max. %s)'; $lang['deletesucc'] = 'Die Datei "%s" wurde gelöscht.'; -$lang['deletefail'] = '"%s" konnte nicht gelöscht werden. Keine Berechtigung?.'; +$lang['deletefail'] = '"%s" konnte nicht gelöscht werden. Keine Berechtigung?.'; $lang['mediainuse'] = 'Die Datei "%s" wurde nicht gelöscht. Sie wird noch verwendet.'; $lang['namespaces'] = 'Namensräume'; $lang['mediafiles'] = 'Vorhandene Dateien in'; @@ -181,7 +181,7 @@ $lang['current'] = 'aktuell'; $lang['yours'] = 'Deine Version'; $lang['diff'] = 'Zeige Unterschiede zu aktueller Version'; $lang['diff2'] = 'Zeige Unterschiede der ausgewählten Versionen'; -$lang['difflink'] = 'Link zu der Versionshistorie'; +$lang['difflink'] = 'Link zu der Vergleichsansicht'; $lang['diff_type'] = 'Unterschiede anzeigen:'; $lang['diff_inline'] = 'Inline'; $lang['diff_side'] = 'Side by Side'; @@ -196,15 +196,16 @@ $lang['restored'] = 'alte Version wiederhergestellt (%s)'; $lang['external_edit'] = 'Externe Bearbeitung'; $lang['summary'] = 'Zusammenfassung'; $lang['noflash'] = 'Das Adobe Flash Plugin wird benötigt, um diesen Inhalt anzuzeigen.'; -$lang['download'] = 'Download-Teil'; +$lang['download'] = 'Schnipsel herunterladen'; $lang['tools'] = 'Werkzeuge'; $lang['user_tools'] = 'Benutzer-Werkzeuge'; $lang['site_tools'] = 'Webseiten-Werkzeuge'; $lang['page_tools'] = 'Seiten-Werkzeuge'; $lang['skip_to_content'] = 'zum Inhalt springen'; +$lang['sidebar'] = 'Seitenleiste'; $lang['mail_newpage'] = 'Neue Seite:'; $lang['mail_changed'] = 'Seite geändert:'; -$lang['mail_subscribe_list'] = 'Seite hat sich im Namespace geändert:'; +$lang['mail_subscribe_list'] = 'Geänderte Seiten im Namensraum:'; $lang['mail_new_user'] = 'Neuer Benutzer:'; $lang['mail_upload'] = 'Datei hochgeladen:'; $lang['changes_type'] = 'Änderungen anzeigen von'; @@ -272,14 +273,14 @@ $lang['subscr_style_digest'] = 'E-Mail mit zusammengefasster Übersicht der Se $lang['subscr_style_list'] = 'Auflistung aller geänderten Seiten seit der letzten E-Mail (alle %.2f Tage)'; $lang['authmodfailed'] = 'Benutzerüberprüfung nicht möglich. Bitte wende dich an den Admin.'; $lang['authtempfail'] = 'Benutzerüberprüfung momentan nicht möglich. Falls das Problem andauert, wende dich an den Admin.'; -$lang['authpwdexpire'] = 'Dein Passwort läuft in %d Tag(en) ab, du solltest es es bald ändern.'; +$lang['authpwdexpire'] = 'Dein Passwort läuft in %d Tag(en) ab. Du solltest es es frühzeitig ändern.'; $lang['i_chooselang'] = 'Wähle deine Sprache'; $lang['i_installer'] = 'DokuWiki-Installation'; $lang['i_wikiname'] = 'Wiki-Name'; $lang['i_enableacl'] = 'Zugangskontrolle (ACL) aktivieren (empfohlen)'; $lang['i_superuser'] = 'Benutzername des Administrators'; $lang['i_problems'] = 'Das Installationsprogramm hat unten aufgeführte Probleme festgestellt, die zunächst behoben werden müssen, bevor du mit der Installation fortfahren kannst.'; -$lang['i_modified'] = 'Aus Sicherheitsgründen arbeitet dieses Script nur mit einer neuen, unmodifizierten DokuWiki-Installation. Du solltest entweder alle Dateien noch einmal frisch installieren oder die Dokuwiki-Installationsanleitung konsultieren.'; +$lang['i_modified'] = 'Aus Sicherheitsgründen arbeitet dieses Skript nur mit einer neuen bzw. nicht modifizierten DokuWiki-Installation. Du solltest entweder alle Dateien noch einmal frisch installieren oder die Dokuwiki-Installationsanleitung konsultieren.'; $lang['i_funcna'] = 'Die PHP-Funktion %s ist nicht verfügbar. Unter Umständen wurde sie von deinem Hoster deaktiviert?'; $lang['i_phpver'] = 'Deine PHP-Version %s ist niedriger als die benötigte Version %s. Bitte aktualisiere deine PHP-Installation.'; $lang['i_permfail'] = '%s ist nicht durch DokuWiki beschreibbar. Du musst die Berechtigungen dieses Ordners ändern!'; @@ -288,11 +289,11 @@ $lang['i_writeerr'] = '%s konnte nicht erzeugt werden. D $lang['i_badhash'] = 'Unbekannte oder modifizierte dokuwiki.php (Hash=%s)'; $lang['i_badval'] = '%s - unerlaubter oder leerer Wert'; $lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Du kannst jetzt die install.php löschen. Dein neues DokuWiki ist jetzt für dich bereit.'; -$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Du musst diese vermutlich von Hand beheben, bevor du dein neues DokuWiki nutzen kannst.'; -$lang['i_policy'] = 'Anfangseinstellung für Zugangskontrolle (ACL)'; -$lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben, hochladen für alle)'; -$lang['i_pol1'] = 'Öffentliches Wiki (lesen für alle, schreiben und hochladen für registrierte Nutzer)'; -$lang['i_pol2'] = 'Geschlossenes Wiki (lesen, schreiben, hochladen nur für registrierte Nutzer)'; +$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Du musst diese von Hand beheben, bevor du dein neues DokuWiki nutzen kannst.'; +$lang['i_policy'] = 'Anfangseinstellungen der Zugangskontrolle (ACL)'; +$lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben und hochladen für alle Nutzer)'; +$lang['i_pol1'] = 'Öffentliches Wiki (Lesen für alle, Schreiben und Hochladen nur für registrierte Nutzer)'; +$lang['i_pol2'] = 'Geschlossenes Wiki (Lesen, Schreiben und Hochladen nur für registrierte Nutzer)'; $lang['i_retry'] = 'Wiederholen'; $lang['i_license'] = 'Bitte wähle die Lizenz aus unter der die Wiki-Inhalte veröffentlicht werden sollen:'; $lang['recent_global'] = 'Im Moment siehst du die Änderungen im Namensraum %s. Du kannst auch die Änderungen im gesamten Wiki sehen.'; diff --git a/inc/lang/de/install.html b/inc/lang/de/install.html index 599eb983b..5af3198d4 100644 --- a/inc/lang/de/install.html +++ b/inc/lang/de/install.html @@ -1,10 +1,10 @@ -

Diese Seite hilft Ihnen bei der Erst-Installation und Konfiguration von -Dokuwiki. Zusätzliche Informationen zu +

Diese Seite hilft Ihnen bei der Erstinstallation und Konfiguration von +DokuWiki. Zusätzliche Informationen zu diesem Installationsskript finden Sie auf der entsprechenden Hilfe Seite (en).

DokuWiki verwendet normale Dateien für das Speichern von Wikiseiten und -anderen Informationen (Bilder, Suchindizes, alte Versionen, usw.). +anderen Informationen (Bilder, Suchindizes, alte Versionen usw.). Um DokuWiki betreiben zu können, muss Schreibzugriff auf die Verzeichnisse bestehen, in denen DokuWiki diese Dateien ablegt. Dieses Installationsprogramm kann diese Rechte nicht für Sie setzen. Sie müssen dies @@ -14,7 +14,7 @@ hosten, über FTP oder ein entsprechendes Werkzeug (z.B. cPanel) durchführen.Dieses Skript hilft Ihnen beim ersten Einrichten des Zugangsschutzes (ACL) von DokuWiki, welcher eine Administratoranmeldung und damit Zugang zum Administrationsmenu ermöglicht. -Dort können Sie dann weitere Tätigkeiten wie das Installieren von Plugins, das +Dort können Sie dann weitere Tätigkeiten wie das Installieren von Plugins, dass Verwalten von Nutzern und das Ändern von Konfigurationseinstellungen durchführen. Das Nutzen der Zugangskontrolle ist nicht zwingend erforderlich, es erleichtert aber die Administration von DokuWiki.

diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php index 23c6a0dc1..160ea53e8 100644 --- a/inc/lang/de/lang.php +++ b/inc/lang/de/lang.php @@ -69,7 +69,7 @@ $lang['user'] = 'Benutzername'; $lang['pass'] = 'Passwort'; $lang['newpass'] = 'Neues Passwort'; $lang['oldpass'] = 'Bestätigen (Altes Passwort)'; -$lang['passchk'] = 'und nochmal'; +$lang['passchk'] = 'Passwort erneut eingeben'; $lang['remember'] = 'Angemeldet bleiben'; $lang['fullname'] = 'Voller Name'; $lang['email'] = 'E-Mail'; @@ -85,7 +85,7 @@ $lang['regsuccess2'] = 'Der neue Nutzer wurde angelegt.'; $lang['regmailfail'] = 'Offenbar ist ein Fehler beim Versenden der Passwort-E-Mail aufgetreten. Bitte wenden Sie sich an den Wiki-Admin.'; $lang['regbadmail'] = 'Die angegebene E-Mail-Adresse scheint ungültig zu sein. Falls dies ein Fehler ist, wenden Sie sich bitte an den Wiki-Admin.'; $lang['regbadpass'] = 'Die beiden eingegeben Passwörter stimmen nicht überein. Bitte versuchen Sie es noch einmal.'; -$lang['regpwmail'] = 'Ihr DokuWiki Passwort'; +$lang['regpwmail'] = 'Ihr DokuWiki-Passwort'; $lang['reghere'] = 'Sie haben noch keinen Zugang? Hier registrieren'; $lang['profna'] = 'Änderung des Benutzerprofils in diesem Wiki nicht möglich.'; $lang['profnochange'] = 'Keine Änderungen, nichts zu tun.'; @@ -94,9 +94,9 @@ $lang['profchanged'] = 'Benutzerprofil erfolgreich geändert.'; $lang['pwdforget'] = 'Passwort vergessen? Fordere ein neues an'; $lang['resendna'] = 'Passwörter versenden ist in diesem Wiki nicht möglich.'; $lang['resendpwd'] = 'Neues Passwort setzen für'; -$lang['resendpwdmissing'] = 'Es tut mir Leid, aber Sie müssen alle Felder ausfüllen.'; -$lang['resendpwdnouser'] = 'Es tut mir Leid, aber der Benutzer existiert nicht in unserer Datenbank.'; -$lang['resendpwdbadauth'] = 'Es tut mir Leid, aber dieser Authentifizierungscode ist ungültig. Stellen Sie sicher, dass Sie den kompletten Bestätigungslink verwendet haben.'; +$lang['resendpwdmissing'] = 'Es tut mir leid, aber Sie müssen alle Felder ausfüllen.'; +$lang['resendpwdnouser'] = 'Es tut mir leid, aber der Benutzer existiert nicht in unserer Datenbank.'; +$lang['resendpwdbadauth'] = 'Es tut mir leid, aber dieser Authentifizierungscode ist ungültig. Stellen Sie sicher, dass Sie den kompletten Bestätigungslink verwendet haben.'; $lang['resendpwdconfirm'] = 'Ein Bestätigungslink wurde per E-Mail versandt.'; $lang['resendpwdsuccess'] = 'Ihr neues Passwort wurde per E-Mail versandt.'; $lang['license'] = 'Falls nicht anders bezeichnet, ist der Inhalt dieses Wikis unter der folgenden Lizenz veröffentlicht:'; @@ -139,7 +139,7 @@ $lang['js']['nosmblinks'] = 'Das Verlinken von Windows-Freigaben funktionie $lang['js']['linkwiz'] = 'Link-Assistent'; $lang['js']['linkto'] = 'Link nach:'; $lang['js']['del_confirm'] = 'Eintrag wirklich löschen?'; -$lang['js']['restore_confirm'] = 'Really restore this version?'; +$lang['js']['restore_confirm'] = 'Wirklich diese Version wiederherstellen?'; $lang['js']['media_diff'] = 'Unterschiede anzeigen:'; $lang['js']['media_diff_both'] = 'Side by Side'; $lang['js']['media_diff_opacity'] = 'Überblenden'; @@ -204,6 +204,7 @@ $lang['user_tools'] = 'Benutzer-Werkzeuge'; $lang['site_tools'] = 'Webseiten-Werkzeuge'; $lang['page_tools'] = 'Seiten-Werkzeuge'; $lang['skip_to_content'] = 'zum Inhalt springen'; +$lang['sidebar'] = 'Seitenleiste'; $lang['mail_newpage'] = 'Neue Seite:'; $lang['mail_changed'] = 'Seite geändert:'; $lang['mail_subscribe_list'] = 'Geänderte Seiten im Namensraum:'; @@ -272,16 +273,16 @@ $lang['subscr_m_receive'] = 'Benachrichtigung'; $lang['subscr_style_every'] = 'E-Mail bei jeder Bearbeitung'; $lang['subscr_style_digest'] = 'Zusammenfassung der Änderungen für jede veränderte Seite (Alle %.2f Tage)'; $lang['subscr_style_list'] = 'Liste der geänderten Seiten (Alle %.2f Tage)'; -$lang['authmodfailed'] = 'Benutzerüberprüfung nicht möglich. Bitte wenden Sie sich an den Systembetreuer.'; -$lang['authtempfail'] = 'Benutzerüberprüfung momentan nicht möglich. Falls das Problem andauert, wenden Sie sich an den Systembetreuer.'; -$lang['authpwdexpire'] = 'Ihr Passwort läuft in %d Tag(en) ab, Sie sollten es bald ändern.'; +$lang['authmodfailed'] = 'Benutzerüberprüfung nicht möglich. Bitte wenden Sie sich an den Admin.'; +$lang['authtempfail'] = 'Benutzerüberprüfung momentan nicht möglich. Falls das Problem andauert, wenden Sie sich an den Admin.'; +$lang['authpwdexpire'] = 'Ihr Passwort läuft in %d Tag(en) ab. Sie sollten es frühzeitig ändern.'; $lang['i_chooselang'] = 'Wählen Sie Ihre Sprache'; $lang['i_installer'] = 'DokuWiki Installation'; $lang['i_wikiname'] = 'Wiki-Name'; $lang['i_enableacl'] = 'Zugangskontrolle (ACL) aktivieren (empfohlen)'; -$lang['i_superuser'] = 'Administrator Benutzername'; +$lang['i_superuser'] = 'Benutzername des Administrators'; $lang['i_problems'] = 'Das Installationsprogramm hat unten aufgeführte Probleme festgestellt, die zunächst behoben werden müssen bevor Sie mit der Installation fortfahren können.'; -$lang['i_modified'] = 'Aus Sicherheitsgründen arbeitet dieses Script nur mit einer neuen, unmodifizierten DokuWiki Installation. Sie sollten entweder alle Dateien noch einmal frisch installieren oder die Dokuwiki-Installationsanleitung konsultieren.'; +$lang['i_modified'] = 'Aus Sicherheitsgründen arbeitet dieses Skript nur mit einer neuen bzw. nicht modifizierten DokuWiki Installation. Sie sollten entweder alle Dateien noch einmal frisch installieren oder die Dokuwiki-Installationsanleitung konsultieren.'; $lang['i_funcna'] = 'Die PHP-Funktion %s ist nicht verfügbar. Unter Umständen wurde sie von Ihrem Hoster deaktiviert?'; $lang['i_phpver'] = 'Ihre PHP-Version %s ist niedriger als die benötigte Version %s. Bitte aktualisieren Sie Ihre PHP-Installation.'; $lang['i_permfail'] = '%s ist nicht durch DokuWiki beschreibbar. Sie müssen die Berechtigungen dieses Ordners ändern!'; @@ -290,11 +291,11 @@ $lang['i_writeerr'] = '%s konnte nicht erzeugt werden. S $lang['i_badhash'] = 'Unbekannte oder modifizierte dokuwiki.php (Hash=%s)'; $lang['i_badval'] = '%s - unerlaubter oder leerer Wert'; $lang['i_success'] = 'Die Konfiguration wurde erfolgreich abgeschlossen. Sie können jetzt die install.php löschen. Ihr neues DokuWiki ist jetzt für Sie bereit.'; -$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Sie müssen diese vermutlich von Hand beheben, bevor Sie Ihr neues DokuWiki nutzen können.'; -$lang['i_policy'] = 'Anfangseinstellung für Zugangskontrolle (ACL)'; -$lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben, hochladen für alle)'; -$lang['i_pol1'] = 'Öffentliches Wiki (lesen für alle, schreiben und hochladen für registrierte Nutzer)'; -$lang['i_pol2'] = 'Geschlossenes Wiki (lesen, schreiben, hochladen nur für registrierte Nutzer)'; +$lang['i_failure'] = 'Es sind Fehler beim Schreiben der Konfigurationsdateien aufgetreten. Sie müssen diese von Hand beheben, bevor Sie Ihr neues DokuWiki nutzen können.'; +$lang['i_policy'] = 'Anfangseinstellungen der Zugangskontrolle (ACL)'; +$lang['i_pol0'] = 'Offenes Wiki (lesen, schreiben und hochladen für alle Nutzer)'; +$lang['i_pol1'] = 'Öffentliches Wiki (Lesen für alle, Schreiben und Hochladen nur für registrierte Nutzer)'; +$lang['i_pol2'] = 'Geschlossenes Wiki (Lesen, Schreiben und Hochladen nur für registrierte Nutzer)'; $lang['i_retry'] = 'Wiederholen'; $lang['i_license'] = 'Bitte wählen Sie die Lizenz, unter die Sie Ihre Inhalte stellen möchten:'; $lang['recent_global'] = 'Im Moment sehen Sie die Änderungen im Namensraum %s. Sie können auch die Änderungen im gesamten Wiki sehen.'; @@ -318,8 +319,8 @@ $lang['media_sort_name'] = 'nach Name'; $lang['media_sort_date'] = 'nach Datum'; $lang['media_namespaces'] = 'Namensraum wählen'; $lang['media_files'] = 'Dateien in %s'; -$lang['media_upload'] = 'In den %s Namespace hochladen.'; -$lang['media_search'] = 'Im Namespace %s suchen.'; +$lang['media_upload'] = 'In den %s Namensraum hochladen.'; +$lang['media_search'] = 'Im Namensraum %s suchen.'; $lang['media_view'] = '%s'; $lang['media_viewold'] = '%s in %s'; $lang['media_edit'] = '%s bearbeiten'; -- cgit v1.2.3 From e93f702b5fe5b7ec5a39c1a080669c8a4eb7d965 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 16 Dec 2012 20:25:46 +0100 Subject: changed popularity link --- install.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.php b/install.php index 8f00d9746..f54c25207 100644 --- a/install.php +++ b/install.php @@ -228,7 +228,7 @@ function print_form($d){

-- cgit v1.2.3 From 6a34de2d02e41ec96359914a9b7fe0d1867bfef9 Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Wed, 19 Dec 2012 14:02:32 +0000 Subject: added to version info if version is unknown --- inc/infoutils.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inc/infoutils.php b/inc/infoutils.php index a9c33acfd..92607e4fa 100644 --- a/inc/infoutils.php +++ b/inc/infoutils.php @@ -77,7 +77,8 @@ function getVersionData(){ if($date) $version['date'] = $date; } }else{ - $version['date'] = 'unknown'; + global $updateVersion; + $version['date'] = 'update version '.$updateVersion; $version['type'] = 'snapshot?'; } return $version; -- cgit v1.2.3 From 27beeed6dddad3cd88bba7ba5ddba653ec86e0ff Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Wed, 19 Dec 2012 14:03:42 +0000 Subject: fixed broken @author link in farm code --- inc/farm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/farm.php b/inc/farm.php index af1035707..54fff3ec6 100644 --- a/inc/farm.php +++ b/inc/farm.php @@ -18,7 +18,7 @@ * @author Michael Klier * @author Christopher Smith * @author virtual host part of farm_confpath() based on conf_path() from Drupal.org's /includes/bootstrap.inc - * (see http://cvs.drupal.org/viewvc/drupal/drupal/includes/bootstrap.inc?view=markup) + * (see https://github.com/drupal/drupal/blob/7.x/includes/bootstrap.inc#L537) * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ -- cgit v1.2.3 From 3cf3c7d60c81d562c8331a377a76e86d41f8f528 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Thu, 20 Dec 2012 17:47:05 +0100 Subject: Add clear function to the indexer that deletes the whole index --- bin/indexer.php | 52 +--------------------------------------------------- inc/indexer.php | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 51 deletions(-) diff --git a/bin/indexer.php b/bin/indexer.php index f6aeb4f0e..78f470ae0 100755 --- a/bin/indexer.php +++ b/bin/indexer.php @@ -91,63 +91,13 @@ function _index($id){ _quietecho("done.\n"); } -/** - * lock the indexer system - */ -function _lock(){ - global $conf; - $lock = $conf['lockdir'].'/_indexer.lock'; - $said = false; - while(!@mkdir($lock, $conf['dmode'])){ - if(time()-@filemtime($lock) > 60*5){ - // looks like a stale lock - remove it - @rmdir($lock); - }else{ - if($said){ - _quietecho("."); - }else{ - _quietecho("Waiting for lockfile (max. 5 min)"); - $said = true; - } - sleep(15); - } - } - if($conf['dperm']) chmod($lock, $conf['dperm']); - if($said) _quietecho("\n"); -} - -/** - * unlock the indexer sytem - */ -function _unlock(){ - global $conf; - $lock = $conf['lockdir'].'/_indexer.lock'; - @rmdir($lock); -} - /** * Clear all index files */ function _clearindex(){ - global $conf; - _lock(); _quietecho("Clearing index... "); - io_saveFile($conf['indexdir'].'/page.idx',''); - io_saveFile($conf['indexdir'].'/title.idx',''); - io_saveFile($conf['indexdir'].'/pageword.idx',''); - io_saveFile($conf['indexdir'].'/metadata.idx',''); - $dir = @opendir($conf['indexdir']); - if($dir!==false){ - while(($f = readdir($dir)) !== false){ - if(substr($f,-4)=='.idx' && - (substr($f,0,1)=='i' || substr($f,0,1)=='w' - || substr($f,-6)=='_w.idx' || substr($f,-6)=='_i.idx' || substr($f,-6)=='_p.idx')) - @unlink($conf['indexdir']."/$f"); - } - } - @unlink($conf['indexdir'].'/lengths.idx'); + idx_get_indexer()->clear(); _quietecho("done.\n"); - _unlock(); } function _quietecho($msg) { diff --git a/inc/indexer.php b/inc/indexer.php index 4dfaa33fb..b9eaf31d9 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -401,6 +401,38 @@ class Doku_Indexer { return true; } + /** + * Clear the whole index + * + * @return bool If the index has been cleared successfully + */ + public function clear() { + global $conf; + + if (!$this->lock()) return false; + + @unlink($conf['indexdir'].'/page.idx'); + @unlink($conf['indexdir'].'/title.idx'); + @unlink($conf['indexdir'].'/pageword.idx'); + @unlink($conf['indexdir'].'/metadata.idx'); + $dir = @opendir($conf['indexdir']); + if($dir!==false){ + while(($f = readdir($dir)) !== false){ + if(substr($f,-4)=='.idx' && + (substr($f,0,1)=='i' || substr($f,0,1)=='w' + || substr($f,-6)=='_w.idx' || substr($f,-6)=='_i.idx' || substr($f,-6)=='_p.idx')) + @unlink($conf['indexdir']."/$f"); + } + } + @unlink($conf['indexdir'].'/lengths.idx'); + + // clear the pid cache + $this->pidCache = array(); + + $this->unlock(); + return true; + } + /** * Split the text into words for fulltext search * -- cgit v1.2.3 From 4f7083212993bf72f0b8969e6d57f587faaa5dfc Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Thu, 20 Dec 2012 17:47:39 +0100 Subject: Remove global $Indexer, clear index in the testing system instead --- _test/core/DokuWikiTest.php | 2 ++ inc/indexer.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/_test/core/DokuWikiTest.php b/_test/core/DokuWikiTest.php index b9e151456..91eb5293b 100644 --- a/_test/core/DokuWikiTest.php +++ b/_test/core/DokuWikiTest.php @@ -30,6 +30,8 @@ abstract class DokuWikiTest extends PHPUnit_Framework_TestCase { // remove any leftovers from the last run if(is_dir(DOKU_TMP_DATA)){ + // clear indexer data and cache + idx_get_indexer()->clear(); TestUtils::rdelete(DOKU_TMP_DATA); } diff --git a/inc/indexer.php b/inc/indexer.php index b9eaf31d9..7a62345bf 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -1228,7 +1228,7 @@ class Doku_Indexer { * @author Tom N Harris */ function idx_get_indexer() { - global $Indexer; + static $Indexer; if (!isset($Indexer)) { $Indexer = new Doku_Indexer(); } -- cgit v1.2.3 From bff17c53db3caca2e08837dc163e10a15f82860b Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Thu, 20 Dec 2012 17:49:19 +0100 Subject: Remove superfluous requires and variables from bin/indexer.php --- bin/indexer.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/bin/indexer.php b/bin/indexer.php index 78f470ae0..6f6b5d9fa 100755 --- a/bin/indexer.php +++ b/bin/indexer.php @@ -5,11 +5,6 @@ if ('cli' != php_sapi_name()) die(); ini_set('memory_limit','128M'); if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); require_once(DOKU_INC.'inc/init.php'); -require_once(DOKU_INC.'inc/common.php'); -require_once(DOKU_INC.'inc/pageutils.php'); -require_once(DOKU_INC.'inc/search.php'); -require_once(DOKU_INC.'inc/indexer.php'); -require_once(DOKU_INC.'inc/auth.php'); require_once(DOKU_INC.'inc/cliopts.php'); session_write_close(); @@ -67,10 +62,6 @@ function _usage() { function _update(){ global $conf; - global $INDEXER; - - $INDEXER = idx_get_indexer(); - $data = array(); _quietecho("Searching pages... "); search($data,$conf['datadir'],'search_allpages',array('skipacl' => true)); @@ -82,7 +73,6 @@ function _update(){ } function _index($id){ - global $INDEXER; global $CLEAR; global $QUIET; -- cgit v1.2.3 From def492a2d77af9effca204483b570061202cda5b Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Sun, 6 Jan 2013 10:18:17 +0100 Subject: Made auth_aclcheck always return int The returned type is important in particular when we deal with xmlrpc. Indeed, this value is directly returned to the client eg when the wiki.getAllPages method is queried. Currently the 'perms' attribute may be either an int or a string, and its up to the xmlrpc client to resolve it (although Dokuwiki's documentation only tells it can be an int). This patch makes sure we'll always return perms as int. --- inc/auth.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/auth.php b/inc/auth.php index 9c458338d..c68a699fe 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -580,7 +580,7 @@ function auth_aclcheck($id, $user, $groups) { } if($perm > -1) { //we had a match - return it - return $perm; + return (int) $perm; } } @@ -610,7 +610,7 @@ function auth_aclcheck($id, $user, $groups) { } //we had a match - return it if($perm != -1) { - return $perm; + return (int) $perm; } } //get next higher namespace -- cgit v1.2.3 From 7d1ae5e244b820e5c98558ef3bac0a764f63e692 Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Mon, 24 Dec 2012 23:47:46 +0100 Subject: Made xmlrpc putPage and appendPage consistent with documentation According to dokuwiki's documentation (https://www.dokuwiki.org/devel:xmlrpc#wikiputpage), those methods should return booleans, not int. --- inc/RemoteAPICore.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php index 36c518881..fbbb7b48b 100644 --- a/inc/RemoteAPICore.php +++ b/inc/RemoteAPICore.php @@ -440,7 +440,7 @@ class RemoteAPICore { // run the indexer if page wasn't indexed yet idx_addPage($id); - return 0; + return true; } /** -- cgit v1.2.3 From e47e9c10c754a8b04f2f5fb07877e55863ffdea5 Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Sun, 6 Jan 2013 11:36:45 +0100 Subject: Fixed declared returned type --- inc/RemoteAPICore.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php index fbbb7b48b..c04a14f5c 100644 --- a/inc/RemoteAPICore.php +++ b/inc/RemoteAPICore.php @@ -48,7 +48,7 @@ class RemoteAPICore { 'public' => '1' ), 'dokuwiki.appendPage' => array( 'args' => array('string', 'string', 'array'), - 'return' => 'int', + 'return' => 'bool', 'doc' => 'Append text to a wiki page.' ), 'wiki.getPage' => array( 'args' => array('string'), @@ -102,7 +102,7 @@ class RemoteAPICore { 'name' => 'pageVersions' ), 'wiki.putPage' => array( 'args' => array('string', 'string', 'array'), - 'return' => 'int', + 'return' => 'bool', 'doc' => 'Saves a wiki page.' ), 'wiki.listLinks' => array( 'args' => array('string'), -- cgit v1.2.3 From 71e90b1c66985b02b7df3387930a5fa007ca9755 Mon Sep 17 00:00:00 2001 From: Osama Al-Kofahi Date: Sun, 6 Jan 2013 15:53:07 +0100 Subject: Arabic language update --- inc/lang/ar/lang.php | 6 ++- inc/lang/ar/mailwrap.html | 13 +++++ lib/plugins/config/lang/ar/lang.php | 101 ++++++++++++++++++------------------ 3 files changed, 68 insertions(+), 52 deletions(-) create mode 100644 inc/lang/ar/mailwrap.html diff --git a/inc/lang/ar/lang.php b/inc/lang/ar/lang.php index 4ea8c6129..4928b3dbd 100644 --- a/inc/lang/ar/lang.php +++ b/inc/lang/ar/lang.php @@ -92,6 +92,7 @@ $lang['searchmedia_in'] = 'ابحث في %s'; $lang['txt_upload'] = 'اختر ملفاً للرفع'; $lang['txt_filename'] = 'رفع كـ (اختياري)'; $lang['txt_overwrt'] = 'اكتب على ملف موجود'; +$lang['maxuploadsize'] = 'الحجم الاقصى %s للملف'; $lang['lockedby'] = 'مقفلة حاليا لـ'; $lang['lockexpire'] = 'ينتهي القفل في'; $lang['js']['willexpire'] = 'سينتهي قفل تحرير هذه الصفحه خلال دقيقة.\nلتجنب التعارض استخدم زر المعاينة لتصفير مؤقت القفل.'; @@ -190,6 +191,7 @@ $lang['user_tools'] = 'أدوات المستخدم'; $lang['site_tools'] = 'أدوات الموقع'; $lang['page_tools'] = 'أدوات الصفحة'; $lang['skip_to_content'] = 'تجاوز إلى المحتوى'; +$lang['sidebar'] = 'العمود الجانبي'; $lang['mail_newpage'] = 'إضافة صفحة:'; $lang['mail_changed'] = 'تعديل صفحة:'; $lang['mail_subscribe_list'] = 'صفحات غيرت في النطاق:'; @@ -284,8 +286,8 @@ $lang['i_badhash'] = 'الملف dokuwiki.php غير مصنف أو (hash=%s)'; $lang['i_badval'] = 'القيمة %s غير شرعية أو فارغة'; $lang['i_success'] = 'الإعدادات تمت بنجاح، يرجى حذف الملف install.php الآن. -ثم تابع إلى دوكو ويكي الجديدة'; -$lang['i_failure'] = 'بعض الأخطاء حدثت أثنا كتابة ملفات الإعدادات، عليك تعديلها يدوياً قبل أن تستطيع استخدام دوكو ويكي الجديدة'; +ثم تابع إلى دوكو ويكي الجديدة'; +$lang['i_failure'] = 'بعض الأخطاء حدثت أثنا كتابة ملفات الإعدادات، عليك تعديلها يدوياً قبل أن تستطيع استخدام دوكو ويكي الجديدة'; $lang['i_policy'] = 'تصريح ACL مبدئي'; $lang['i_pol0'] = 'ويكي مفتوحة؛ أي القراءة والكتابة والتحميل مسموحة للجميع'; $lang['i_pol1'] = 'ويكي عامة؛ أي القراءة للجميع ولكن الكتابة والتحميل للمشتركين المسجلين فقط'; diff --git a/inc/lang/ar/mailwrap.html b/inc/lang/ar/mailwrap.html new file mode 100644 index 000000000..554e34510 --- /dev/null +++ b/inc/lang/ar/mailwrap.html @@ -0,0 +1,13 @@ + + +@TITLE@ + + + + +@HTMLBODY@ + +

+تم انشاء هذا البريد الالكتروني بواسطة DokuWiki في @DOKUWIKIURL@. + + \ No newline at end of file diff --git a/lib/plugins/config/lang/ar/lang.php b/lib/plugins/config/lang/ar/lang.php index 2e55446ec..76c155812 100644 --- a/lib/plugins/config/lang/ar/lang.php +++ b/lib/plugins/config/lang/ar/lang.php @@ -28,6 +28,7 @@ $lang['_anti_spam'] = 'اعدادات مضاد النفاية'; $lang['_editing'] = 'اعدادات التحرير'; $lang['_links'] = 'اعدادات الروابط'; $lang['_media'] = 'اعدادات الوسائط'; +$lang['_notifications'] = 'اعدادات التنبيه'; $lang['_advanced'] = 'اعدادات متقدمة'; $lang['_network'] = 'اعدادات الشبكة'; $lang['_plugin_sufix'] = 'اعدادات الملحقات'; @@ -35,29 +36,30 @@ $lang['_template_sufix'] = 'اعدادات القوالب'; $lang['_msg_setting_undefined'] = 'لا بيانات إعدادات.'; $lang['_msg_setting_no_class'] = 'لا صنف إعدادات.'; $lang['_msg_setting_no_default'] = 'لا قيمة افتراضية.'; -$lang['fmode'] = 'نمط انشاء الملفات'; -$lang['dmode'] = 'نمط انشاء المجلدات'; -$lang['lang'] = 'لغة الواجهة'; -$lang['basedir'] = 'مسار الخادوم (مثال. /dokuwiki/) اترك فارغا للاكتشاف التلقائي.'; -$lang['baseurl'] = 'عنوان الخادوم (مثال. http://www.yourserver.com). اترك فارغا للاكتشاف التلقائي.'; -$lang['savedir'] = 'دليل حفظ البيانات'; -$lang['cookiedir'] = 'مسار الكعكات. اترك فارغا لاستخدام baseurl.'; -$lang['start'] = 'اسم صفحة البداية'; $lang['title'] = 'عنوان الويكي'; +$lang['start'] = 'اسم صفحة البداية'; +$lang['lang'] = 'لغة الواجهة'; $lang['template'] = 'القالب'; $lang['tagline'] = 'Tagline (في حال دعم القالب له) '; $lang['sidebar'] = 'اسم صفحة الشريط الجانبي (في حال دعم القالب له). تركه فارغا يعطل الشريط الجانبي.'; $lang['license'] = 'تحت أي رخصة تريد اصدار المحتوى؟'; -$lang['fullpath'] = 'اظهر المحتوى الكامل للصفحات في '; +$lang['savedir'] = 'دليل حفظ البيانات'; +$lang['basedir'] = 'مسار الخادوم (مثال. /dokuwiki/) اترك فارغا للاكتشاف التلقائي.'; +$lang['baseurl'] = 'عنوان الخادوم (مثال. http://www.yourserver.com). اترك فارغا للاكتشاف التلقائي.'; +$lang['cookiedir'] = 'مسار الكعكات. اترك فارغا لاستخدام baseurl.'; +$lang['dmode'] = 'نمط انشاء المجلدات'; +$lang['fmode'] = 'نمط انشاء الملفات'; +$lang['allowdebug'] = 'مكّن التنقيح عطّلها إن لم تكن بحاجلة لها!'; $lang['recent'] = 'أحدث التغييرات'; +$lang['recent_days'] = 'مدة إبقاء أحدث التغييرات (ايام)'; $lang['breadcrumbs'] = 'عدد العناقيد للزيارات'; $lang['youarehere'] = 'عناقيد هرمية'; +$lang['fullpath'] = 'اظهر المحتوى الكامل للصفحات في '; $lang['typography'] = 'اعمل استبدالات طبوغرافية'; -$lang['htmlok'] = 'مكّن تضمين HTML'; -$lang['phpok'] = 'مكّن تضمين PHP'; $lang['dformat'] = 'تنسيق التاريخ (انظر وظيفة PHP,s strftime)'; $lang['signature'] = 'التوقيع'; +$lang['showuseras'] = 'الذي يعرض لاظهار المستخدم الذي قام بآخر تحرير لصفحة'; $lang['toptoclevel'] = 'المستوى الأعلى لمحتويات الجدول'; $lang['tocminheads'] = 'الحد الأدنى من الترويسات لبناء جدول المحتويات'; $lang['maxtoclevel'] = 'المستوى الأقصى لمحتويات الجدول'; @@ -65,16 +67,8 @@ $lang['maxseclevel'] = 'المستوى الأقصى لتحرير ال $lang['camelcase'] = 'استخدم CamelCase للروابط'; $lang['deaccent'] = 'نظّف اسماء الصفحات'; $lang['useheading'] = 'استخدم اول ترويسة كأسم للصفحة'; -$lang['refcheck'] = 'التحقق من مرجع الوسائط'; -$lang['refshow'] = 'عدد مراجع الوسائط لتعرض'; -$lang['allowdebug'] = 'مكّن التنقيح عطّلها إن لم تكن بحاجلة لها!'; -$lang['mediarevisions'] = 'تفعيل إصدارات الوسائط؟'; -$lang['usewordblock'] = 'احجز الغثاء بناء على قائمة كلمات'; -$lang['indexdelay'] = 'التأخير قبل الفهرسة (ثوان)'; -$lang['relnofollow'] = 'استخدم rel="nofollow" للروابط الخارجية'; -$lang['mailguard'] = 'عناوين بريدية مبهمة'; -$lang['iexssprotect'] = 'تحقق الملفات المرفوعة من احتمال وجود أكواد جافاسكربت أو HTML ضارة'; -$lang['showuseras'] = 'الذي يعرض لاظهار المستخدم الذي قام بآخر تحرير لصفحة'; +$lang['sneaky_index'] = 'افتراضيا، ستعرض دوكو ويكي كل اسماء النطاقات في عرض الفهرس. تفعيل هذا الخيار سيخفي مالا يملك المستخدم صلاحية قراءته. قد يؤدي هذا إلى اخفاء نطاقات فرعية متاحة. وقد يؤدي لجعل صفحة الفهرس معطلة في بعض اعدادات ACL.'; +$lang['hidepages'] = 'أخف الصفحات المنطبق عليها (تعابير شرطية)'; $lang['useacl'] = 'استخدم قائمة التحم بالوصول'; $lang['autopasswd'] = 'ولد كلمات سر تلقائيا'; $lang['authtype'] = 'آلية المواثقة'; @@ -83,61 +77,68 @@ $lang['defaultgroup'] = 'المجموعة الافتراضية'; $lang['superuser'] = 'مجموعة المستخدم المتفوق أو مستخدم أو قائمة مفصولة بالفاصلة مستخدم1،@مجموعة، مستخدم2 صلاحيتهم الوصول الكامل لكل الصفحات و الوظائف بغض النظر عن اعدادات ACL'; $lang['manager'] = 'مجموعة المدراء أو مستخدم أو قائمة مفصولة بالفاصلة مستخدم1،@مجموعة، مستخدم2 صلاحيتهم بعض الوظائف الادارية'; $lang['profileconfirm'] = 'اكد تغيير اللاحة بكلمة المرور'; +$lang['rememberme'] = 'اسمح بكعكات الدخول الدائم (تذكرني)'; $lang['disableactions'] = 'عطّل اجراءات دوكو ويكي'; $lang['disableactions_check'] = 'تحقق'; $lang['disableactions_subscription'] = 'اشترك/الغ الاشتراك'; $lang['disableactions_wikicode'] = 'اعرض المصدر/صدّر صرفا'; $lang['disableactions_other'] = 'اجراءات أخرى (مفصولة بالفاصلة)'; -$lang['sneaky_index'] = 'افتراضيا، ستعرض دوكو ويكي كل اسماء النطاقات في عرض الفهرس. تفعيل هذا الخيار سيخفي مالا يملك المستخدم صلاحية قراءته. قد يؤدي هذا إلى اخفاء نطاقات فرعية متاحة. وقد يؤدي لجعل صفحة الفهرس معطلة في بعض اعدادات ACL.'; $lang['auth_security_timeout'] = 'زمن انتهاء أمان المواثقة (ثوان)'; $lang['securecookie'] = 'هل يفرض على كعكات التصفح المعدة عبر HTTPS ان ترسل فقط عبر HTTPS من قبل المتصفح؟ عطل هذا إن كان الولوج للويكي مؤمنا فقط عبر SSL لكن تصفح الويكي غير مؤمن.'; $lang['remote'] = 'مكّن نظام API البعيد. يسمح هذا لبرامج أخرى بالوصول للويكي عبر XML-RPC أو آليات أخرى.'; $lang['remoteuser'] = 'احصر الوصول البعيد ل API لمستخدمين ومجموعات يفصل بينها بالفاصلة هنا. اترك فارغا لتمكين الجميع.'; +$lang['usewordblock'] = 'احجز الغثاء بناء على قائمة كلمات'; +$lang['relnofollow'] = 'استخدم rel="nofollow" للروابط الخارجية'; +$lang['indexdelay'] = 'التأخير قبل الفهرسة (ثوان)'; +$lang['mailguard'] = 'عناوين بريدية مبهمة'; +$lang['iexssprotect'] = 'تحقق الملفات المرفوعة من احتمال وجود أكواد جافاسكربت أو HTML ضارة'; +$lang['usedraft'] = 'احفظ المسودة تلقائيا أثناء التحرير'; +$lang['htmlok'] = 'مكّن تضمين HTML'; +$lang['phpok'] = 'مكّن تضمين PHP'; +$lang['locktime'] = 'الحد الأعظمي لقفل الملف (ثوان)'; +$lang['cachetime'] = 'الحد الأعظم لعمر المخُبأ (ثوان)'; +$lang['target____wiki'] = 'النافذة الهدف للروابط الداخلية'; +$lang['target____interwiki'] = 'النافذة الهدف للروابط الممرة interwiki'; +$lang['target____extern'] = 'النافذة الهدف للروابط الخارجية'; +$lang['target____media'] = 'النافذة الهدف لروابط الوسائط'; +$lang['target____windows'] = 'النافذة الهدف لروابط النوافذ'; +$lang['mediarevisions'] = 'تفعيل إصدارات الوسائط؟'; +$lang['refcheck'] = 'التحقق من مرجع الوسائط'; +$lang['refshow'] = 'عدد مراجع الوسائط لتعرض'; +$lang['gdlib'] = 'اصدار مكتبة GD'; +$lang['im_convert'] = 'المسار إلى اداة تحويل ImageMagick'; +$lang['jpg_quality'] = 'دقة ضغط JPG (0-100)'; +$lang['fetchsize'] = 'الحجم الأعظمي (بايت) ل fetch.php لتنزيله من الخارج'; +$lang['subscribers'] = 'مكن دعم اشتراك الصفحة'; +$lang['subscribe_time'] = 'المهلة بعد ارسال قوائم الاشتراكات والملخصات (ثوان); هذا يجب أن يكون أقل من الوقت المخصص في أيام أحدث التغييرات.'; +$lang['notify'] = 'ارسل تنبيهات التغيير لهذا البريد'; +$lang['registernotify'] = 'ارسل بيانات عن المستخدمين المسجلين جديدا لهذا البريد'; +$lang['mailfrom'] = 'البريد الالكتروني ليستخدم للرسائل الآلية'; +$lang['mailprefix'] = 'بادئة موضوع البريد لتستخدم مع الرسائل الآلية'; +$lang['sitemap'] = 'ولد خرائط موقع جوجل (أيام)'; +$lang['rss_type'] = 'نوع تلقيمات XML'; +$lang['rss_linkto'] = 'تلقيمات XML توصل إلى'; +$lang['rss_content'] = 'مالذي يعرض في عناصر تلقيمات XML؟'; +$lang['rss_update'] = 'تحديث تلقيم XML (ثوان)'; +$lang['rss_show_summary'] = 'تلقيم XML يظهر ملخصا في العنوان'; +$lang['rss_media'] = 'مانوع التغييرات التي ستدرج في تغذية XML؟'; $lang['updatecheck'] = 'تحقق من التحديثات و تنبيهات الأمان؟ دوكو ويكي ستحتاج للاتصال ب update.dokuwiki.org لأجل ذلك'; $lang['userewrite'] = 'استعمل عناوين URLs جميلة'; $lang['useslash'] = 'استخدم الشرطة كفاصل النطاق في العناوين'; -$lang['usedraft'] = 'احفظ المسودة تلقائيا أثناء التحرير'; $lang['sepchar'] = 'فاصل كلمة اسم الصفحة'; $lang['canonical'] = 'استخدم العناوين الشائعة كاملة'; $lang['fnencode'] = 'نظام ترميز اسماء الملفات بغير الأسكي.'; $lang['autoplural'] = 'تحقق من صيغ الجمع في الروابط'; $lang['compression'] = 'طريقة الغضط لملفات attic'; -$lang['cachetime'] = 'الحد الأعظم لعمر المخُبأ (ثوان)'; -$lang['locktime'] = 'الحد الأعظمي لقفل الملف (ثوان)'; -$lang['fetchsize'] = 'الحجم الأعظمي (بايت) ل fetch.php لتنزيله من الخارج'; -$lang['notify'] = 'ارسل تنبيهات التغيير لهذا البريد'; -$lang['registernotify'] = 'ارسل بيانات عن المستخدمين المسجلين جديدا لهذا البريد'; -$lang['mailfrom'] = 'البريد الالكتروني ليستخدم للرسائل الآلية'; -$lang['mailprefix'] = 'بادئة موضوع البريد لتستخدم مع الرسائل الآلية'; $lang['gzip_output'] = 'استخدم ترميز-محتوى gzip ل xhtml'; -$lang['gdlib'] = 'اصدار مكتبة GD'; -$lang['im_convert'] = 'المسار إلى اداة تحويل ImageMagick'; -$lang['jpg_quality'] = 'دقة ضغط JPG (0-100)'; -$lang['subscribers'] = 'مكن دعم اشتراك الصفحة'; -$lang['subscribe_time'] = 'المهلة بعد ارسال قوائم الاشتراكات والملخصات (ثوان); هذا يجب أن يكون أقل من الوقت المخصص في أيام أحدث التغييرات.'; $lang['compress'] = 'رُص مخرجات CSS و جافا سكربت'; $lang['cssdatauri'] = 'الحجم بالبايتات للصور المذكورة في CSS التي ستُضمن في صفحة-التنسيق لخفض طلبات HTTP. لن تعمل هذه التقنية في IE 7 أو أقل! 400 إلى 600 بايت تعد قيمة جيدة. اضبط إلى 0 لتعطلها.'; -$lang['hidepages'] = 'أخف الصفحات المنطبق عليها (تعابير شرطية)'; $lang['send404'] = 'ارسل "HTTP 404/Page Not Found" للصفحات غير الموجودة'; -$lang['sitemap'] = 'ولد خرائط موقع جوجل (أيام)'; $lang['broken_iua'] = 'هل الوظيفة ignore_user_abort معطلة على جهازك؟ قد يؤدي ذلك لتعطيل فهرسة البحث. IIS+PHP/CGI تعرف بأنها لاتعمل. أنظر العلة 852 لمزيد من المعلومات.'; $lang['xsendfile'] = 'استخدم ترويسة X-Sendfile لتمكين خادم الوب من تقديم ملفات ثابتة؟ يجب أن يكون خادم الوب داعما له.'; $lang['renderer_xhtml'] = 'المحرك ليستخدم لمخرجات الويكي الأساسية وفق (xhtml).'; $lang['renderer__core'] = '%s (نواة دوكو ويكي)'; $lang['renderer__plugin'] = '%s (ملحق)'; -$lang['rememberme'] = 'اسمح بكعكات الدخول الدائم (تذكرني)'; -$lang['rss_type'] = 'نوع تلقيمات XML'; -$lang['rss_linkto'] = 'تلقيمات XML توصل إلى'; -$lang['rss_content'] = 'مالذي يعرض في عناصر تلقيمات XML؟'; -$lang['rss_update'] = 'تحديث تلقيم XML (ثوان)'; -$lang['recent_days'] = 'مدة إبقاء أحدث التغييرات (ايام)'; -$lang['rss_show_summary'] = 'تلقيم XML يظهر ملخصا في العنوان'; -$lang['rss_media'] = 'مانوع التغييرات التي ستدرج في تغذية XML؟'; -$lang['target____wiki'] = 'النافذة الهدف للروابط الداخلية'; -$lang['target____interwiki'] = 'النافذة الهدف للروابط الممرة interwiki'; -$lang['target____extern'] = 'النافذة الهدف للروابط الخارجية'; -$lang['target____media'] = 'النافذة الهدف لروابط الوسائط'; -$lang['target____windows'] = 'النافذة الهدف لروابط النوافذ'; $lang['proxy____host'] = 'اسم خادوم الوكيل'; $lang['proxy____port'] = 'منفذ الوكيل'; $lang['proxy____user'] = 'اسم مستخدم الوكيل'; -- cgit v1.2.3 From 629196125e06679f0f7111b6b4ce740d28db8a99 Mon Sep 17 00:00:00 2001 From: Dominik Eckelmann Date: Tue, 8 Jan 2013 09:38:39 +0100 Subject: allow template unit tests --- _test/phpunit.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_test/phpunit.xml b/_test/phpunit.xml index 13676f207..fc7dd8be0 100644 --- a/_test/phpunit.xml +++ b/_test/phpunit.xml @@ -10,6 +10,9 @@ ../lib/plugins/*/_test + + ../lib/tpl/*/_test + @@ -19,6 +22,7 @@ ../_cs/ ../_test/ ../lib/plugins/*/_test/ + ../lib/tpl/*/_test/ -- cgit v1.2.3 From 7eaa7703a43b9f22f12be04e8580a3f2515fb146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=97=A5=E5=90=91=E5=B0=8F=E9=83=8E?= Date: Wed, 9 Jan 2013 20:30:03 +0100 Subject: Traditional Chinese language update --- inc/lang/zh-tw/adminplugins.txt | 2 +- inc/lang/zh-tw/backlinks.txt | 2 +- inc/lang/zh-tw/diff.txt | 2 +- inc/lang/zh-tw/edit.txt | 2 +- inc/lang/zh-tw/editrev.txt | 2 +- inc/lang/zh-tw/index.txt | 2 +- inc/lang/zh-tw/install.html | 6 +- inc/lang/zh-tw/lang.php | 101 ++++++++++++------------ inc/lang/zh-tw/locked.txt | 2 +- inc/lang/zh-tw/login.txt | 3 +- inc/lang/zh-tw/mailtext.txt | 2 +- inc/lang/zh-tw/norev.txt | 2 +- inc/lang/zh-tw/preview.txt | 2 +- inc/lang/zh-tw/pwconfirm.txt | 8 +- inc/lang/zh-tw/read.txt | 2 +- inc/lang/zh-tw/register.txt | 3 +- inc/lang/zh-tw/registermail.txt | 4 +- inc/lang/zh-tw/resendpwd.txt | 2 +- inc/lang/zh-tw/revisions.txt | 2 +- inc/lang/zh-tw/stopwords.txt | 10 +-- inc/lang/zh-tw/subscr_digest.txt | 6 +- inc/lang/zh-tw/subscr_form.txt | 2 +- inc/lang/zh-tw/subscr_list.txt | 6 +- inc/lang/zh-tw/subscr_single.txt | 6 +- inc/lang/zh-tw/updateprofile.txt | 2 +- inc/lang/zh-tw/uploadmail.txt | 4 +- lib/plugins/acl/lang/zh-tw/help.txt | 8 +- lib/plugins/acl/lang/zh-tw/lang.php | 21 ++--- lib/plugins/config/lang/zh-tw/intro.txt | 6 +- lib/plugins/config/lang/zh-tw/lang.php | 56 +++++++------ lib/plugins/plugin/lang/zh-tw/admin_plugin.txt | 4 +- lib/plugins/plugin/lang/zh-tw/lang.php | 55 ++++++------- lib/plugins/popularity/lang/zh-tw/intro.txt | 9 +-- lib/plugins/popularity/lang/zh-tw/lang.php | 9 ++- lib/plugins/popularity/lang/zh-tw/submitted.txt | 2 +- lib/plugins/revert/lang/zh-tw/intro.txt | 2 +- lib/plugins/revert/lang/zh-tw/lang.php | 5 +- lib/plugins/usermanager/lang/zh-tw/lang.php | 17 ++-- 38 files changed, 197 insertions(+), 184 deletions(-) diff --git a/inc/lang/zh-tw/adminplugins.txt b/inc/lang/zh-tw/adminplugins.txt index fb1999269..6d21ac2cd 100644 --- a/inc/lang/zh-tw/adminplugins.txt +++ b/inc/lang/zh-tw/adminplugins.txt @@ -1 +1 @@ -===== 外加插件 ===== \ No newline at end of file +===== 附加元件 ===== \ No newline at end of file diff --git a/inc/lang/zh-tw/backlinks.txt b/inc/lang/zh-tw/backlinks.txt index 5b36728e7..6a8bf8896 100644 --- a/inc/lang/zh-tw/backlinks.txt +++ b/inc/lang/zh-tw/backlinks.txt @@ -1,4 +1,4 @@ ====== 反向連結 ====== -這裡是引用、連結到目前頁面的頁面清單。 +這是引用、連結到目前頁面的頁面清單。 diff --git a/inc/lang/zh-tw/diff.txt b/inc/lang/zh-tw/diff.txt index 17fad7ba0..e2c05001f 100644 --- a/inc/lang/zh-tw/diff.txt +++ b/inc/lang/zh-tw/diff.txt @@ -1,3 +1,3 @@ ====== 差異處 ====== -這裏顯示二個版本的差異處。 \ No newline at end of file +這裏顯示兩個版本的差異處。 \ No newline at end of file diff --git a/inc/lang/zh-tw/edit.txt b/inc/lang/zh-tw/edit.txt index bbe5bb8ed..f6b74794f 100644 --- a/inc/lang/zh-tw/edit.txt +++ b/inc/lang/zh-tw/edit.txt @@ -1 +1 @@ -編輯本頁並按下''儲存''即可。可在[[wiki:syntax|維基語法]]找到語法說明。請只在能讓本文品質「**更好**」時才編輯。如果只是要測試,請使用 [[playground:playground|遊樂場]]。 +編輯本頁後,請按下「儲存」按鈕。若要參看語法說明,請到[[wiki:syntax|語法]]頁。請只在能讓本文品質**更好**時才編輯。如果只是要測試,請移玉步至 [[playground:playground|遊樂場]]。 \ No newline at end of file diff --git a/inc/lang/zh-tw/editrev.txt b/inc/lang/zh-tw/editrev.txt index 96f9a7c6a..98a800ab1 100644 --- a/inc/lang/zh-tw/editrev.txt +++ b/inc/lang/zh-tw/editrev.txt @@ -1,2 +1,2 @@ -**您目前載入的是本份文件的舊版!** 您如果存檔,這些資料就會被存成另一份。 +**您目前載入的是本份文件的舊版!** 您如果存檔,這些舊版資料就會變成最新版本。 ---- diff --git a/inc/lang/zh-tw/index.txt b/inc/lang/zh-tw/index.txt index bba277041..1b89e0c5d 100644 --- a/inc/lang/zh-tw/index.txt +++ b/inc/lang/zh-tw/index.txt @@ -1,3 +1,3 @@ ====== 站台地圖 ====== -這個站台地圖列出了所有允許的頁面,依 [[doku>namespaces|分類空間]] 排序。 \ No newline at end of file +這個站台地圖列出了所有允許的頁面,依 [[doku>namespaces|分類名稱]] 排序。 \ No newline at end of file diff --git a/inc/lang/zh-tw/install.html b/inc/lang/zh-tw/install.html index 2a8b1aac3..9a0d1dcd9 100644 --- a/inc/lang/zh-tw/install.html +++ b/inc/lang/zh-tw/install.html @@ -1,8 +1,8 @@

本頁面旨在幫助您完成第一次安装和設定 Dokuwiki。關於安裝工具的更多訊息請參閱 官方文檔頁面

-

DokuWiki 使用普通檔案儲存維基頁面以及與頁面相關的訊息(例如:圖像,搜尋索引,修訂記錄等)。為了正常運作,DokuWiki 必須 擁有針對那些路徑和檔案的寫入權限。本安裝工具無法設定目錄權限,這通常要透過命令行、FTP 或您主機上的控制台(如cPanel)進行。

+

DokuWiki 使用普通檔案來儲存 wiki 頁面,以及與頁面相關的訊息(例如:圖像、搜尋索引、修訂記錄等)。為了正常運作,DokuWiki 必須 擁有針對那些路徑和檔案的寫入權限。本安裝工具無法設定目錄權限,這通常要透過命令行、FTP 或您主機上的控制台(如cPanel)進行。

-

本安裝工具將設定您的 DokuWiki 用於 ACL 的設定檔,它能讓管理員登入並使用「管理」功能來安裝插件、管理用户、管理訪問權限和其他設定設定。它並不是 DokuWiki 正常運作所必須,但安裝之後將更方便管理。

+

本安裝工具將設定您的 DokuWiki 用於 ACL 的設定檔,它能讓管理員登入並使用「管理」功能來安裝附加元件、管理使用者、管理訪問權限和其他設定設定。它並不是 DokuWiki 正常運作所必須,但安裝之後將更方便管理。

-

有經驗的用戶或有特殊需求的用戶請參閱更詳細的 安裝指南 +

有經驗的或有特殊需求的使用者,請參閱更詳細的 安裝指南設定

\ No newline at end of file diff --git a/inc/lang/zh-tw/lang.php b/inc/lang/zh-tw/lang.php index 9f380acb5..ddb35617e 100644 --- a/inc/lang/zh-tw/lang.php +++ b/inc/lang/zh-tw/lang.php @@ -11,6 +11,7 @@ * @author Danny Lin * @author Shuo-Ting Jian * @author syaoranhinata@gmail.com + * @author Ichirou Uchiki */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -19,7 +20,7 @@ $lang['doublequoteclosing'] = '”'; $lang['singlequoteopening'] = '‘'; $lang['singlequoteclosing'] = '’'; $lang['apostrophe'] = '’'; -$lang['btn_edit'] = '編修本頁'; +$lang['btn_edit'] = '編輯本頁'; $lang['btn_source'] = '顯示原始碼'; $lang['btn_show'] = '顯示頁面'; $lang['btn_create'] = '建立此頁'; @@ -34,7 +35,7 @@ $lang['btn_recent'] = '最近更新'; $lang['btn_upload'] = '上傳'; $lang['btn_cancel'] = '取消'; $lang['btn_index'] = '站台地圖'; -$lang['btn_secedit'] = '改這段'; +$lang['btn_secedit'] = '編輯此段'; $lang['btn_login'] = '登入'; $lang['btn_logout'] = '登出'; $lang['btn_admin'] = '管理選單'; @@ -61,40 +62,40 @@ $lang['newpass'] = '新密碼'; $lang['oldpass'] = '目前密碼'; $lang['passchk'] = '確認密碼'; $lang['remember'] = '記住帳號密碼'; -$lang['fullname'] = '真實姓名'; +$lang['fullname'] = '姓名'; $lang['email'] = '電郵'; $lang['profile'] = '使用者個人資料'; $lang['badlogin'] = '很抱歉,您的使用者名稱或密碼可能有錯誤。'; $lang['minoredit'] = '小修改'; $lang['draftdate'] = '草稿已自動存檔於'; -$lang['nosecedit'] = '頁面在這之間已被修改,過時的區段資料已載入全頁取代。'; +$lang['nosecedit'] = '在您編輯期間,其他使用者修改過本頁面。區段資料已逾時,因此系統載入了全頁,以取代之。'; $lang['regmissing'] = '很抱歉,所有欄位都要填寫。'; -$lang['reguexists'] = '很抱歉,本帳號已被註冊。'; -$lang['regsuccess'] = '使用者已建立,密碼已寄發至該 email。'; -$lang['regsuccess2'] = '使用者已建立。'; +$lang['reguexists'] = '很抱歉,有人已使用了這個帳號。'; +$lang['regsuccess'] = '使用者帳號已建立,密碼已寄發至該電郵。'; +$lang['regsuccess2'] = '使用者帳號已建立。'; $lang['regmailfail'] = '寄出密碼信似乎發生錯誤,請跟管理員聯絡!'; -$lang['regbadmail'] = '您輸入的 email 似乎不對,如果您認為是正確的,請與管理員聯絡。'; +$lang['regbadmail'] = '您輸入的電郵似乎不對,如果您認為是正確的,請與管理員聯絡。'; $lang['regbadpass'] = '兩次輸入的密碼不一致,請再試一次。'; $lang['regpwmail'] = '您的 DokuWiki 帳號密碼'; $lang['reghere'] = '您還沒有帳號嗎?註冊一個吧。'; -$lang['profna'] = '本維基不開放修改個人資料。'; -$lang['profnochange'] = '未做任何變更。'; +$lang['profna'] = '在本 wiki 上,不能修改個人資料。'; +$lang['profnochange'] = '並未作任何變更。'; $lang['profnoempty'] = '帳號或電郵地址不可空白!'; -$lang['profchanged'] = '個人資料已成功更新。'; +$lang['profchanged'] = '個人資料已更新。'; $lang['pwdforget'] = '忘記密碼了?索取新密碼!'; -$lang['resendna'] = '本維基不開放重寄密碼。'; +$lang['resendna'] = '本 wiki 並不支援重寄密碼。'; $lang['resendpwd'] = '設定新密碼供'; $lang['resendpwdmissing'] = '抱歉,您必須填寫所有欄位。'; $lang['resendpwdnouser'] = '抱歉,資料庫內找不到這個使用者。'; $lang['resendpwdbadauth'] = '抱歉,認證碼無效。請確認您使用了完整的確認連結。'; $lang['resendpwdconfirm'] = '確認連結已通過郵件發送給您了。'; $lang['resendpwdsuccess'] = '您的新密碼已寄出。'; -$lang['license'] = '若未特別註明,此維基上的內容都是採用以下授權方式:'; +$lang['license'] = '若無特別註明,本 wiki 上的內容都是採用以下授權方式:'; $lang['licenseok'] = '注意:編輯此頁面表示您已同意以下的授權方式:'; $lang['searchmedia'] = '搜尋檔名:'; $lang['searchmedia_in'] = '在 %s 裏搜尋'; $lang['txt_upload'] = '請選擇要上傳的檔案'; -$lang['txt_filename'] = '請輸入要存在維基內的檔案名稱 (非必要)'; +$lang['txt_filename'] = '請輸入要上傳至本 wiki 的檔案名稱 (非必要)'; $lang['txt_overwrt'] = '是否要覆蓋原有檔案'; $lang['maxuploadsize'] = '每個上傳檔案不可大於 %s 。'; $lang['lockedby'] = '目前已被下列人員鎖定'; @@ -135,7 +136,7 @@ $lang['js']['media_diff'] = '檢視差異:'; $lang['js']['media_diff_both'] = '並排'; $lang['js']['media_diff_opacity'] = '重疊'; $lang['js']['media_diff_portions'] = '滑動'; -$lang['js']['media_select'] = '選擇檔案…'; +$lang['js']['media_select'] = '選擇檔案……'; $lang['js']['media_upload_btn'] = '上傳'; $lang['js']['media_done_btn'] = '完成'; $lang['js']['media_drop'] = '拖拉檔案到此上傳'; @@ -145,27 +146,27 @@ $lang['rssfailed'] = '擷取 RSS 饋送檔時發生錯誤:'; $lang['nothingfound'] = '沒找到任何結果。'; $lang['mediaselect'] = '媒體檔案'; $lang['fileupload'] = '上傳媒體檔案'; -$lang['uploadsucc'] = '上傳成功'; -$lang['uploadfail'] = '上傳失敗。似乎是權限錯誤?'; +$lang['uploadsucc'] = '已上傳'; +$lang['uploadfail'] = '無法上傳。是否因權限錯誤?'; $lang['uploadwrong'] = '拒絕上傳。這個副檔名被禁止了!'; $lang['uploadexist'] = '檔案已存在,未處理。'; $lang['uploadbadcontent'] = '上傳檔案的內容不符合 %s 檔的副檔名。'; -$lang['uploadspam'] = '這次的上傳被垃圾訊息黑名單阻檔了。'; -$lang['uploadxss'] = '這次的上傳因可能的惡意的內容而被阻檔。'; -$lang['uploadsize'] = '上傳的檔案太大了 (最大:%s)'; +$lang['uploadspam'] = '是次上傳被垃圾訊息黑名單阻檔了。'; +$lang['uploadxss'] = '因可能含有惡意內容,是次上傳已被阻檔。'; +$lang['uploadsize'] = '上傳的檔案太大了 (最大為:%s)'; $lang['deletesucc'] = '檔案 "%s" 已刪除。'; $lang['deletefail'] = '檔案 "%s" 無法刪除,請檢查權限定。'; -$lang['mediainuse'] = '檔案 "%s" 未刪除,因為它正被使用。'; -$lang['namespaces'] = '分類空間'; +$lang['mediainuse'] = '檔案 "%s" 仍在使用,並未刪除。'; +$lang['namespaces'] = '分類名稱'; $lang['mediafiles'] = '可用的檔案有'; $lang['accessdenied'] = '您不可以檢視此頁面。'; $lang['mediausage'] = '使用以下的語法來連結此檔案:'; $lang['mediaview'] = '檢視原始檔案'; $lang['mediaroot'] = 'root'; -$lang['mediaupload'] = '上傳檔案至目前的分類空間。要建立子分類空間,將其名稱加在「上傳並重命名為」檔案名的前面,並用英文冒號隔開。'; +$lang['mediaupload'] = '上傳檔案至目前分類名稱之下。要建立子分類名稱,請將其名稱加在「上傳並重命名為」檔案名的前面,並用英文冒號隔開。'; $lang['mediaextchange'] = '檔案類型已由 .%s 變更為 .%s !'; $lang['reference'] = '引用到本頁的,合計有'; -$lang['ref_inuse'] = '此檔案無法刪除,因為它正被以下頁面使用:'; +$lang['ref_inuse'] = '此檔案無法刪除,因以下頁面正在使用它:'; $lang['ref_hidden'] = '一些參考內容位於您沒有讀取權限的頁面中'; $lang['hits'] = '個符合'; $lang['quickhits'] = '符合的頁面名稱'; @@ -175,12 +176,12 @@ $lang['yours'] = '您的版本'; $lang['diff'] = '顯示與目前版本的差異'; $lang['diff2'] = '顯示選擇版本間的差異'; $lang['difflink'] = '連向這個比對檢視'; -$lang['diff_type'] = '檢視差異:'; +$lang['diff_type'] = '檢視差異:'; $lang['diff_inline'] = '行內'; $lang['diff_side'] = '並排'; $lang['line'] = '行'; $lang['breadcrumb'] = '足跡'; -$lang['youarehere'] = '您在這裡'; +$lang['youarehere'] = '您在這裏'; $lang['lastmod'] = '上一次變更'; $lang['by'] = '由'; $lang['deleted'] = '移除'; @@ -188,17 +189,17 @@ $lang['created'] = '建立'; $lang['restored'] = '恢復為舊版'; $lang['external_edit'] = '外部編輯'; $lang['summary'] = '編輯摘要'; -$lang['noflash'] = '顯示此內容需要 Adobe Flash Plugin'; +$lang['noflash'] = '顯示此內容需要 Adobe Flash 附加元件。'; $lang['download'] = '下載程式碼片段'; $lang['tools'] = '工具'; -$lang['user_tools'] = '用戶工具'; +$lang['user_tools'] = '使用者工具'; $lang['site_tools'] = '網站工具'; $lang['page_tools'] = '頁面工具'; $lang['skip_to_content'] = '跳至內容'; $lang['sidebar'] = '側欄'; $lang['mail_newpage'] = '增加的頁面:'; $lang['mail_changed'] = '變更的頁面:'; -$lang['mail_subscribe_list'] = '分類空間中更動的頁面:'; +$lang['mail_subscribe_list'] = '分類名稱中變更的頁面:'; $lang['mail_new_user'] = '新使用者:'; $lang['mail_upload'] = '已上傳檔案:'; $lang['changes_type'] = '檢視最近更新類型'; @@ -229,10 +230,10 @@ $lang['qb_media'] = '加入圖片或檔案'; $lang['qb_sig'] = '插入簽名'; $lang['qb_smileys'] = '表情符號'; $lang['qb_chars'] = '特殊字元'; -$lang['upperns'] = '前往父分類空間'; +$lang['upperns'] = '前往父分類名稱'; $lang['admin_register'] = '新增使用者'; $lang['metaedit'] = '編輯後設資料'; -$lang['metasaveerr'] = '後設資料寫入失敗'; +$lang['metasaveerr'] = '後設資料無法寫入'; $lang['metasaveok'] = '後設資料已儲存'; $lang['img_backto'] = '回上一頁'; $lang['img_title'] = '標題'; @@ -253,9 +254,9 @@ $lang['subscr_subscribe_error'] = '將 %s 加入至 %s 的訂閱列表時發生 $lang['subscr_subscribe_noaddress'] = '沒有與您登入相關的地址,無法將您加入訂閱列表'; $lang['subscr_unsubscribe_success'] = '已將 %s 移除自 %s 的訂閱列表'; $lang['subscr_unsubscribe_error'] = '將 %s 移除自 %s 的訂閱列表時發生錯誤'; -$lang['subscr_already_subscribed'] = '%s 已經被 %s 訂閱了'; -$lang['subscr_not_subscribed'] = '%s 尚未被 %s 訂閱'; -$lang['subscr_m_not_subscribed'] = '您尚未訂閱目前的頁面或分類空間。'; +$lang['subscr_already_subscribed'] = '%s 已經獲 %s 訂閱了'; +$lang['subscr_not_subscribed'] = '%s 尚未獲 %s 訂閱'; +$lang['subscr_m_not_subscribed'] = '您尚未訂閱目前的頁面或分類名稱。'; $lang['subscr_m_new_header'] = '加入訂閱'; $lang['subscr_m_current_header'] = '目前訂閱'; $lang['subscr_m_unsubscribe'] = '取消訂閱'; @@ -264,34 +265,34 @@ $lang['subscr_m_receive'] = '接收'; $lang['subscr_style_every'] = '每次更改都發送信件'; $lang['subscr_style_digest'] = '對每個頁面發送更改的摘要信件 (每 %.2f 天)'; $lang['subscr_style_list'] = '自上次發信以來更改的頁面的列表 (每 %.2f 天)'; -$lang['authmodfailed'] = '帳號認證的設定不正確,請通知該維基管理員。'; -$lang['authtempfail'] = '帳號認證目前暫不提供,若本狀況持續發生的話,請通知該維基管理員。'; +$lang['authmodfailed'] = '帳號認證的設定不正確,請通知該本 wiki 管理員。'; +$lang['authtempfail'] = '帳號認證目前暫不提供。若本狀況持續,請通知本 wiki 管理員。'; $lang['authpwdexpire'] = '您的密碼將在 %d 天內到期,請馬上更換新密碼。'; $lang['i_chooselang'] = '選擇您的語系'; $lang['i_installer'] = 'DokuWiki 安裝工具'; -$lang['i_wikiname'] = '維基名稱'; +$lang['i_wikiname'] = '本 wiki 的名稱'; $lang['i_enableacl'] = '啟用 ACL (建議)'; -$lang['i_superuser'] = '超級用戶'; +$lang['i_superuser'] = '超級使用者'; $lang['i_problems'] = '安裝程式發現如下的問題。您必須修正它們才能繼續。'; $lang['i_modified'] = '出於安全考量,本腳本只能用於安裝全新且未修改的 Dokuwiki。 您可以重新解壓下載的封包或查閱完整的Dokuwiki 安裝指南'; $lang['i_funcna'] = 'PHP 函數 %s 無法使用。也許您的主機供應者基於某些理由停用了它?'; $lang['i_phpver'] = '您的 PHP 版本 %s 比需要的版本 %s 還低。您必須更新您的PHP。'; -$lang['i_permfail'] = '%s 無法被 DokuWiki 寫入。您必須修正該目錄的權限!'; +$lang['i_permfail'] = '%s 無法經由 DokuWiki 寫入。您必須修正該目錄的權限!'; $lang['i_confexists'] = '%s 已經存在'; $lang['i_writeerr'] = '無法建立 %s。您必須檢查目錄/檔案的權限並手動建立該檔案。'; -$lang['i_badhash'] = '無法辨識或被變更的 dokuwiki.php (hash=%s)'; -$lang['i_badval'] = '%s - 非法或空白的值'; -$lang['i_success'] = '設定已成功完成。您現在可以刪除 install.php 檔案。繼續到 -您的新 DokuWiki.'; -$lang['i_failure'] = '寫入設定檔時發生了一些錯誤。您必須在使用您的新 Dokuwiki 之前手動修正它們。'; +$lang['i_badhash'] = '無法辨識或已遭修改的 dokuwiki.php (hash=%s)'; +$lang['i_badval'] = '%s —— 非法或空白的值'; +$lang['i_success'] = '設定已完成。您現在可以刪除 install.php 檔案。繼續到 +您的新 DokuWiki.'; +$lang['i_failure'] = '寫入設定檔時發生了一些錯誤。您必須在使用您的新 Dokuwiki 之前手動修正它們。'; $lang['i_policy'] = '初步的 ACL 政策'; -$lang['i_pol0'] = '開放的維基 (任何人可讀取、寫入、上傳)'; -$lang['i_pol1'] = '公開的維基 (任何人可讀取,註冊使用者可寫入與上傳)'; -$lang['i_pol2'] = '封閉的維基 (只有註冊使用者可讀取、寫入、上傳)'; +$lang['i_pol0'] = '開放的 wiki (任何人可讀取、寫入、上傳)'; +$lang['i_pol1'] = '公開的 wiki (任何人可讀取,註冊使用者可寫入與上傳)'; +$lang['i_pol2'] = '封閉的 wiki (只有註冊使用者可讀取、寫入、上傳)'; $lang['i_retry'] = '重試'; $lang['i_license'] = '請選擇您想要的內容發布許可協議:'; -$lang['recent_global'] = '您正在閱讀分類空間: %s 中的變更。您亦可觀看整個維基的最近更新。'; +$lang['recent_global'] = '您正在閱讀分類名稱: %s 中的變更。您亦可觀看本 wiki 所有的最近更新。'; $lang['years'] = '%d 年前'; $lang['months'] = '%d 個月前'; $lang['weeks'] = '%d 週前'; @@ -299,7 +300,7 @@ $lang['days'] = '%d 天前'; $lang['hours'] = '%d 個小時前'; $lang['minutes'] = '%d 分鐘前'; $lang['seconds'] = '%s 秒鐘前'; -$lang['wordblock'] = '您的更改沒有被儲存,因为它包含被阻擋的文字 (垃圾訊息)。'; +$lang['wordblock'] = '無法儲存您的更改,因為它含有受阻擋的文字 (垃圾訊息)。'; $lang['media_uploadtab'] = '上傳'; $lang['media_searchtab'] = '搜尋'; $lang['media_file'] = '檔案'; @@ -310,7 +311,7 @@ $lang['media_list_thumbs'] = '縮圖'; $lang['media_list_rows'] = '列表'; $lang['media_sort_name'] = '名稱'; $lang['media_sort_date'] = '日期'; -$lang['media_namespaces'] = '選擇分類空間'; +$lang['media_namespaces'] = '選擇分類名稱'; $lang['media_files'] = '在 %s 中的檔案'; $lang['media_upload'] = '上傳至 %s'; $lang['media_search'] = '在 %s 中搜尋'; diff --git a/inc/lang/zh-tw/locked.txt b/inc/lang/zh-tw/locked.txt index e13fdc890..819e59e2f 100644 --- a/inc/lang/zh-tw/locked.txt +++ b/inc/lang/zh-tw/locked.txt @@ -1,3 +1,3 @@ ====== 頁面鎖定 ====== -本頁目前正由其他使用者編修中,您必須等他完成編輯或等鎖定時間過去。 +其他使用者正在編輯本頁,您必須等他完成編輯或等鎖定時間過去。 diff --git a/inc/lang/zh-tw/login.txt b/inc/lang/zh-tw/login.txt index 058cc5712..b82f08a20 100644 --- a/inc/lang/zh-tw/login.txt +++ b/inc/lang/zh-tw/login.txt @@ -1,5 +1,4 @@ ====== 登入 ====== -您尚未登入,請輸入您的使用者名稱和密碼。 另外,瀏覽器需要打開 cookies 設定以進行登入。 - +您尚未登入,請輸入您的使用者名稱和密碼。 另外,瀏覽器需要啟用 cookies 以登入本 wiki。 diff --git a/inc/lang/zh-tw/mailtext.txt b/inc/lang/zh-tw/mailtext.txt index 3b6ece377..2a402c2fb 100644 --- a/inc/lang/zh-tw/mailtext.txt +++ b/inc/lang/zh-tw/mailtext.txt @@ -2,7 +2,7 @@ 日期 : @DATE@ 瀏覽器 : @BROWSER@ -IP位址 : @IPADDRESS@ +IP 位址 : @IPADDRESS@ 主機名稱 : @HOSTNAME@ 舊版本 : @OLDPAGE@ 新版本 : @NEWPAGE@ diff --git a/inc/lang/zh-tw/norev.txt b/inc/lang/zh-tw/norev.txt index bd1c7a623..2a32ba6a8 100644 --- a/inc/lang/zh-tw/norev.txt +++ b/inc/lang/zh-tw/norev.txt @@ -1,3 +1,3 @@ ====== 無此版本 ====== -該版本的文件不存在。請用 「舊版」按鈕檢視該文件所有舊版本清單。 \ No newline at end of file +該版本的文件不存在。請用「舊版」按鈕檢視該文件所有舊版本清單。 \ No newline at end of file diff --git a/inc/lang/zh-tw/preview.txt b/inc/lang/zh-tw/preview.txt index c68f94819..95d4b10e1 100644 --- a/inc/lang/zh-tw/preview.txt +++ b/inc/lang/zh-tw/preview.txt @@ -1,4 +1,4 @@ ====== 預覽 ====== -以下是預覽該文件的狀態。請記住:**它還沒被儲存喔**! +以下是該文件的預覽。請記住:**您還未儲存它**! diff --git a/inc/lang/zh-tw/pwconfirm.txt b/inc/lang/zh-tw/pwconfirm.txt index 994367980..fb8a5cb82 100644 --- a/inc/lang/zh-tw/pwconfirm.txt +++ b/inc/lang/zh-tw/pwconfirm.txt @@ -1,13 +1,13 @@ @FULLNAME@ 您好! -有人為您在 @DOKUWIKIURL@ 註冊的使用者 @TITLE@ 請求新密碼 +感謝您在 @TITLE@ ( @DOKUWIKIURL@ ) 註冊了使用者帳號。我們收到請求,希望能允許此帳號使用新密碼。 -如果您沒有請求新密碼,請忽略這封郵件。 +如果您沒有發送此請求,請忽略這封郵件。 -要確認使用新密碼,請拜訪以下的連結。 +若您真的要使用新密碼,請拜訪以下的連結。 @CONFIRM@ -- 本信件由以下 DokuWiki 站台產生: -@DOKUWIKIURL@ +@DOKUWIKIURL@ \ No newline at end of file diff --git a/inc/lang/zh-tw/read.txt b/inc/lang/zh-tw/read.txt index a8305611f..4a472cd0d 100644 --- a/inc/lang/zh-tw/read.txt +++ b/inc/lang/zh-tw/read.txt @@ -1 +1 @@ -本頁是唯讀的,您可以看到原始碼,但不能更動它。您如果覺得這是誤判,請詢問管理員。 \ No newline at end of file +本頁是唯讀的,您可以看到原始碼,但不能更動它。您如果覺得它不應被鎖上,請詢問管理員。 \ No newline at end of file diff --git a/inc/lang/zh-tw/register.txt b/inc/lang/zh-tw/register.txt index 0da401ccd..3ff68dee3 100644 --- a/inc/lang/zh-tw/register.txt +++ b/inc/lang/zh-tw/register.txt @@ -1,4 +1,3 @@ ====== 註冊新使用者 ====== -填寫以下資料以註冊維基帳號,請確定您提供的是**合法的 email 地址**-如果這裡沒要求您填寫密碼,您的新密碼會自動產生並寄送到該地址。登錄名稱必須是合法的[[doku>pagename|頁面名稱]]。 - +若要註冊本 wiki 的帳號,請填寫下列資料。請確定您提供的是**合法的電郵地址**。如果您不必填寫密碼,系統就會為您自動產生登入密碼,並寄送到該電郵地址。登錄名稱須符合正確[[doku>pagename|頁面名稱]]之條件。 diff --git a/inc/lang/zh-tw/registermail.txt b/inc/lang/zh-tw/registermail.txt index 489e3f9d3..fb4951d60 100644 --- a/inc/lang/zh-tw/registermail.txt +++ b/inc/lang/zh-tw/registermail.txt @@ -2,11 +2,11 @@ 帳號 : @NEWUSER@ 姓名 : @NEWNAME@ -E-mail : @NEWEMAIL@ +電郵 : @NEWEMAIL@ 日期 : @DATE@ 瀏覽器 : @BROWSER@ -IP位址 : @IPADDRESS@ +IP 位址 : @IPADDRESS@ 主機名稱 : @HOSTNAME@ -- diff --git a/inc/lang/zh-tw/resendpwd.txt b/inc/lang/zh-tw/resendpwd.txt index 3dbfad750..46078a348 100644 --- a/inc/lang/zh-tw/resendpwd.txt +++ b/inc/lang/zh-tw/resendpwd.txt @@ -1,3 +1,3 @@ ====== 寄送新密碼 ====== -請在以下欄位輸入您的帳號,新密碼將會寄送到您註冊時填寫的 email 地址。 +請在以下欄位輸入您的帳號,新密碼將會寄送到您註冊時填寫的電郵地址。 \ No newline at end of file diff --git a/inc/lang/zh-tw/revisions.txt b/inc/lang/zh-tw/revisions.txt index 479705b95..4818839ac 100644 --- a/inc/lang/zh-tw/revisions.txt +++ b/inc/lang/zh-tw/revisions.txt @@ -1,3 +1,3 @@ ====== 舊版 ====== -以下是該文件的舊版本。如要恢復成某個舊版次,就點下它,然後按「編修本頁」,並存檔起來就可以了。 +以下是該文件的舊版本。如要恢復成某個舊版次,就點下它,然後按「編輯本頁」,並存檔起來就可以了。 diff --git a/inc/lang/zh-tw/stopwords.txt b/inc/lang/zh-tw/stopwords.txt index 55b67ed16..e549250bd 100644 --- a/inc/lang/zh-tw/stopwords.txt +++ b/inc/lang/zh-tw/stopwords.txt @@ -1,9 +1,9 @@ -# 這檔是製作索引檔(index)時不要列入的關鍵字,格式為每字(詞)就使用一行。 -# 在修改時,請注意要用 UNIX 格式的換行符號(newline)處理,而非 DOS 的 CR-LR 喔 -# (如果在 MS Windows 環境使用的話,可使用 vim win32版 或 UltraEdit或其他類似編輯器修改) +# 本清單列出製作索引檔 (index) 時不要列入的關鍵字,格式為每字 (詞) 佔一行。 +# 在修改本清單時,請注意要用 UNIX 格式的換行符號 (newline) 處理,而非 DOS 的 CR-LR 。 +# (如果在 MS Windows 環境使用的話,可使用 vim win32 版、 UltraEdit 或其他類似編輯器修改。) # -# 還有,不必把小於 3 個字元(英數字元)都包括進來。 -# 目前本清單的內容是以 http://www.ranks.nl/stopwords/ 為基礎而發展的。 +# 還有,不必把小於 3 個字元 (英數字元) 都包括進來。 +# 目前本清單的內容是以 http://www.ranks.nl/stopwords/ 為基礎,發展而成的。 about are and diff --git a/inc/lang/zh-tw/subscr_digest.txt b/inc/lang/zh-tw/subscr_digest.txt index a0f2be73e..a17a0551d 100644 --- a/inc/lang/zh-tw/subscr_digest.txt +++ b/inc/lang/zh-tw/subscr_digest.txt @@ -1,6 +1,6 @@ 您好! -維基 @TITLE@ 的頁面 @PAGE@ 已更改。 +本 wiki ( @TITLE@ ) 的頁面 @PAGE@ 已更改。 更改內容如下: -------------------------------------------------------- @@ -10,9 +10,9 @@ 舊版本:@OLDPAGE@ 新版本:@NEWPAGE@ -要取消頁面提醒,請登入維基 @DOKUWIKIURL@ +要取消頁面提醒,請登入本 wiki @DOKUWIKIURL@ 然後拜訪 @SUBSCRIBE@ -並取消訂閱頁面或分類空間的更改。 +並取消訂閱頁面或分類名稱的更改。 -- 本信件由以下 DokuWiki 站台產生: diff --git a/inc/lang/zh-tw/subscr_form.txt b/inc/lang/zh-tw/subscr_form.txt index 394d4cbad..ba3f16113 100644 --- a/inc/lang/zh-tw/subscr_form.txt +++ b/inc/lang/zh-tw/subscr_form.txt @@ -1,3 +1,3 @@ ====== 訂閱管理 ====== -這個頁面允許您管理在目前頁面和分類空間的訂閱。 \ No newline at end of file +在此頁裏,您可以管理在目前頁面及分類名稱之訂閱。 \ No newline at end of file diff --git a/inc/lang/zh-tw/subscr_list.txt b/inc/lang/zh-tw/subscr_list.txt index 078eae63e..ea82dd35d 100644 --- a/inc/lang/zh-tw/subscr_list.txt +++ b/inc/lang/zh-tw/subscr_list.txt @@ -1,15 +1,15 @@ 您好! -維基 @TITLE@ 的 @PAGE@ 分類空間的頁面已更改。 +本 wiki ( @TITLE@ ) 的 @PAGE@ 分類名稱頁面已更改。 更改內容如下: -------------------------------------------------------- @DIFF@ -------------------------------------------------------- -要取消頁面提醒,請登入維基 @DOKUWIKIURL@ +要取消頁面提醒,請登入本 wiki @DOKUWIKIURL@ 然後拜訪 @SUBSCRIBE@ -並取消訂閱頁面或分類空間的更改。 +並取消訂閱頁面或分類名稱的更改。 -- 本信件由以下 DokuWiki 站台產生: diff --git a/inc/lang/zh-tw/subscr_single.txt b/inc/lang/zh-tw/subscr_single.txt index 5128140d0..14d87bb73 100644 --- a/inc/lang/zh-tw/subscr_single.txt +++ b/inc/lang/zh-tw/subscr_single.txt @@ -1,6 +1,6 @@ 您好! -維基 @TITLE@ 的頁面 @PAGE@ 已更改。 +本 wiki ( @TITLE@ ) 的頁面 @PAGE@ 已更改。 更改內容如下: -------------------------------------------------------- @@ -13,9 +13,9 @@ 舊版本 : @OLDPAGE@ 新版本 : @NEWPAGE@ -要取消頁面提醒,請登入維基 @DOKUWIKIURL@ +要取消頁面提醒,請登入本 wiki @DOKUWIKIURL@ 然後拜訪 @NEWPAGE@ -並取消訂閱頁面或分類空間的更改。 +並取消訂閱頁面或分類名稱的更改。 -- 本信件由以下 DokuWiki 站台產生: diff --git a/inc/lang/zh-tw/updateprofile.txt b/inc/lang/zh-tw/updateprofile.txt index 47f2ae1c4..a7a2ad803 100644 --- a/inc/lang/zh-tw/updateprofile.txt +++ b/inc/lang/zh-tw/updateprofile.txt @@ -1,3 +1,3 @@ ====== 更新個人資料 ====== -您只需變更想更新的欄位就好,帳號名稱不能變更。 \ No newline at end of file +您只需修改想更新的欄位就好,帳號名稱不能變更。 \ No newline at end of file diff --git a/inc/lang/zh-tw/uploadmail.txt b/inc/lang/zh-tw/uploadmail.txt index b4c1311ba..87bac7c9a 100644 --- a/inc/lang/zh-tw/uploadmail.txt +++ b/inc/lang/zh-tw/uploadmail.txt @@ -3,7 +3,7 @@ 檔名 : @MEDIA@ 日期 : @DATE@ 瀏覽器 : @BROWSER@ -IP位址 : @IPADDRESS@ +IP 位址 : @IPADDRESS@ 主機名稱 : @HOSTNAME@ 大小 : @SIZE@ MIME類型 : @MIME@ @@ -11,4 +11,4 @@ MIME類型 : @MIME@ -- 本信件由以下 DokuWiki 站台產生: -@DOKUWIKIURL@ +@DOKUWIKIURL@ \ No newline at end of file diff --git a/lib/plugins/acl/lang/zh-tw/help.txt b/lib/plugins/acl/lang/zh-tw/help.txt index d5d031059..2d1c84b7d 100644 --- a/lib/plugins/acl/lang/zh-tw/help.txt +++ b/lib/plugins/acl/lang/zh-tw/help.txt @@ -1,11 +1,11 @@ -=== 快速指南: === +=== 快速指南: === -你可以用這個頁面為維基中的分類空間或頁面增加或移除權限。 +你可以用這個頁面,為本 wiki 中的分類名稱或頁面增加或移除權限。 -左方面板顯示了所有分類空間和頁面。 +左方面板顯示了所有分類名稱和頁面。 上方表格允許你觀看及修改選取的使用者或群組的權限。 下方表格顯示了目前所有的存取控制表 (ACL),你可以用它快速刪除或更改多項規則。 -閱讀 [[doku>acl|official documentation on ACL]] 可以幫助你完整地了解 DokuWiki 存取控制的運作。 +閱讀 [[doku>acl|official documentation on ACL]] 可以幫助你完整地了解 DokuWiki 存取控制的運作。 \ No newline at end of file diff --git a/lib/plugins/acl/lang/zh-tw/lang.php b/lib/plugins/acl/lang/zh-tw/lang.php index ff115df18..ff2c6a184 100644 --- a/lib/plugins/acl/lang/zh-tw/lang.php +++ b/lib/plugins/acl/lang/zh-tw/lang.php @@ -12,25 +12,26 @@ * @author Danny Lin * @author Shuo-Ting Jian * @author syaoranhinata@gmail.com + * @author Ichirou Uchiki */ $lang['admin_acl'] = '管理存取控制表 (ACL)'; $lang['acl_group'] = '群組'; $lang['acl_user'] = '使用者'; $lang['acl_perms'] = '設定權限於'; $lang['page'] = '頁面'; -$lang['namespace'] = '分類空間'; +$lang['namespace'] = '分類名稱'; $lang['btn_select'] = '選擇'; -$lang['p_user_id'] = '使用者 %s 目前在頁面 %s 擁有以下權限:%s。'; -$lang['p_user_ns'] = '使用者 %s 目前在分類空間 %s 擁有以下權限:%s。'; -$lang['p_group_id'] = '群組 %s 的成員目前在頁面 %s 擁有以下權限:%s。'; -$lang['p_group_ns'] = '群組 %s 的成員目前在分類空間 %s 擁有以下權限:%s。'; +$lang['p_user_id'] = '使用者 %s 目前在頁面 %s 裏擁有以下權限:%s。'; +$lang['p_user_ns'] = '使用者 %s 目前在分類名稱 %s 裏擁有以下權限:%s。'; +$lang['p_group_id'] = '群組 %s 的成員目前在頁面 %s 裏擁有以下權限:%s。'; +$lang['p_group_ns'] = '群組 %s 的成員目前在分類名稱 %s 裏擁有以下權限:%s。'; $lang['p_choose_id'] = '請在上方表格輸入使用者或群組以檢視或編輯頁面 %s 的權限設定。'; -$lang['p_choose_ns'] = '請在上方表格輸入使用者或群組以檢視或編輯分類空間 %s 的權限設定。'; -$lang['p_inherited'] = '注意:這些權限並未明確指定,而是從群組或上層的分類空間繼承而來。'; -$lang['p_isadmin'] = '注意:選取的群組或使用者擁有完整權限,因為它被設定為超級使用者。'; -$lang['p_include'] = '較高的權限亦包含了較低的權限。新增、上傳與刪除權限只能設定在分類空間,不能設定在頁面。'; +$lang['p_choose_ns'] = '請在上方表格輸入使用者或群組以檢視或編輯分類名稱 %s 的權限設定。'; +$lang['p_inherited'] = '注意:這些權限並未明確指定,它們是從群組或上層的分類名稱繼承而來。'; +$lang['p_isadmin'] = '注意:選取的群組或使用者擁有完整權限,因為他或他們已成為超級使用者。'; +$lang['p_include'] = '較高的權限亦包含了較低的權限。新增、上傳與刪除權限只能套用至分類名稱,不能套用至頁面。'; $lang['current'] = '目前的存取控制規則'; -$lang['where'] = '頁面/分類空間'; +$lang['where'] = '頁面/分類名稱'; $lang['who'] = '使用者/群組'; $lang['perm'] = '權限'; $lang['acl_perm0'] = '無'; diff --git a/lib/plugins/config/lang/zh-tw/intro.txt b/lib/plugins/config/lang/zh-tw/intro.txt index 4cacfc43f..228c12e0a 100644 --- a/lib/plugins/config/lang/zh-tw/intro.txt +++ b/lib/plugins/config/lang/zh-tw/intro.txt @@ -1,7 +1,7 @@ ====== 設定管理器 ====== -使用本頁控制您的 Dokuwiki 設定。每個獨立設定的相關訊息可參閱 [[doku>config]]。設定管理器的更多訊息請參閱 [[doku>plugin:config]]。 +使用本頁控制您的 Dokuwiki 設定。您可以參閱 [[doku>config]],查看每個獨立設定的相關訊息。要知道更多設定管理器的資訊,請瀏覽 [[doku>plugin:config]]。 -淡紅色背景的項目是被保護的,不能通過這個管理器更改。藍色背景的項目是系統的預設值,白色背景的項目是您更改過的。藍色和白色的設定項目都可以更改。 +淡紅色背景的項目是受到保護的,不能通過這管理器更改。藍色背景的項目是系統的預設值,白色背景的項目是您更改過的。藍色和白色的設定項目都可以更改。 -離開本頁之前不要忘記點擊最下面的 **儲存** 按鈕,否則您的修改將不會生效。 \ No newline at end of file +離開本頁之前,不要忘記點擊最下面的 **儲存** 按鈕,否則您的修改不會生效。 \ No newline at end of file diff --git a/lib/plugins/config/lang/zh-tw/lang.php b/lib/plugins/config/lang/zh-tw/lang.php index 204b2b229..8f5b16220 100644 --- a/lib/plugins/config/lang/zh-tw/lang.php +++ b/lib/plugins/config/lang/zh-tw/lang.php @@ -10,19 +10,20 @@ * @author Danny Lin * @author Shuo-Ting Jian * @author syaoranhinata@gmail.com + * @author Ichirou Uchiki */ $lang['menu'] = '系統設定'; -$lang['error'] = '設定因為不合法的值而未更新,請檢查您的更改並重新送出。 -
不正確的值會被紅色方框包住。'; -$lang['updated'] = '成功地更新設定。'; +$lang['error'] = '因為含有不合規格的設定值,故未能更新設定。請檢查您的更改並重新送出。 +
不正確的設定值,會以紅色方框包住。'; +$lang['updated'] = '設定已更新。'; $lang['nochoice'] = '(無其他可用選項)'; $lang['locked'] = '設定檔無法更新,若非故意,請確認本地檔名及權限正確。'; -$lang['danger'] = '危險:改變此選項可能使您無法存取維基及設定選單。'; +$lang['danger'] = '危險:改變此選項,可能使您無法存取本 wiki 及設定選單。'; $lang['warning'] = '警告:改變此選項可能導致不可預期的行為。'; $lang['security'] = '安全性警告:改變此選項可能造成安全風險。'; $lang['_configuration_manager'] = '設定管理器'; $lang['_header_dokuwiki'] = 'DokuWiki 設定'; -$lang['_header_plugin'] = '插件設定'; +$lang['_header_plugin'] = '附加元件設定'; $lang['_header_template'] = '樣板設定'; $lang['_header_undefined'] = '未定義設定'; $lang['_basic'] = '基本設定'; @@ -32,17 +33,21 @@ $lang['_anti_spam'] = '反垃圾設定'; $lang['_editing'] = '編輯設定'; $lang['_links'] = '連結設定'; $lang['_media'] = '媒體設定'; +$lang['_notifications'] = '提醒設定'; +$lang['_syndication'] = '聚合設定'; $lang['_advanced'] = '進階設定'; $lang['_network'] = '網路設定'; -$lang['_plugin_sufix'] = '插件設定'; +$lang['_plugin_sufix'] = '附加元件設定'; $lang['_template_sufix'] = '樣板設定'; $lang['_msg_setting_undefined'] = '設定的後設數據不存在。'; $lang['_msg_setting_no_class'] = '設定的分類不存在。'; $lang['_msg_setting_no_default'] = '無預設值'; -$lang['title'] = '維基標題'; +$lang['title'] = '本 wiki 的標題'; $lang['start'] = '開始頁面的名稱'; $lang['lang'] = '語系'; $lang['template'] = '樣板'; +$lang['tagline'] = '副標題 (若模板支援此功能)'; +$lang['sidebar'] = '側欄的頁面名稱 (若模板支援此功能) 。若把它留空,則會停用側欄'; $lang['license'] = '您希望您的內容為何種授權方式?'; $lang['savedir'] = '儲存資料的目錄'; $lang['basedir'] = '根目錄'; @@ -67,15 +72,15 @@ $lang['maxseclevel'] = '可編輯段落的最大層級'; $lang['camelcase'] = '對連結使用 CamelCase'; $lang['deaccent'] = '清理頁面名稱'; $lang['useheading'] = '使用第一個標題作為頁面名稱'; -$lang['sneaky_index'] = '預設情況下,DokuWiki 會在索引頁會顯示所有分類空間。啟用此選項會隱藏用戶沒有閱讀權限的頁面,但也可能將能閱讀的子頁面一併隱藏。在特定 ACL 設定下,這可能導致索引無法使用。'; +$lang['sneaky_index'] = '預設情況下,DokuWiki 會在索引頁會顯示所有分類名稱。啟用此選項,會隱藏使用者沒有閱讀權限的頁面,但也可能將他可以閱讀的子頁面一併隱藏。在特定 ACL 設定下,這可能導致索引無法使用。'; $lang['hidepages'] = '隱藏匹配的界面 (正規式)'; $lang['useacl'] = '使用存取控制名單'; $lang['autopasswd'] = '自動產生密碼'; $lang['authtype'] = '認證後台管理方式'; $lang['passcrypt'] = '密碼加密方式'; $lang['defaultgroup'] = '預設群組'; -$lang['superuser'] = '超級用戶 - 不論 ACL 如何設定,都能訪問所有頁面與功能的用戶組/用戶'; -$lang['manager'] = '管理員 - 能訪問相應管理功能的用戶组/用戶'; +$lang['superuser'] = '超級使用者 —— 不論 ACL 如何設定,都能訪問所有頁面與功能的群組或使用者'; +$lang['manager'] = '管理員 —— 能訪問相應管理功能的群組或使用者'; $lang['profileconfirm'] = '修改個人資料時需要確認密碼'; $lang['rememberme'] = '允許自動登入 (記住我)'; $lang['disableactions'] = '停用的 DokuWiki 動作'; @@ -84,11 +89,13 @@ $lang['disableactions_subscription'] = '訂閱/取消訂閱'; $lang['disableactions_wikicode'] = '檢視原始碼/匯出原始檔'; $lang['disableactions_other'] = '其他功能 (逗號分隔)'; $lang['auth_security_timeout'] = '安全認證的計時 (秒)'; -$lang['securecookie'] = 'HTTPS 頁面設定的 cookie 是否只能由瀏覽器經 HTTPS 傳送?取消此選項後,只有登入維基會被 SSL 保護而瀏覽時不會。'; +$lang['securecookie'] = 'HTTPS 頁面設定的 cookie 是否只能由瀏覽器經 HTTPS 傳送?取消此選項後,只有登入本 wiki 才會受 SSL 保護,瀏覽時則不受保護。'; +$lang['remote'] = '啟用遠程 API 系统。這允許其他程式經 XML-RPC 或其他機制來訪問本 wiki 。'; +$lang['remoteuser'] = '將遠程 API 的訪問權限,限制在指定的群組或使用者中。以逗號分隔群組或使用者。留空表示允許任何人訪問。'; $lang['usewordblock'] = '根據字詞表阻擋垃圾訊息'; $lang['relnofollow'] = '外部連結使用 rel="nofollow"'; $lang['indexdelay'] = '建立索引前的延遲時間 (秒)'; -$lang['mailguard'] = '混淆 E-mail 位址'; +$lang['mailguard'] = '自動弄亂使用者的電郵地址,以作保護'; $lang['iexssprotect'] = '檢查上傳的檔案中是否隱含惡意的 JavaScript 或 HTML 碼'; $lang['usedraft'] = '編輯時自動儲存草稿'; $lang['htmlok'] = '允許嵌入式 HTML'; @@ -96,10 +103,11 @@ $lang['phpok'] = '允許嵌入式 PHP'; $lang['locktime'] = '檔案的最大鎖定時間 (秒)'; $lang['cachetime'] = '緩存的最大存在時間 (秒)'; $lang['target____wiki'] = '內部連結的目標視窗'; -$lang['target____interwiki'] = '跨維基連結的目標視窗'; +$lang['target____interwiki'] = 'Wiki間互連的目標視窗'; $lang['target____extern'] = '外部連結的目標視窗'; $lang['target____media'] = '媒體連結的目標視窗'; $lang['target____windows'] = 'Windows 連結的目標視窗'; +$lang['mediarevisions'] = '啟用媒體修訂歷史嗎?'; $lang['refcheck'] = '媒體連結檢查'; $lang['refshow'] = '媒體連結的顯示數量'; $lang['gdlib'] = 'GD Lib 版本'; @@ -108,11 +116,12 @@ $lang['jpg_quality'] = 'JPG 壓縮品質(0-100)'; $lang['fetchsize'] = 'fetch.php 可以從外部下載的最大檔案尺寸 (bytes)'; $lang['subscribers'] = '啟用頁面訂閱'; $lang['subscribe_time'] = '訂閱列表和摘要發送的時間間隔 (秒);這個值應該小於指定的最近更改保留時間 (recent_days)。'; -$lang['notify'] = '寄送變更通知信到這個 E-mail 位址'; -$lang['registernotify'] = '寄送新使用者註冊資訊到這個 E-mail 位址'; +$lang['notify'] = '寄送變更通知信到這個電郵地址'; +$lang['registernotify'] = '寄送新使用者註冊資訊到這個電郵地址'; $lang['mailfrom'] = '自動發送郵件時使用的郵件地址'; $lang['mailprefix'] = '自動發送郵件時使用的標題前綴'; -$lang['sitemap'] = '產生 Google 站台地圖 (天)'; +$lang['htmlmail'] = '發送更加美觀,但體積會更大的 HTML 多部份電郵。若停用它,表示只發送純文字電郵。'; +$lang['sitemap'] = '產生 Google 站台地圖 (以多少天計算) 。輸入0表示停用'; $lang['rss_type'] = 'XML feed 類型'; $lang['rss_linkto'] = 'XML feed 連結到'; $lang['rss_content'] = 'XML feed 項目中顯示什麼呢?'; @@ -121,7 +130,7 @@ $lang['rss_show_summary'] = '於標題中顯示簡要的 XML feed'; $lang['rss_media'] = '在 XML feed 中應列出哪些變更?'; $lang['updatecheck'] = '檢查更新與安全性警告?DokuWiki 需要聯繫 update.dokuwiki.org 才能使用此功能。'; $lang['userewrite'] = '使用好看的 URL'; -$lang['useslash'] = '在 URL 中使用斜線作為分類空間的分隔字元'; +$lang['useslash'] = '在 URL 中使用斜線作為分類名稱的分隔字元'; $lang['sepchar'] = '頁面名稱中單字的分隔字元'; $lang['canonical'] = '使用最典型的 URL'; $lang['fnencode'] = '非 ASCII 文件名稱的編輯方法。'; @@ -129,13 +138,14 @@ $lang['autoplural'] = '檢查複數形式的連結 (英文)'; $lang['compression'] = 'attic 文件的壓縮方式'; $lang['gzip_output'] = '對 xhtml 使用 gzip 內容編碼'; $lang['compress'] = '壓縮 CSS 與 JavaScript 的輸出'; -$lang['cssdatauri'] = 'CSS 中所引用的圖片假如小於該數字大小(bytes),將會被直接嵌入 CSS 中來減少 HTTP Request 的發送。此功能在 IE 7 及之下版本不支援。推薦使用 400600 之間。設定為0 則停用。'; +$lang['cssdatauri'] = '假如 CSS 中所引用的圖片小於該數字大小(bytes),圖片將被直接嵌入 CSS 中,以減少 HTTP Request 的發送。 IE 7 及以下的版本並不支援此功能。推薦把此數值設定成 400600 bytes 之間。若輸入 0 則停用此功能。'; $lang['send404'] = '存取不存在的頁面時送出 "HTTP 404/Page Not Found"'; $lang['broken_iua'] = 'ignore_user_abort 功能失效了?這有可能導致搜索索引不可用。IIS+PHP/CGI 已損壞。請參閱 Bug 852 獲取更多信息。'; $lang['xsendfile'] = '使用 X-Sendfile 頭讓服務器發送狀態文件?您的服務器需要支持該功能。'; -$lang['renderer_xhtml'] = '主要維基輸出 (xhtml) 的的渲染器'; +$lang['renderer_xhtml'] = '主要wiki輸出 (xhtml) 的渲染器'; $lang['renderer__core'] = '%s (dokuwiki 核心)'; -$lang['renderer__plugin'] = '%s (插件)'; +$lang['renderer__plugin'] = '%s (附加元件)'; +$lang['dnslookups'] = 'Dokuwiki 將查詢使用者編輯頁面的遠程 IP 位址主機名稱。若您的 DNS 服務器速度較慢、失效,或者您不想要此功能,请停用此選項'; $lang['proxy____host'] = 'Proxy 伺服器名稱'; $lang['proxy____port'] = 'Proxy 連接埠'; $lang['proxy____user'] = 'Proxy 使用者名稱'; @@ -183,10 +193,10 @@ $lang['xsendfile_o_2'] = '標準 X-Sendfile 標頭'; $lang['xsendfile_o_3'] = '專有 Nginx X-Accel-Redirect 標頭'; $lang['showuseras_o_loginname'] = '登入名稱'; $lang['showuseras_o_username'] = '完整姓名'; -$lang['showuseras_o_email'] = '使用者的 email 位址 (根據郵件監控設定混淆化)'; -$lang['showuseras_o_email_link'] = '使用者的 email 位址標示成 mailto: link'; +$lang['showuseras_o_email'] = '使用者的電郵地址 (根據郵件監控設定混淆化)'; +$lang['showuseras_o_email_link'] = '使用者的電郵地址標示成 mailto: 連結'; $lang['useheading_o_0'] = '永不'; $lang['useheading_o_navigation'] = '僅導覽'; -$lang['useheading_o_content'] = '僅維基內容'; +$lang['useheading_o_content'] = '僅本 wiki 內容'; $lang['useheading_o_1'] = '總是'; $lang['readdircache'] = 'readdir 緩存的最大存在時間 (秒)'; diff --git a/lib/plugins/plugin/lang/zh-tw/admin_plugin.txt b/lib/plugins/plugin/lang/zh-tw/admin_plugin.txt index 84d095f51..54fe7a59e 100644 --- a/lib/plugins/plugin/lang/zh-tw/admin_plugin.txt +++ b/lib/plugins/plugin/lang/zh-tw/admin_plugin.txt @@ -1,3 +1,3 @@ -====== 插件管理器 ====== +====== 附加元件管理器 ====== -您可以用本頁管理與 Dokuwiki [[doku>plugins|插件]] 相關的選項。若要正常下載及安裝插件,插件所在的資料夾必須允許網頁伺服器寫入。 +您可以用本頁管理與 Dokuwiki [[doku>plugins|附加元件]] 相關的選項。若要正常下載及安裝附加元件,附加元件所在的資料夾必須允許網頁伺服器寫入。 \ No newline at end of file diff --git a/lib/plugins/plugin/lang/zh-tw/lang.php b/lib/plugins/plugin/lang/zh-tw/lang.php index 8fa3efb0a..7b38a02c8 100644 --- a/lib/plugins/plugin/lang/zh-tw/lang.php +++ b/lib/plugins/plugin/lang/zh-tw/lang.php @@ -10,10 +10,11 @@ * @author Danny Lin * @author Shuo-Ting Jian * @author syaoranhinata@gmail.com + * @author Ichirou Uchiki */ -$lang['menu'] = '管理插件 (Plugins)'; -$lang['download'] = '下載與安裝插件'; -$lang['manage'] = '已安裝的插件'; +$lang['menu'] = '管理附加元件'; +$lang['download'] = '下載與安裝附加元件'; +$lang['manage'] = '已安裝的附加元件'; $lang['btn_info'] = '資訊'; $lang['btn_update'] = '更新'; $lang['btn_delete'] = '刪除'; @@ -25,34 +26,34 @@ $lang['installed'] = '安裝:'; $lang['lastupdate'] = '上次更新:'; $lang['source'] = '來源:'; $lang['unknown'] = '未知'; -$lang['updating'] = '更新中 ...'; -$lang['updated'] = '插件 %s 成功地更新'; -$lang['updates'] = '以下的插件已經成功地更新'; -$lang['update_none'] = '找不到更新'; -$lang['deleting'] = '刪除中 ...'; -$lang['deleted'] = '插件 %s 已刪除。'; -$lang['downloading'] = '下載中 ...'; -$lang['downloaded'] = '插件 %s 已成功地安裝'; -$lang['downloads'] = '以下的插件已成功地安裝:'; -$lang['download_none'] = '找不到插件,或在下載與安裝時發生了未知的問題'; -$lang['plugin'] = '插件:'; +$lang['updating'] = '更新中……'; +$lang['updated'] = '已更新附加元件 %s '; +$lang['updates'] = '已更新下列附加元件'; +$lang['update_none'] = '找不到更新。'; +$lang['deleting'] = '刪除中……'; +$lang['deleted'] = '已刪除附加元件 %s 。'; +$lang['downloading'] = '下載中……'; +$lang['downloaded'] = '已安裝附加元件 %s '; +$lang['downloads'] = '已安裝下列附加元件:'; +$lang['download_none'] = '找不到附加元件,或者在下載與安裝時發生了未知的問題。'; +$lang['plugin'] = '附加元件:'; $lang['components'] = '元件'; -$lang['noinfo'] = '此插件沒有回傳任何資訊,可能是無效的'; +$lang['noinfo'] = '此附加元件沒有回傳任何資訊,它可能已失效。'; $lang['name'] = '名稱:'; $lang['date'] = '日期:'; $lang['type'] = '類型:'; $lang['desc'] = '描述:'; $lang['author'] = '作者:'; -$lang['www'] = '網頁:'; -$lang['error'] = '一個未知的錯誤發生。'; -$lang['error_download'] = '無法下載插件檔案: %s'; -$lang['error_badurl'] = 'URL 可能有問題 - 從 URL 中無法得知文件名'; +$lang['www'] = '網頁:'; +$lang['error'] = '發生了未知的錯誤。'; +$lang['error_download'] = '無法下載附加元件檔案: %s'; +$lang['error_badurl'] = 'URL 可能有問題 —— 從 URL 中無法得知文件名'; $lang['error_dircreate'] = '無法建立暫存目錄來接收下載的內容'; -$lang['error_decompress'] = '插件管理器無法解壓下載的文件。這可能是由於下載出現錯誤,遇到這種情況,請您再次嘗試;或者是壓縮格式無法識別,遇到這種情況,您需要手動下載並安裝該插件。'; -$lang['error_copy'] = '嘗試安裝插件 %s 的相關文件時發生複製錯誤:可能是磁碟空間不足或檔案存取權限錯誤。這可能是由於未安裝完全的插件使維基系統不穩定導致。'; -$lang['error_delete'] = '嘗試刪除插件 %s 時發生錯誤。最可能原因是檔案或目錄存取權限不足'; -$lang['enabled'] = '插件 %s 已啟用。'; -$lang['notenabled'] = '插件 %s 無法啟用,請檢查檔案權限。'; -$lang['disabled'] = '插件 %s 已停用。'; -$lang['notdisabled'] = '插件 %s 無法停用,請檢查檔案權限。'; -$lang['packageinstalled'] = '插件 (%d 插件%s: %s) 已成功地安裝。'; +$lang['error_decompress'] = '附加元件管理器無法把下載的文件解壓,這可能是由於下載出現錯誤。遇到這種情況,請您再次嘗試。此外,無法識別壓縮格式也可能導致無法解壓。若是如此,您需要手動下載並安裝該附加元件。'; +$lang['error_copy'] = '嘗試安裝附加元件 %s 的相關文件時,發生複製錯誤。這可能是磁碟空間不足,或檔案存取權限錯誤。未安裝好的附加元件,也許會令wiki系統不穩定。'; +$lang['error_delete'] = '嘗試刪除附加元件 %s 時發生錯誤。最有可能原因是檔案或目錄存取權限不足'; +$lang['enabled'] = '附加元件 %s 已啟用。'; +$lang['notenabled'] = '附加元件 %s 無法啟用,請檢查檔案權限。'; +$lang['disabled'] = '附加元件 %s 已停用。'; +$lang['notdisabled'] = '附加元件 %s 無法停用,請檢查檔案權限。'; +$lang['packageinstalled'] = '附加元件 (%d 附加元件%s: %s) 已安裝好。'; diff --git a/lib/plugins/popularity/lang/zh-tw/intro.txt b/lib/plugins/popularity/lang/zh-tw/intro.txt index 37c63dced..2a6337237 100644 --- a/lib/plugins/popularity/lang/zh-tw/intro.txt +++ b/lib/plugins/popularity/lang/zh-tw/intro.txt @@ -1,10 +1,9 @@ ====== 人氣回饋 ====== -本工具會從您的維基站台收集訊息,並以匿名的方式發送給 DokuWiki 的開發者。這有助於他們了解使用者們如何使用 DokuWiki ,並能基於實際統計資料對未來開發做出更準確的決策。 +本工具會從您的 wiki 站台收集訊息,並以匿名的方式發送給 DokuWiki 的開發者。這有助於他們了解使用者們如何使用 DokuWiki ,並能基於實際統計資料對未來開發做出更準確的決策。 -我們鼓勵您經常重複這個步驟,讓開發者了解您的維基站台的成長情形。您的資料集將會被標識為一個匿名的識別碼 (ID)。 +我們鼓勵您經常重複這個步驟,讓開發者了解您的 wiki 站台的成長情形。您的資料集將會被標識為一個匿名的識別碼 (ID) 。 -收集的資料包括 DokuWiki 版本、頁面數量、檔案大小、安裝的插件、伺服器的 PHP 資訊。 - -將被發送的原始資料顯示如下。請點擊「發送資料」按鈕進行傳輸。 +收集的資料包括 DokuWiki 版本、頁面數量、檔案大小、安裝的附加元件,以及伺服器的 PHP 資訊。 +將送出的原始資料顯示如下。請點擊「發送資料」按鈕進行傳輸。 \ No newline at end of file diff --git a/lib/plugins/popularity/lang/zh-tw/lang.php b/lib/plugins/popularity/lang/zh-tw/lang.php index 3d19ce53a..890c23bfa 100644 --- a/lib/plugins/popularity/lang/zh-tw/lang.php +++ b/lib/plugins/popularity/lang/zh-tw/lang.php @@ -10,11 +10,12 @@ * @author Danny Lin * @author Shuo-Ting Jian * @author syaoranhinata@gmail.com + * @author Ichirou Uchiki */ -$lang['name'] = '人氣回饋(載入可能需要一些時間)'; +$lang['name'] = '人氣回饋(可能需要一些時間載入)'; $lang['submit'] = '發送資料'; $lang['autosubmit'] = '每月自動發送'; -$lang['submissionFailed'] = '由於以下原因,資料無法發送:'; -$lang['submitDirectly'] = '你可以利用以下的表單來發手動發送資料.'; -$lang['autosubmitError'] = '由於以下原因,上次自動發送失敗:'; +$lang['submissionFailed'] = '由於以下原因,資料無法發送:'; +$lang['submitDirectly'] = '你可以利用以下的表單來發手動發送資料。'; +$lang['autosubmitError'] = '由於以下原因,上次自動發送無法進行:'; $lang['lastSent'] = '資料已發送'; diff --git a/lib/plugins/popularity/lang/zh-tw/submitted.txt b/lib/plugins/popularity/lang/zh-tw/submitted.txt index 6febcd5b8..430a8a47a 100644 --- a/lib/plugins/popularity/lang/zh-tw/submitted.txt +++ b/lib/plugins/popularity/lang/zh-tw/submitted.txt @@ -1,3 +1,3 @@ ====== 人氣回饋 ====== -資料已發送成功 \ No newline at end of file +資料已發送。 \ No newline at end of file diff --git a/lib/plugins/revert/lang/zh-tw/intro.txt b/lib/plugins/revert/lang/zh-tw/intro.txt index 17632b1dd..b6da47e58 100644 --- a/lib/plugins/revert/lang/zh-tw/intro.txt +++ b/lib/plugins/revert/lang/zh-tw/intro.txt @@ -1,3 +1,3 @@ ====== 還原管理器 ====== -本頁面能幫助您自動還原被垃圾訊息攻擊的頁面過來。先輸入關鍵字詞搜尋包含垃圾訊息的頁面(如垃圾訊息的 URL),確認找到的頁面確實包含垃圾訊息,再將它們還原。 +本頁面能幫助您自動還原遭垃圾訊息攻擊的頁面。先輸入關鍵字詞,搜尋包含垃圾訊息的頁面(例如垃圾訊息的 URL),確認找到的頁面確實包含垃圾訊息,再將它們還原。 \ No newline at end of file diff --git a/lib/plugins/revert/lang/zh-tw/lang.php b/lib/plugins/revert/lang/zh-tw/lang.php index 64da648cd..afd858455 100644 --- a/lib/plugins/revert/lang/zh-tw/lang.php +++ b/lib/plugins/revert/lang/zh-tw/lang.php @@ -10,6 +10,7 @@ * @author Danny Lin * @author Shuo-Ting Jian * @author syaoranhinata@gmail.com + * @author Ichirou Uchiki */ $lang['menu'] = '還原管理'; $lang['filter'] = '搜索包含垃圾訊息的頁面'; @@ -17,6 +18,6 @@ $lang['revert'] = '還原選取的頁面'; $lang['reverted'] = '%s 已還原為版本 %s'; $lang['removed'] = '%s 已移除'; $lang['revstart'] = '已開始還原操作。有可能需要很長時間。如果程式執行逾時,請嘗試分次還原少量內容。'; -$lang['revstop'] = '還原程序已成功完成。'; +$lang['revstop'] = '還原程序已完成。'; $lang['note1'] = '注意:搜尋區分大小寫'; -$lang['note2'] = '注意:此頁面將被還原為最後一個不含垃圾訊息 %s 的版本。'; +$lang['note2'] = '注意:我們將把此頁面還原作最後一個不含垃圾訊息 %s 的版本。'; diff --git a/lib/plugins/usermanager/lang/zh-tw/lang.php b/lib/plugins/usermanager/lang/zh-tw/lang.php index 23b4fdac6..1db35cc82 100644 --- a/lib/plugins/usermanager/lang/zh-tw/lang.php +++ b/lib/plugins/usermanager/lang/zh-tw/lang.php @@ -11,6 +11,7 @@ * @author Danny Lin * @author Shuo-Ting Jian * @author syaoranhinata@gmail.com + * @author Ichirou Uchiki */ $lang['menu'] = '帳號管理器'; $lang['noauth'] = '(帳號認證尚未開放)'; @@ -18,8 +19,8 @@ $lang['nosupport'] = '(尚不支援帳號管理)'; $lang['badauth'] = '錯誤的認證機制'; $lang['user_id'] = '帳號'; $lang['user_pass'] = '密碼'; -$lang['user_name'] = '真實姓名'; -$lang['user_mail'] = 'E-mail'; +$lang['user_name'] = '名稱'; +$lang['user_mail'] = '電郵'; $lang['user_groups'] = '群組'; $lang['field'] = '欄位'; $lang['value'] = '設定值'; @@ -36,10 +37,10 @@ $lang['filter'] = '篩選條件(Filter)'; $lang['summary'] = '顯示帳號 %1$d-%2$d,共 %3$d 筆符合。共有 %4$d 個帳號。'; $lang['nonefound'] = '找不到帳號。共有 %d 個帳號。'; $lang['delete_ok'] = '已刪除 %d 個帳號'; -$lang['delete_fail'] = '%d 個帳號刪除失敗。'; +$lang['delete_fail'] = '%d 個帳號無法刪除。'; $lang['update_ok'] = '已更新該帳號'; -$lang['update_fail'] = '更新該帳號時失敗'; -$lang['update_exists'] = '變更帳號名稱 (%s) 失敗,因為有同名帳號存在(其他修改已套用)。'; +$lang['update_fail'] = '無法更新該帳號'; +$lang['update_exists'] = '無法變更帳號名稱 (%s) ,因為有同名帳號存在。其他修改則已套用。'; $lang['start'] = '開始'; $lang['prev'] = '上一頁'; $lang['next'] = '下一頁'; @@ -47,9 +48,9 @@ $lang['last'] = '最後一頁'; $lang['edit_usermissing'] = '找不到選取的帳號,可能已被刪除或改為其他名稱。'; $lang['user_notify'] = '通知使用者'; $lang['note_notify'] = '通知信只會在指定使用者新密碼時寄送。'; -$lang['note_group'] = '如果沒有指定群組,新使用者將會被加入到預設群組(%s)當中。'; +$lang['note_group'] = '如果沒有指定群組,新使用者將會列入至預設群組(%s)當中。'; $lang['note_pass'] = '如果沒有輸入這個欄位而且有勾選通知使用者,則會自動產生一組密碼。'; -$lang['add_ok'] = '新增使用者成功'; -$lang['add_fail'] = '新增使用者失敗'; +$lang['add_ok'] = '已新增使用者'; +$lang['add_fail'] = '無法新增使用者'; $lang['notify_ok'] = '通知信已寄出'; $lang['notify_fail'] = '通知信無法寄出'; -- cgit v1.2.3 From ffb060ea6b02211074dfc314f8651936065b3f7f Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 9 Jan 2013 21:09:42 +0100 Subject: show filesize of local file links in tooltip --- inc/parser/xhtml.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index 68b92ca43..71f3aa4bf 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -803,6 +803,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext); $link['class'] .= ' mediafile mf_'.$class; $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache),true); + $link['title'] .= ' (' . filesize_h(filesize(mediaFN($src))).')'; } if($hash) $link['url'] .= '#'.$hash; -- cgit v1.2.3 From c647387e09a52c1a67a72b8923ca4de06f8555cf Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Wed, 9 Jan 2013 22:26:22 +0100 Subject: Check search limit depth with an inequality Otherwise, when we check for equality, the test fails if the search start beneath the max depth. Eg: if I have the page ns1:ns2:mypage in my wiki, and launch the xmlrpc query getPagelist("ns1", "depth => 1"), without this patch, it retrieves mypage --- inc/search.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/inc/search.php b/inc/search.php index 1cecfd5ec..e18777063 100644 --- a/inc/search.php +++ b/inc/search.php @@ -247,11 +247,16 @@ function search_pagename(&$data,$base,$file,$type,$lvl,$opts){ * @author Andreas Gohr */ function search_allpages(&$data,$base,$file,$type,$lvl,$opts){ + if(isset($opts['depth'])){ + $parts = explode('/',ltrim($file,'/')); + if(($type == 'd' && count($parts) > $opts['depth']) + || ($type != 'd' && count($parts) > $opts['depth'] + 1)){ + return false; // depth reached + } + } + //we do nothing with directories if($type == 'd'){ - if(!$opts['depth']) return true; // recurse forever - $parts = explode('/',ltrim($file,'/')); - if(count($parts) == $opts['depth']) return false; // depth reached return true; } -- cgit v1.2.3 From 8451f4ad87cd104e80eb42532adebd7b2882e62e Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Thu, 10 Jan 2013 22:55:43 +0100 Subject: If depth option is set to 0, we should recurse forever At least if we want to be consistent with search_universal --- inc/search.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/search.php b/inc/search.php index e18777063..53bd240e8 100644 --- a/inc/search.php +++ b/inc/search.php @@ -247,7 +247,7 @@ function search_pagename(&$data,$base,$file,$type,$lvl,$opts){ * @author Andreas Gohr */ function search_allpages(&$data,$base,$file,$type,$lvl,$opts){ - if(isset($opts['depth'])){ + if(isset($opts['depth']) && $opts['depth']){ $parts = explode('/',ltrim($file,'/')); if(($type == 'd' && count($parts) > $opts['depth']) || ($type != 'd' && count($parts) > $opts['depth'] + 1)){ -- cgit v1.2.3 From f8591821bac23569788706524f8d6b14bd73775c Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Thu, 10 Jan 2013 08:02:26 +0100 Subject: Don't remove page version from result if uneeded It may happen when the page has few versions --- inc/RemoteAPICore.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php index c04a14f5c..fef0b81dd 100644 --- a/inc/RemoteAPICore.php +++ b/inc/RemoteAPICore.php @@ -654,7 +654,9 @@ class RemoteAPICore { if(count($revisions)>0 && $first==0) { array_unshift($revisions, ''); // include current revision - array_pop($revisions); // remove extra log entry + if ( count($revisions) > $conf['recent'] ){ + array_pop($revisions); // remove extra log entry + } } if(count($revisions) > $conf['recent']) { -- cgit v1.2.3 From 1512eb894e36e3bccfe8e99736bb9d33ebe75beb Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Fri, 11 Jan 2013 01:15:09 +0100 Subject: Fix content of pages with incorrect metadata in list feeds Before this change the last modification time was taken from metadata and then the revision that was specified there was loaded from the attic. Now revisions from attic are only loaded when the page has been modified more recently and the date is normally the last modification time of the page source. This was a problem when the most recent change was an external edit, then an older revision was shown in the feed. --- feed.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/feed.php b/feed.php index 9e5c5c6b5..7803982b8 100644 --- a/feed.php +++ b/feed.php @@ -209,12 +209,14 @@ function rss_buildItems(&$rss, &$data, $opt) { // add date if($ditem['date']) { $date = $ditem['date']; + } elseif ($ditem['media']) { + $date = @filemtime(mediaFN($id)); + } elseif (@file_exists(wikiFN($id))) { + $date = @filemtime(wikiFN($id)); } elseif($meta['date']['modified']) { $date = $meta['date']['modified']; - } else if ($ditem['media']) { - $date = @filemtime(mediaFN($id)); } else { - $date = @filemtime(wikiFN($id)); + $date = 0; } if($date) $item->date = date('r', $date); @@ -350,7 +352,11 @@ function rss_buildItems(&$rss, &$data, $opt) { $content = ''; } } else { - $content = p_wiki_xhtml($id, $date, false); + if (@filemtime(wikiFN($id)) === $date) { + $content = p_wiki_xhtml($id, '', false); + } else { + $content = p_wiki_xhtml($id, $date, false); + } // no TOC in feeds $content = preg_replace('/().*()/s', '', $content); -- cgit v1.2.3 From d0ad4a7dbf04cff927ca85efa1a53176a0401620 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 13 Jan 2013 10:53:58 +0100 Subject: grayscaled some interwiki icons --- lib/images/interwiki/dokubug.gif | Bin 166 -> 194 bytes lib/images/interwiki/paypal.gif | Bin 138 -> 139 bytes lib/images/interwiki/skype.gif | Bin 157 -> 142 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/images/interwiki/dokubug.gif b/lib/images/interwiki/dokubug.gif index 3432b8d57..08c1ca1f1 100644 Binary files a/lib/images/interwiki/dokubug.gif and b/lib/images/interwiki/dokubug.gif differ diff --git a/lib/images/interwiki/paypal.gif b/lib/images/interwiki/paypal.gif index a2dc89431..633797fac 100644 Binary files a/lib/images/interwiki/paypal.gif and b/lib/images/interwiki/paypal.gif differ diff --git a/lib/images/interwiki/skype.gif b/lib/images/interwiki/skype.gif index 2c900a8b2..d9bd575a6 100644 Binary files a/lib/images/interwiki/skype.gif and b/lib/images/interwiki/skype.gif differ -- cgit v1.2.3 From 187b13eb2e4f044659ad056a038b7aed65033579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Prat?= Date: Fri, 18 Jan 2013 10:07:50 +0100 Subject: Catalan language update --- inc/lang/ca/lang.php | 129 ++++++++++++++++++++++++++----- inc/lang/ca/mailwrap.html | 13 ++++ inc/lang/ca/resetpwd.txt | 3 + inc/lang/ca/subscr_digest.txt | 21 +++++ inc/lang/ca/subscr_form.txt | 3 + inc/lang/ca/subscr_list.txt | 21 +++++ lib/plugins/acl/lang/ca/lang.php | 1 + lib/plugins/config/lang/ca/lang.php | 96 ++++++++++++----------- lib/plugins/plugin/lang/ca/lang.php | 2 + lib/plugins/popularity/lang/ca/lang.php | 1 + lib/plugins/revert/lang/ca/lang.php | 1 + lib/plugins/usermanager/lang/ca/lang.php | 1 + 12 files changed, 228 insertions(+), 64 deletions(-) create mode 100644 inc/lang/ca/mailwrap.html create mode 100644 inc/lang/ca/resetpwd.txt create mode 100644 inc/lang/ca/subscr_digest.txt create mode 100644 inc/lang/ca/subscr_form.txt create mode 100644 inc/lang/ca/subscr_list.txt diff --git a/inc/lang/ca/lang.php b/inc/lang/ca/lang.php index 0fd88ec39..cb2b64686 100644 --- a/inc/lang/ca/lang.php +++ b/inc/lang/ca/lang.php @@ -5,6 +5,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Carles Bellver * @author Carles Bellver + * @author daniel@6temes.cat */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -27,7 +28,7 @@ $lang['btn_revs'] = 'Revisions anteriors'; $lang['btn_recent'] = 'Canvis recents'; $lang['btn_upload'] = 'Penja'; $lang['btn_cancel'] = 'Cancel·la'; -$lang['btn_index'] = 'Índex'; +$lang['btn_index'] = 'Mapa del lloc'; $lang['btn_secedit'] = 'Edita'; $lang['btn_login'] = 'Entra'; $lang['btn_logout'] = 'Surt'; @@ -38,14 +39,15 @@ $lang['btn_back'] = 'Enrere'; $lang['btn_backlink'] = 'Què hi enllaça'; $lang['btn_backtomedia'] = 'Torna a la selecció de fitxers'; $lang['btn_subscribe'] = 'Subscripció a canvis d\'aquesta pàgina'; -$lang['btn_unsubscribe'] = 'Cancel·la subscripció a pàgina'; $lang['btn_profile'] = 'Actualització del perfil'; $lang['btn_reset'] = 'Reinicia'; +$lang['btn_resendpwd'] = 'Estableix una nova contrasenya'; $lang['btn_draft'] = 'Edita esborrany'; $lang['btn_recover'] = 'Recupera esborrany'; $lang['btn_draftdel'] = 'Suprimeix esborrany'; $lang['btn_revert'] = 'Restaura'; $lang['btn_register'] = 'Registra\'m'; +$lang['btn_apply'] = 'Aplica'; $lang['loggedinas'] = 'Heu entrat com'; $lang['user'] = 'Nom d\'usuari'; $lang['pass'] = 'Contrasenya'; @@ -75,6 +77,7 @@ $lang['profnoempty'] = 'No es pot deixar en blanc el nom o l\'adreça $lang['profchanged'] = 'El perfil d\'usuari s\'ha actualitzat correctament.'; $lang['pwdforget'] = 'Heu oblidat la contrasenya? Podeu obtenir-ne una de nova.'; $lang['resendna'] = 'Aquest wiki no permet tornar a enviar la contrasenya.'; +$lang['resendpwd'] = 'Estableix una nova contrasenya per'; $lang['resendpwdmissing'] = 'Heu d\'emplenar tots els camps.'; $lang['resendpwdnouser'] = 'No s\'ha pogut trobar aquest usuari a la base de dades.'; $lang['resendpwdbadauth'] = 'Aquest codi d\'autenticació no és vàlid. Assegureu-vos d\'utilitzar l\'enllaç de confirmació complet.'; @@ -87,10 +90,52 @@ $lang['searchmedia_in'] = 'Cerca en: %s'; $lang['txt_upload'] = 'Trieu el fitxer que voleu penjar'; $lang['txt_filename'] = 'Introduïu el nom wiki (opcional)'; $lang['txt_overwrt'] = 'Sobreescriu el fitxer actual'; +$lang['maxuploadsize'] = 'Puja com a màxim %s per arxiu.'; $lang['lockedby'] = 'Actualment blocat per:'; $lang['lockexpire'] = 'Venciment del blocatge:'; -$lang['js']['willexpire'] = 'El blocatge per a editar aquesta pàgina venç d\'aquí a un minut.\nUtilitzeu la visualització prèvia per reiniciar el rellotge i evitar conflictes.'; -$lang['js']['notsavedyet'] = "Heu fet canvis que es perdran si no els deseu.\nVoleu continuar?"; +$lang['js']['willexpire'] = 'El blocatge per a editar aquesta pàgina venç d\'aquí a un minut.\nUtilitzeu la visualització prèvia per reiniciar el rellotge i evitar conflictes.'; +$lang['js']['notsavedyet'] = 'Heu fet canvis que es perdran si no els deseu. +Voleu continuar?'; +$lang['js']['searchmedia'] = 'Cerca fitxers'; +$lang['js']['keepopen'] = 'Manté la finestra oberta'; +$lang['js']['hidedetails'] = 'Oculta detalls'; +$lang['js']['mediatitle'] = 'Propietats de l\'enllaç'; +$lang['js']['mediadisplay'] = 'Tipus d\'enllaç'; +$lang['js']['mediaalign'] = 'Alineació'; +$lang['js']['mediasize'] = 'Mida de la imatge'; +$lang['js']['mediatarget'] = 'Destí de l\'enllaç'; +$lang['js']['mediaclose'] = 'Tanca'; +$lang['js']['mediainsert'] = 'Inserta'; +$lang['js']['mediadisplayimg'] = 'Mostra la imatge'; +$lang['js']['mediadisplaylnk'] = 'Mostra només l\'enllaç'; +$lang['js']['mediasmall'] = 'Versió petita'; +$lang['js']['mediamedium'] = 'Versió mitjana'; +$lang['js']['medialarge'] = 'Versió gran'; +$lang['js']['mediaoriginal'] = 'Versió original'; +$lang['js']['medialnk'] = 'Enllaç a la pàgina de detalls'; +$lang['js']['mediadirect'] = 'Enllaç directe a l\'original'; +$lang['js']['medianolnk'] = 'No hi ha enllaç'; +$lang['js']['medianolink'] = 'No enllacis la imatge'; +$lang['js']['medialeft'] = 'Alinea la imatge a l\'esquerra.'; +$lang['js']['mediaright'] = 'Alinea la imatge a la dreta.'; +$lang['js']['mediacenter'] = 'Alinea la imatge al mig.'; +$lang['js']['medianoalign'] = 'No facis servir alineació.'; +$lang['js']['nosmblinks'] = 'Els enllaços amb recursos compartits de Windows només funcionen amb el Microsoft Internet Explorer. +Si voleu podeu copiar i enganxar l\'enllaç.'; +$lang['js']['linkwiz'] = 'Auxiliar d\'enllaços'; +$lang['js']['linkto'] = 'Enllaça a:'; +$lang['js']['del_confirm'] = 'Suprimiu aquesta entrada?'; +$lang['js']['restore_confirm'] = 'Vols realment restaurar aquesta versió?'; +$lang['js']['media_diff'] = 'Veure les diferències:'; +$lang['js']['media_diff_both'] = 'Un al costat de l\'altre'; +$lang['js']['media_diff_opacity'] = 'Resalta'; +$lang['js']['media_diff_portions'] = 'Llisca'; +$lang['js']['media_select'] = 'Escull els arxius'; +$lang['js']['media_upload_btn'] = 'Pujar'; +$lang['js']['media_done_btn'] = 'Fet'; +$lang['js']['media_drop'] = 'Arrossega aquí els arxius a pujar'; +$lang['js']['media_cancel'] = 'esborra'; +$lang['js']['media_overwrt'] = 'Sobreescriu els arxius existents'; $lang['rssfailed'] = 'S\'ha produït un error en recollir aquesta alimentació: '; $lang['nothingfound'] = 'No s\'ha trobat res.'; $lang['mediaselect'] = 'Selecció de fitxers'; @@ -108,14 +153,7 @@ $lang['deletefail'] = 'No s\'ha pogut suprimir el fitxer "%s". Compro $lang['mediainuse'] = 'No s\'ha pogut suprimir el fitxer "%s". Encara s\'està utilitzant.'; $lang['namespaces'] = 'Espais'; $lang['mediafiles'] = 'Fitxers disponibles en'; -$lang['js']['searchmedia'] = 'Cerca fitxers'; -$lang['js']['keepopen'] = 'Manté la finestra oberta'; -$lang['js']['hidedetails'] = 'Oculta detalls'; -$lang['js']['nosmblinks'] = 'Els enllaços amb recursos compartits de Windows només funcionen amb el Microsoft Internet Explorer. -Si voleu podeu copiar i enganxar l\'enllaç.'; -$lang['js']['linkwiz'] = 'Auxiliar d\'enllaços'; -$lang['js']['linkto'] = 'Enllaça a:'; -$lang['js']['del_confirm'] = 'Suprimiu aquesta entrada?'; +$lang['accessdenied'] = 'No teniu permís per a veure aquesta pàgina.'; $lang['mediausage'] = 'Utilitzeu la sintaxi següent per referir-vos a aquest enllaç:'; $lang['mediaview'] = 'Mostra el fitxer original'; $lang['mediaroot'] = 'arrel'; @@ -131,6 +169,10 @@ $lang['current'] = 'actual'; $lang['yours'] = 'La vostra versió'; $lang['diff'] = 'Mostra diferències amb la versió actual'; $lang['diff2'] = 'Mostra diferències entre les revisions seleccionades'; +$lang['difflink'] = 'Enllaç a la visualització de la comparació'; +$lang['diff_type'] = 'Veieu les diferències:'; +$lang['diff_inline'] = 'En línia'; +$lang['diff_side'] = 'Un al costat de l\'altre'; $lang['line'] = 'Línia'; $lang['breadcrumb'] = 'Camí'; $lang['youarehere'] = 'Sou aquí'; @@ -143,10 +185,20 @@ $lang['external_edit'] = 'edició externa'; $lang['summary'] = 'Resum d\'edició'; $lang['noflash'] = 'Per a visualitzar aquest contingut necessiteu el connector d\'Adobe Flash.'; $lang['download'] = 'Baixa el fragment'; +$lang['tools'] = 'Eines'; +$lang['user_tools'] = 'Eines de l\'usuari'; +$lang['site_tools'] = 'Eines del lloc'; +$lang['page_tools'] = 'Eines de la pàgina'; +$lang['skip_to_content'] = 'salta al contingut'; +$lang['sidebar'] = 'Barra lateral'; $lang['mail_newpage'] = 'pàgina afegida:'; $lang['mail_changed'] = 'pàgina modificada:'; $lang['mail_new_user'] = 'nou usuari:'; $lang['mail_upload'] = 'fitxer penjat:'; +$lang['changes_type'] = 'Veure els canvis de'; +$lang['pages_changes'] = 'Pàgines'; +$lang['media_changes'] = 'Arxius gràfics'; +$lang['both_changes'] = 'Pàgines i arxius gràfics'; $lang['qb_bold'] = 'Negreta'; $lang['qb_italic'] = 'Cursiva'; $lang['qb_underl'] = 'Subratllat'; @@ -187,13 +239,27 @@ $lang['img_copyr'] = 'Copyright'; $lang['img_format'] = 'Format'; $lang['img_camera'] = 'Càmera'; $lang['img_keywords'] = 'Paraules clau'; -$lang['subscribe_success'] = 'S\'ha afegit %s a la llista de subscripcions de %s'; -$lang['subscribe_error'] = 'S\'ha produït un error en afegir %s a la llista de subscripcions de %s'; -$lang['subscribe_noaddress'] = 'No hi ha cap adreça de correu associada al vostre nom d\'usuari. No se us ha pogut afegir a la llista de subscripcions.'; -$lang['unsubscribe_success'] = '%s ha estat suprimit de la llista de subscripcions de %s'; -$lang['unsubscribe_error'] = 'S\'ha produït un error en suprimir %s de la llista de subscripcions de %s'; +$lang['img_width'] = 'Ample'; +$lang['img_height'] = 'Alçada'; +$lang['subscr_subscribe_success'] = 'S\'ha afegit %s a la llista de subscripcions per %s'; +$lang['subscr_subscribe_error'] = 'Hi ha hagut un error a l\'afegir %s a la llista per %s'; +$lang['subscr_subscribe_noaddress'] = 'No hi ha cap adreça associada pel vostre nom d\'usuari, no podeu ser afegit a la llista de subscripcions'; +$lang['subscr_unsubscribe_success'] = 'S\'ha esborrat %s de la llista de subscripcions per %s'; +$lang['subscr_unsubscribe_error'] = 'Hi ha hagut un error a l\'esborrar %s de la llista de subscripcions per %s'; +$lang['subscr_already_subscribed'] = '%s ja està subscrit a %s'; +$lang['subscr_not_subscribed'] = '%s no està subscrit a %s'; +$lang['subscr_m_not_subscribed'] = 'En aquests moments no esteu subscrit a l\'actual pàgina o espai'; +$lang['subscr_m_new_header'] = 'Afegeix subcripció'; +$lang['subscr_m_current_header'] = 'Subscripcions actuals'; +$lang['subscr_m_unsubscribe'] = 'Donar-se de baixa'; +$lang['subscr_m_subscribe'] = 'Donar-se d\'alta'; +$lang['subscr_m_receive'] = 'Rebre'; +$lang['subscr_style_every'] = 'Envia\'m un correu electrònic per a cada canvi'; +$lang['subscr_style_digest'] = 'Envia\'m un correu electrònic amb un resum dels canvis per a cada pàgina (cada %.2f dies)'; +$lang['subscr_style_list'] = 'llistat de pàgines canviades des de l\'últim correu electrònic (cada %.2f dies)'; $lang['authmodfailed'] = 'La configuració de l\'autenticació d\'usuaris és errònia. Informeu els administradors del wiki.'; $lang['authtempfail'] = 'L\'autenticació d\'usuaris no està disponible temporalment. Si aquesta situació persisteix, si us plau informeu els administradors del wiki.'; +$lang['authpwdexpire'] = 'La vostra contrasenya caducarà en %d dies, l\'hauríeu de canviar aviat.'; $lang['i_chooselang'] = 'Trieu l\'idioma'; $lang['i_installer'] = 'Instal·lador de DokuWiki'; $lang['i_wikiname'] = 'Nom del wiki'; @@ -208,13 +274,14 @@ $lang['i_confexists'] = '%s ja existeix'; $lang['i_writeerr'] = 'No es pot crear %s. Comproveu els permisos del directori i/o del fitxer i creeu el fitxer manualment.'; $lang['i_badhash'] = 'dokuwiki.php no reconegut o modificat (hash=%s)'; $lang['i_badval'] = '%s - valor il·legal o buit'; -$lang['i_success'] = 'La configuració s\'ha acabat amb èxit. Ara podeu suprimir el fitxer install.php. Aneu al vostre nou DokuWiki.'; -$lang['i_failure'] = 'S\'han produït alguns errors en escriure els fitxers de configuració. Potser caldrà que els arregleu manualment abans d\'utilitzar el vostre nou DokuWiki.'; +$lang['i_success'] = 'La configuració s\'ha acabat amb èxit. Ara podeu suprimir el fitxer install.php. Aneu al vostre nou DokuWiki.'; +$lang['i_failure'] = 'S\'han produït alguns errors en escriure els fitxers de configuració. Potser caldrà que els arregleu manualment abans d\'utilitzar el vostre nou DokuWiki.'; $lang['i_policy'] = 'Política ACL inicial'; $lang['i_pol0'] = 'Wiki obert (tothom pot llegir, escriure i penjar fitxers)'; $lang['i_pol1'] = 'Wiki públic (tothom pot llegir, els usuaris registrats poden escriure i penjar fitxers)'; $lang['i_pol2'] = 'Wiki tancat (només els usuaris registrats poden llegir, escriure i penjar fitxers)'; $lang['i_retry'] = 'Reintenta'; +$lang['i_license'] = 'Escolliu el tipus de llicència que voleu fer servir per al vostre contingut:'; $lang['recent_global'] = 'Esteu veient els canvis recents de l\'espai %s. També podeu veure els canvis recents de tot el wiki.'; $lang['years'] = 'fa %d anys'; $lang['months'] = 'fa %d mesos'; @@ -223,3 +290,27 @@ $lang['days'] = 'fa %d dies'; $lang['hours'] = 'fa %d hores'; $lang['minutes'] = 'fa %d minuts'; $lang['seconds'] = 'fa %d segons'; +$lang['wordblock'] = 'El vostre canvi no s\'ha guardat perquè conté text blocat (spam)'; +$lang['media_uploadtab'] = 'Puja'; +$lang['media_searchtab'] = 'Busca'; +$lang['media_file'] = 'Fitxer'; +$lang['media_viewtab'] = 'Mostra'; +$lang['media_edittab'] = 'Edita'; +$lang['media_historytab'] = 'Històric'; +$lang['media_list_thumbs'] = 'Miniatura'; +$lang['media_list_rows'] = 'Files'; +$lang['media_sort_name'] = 'Nom'; +$lang['media_sort_date'] = 'Data'; +$lang['media_namespaces'] = 'Escolliu l\'espai'; +$lang['media_files'] = 'Arxius a %s'; +$lang['media_upload'] = 'Puja a %s'; +$lang['media_search'] = 'Busca a %s'; +$lang['media_view'] = '%s'; +$lang['media_viewold'] = '%s a %s'; +$lang['media_edit'] = 'Edita %s'; +$lang['media_history'] = 'Històric de %s'; +$lang['media_meta_edited'] = 'metadata editada'; +$lang['media_perm_read'] = 'No teniu permisos suficients per a llegir arxius.'; +$lang['media_perm_upload'] = 'No teniu permisos suficients per a pujar arxius'; +$lang['media_update'] = 'Puja la nova versió'; +$lang['media_restore'] = 'Restaura aquesta versió'; diff --git a/inc/lang/ca/mailwrap.html b/inc/lang/ca/mailwrap.html new file mode 100644 index 000000000..ed3bb6e9d --- /dev/null +++ b/inc/lang/ca/mailwrap.html @@ -0,0 +1,13 @@ + + +@TITLE@ + + + + +@HTMLBODY@ + +

+Aquest correu electrònic ha estat generat per DokuWiki a @DOKUWIKIURL@. + + \ No newline at end of file diff --git a/inc/lang/ca/resetpwd.txt b/inc/lang/ca/resetpwd.txt new file mode 100644 index 000000000..565f1d5b0 --- /dev/null +++ b/inc/lang/ca/resetpwd.txt @@ -0,0 +1,3 @@ +===== Establiu una nova contrasenya ===== + +Introdueixi una nova contrasenya pel seu compte a aquest wiki. \ No newline at end of file diff --git a/inc/lang/ca/subscr_digest.txt b/inc/lang/ca/subscr_digest.txt new file mode 100644 index 000000000..2b95f97a5 --- /dev/null +++ b/inc/lang/ca/subscr_digest.txt @@ -0,0 +1,21 @@ +Hola! + +La pàgina @PAGE@ al wiki @TITLE@ ha canviat. +A continuació podeu veure els canvis: + +-------------------------------------------------------- +@DIFF@ +-------------------------------------------------------- + +Versió anterior: @OLDPAGE@ +Nova versió: @NEWPAGE@ + +Si voleu cancel·lar les notificacions per a la pàgina, accediu al wiki a +@DOKUWIKIURL@, visiteu +@SUBSCRIBE@ +i doneu-vos de baixa dels canvis de la pàgina o de l'espai. + + +-- +Aquest mail ha estat generat per DokuWiki a +@DOKUWIKIURL@ \ No newline at end of file diff --git a/inc/lang/ca/subscr_form.txt b/inc/lang/ca/subscr_form.txt new file mode 100644 index 000000000..d3679454f --- /dev/null +++ b/inc/lang/ca/subscr_form.txt @@ -0,0 +1,3 @@ +===== Gestió de les Subscripcions ===== + +Aquesta pàgina podeu gestiona les vostres subscripcions per a les pàgines i els espais actuals. \ No newline at end of file diff --git a/inc/lang/ca/subscr_list.txt b/inc/lang/ca/subscr_list.txt new file mode 100644 index 000000000..56bcad545 --- /dev/null +++ b/inc/lang/ca/subscr_list.txt @@ -0,0 +1,21 @@ +Hola! + +Alguna(es) pàgina(es) de l'espai @PAGE@ al wiki @TITLE@ han canviat. +A continuació podeu veure els canvis: + +-------------------------------------------------------- +@DIFF@ +-------------------------------------------------------- + +Versió anterior: @OLDPAGE@ +Nova versió: @NEWPAGE@ + +Si voleu cancel·lar les notificacions per a la pàgina, accediu al wiki a +@DOKUWIKIURL@, visiteu +@SUBSCRIBE@ +i doneu-vos de baixa dels canvis de la pàgina o de l'espai. + + +-- +Aquest mail ha estat generat per DokuWiki a +@DOKUWIKIURL@ \ No newline at end of file diff --git a/lib/plugins/acl/lang/ca/lang.php b/lib/plugins/acl/lang/ca/lang.php index 10f656062..183db711b 100644 --- a/lib/plugins/acl/lang/ca/lang.php +++ b/lib/plugins/acl/lang/ca/lang.php @@ -7,6 +7,7 @@ * @author Carles Bellver * @author carles.bellver@gmail.com * @author carles.bellver@cent.uji.es + * @author daniel@6temes.cat */ $lang['admin_acl'] = 'Gestió de la Llista de Control d\'Accés'; $lang['acl_group'] = 'Grup'; diff --git a/lib/plugins/config/lang/ca/lang.php b/lib/plugins/config/lang/ca/lang.php index 84680450a..205d7aa6b 100644 --- a/lib/plugins/config/lang/ca/lang.php +++ b/lib/plugins/config/lang/ca/lang.php @@ -6,6 +6,7 @@ * @author carles.bellver@gmail.com * @author carles.bellver@cent.uji.es * @author Carles Bellver + * @author daniel@6temes.cat */ $lang['menu'] = 'Paràmetres de configuració'; $lang['error'] = 'Els paràmetres no s\'han pogut actualitzar per causa d\'un valor incorrecte Reviseu els canvis i torneu a enviar-los.
Els valors incorrectes es ressaltaran amb un marc vermell.'; @@ -28,6 +29,8 @@ $lang['_anti_spam'] = 'Paràmetres anti-brossa'; $lang['_editing'] = 'Paràmetres d\'edició'; $lang['_links'] = 'Paràmetres d\'enllaços'; $lang['_media'] = 'Paràmetres de mitjans'; +$lang['_notifications'] = 'Paràmetres de notificació'; +$lang['_syndication'] = 'Paràmetres de sindicació'; $lang['_advanced'] = 'Paràmetres avançats'; $lang['_network'] = 'Paràmetres de xarxa'; $lang['_plugin_sufix'] = 'Paràmetres de connectors'; @@ -35,25 +38,29 @@ $lang['_template_sufix'] = 'Paràmetres de plantilla'; $lang['_msg_setting_undefined'] = 'Falten metadades de paràmetre.'; $lang['_msg_setting_no_class'] = 'Falta classe de paràmetre.'; $lang['_msg_setting_no_default'] = 'No hi ha valor per defecte.'; -$lang['fmode'] = 'Mode de creació de fitxers'; -$lang['dmode'] = 'Mode de creació de directoris'; -$lang['lang'] = 'Idioma'; -$lang['basedir'] = 'Directori base'; -$lang['baseurl'] = 'URL base'; -$lang['savedir'] = 'Directori per desar les dades'; -$lang['start'] = 'Nom de la pàgina d\'inici'; $lang['title'] = 'Títol del wiki'; +$lang['start'] = 'Nom de la pàgina d\'inici'; +$lang['lang'] = 'Idioma'; $lang['template'] = 'Plantilla'; +$lang['tagline'] = 'Lema (si la plantilla ho suporta)'; +$lang['sidebar'] = 'Nom de la barra lateral (si la plantilla ho suporta). Si ho deixeu buit, la barra lateral es deshabilitarà.'; $lang['license'] = 'Amb quina llicència voleu publicar el contingut?'; -$lang['fullpath'] = 'Mostra el camí complet de les pàgines al peu'; +$lang['savedir'] = 'Directori per desar les dades'; +$lang['basedir'] = 'Directori base'; +$lang['baseurl'] = 'URL base'; +$lang['cookiedir'] = 'Adreça per a les galetes. Si ho deixeu en blanc, es farà servir la URL base.'; +$lang['dmode'] = 'Mode de creació de directoris'; +$lang['fmode'] = 'Mode de creació de fitxers'; +$lang['allowdebug'] = 'Permet depuració inhabiliteu si no és necessari'; $lang['recent'] = 'Canvis recents'; +$lang['recent_days'] = 'Quantitat de canvis recents que es mantenen (dies)'; $lang['breadcrumbs'] = 'Nombre d\'engrunes'; $lang['youarehere'] = 'Camí d\'engrunes jeràrquic'; +$lang['fullpath'] = 'Mostra el camí complet de les pàgines al peu'; $lang['typography'] = 'Substitucions tipogràfiques'; -$lang['htmlok'] = 'Permet HTML incrustat'; -$lang['phpok'] = 'Permet PHP incrustat'; $lang['dformat'] = 'Format de data (vg. la funció PHP strftime)'; $lang['signature'] = 'Signatura'; +$lang['showuseras'] = 'Què cal visualitzar quan es mostra el darrer usuari que ha editat la pàgina'; $lang['toptoclevel'] = 'Nivell superior per a la taula de continguts'; $lang['tocminheads'] = 'Quantitat mínima d\'encapçalaments que determina si es construeix o no la taula de continguts.'; $lang['maxtoclevel'] = 'Nivell màxim per a la taula de continguts'; @@ -61,15 +68,8 @@ $lang['maxseclevel'] = 'Nivell màxim d\'edició de seccions'; $lang['camelcase'] = 'Utilitza CamelCase per als enllaços'; $lang['deaccent'] = 'Noms de pàgina nets'; $lang['useheading'] = 'Utilitza el primer encapçalament per als noms de pàgina'; -$lang['refcheck'] = 'Comprova la referència en els fitxers de mitjans'; -$lang['refshow'] = 'Nombre de referències de mitjans per mostrar'; -$lang['allowdebug'] = 'Permet depuració inhabiliteu si no és necessari'; -$lang['usewordblock'] = 'Bloca brossa per llista de paraules'; -$lang['indexdelay'] = 'Retard abans d\'indexar (segons)'; -$lang['relnofollow'] = 'Utilitza rel="nofollow" en enllaços externs'; -$lang['mailguard'] = 'Ofusca les adreces de correu'; -$lang['iexssprotect'] = 'Comprova codi HTML o Javascript maligne en els fitxers penjats'; -$lang['showuseras'] = 'Què cal visualitzar quan es mostra el darrer usuari que ha editat la pàgina'; +$lang['sneaky_index'] = 'Per defecte, DokuWiki mostrarà tots els espai en la visualització d\'índex. Si activeu aquest paràmetre, s\'ocultaran aquells espais en els quals l\'usuari no té accés de lectura. Això pot fer que s\'ocultin subespais que sí que són accessibles. En algunes configuracions ACL pot fer que l\'índex resulti inutilitzable.'; +$lang['hidepages'] = 'Oculta pàgines coincidents (expressions regulars)'; $lang['useacl'] = 'Utilitza llistes de control d\'accés'; $lang['autopasswd'] = 'Generació automàtica de contrasenyes'; $lang['authtype'] = 'Rerefons d\'autenticació'; @@ -78,54 +78,60 @@ $lang['defaultgroup'] = 'Grup per defecte'; $lang['superuser'] = 'Superusuari: un grup o usuari amb accés complet a totes les pàgines i funcions independentment dels paràmetres ACL'; $lang['manager'] = 'Administrador: un grup o usuari amb accés a certes funcions d\'administració'; $lang['profileconfirm'] = 'Confirma amb contrasenya els canvis en el perfil'; +$lang['rememberme'] = 'Permet galetes de sessió permanents ("recorda\'m")'; $lang['disableactions'] = 'Inhabilita accions DokuWiki'; $lang['disableactions_check'] = 'Revisa'; $lang['disableactions_subscription'] = 'Subscripció/cancel·lació'; $lang['disableactions_wikicode'] = 'Mostra/exporta font'; $lang['disableactions_other'] = 'Altres accions (separades per comes)'; -$lang['sneaky_index'] = 'Per defecte, DokuWiki mostrarà tots els espai en la visualització d\'índex. Si activeu aquest paràmetre, s\'ocultaran aquells espais en els quals l\'usuari no té accés de lectura. Això pot fer que s\'ocultin subespais que sí que són accessibles. En algunes configuracions ACL pot fer que l\'índex resulti inutilitzable.'; $lang['auth_security_timeout'] = 'Temps d\'espera de seguretat en l\'autenticació (segons)'; $lang['securecookie'] = 'Les galetes que s\'han creat via HTTPS, només s\'han d\'enviar des del navegador per HTTPS? Inhabiliteu aquesta opció si només l\'inici de sessió del wiki es fa amb SSL i la navegació del wiki es fa sense seguretat.'; +$lang['usewordblock'] = 'Bloca brossa per llista de paraules'; +$lang['relnofollow'] = 'Utilitza rel="nofollow" en enllaços externs'; +$lang['indexdelay'] = 'Retard abans d\'indexar (segons)'; +$lang['mailguard'] = 'Ofusca les adreces de correu'; +$lang['iexssprotect'] = 'Comprova codi HTML o Javascript maligne en els fitxers penjats'; +$lang['usedraft'] = 'Desa automàticament un esborrany mentre s\'edita'; +$lang['htmlok'] = 'Permet HTML incrustat'; +$lang['phpok'] = 'Permet PHP incrustat'; +$lang['locktime'] = 'Durada màxima dels fitxers de bloqueig (segons)'; +$lang['cachetime'] = 'Durada màxima de la memòria cau (segons)'; +$lang['target____wiki'] = 'Finestra de destinació en enllaços interns'; +$lang['target____interwiki'] = 'Finestra de destinació en enllaços interwiki'; +$lang['target____extern'] = 'Finestra de destinació en enllaços externs'; +$lang['target____media'] = 'Finestra de destinació en enllaços de mitjans'; +$lang['target____windows'] = 'Finestra de destinació en enllaços de Windows'; +$lang['refcheck'] = 'Comprova la referència en els fitxers de mitjans'; +$lang['refshow'] = 'Nombre de referències de mitjans per mostrar'; +$lang['gdlib'] = 'Versió GD Lib'; +$lang['im_convert'] = 'Camí de la utilitat convert d\'ImageMagick'; +$lang['jpg_quality'] = 'Qualitat de compressió JPEG (0-100)'; +$lang['fetchsize'] = 'Mida màxima (bytes) que fetch.php pot baixar d\'un lloc extern'; +$lang['subscribers'] = 'Habilita la subscripció a pàgines'; +$lang['notify'] = 'Envia notificacions de canvis a aquesta adreça de correu'; +$lang['registernotify'] = 'Envia informació sobre nous usuaris registrats a aquesta adreça de correu'; +$lang['mailfrom'] = 'Adreça de correu remitent per a missatges automàtics'; +$lang['sitemap'] = 'Genera mapa del lloc en format Google (dies)'; +$lang['rss_type'] = 'Tipus de canal XML'; +$lang['rss_linkto'] = 'Destinació dels enllaços en el canal XML'; +$lang['rss_content'] = 'Què es mostrarà en els elements del canal XML?'; +$lang['rss_update'] = 'Interval d\'actualització del canal XML (segons)'; +$lang['rss_show_summary'] = 'Mostra resum en els títols del canal XML'; $lang['updatecheck'] = 'Comprova actualitzacions i avisos de seguretat. DokuWiki necessitarà contactar amb update.dokuwiki.org per utilitzar aquesta característica.'; $lang['userewrite'] = 'Utilitza URL nets'; $lang['useslash'] = 'Utilitza la barra / com a separador d\'espais en els URL'; -$lang['usedraft'] = 'Desa automàticament un esborrany mentre s\'edita'; $lang['sepchar'] = 'Separador de paraules en els noms de pàgina'; $lang['canonical'] = 'Utilitza URL canònics complets'; $lang['autoplural'] = 'Comprova formes plurals en els enllaços'; $lang['compression'] = 'Mètode de compressió per als fitxers de les golfes'; -$lang['cachetime'] = 'Durada màxima de la memòria cau (segons)'; -$lang['locktime'] = 'Durada màxima dels fitxers de bloqueig (segons)'; -$lang['fetchsize'] = 'Mida màxima (bytes) que fetch.php pot baixar d\'un lloc extern'; -$lang['notify'] = 'Envia notificacions de canvis a aquesta adreça de correu'; -$lang['registernotify'] = 'Envia informació sobre nous usuaris registrats a aquesta adreça de correu'; -$lang['mailfrom'] = 'Adreça de correu remitent per a missatges automàtics'; $lang['gzip_output'] = 'Codifica contingut xhtml com a gzip'; -$lang['gdlib'] = 'Versió GD Lib'; -$lang['im_convert'] = 'Camí de la utilitat convert d\'ImageMagick'; -$lang['jpg_quality'] = 'Qualitat de compressió JPEG (0-100)'; -$lang['subscribers'] = 'Habilita la subscripció a pàgines'; $lang['compress'] = 'Sortida CSS i Javascript compacta'; -$lang['hidepages'] = 'Oculta pàgines coincidents (expressions regulars)'; $lang['send404'] = 'Envia "HTTP 404/Page Not Found" per a les pàgines inexistents'; -$lang['sitemap'] = 'Genera mapa del lloc en format Google (dies)'; $lang['broken_iua'] = 'No funciona en el vostre sistema la funció ignore_user_abort? Això podria malmetre l\'índex de cerques. Amb IIS+PHP/CGI se sap que no funciona. Vg. Bug 852 per a més informació.'; $lang['xsendfile'] = 'Utilitza la capçalera X-Sendfile perquè el servidor web distribueixi fitxers estàtics. No funciona amb tots els servidors web.'; $lang['renderer_xhtml'] = 'Renderitzador que cal utilitzar per a la sortida principal (xhtml) del wiki'; $lang['renderer__core'] = '%s (ànima del dokuwiki)'; $lang['renderer__plugin'] = '%s (connector)'; -$lang['rememberme'] = 'Permet galetes de sessió permanents ("recorda\'m")'; -$lang['rss_type'] = 'Tipus de canal XML'; -$lang['rss_linkto'] = 'Destinació dels enllaços en el canal XML'; -$lang['rss_content'] = 'Què es mostrarà en els elements del canal XML?'; -$lang['rss_update'] = 'Interval d\'actualització del canal XML (segons)'; -$lang['recent_days'] = 'Quantitat de canvis recents que es mantenen (dies)'; -$lang['rss_show_summary'] = 'Mostra resum en els títols del canal XML'; -$lang['target____wiki'] = 'Finestra de destinació en enllaços interns'; -$lang['target____interwiki'] = 'Finestra de destinació en enllaços interwiki'; -$lang['target____extern'] = 'Finestra de destinació en enllaços externs'; -$lang['target____media'] = 'Finestra de destinació en enllaços de mitjans'; -$lang['target____windows'] = 'Finestra de destinació en enllaços de Windows'; $lang['proxy____host'] = 'Nom del servidor intermediari'; $lang['proxy____port'] = 'Port del servidor intermediari'; $lang['proxy____user'] = 'Nom d\'usuari del servidor intermediari'; diff --git a/lib/plugins/plugin/lang/ca/lang.php b/lib/plugins/plugin/lang/ca/lang.php index 0e3ef05df..5c7933666 100644 --- a/lib/plugins/plugin/lang/ca/lang.php +++ b/lib/plugins/plugin/lang/ca/lang.php @@ -6,6 +6,7 @@ * @author carles.bellver@gmail.com * @author carles.bellver@cent.uji.es * @author Carles Bellver + * @author daniel@6temes.cat */ $lang['menu'] = 'Gestió de connectors'; $lang['download'] = 'Baixa i instal·la un nou connector'; @@ -51,3 +52,4 @@ $lang['enabled'] = 'S\'ha habilitat el connector %s.'; $lang['notenabled'] = 'No s\'ha pogut habilitar el connector %s. Comproveu els permisos dels fitxers.'; $lang['disabled'] = 'S\'ha inhabilitat el connector %s.'; $lang['notdisabled'] = 'No s\'ha pogut inhabilitar el connector %s. Comproveu els permisos dels fitxers.'; +$lang['packageinstalled'] = 'El paquet del connector (%d plugins(s): %s) s\'ha instal·lat correctament.'; diff --git a/lib/plugins/popularity/lang/ca/lang.php b/lib/plugins/popularity/lang/ca/lang.php index e6fdcd533..b30846118 100644 --- a/lib/plugins/popularity/lang/ca/lang.php +++ b/lib/plugins/popularity/lang/ca/lang.php @@ -5,6 +5,7 @@ * @author Carles Bellver * @author Carles Bellver * @author carles.bellver@cent.uji.es + * @author daniel@6temes.cat */ $lang['name'] = 'Retroacció sobre popularitat (pot trigar una mica a carregar)'; $lang['submit'] = 'Envia dades'; diff --git a/lib/plugins/revert/lang/ca/lang.php b/lib/plugins/revert/lang/ca/lang.php index b8800911f..4f4d518ea 100644 --- a/lib/plugins/revert/lang/ca/lang.php +++ b/lib/plugins/revert/lang/ca/lang.php @@ -6,6 +6,7 @@ * @author carles.bellver@gmail.com * @author carles.bellver@cent.uji.es * @author Carles Bellver + * @author daniel@6temes.cat */ $lang['menu'] = 'Gestió de reversions'; $lang['filter'] = 'Cerca pàgines brossa'; diff --git a/lib/plugins/usermanager/lang/ca/lang.php b/lib/plugins/usermanager/lang/ca/lang.php index 445556973..6debd73ca 100644 --- a/lib/plugins/usermanager/lang/ca/lang.php +++ b/lib/plugins/usermanager/lang/ca/lang.php @@ -6,6 +6,7 @@ * @author carles.bellver@gmail.com * @author carles.bellver@cent.uji.es * @author Carles Bellver + * @author daniel@6temes.cat */ $lang['menu'] = 'Gestió d\'usuaris'; $lang['noauth'] = '(l\'autenticació d\'usuaris no està disponible)'; -- cgit v1.2.3 From e6c4a8221e93692572a1e78b9319a94b5ba07a0c Mon Sep 17 00:00:00 2001 From: Erdem Date: Fri, 18 Jan 2013 10:08:48 +0100 Subject: Turkish language update --- inc/lang/tr/lang.php | 55 ++++++++++++++++++++++++++++++-- inc/lang/tr/resetpwd.txt | 3 ++ lib/plugins/acl/lang/tr/lang.php | 1 + lib/plugins/config/lang/tr/lang.php | 47 ++++++++++++++------------- lib/plugins/plugin/lang/tr/lang.php | 1 + lib/plugins/popularity/lang/tr/lang.php | 2 ++ lib/plugins/revert/lang/tr/lang.php | 1 + lib/plugins/usermanager/lang/tr/lang.php | 1 + 8 files changed, 85 insertions(+), 26 deletions(-) create mode 100644 inc/lang/tr/resetpwd.txt diff --git a/inc/lang/tr/lang.php b/inc/lang/tr/lang.php index a8d8c5ac9..5430905b1 100644 --- a/inc/lang/tr/lang.php +++ b/inc/lang/tr/lang.php @@ -8,6 +8,7 @@ * @author Cihan Kahveci * @author Yavuz Selim * @author Caleb Maclennan + * @author farukerdemoncel@gmail.com */ $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; @@ -43,11 +44,14 @@ $lang['btn_backtomedia'] = 'Çokluortam dosyası seçimine dön'; $lang['btn_subscribe'] = 'Sayfa Değişikliklerini Bildir'; $lang['btn_profile'] = 'Kullanıcı Bilgilerini Güncelle'; $lang['btn_reset'] = 'Sıfırla'; +$lang['btn_resendpwd'] = 'Yeni şifre belirle'; $lang['btn_draft'] = 'Taslağı düzenle'; $lang['btn_recover'] = 'Taslağı geri yükle'; $lang['btn_draftdel'] = 'Taslağı sil'; $lang['btn_revert'] = 'Geri Yükle'; $lang['btn_register'] = 'Kayıt ol'; +$lang['btn_apply'] = 'Uygula'; +$lang['btn_media'] = 'Çokluortam Yöneticisi'; $lang['loggedinas'] = 'Giriş ismi'; $lang['user'] = 'Kullanıcı ismi'; $lang['pass'] = 'Parola'; @@ -77,6 +81,7 @@ $lang['profnoempty'] = 'Boş isim veya e-posta adresine izin verilmiyo $lang['profchanged'] = 'Kullanıcı bilgileri başarıyla değiştirildi.'; $lang['pwdforget'] = 'Parolanızı mı unuttunuz? Yeni bir parola alın'; $lang['resendna'] = 'Bu wiki parolayı tekrar göndermeyi desteklememektedir.'; +$lang['resendpwd'] = 'İçin yeni şifre belirle'; $lang['resendpwdmissing'] = 'Üzgünüz, tüm alanları doldurmalısınız.'; $lang['resendpwdnouser'] = 'Üzgünüz, veritabanımızda bu kullanıcıyı bulamadık.'; $lang['resendpwdbadauth'] = 'Üzgünüz, bu doğrulama kodu doğru değil. Doğrulama linkini tam olarak kullandığınıza emin olun.'; @@ -91,7 +96,7 @@ $lang['txt_filename'] = 'Dosya adı (zorunlu değil)'; $lang['txt_overwrt'] = 'Mevcut dosyanın üstüne yaz'; $lang['lockedby'] = 'Şu an şunun tarafından kilitli:'; $lang['lockexpire'] = 'Kilitin açılma tarihi:'; -$lang['js']['willexpire'] = 'Bu sayfayı değiştirme kilidinin süresi yaklaşık bir dakika içinde geçecek.\nÇakışmaları önlemek için önizleme tuşunu kullanarak kilit sayacını sıfırla.'; +$lang['js']['willexpire'] = 'Bu sayfayı değiştirme kilidinin süresi yaklaşık bir dakika içinde geçecek.\nÇakışmaları önlemek için önizleme tuşunu kullanarak kilit sayacını sıfırla.'; $lang['js']['notsavedyet'] = 'Kaydedilmemiş değişiklikler kaybolacak. Devam etmek istiyor musunuz?'; $lang['js']['searchmedia'] = 'Dosyalar için Ara'; @@ -122,6 +127,14 @@ $lang['js']['nosmblinks'] = 'Windows paylaşımı sadece Microsoft Internet $lang['js']['linkwiz'] = 'Bağlantı sihirbazı'; $lang['js']['linkto'] = 'Bağlantı:'; $lang['js']['del_confirm'] = 'Bu girişi sil?'; +$lang['js']['restore_confirm'] = 'Bu sürüme geri dönmek istediğinizden emin misiniz?'; +$lang['js']['media_diff'] = 'Farkları gör:'; +$lang['js']['media_select'] = 'Dosyalar seç...'; +$lang['js']['media_upload_btn'] = 'Yükle'; +$lang['js']['media_done_btn'] = 'Bitti'; +$lang['js']['media_drop'] = 'Yüklemek istediğiniz dosyaları buraya bırakın'; +$lang['js']['media_cancel'] = 'kaldır'; +$lang['js']['media_overwrt'] = 'Var olan dosyaların üzerine yaz'; $lang['rssfailed'] = 'Bu beslemeyi çekerken hata oluştu: '; $lang['nothingfound'] = 'Hiçbir şey yok.'; $lang['mediaselect'] = 'Çokluortam dosyası seçimi'; @@ -172,6 +185,9 @@ $lang['mail_newpage'] = 'sayfa eklenme:'; $lang['mail_changed'] = 'sayfa değiştirilme:'; $lang['mail_new_user'] = 'yeni kullanıcı'; $lang['mail_upload'] = 'dosya yüklendi:'; +$lang['pages_changes'] = 'Sayfalar'; +$lang['media_changes'] = 'Çokluortam dosyaları'; +$lang['both_changes'] = 'Sayfalar ve çoklu ortam dosyaları'; $lang['qb_bold'] = 'Kalın Yazı'; $lang['qb_italic'] = 'Eğik Yazı'; $lang['qb_underl'] = 'Altı Çizgili Yazı'; @@ -209,8 +225,14 @@ $lang['img_copyr'] = 'Telif Hakkı'; $lang['img_format'] = 'Biçim'; $lang['img_camera'] = 'Fotoğraf Makinası'; $lang['img_keywords'] = 'Anahtar Sözcükler'; +$lang['img_width'] = 'Genişlik'; +$lang['img_height'] = 'Yükseklik'; +$lang['img_manager'] = 'Ortam oynatıcısında göster'; +$lang['subscr_m_subscribe'] = 'Kayıt ol'; +$lang['subscr_m_receive'] = 'Al'; $lang['authmodfailed'] = 'Yanlış kullanıcı onaylama ayarı. Lütfen Wiki yöneticisine bildiriniz.'; $lang['authtempfail'] = 'Kullanıcı doğrulama geçici olarak yapılamıyor. Eğer bu durum devam ederse lütfen Wiki yöneticine haber veriniz.'; +$lang['authpwdexpire'] = 'Şifreniz %d gün sonra geçersiz hale gelecek, yakın bir zamanda değiştirmelisiniz.'; $lang['i_chooselang'] = 'Dili seçiniz'; $lang['i_installer'] = 'Dokuwiki Kurulum Sihirbazı'; $lang['i_wikiname'] = 'Wiki Adı'; @@ -225,11 +247,38 @@ $lang['i_confexists'] = '%s zaten var'; $lang['i_writeerr'] = '%s oluşturulamadı. Dosya/Klasör izin ayarlarını gözden geçirip dosyayı elle oluşturmalısınız.'; $lang['i_badhash'] = 'dokuwiki.php tanınamadı ya da değiştirilmiş (hash=%s)'; $lang['i_badval'] = '%s - Yanlış veya boş değer'; -$lang['i_success'] = 'Kurulum başarıyla tamamlandı. Şimdi install.php dosyasını silebilirsiniz. Yeni DokuWikinizi kullanabilirsiniz.'; -$lang['i_failure'] = 'Ayar dosyalarını yazarken bazı hatalar oluştu. Yeni DokuWikinizi kullanmadan önce bu hatalarınızı elle düzeltmeniz gerekebilir.'; +$lang['i_success'] = 'Kurulum başarıyla tamamlandı. Şimdi install.php dosyasını silebilirsiniz. Yeni DokuWikinizi kullanabilirsiniz.'; +$lang['i_failure'] = 'Ayar dosyalarını yazarken bazı hatalar oluştu. Yeni DokuWikinizi kullanmadan önce bu hatalarınızı elle düzeltmeniz gerekebilir.'; $lang['i_policy'] = 'İlk ACL ayarı'; $lang['i_pol0'] = 'Tamamen Açık Wiki (herkes okuyabilir, yazabilir ve dosya yükleyebilir)'; $lang['i_pol1'] = 'Açık Wiki (herkes okuyabilir, ancak sadece üye olanlar yazabilir ve dosya yükleyebilir)'; $lang['i_pol2'] = 'Kapalı Wiki (sadece üye olanlar okuyabilir, yazabilir ve dosya yükleyebilir)'; $lang['i_retry'] = 'Tekrar Dene'; +$lang['i_license'] = 'Lütfen içeriği hangi lisans altında yayınlamak istediğniizi belirtin:'; $lang['recent_global'] = '%s namespace\'i içerisinde yapılan değişiklikleri görüntülemektesiniz. Wiki\'deki tüm değişiklikleri de bu adresten görebilirsiniz. '; +$lang['years'] = '%d yıl önce'; +$lang['months'] = '%d ay önce'; +$lang['weeks'] = '%d hafta önce'; +$lang['days'] = '%d gün önce'; +$lang['hours'] = '%d saat önce'; +$lang['minutes'] = '%d dakika önce'; +$lang['seconds'] = '%d saniye önce'; +$lang['wordblock'] = 'Değişikliğiniz kaydedilmedi çünkü istenmeyen mesaj içeriyor (spam).'; +$lang['media_uploadtab'] = 'Karşıya yükle'; +$lang['media_searchtab'] = 'Ara'; +$lang['media_file'] = 'Dosya'; +$lang['media_viewtab'] = 'Görünüm'; +$lang['media_edittab'] = 'Düzenle'; +$lang['media_historytab'] = 'Geçmiş'; +$lang['media_list_thumbs'] = 'Küçük resimler'; +$lang['media_list_rows'] = 'Satırlar'; +$lang['media_sort_name'] = 'İsim'; +$lang['media_sort_date'] = 'Tarih'; +$lang['media_files'] = '%s deki dosyalar'; +$lang['media_upload'] = '%s dizinine yükle'; +$lang['media_search'] = '%s dizininde ara'; +$lang['media_view'] = '%s'; +$lang['media_edit'] = 'Düzenle %s'; +$lang['media_history'] = 'Geçmiş %s'; +$lang['media_perm_upload'] = 'Üzgünüm, karşıya dosya yükleme yetkiniz yok.'; +$lang['media_restore'] = 'Bu sürümü eski haline getir'; diff --git a/inc/lang/tr/resetpwd.txt b/inc/lang/tr/resetpwd.txt new file mode 100644 index 000000000..1ed758693 --- /dev/null +++ b/inc/lang/tr/resetpwd.txt @@ -0,0 +1,3 @@ + ====== Yeni şifre belirle ====== + +Lütfen bu wiki hesabınız için yeni bir şifre belirleyin. \ No newline at end of file diff --git a/lib/plugins/acl/lang/tr/lang.php b/lib/plugins/acl/lang/tr/lang.php index de96d2906..629ca546b 100644 --- a/lib/plugins/acl/lang/tr/lang.php +++ b/lib/plugins/acl/lang/tr/lang.php @@ -8,6 +8,7 @@ * @author Cihan Kahveci * @author Yavuz Selim * @author Caleb Maclennan + * @author farukerdemoncel@gmail.com */ $lang['admin_acl'] = 'Erişim Kontrol Listesi (ACL) Yönetimi'; $lang['acl_group'] = 'Grup'; diff --git a/lib/plugins/config/lang/tr/lang.php b/lib/plugins/config/lang/tr/lang.php index 6d7d7cc2e..5bc4f3fc1 100644 --- a/lib/plugins/config/lang/tr/lang.php +++ b/lib/plugins/config/lang/tr/lang.php @@ -6,6 +6,7 @@ * @author Cihan Kahveci * @author Yavuz Selim * @author Caleb Maclennan + * @author farukerdemoncel@gmail.com */ $lang['menu'] = 'Site Ayarları'; $lang['error'] = 'Ayarlar yanlış bir değer girildiği için güncellenemedi. Lütfen değişikliklerinizi gözden geçirin ve tekrar gönderin. @@ -36,25 +37,25 @@ $lang['_template_sufix'] = 'Şablon (Template) Ayarları'; $lang['_msg_setting_undefined'] = 'Ayar üstverisi yok.'; $lang['_msg_setting_no_class'] = 'Ayar sınıfı yok.'; $lang['_msg_setting_no_default'] = 'Varsayılan değer yok.'; -$lang['fmode'] = 'Dosya oluşturma yetkisi'; -$lang['dmode'] = 'Klasör oluşturma yetkisi'; -$lang['lang'] = 'Dil'; -$lang['basedir'] = 'Kök dizin'; -$lang['baseurl'] = 'Kök URL'; -$lang['savedir'] = 'Verileri kaydetmek için kullanılacak klasör'; -$lang['start'] = 'Ana sayfa adı'; $lang['title'] = 'Wiki başlığı'; +$lang['start'] = 'Ana sayfa adı'; +$lang['lang'] = 'Dil'; $lang['template'] = 'Şablon (Template)'; $lang['license'] = 'İçeriğinizi hangi lisans altında yayınlansın?'; -$lang['fullpath'] = 'sayfaların tüm patikasını (full path) göster'; +$lang['savedir'] = 'Verileri kaydetmek için kullanılacak klasör'; +$lang['basedir'] = 'Kök dizin'; +$lang['baseurl'] = 'Kök URL'; +$lang['dmode'] = 'Klasör oluşturma yetkisi'; +$lang['fmode'] = 'Dosya oluşturma yetkisi'; +$lang['allowdebug'] = 'Yanlış ayıklamasına izin ver lazım değilse etkisiz kıl!'; $lang['recent'] = 'En son değiştirilenler'; $lang['breadcrumbs'] = 'Ekmek kırıntıların sayısı'; $lang['youarehere'] = 'hiyerarşik ekmek kırıntıları'; +$lang['fullpath'] = 'sayfaların tüm patikasını (full path) göster'; $lang['typography'] = 'Tipografik değiştirmeleri yap'; -$lang['htmlok'] = 'Gömülü HTML koduna izin ver'; -$lang['phpok'] = 'Gömülü PHP koduna izin ver'; $lang['dformat'] = 'Tarih biçimi (PHP\'nin strftime fonksiyonuna bakın)'; $lang['signature'] = 'İmza'; +$lang['showuseras'] = 'Bir sayfayı en son düzenleyen kullanıcıya ne gösterilsin'; $lang['toptoclevel'] = 'İçindekiler için en üst seviye'; $lang['tocminheads'] = 'İçindekilerin oluşturulması için gereken (en az) başlık sayısı'; $lang['maxtoclevel'] = 'İçindekiler için en fazla seviye'; @@ -62,15 +63,6 @@ $lang['maxseclevel'] = 'Bölümün azami düzenleme düzeyi'; $lang['camelcase'] = 'Linkler için CamelCase kullan'; $lang['deaccent'] = 'Sayfa adlarınız temizle'; $lang['useheading'] = 'Sayfa isimleri için ilk başlığı kullan'; -$lang['refcheck'] = 'Araç kaynak denetimi'; -$lang['refshow'] = 'Gösterilecek araç kaynağı sayısı'; -$lang['allowdebug'] = 'Yanlış ayıklamasına izin ver lazım değilse etkisiz kıl!'; -$lang['usewordblock'] = 'Wordlistesine göre spam engelle'; -$lang['indexdelay'] = 'Indekslemeden evvel zaman gecikmesi (saniye)'; -$lang['relnofollow'] = 'Dışsal linkler rel="nofollow" kullan'; -$lang['mailguard'] = 'Email adreslerini karart'; -$lang['iexssprotect'] = 'Yüklenmiş dosyaları muhtemel kötu niyetli JavaScript veya HTML koduna kontrol et'; -$lang['showuseras'] = 'Bir sayfayı en son düzenleyen kullanıcıya ne gösterilsin'; $lang['useacl'] = 'Erişim kontrol listesini kullan'; $lang['autopasswd'] = 'Parolaları otamatikmen üret'; $lang['authtype'] = 'Kimlik denetleme arka uç'; @@ -79,16 +71,25 @@ $lang['defaultgroup'] = 'Varsayılan grup'; $lang['disableactions'] = 'DokuWiki eylemlerini etkisiz kıl'; $lang['disableactions_check'] = 'Kontrol et'; $lang['disableactions_subscription'] = 'Abone ol/Abonelikten vazgeç'; -$lang['canonical'] = 'Tamolarak kurallara uygun URL\'leri kullan'; -$lang['mailfrom'] = 'Otomatik e-postalar için kullanılacak e-posta adresi'; +$lang['usewordblock'] = 'Wordlistesine göre spam engelle'; +$lang['relnofollow'] = 'Dışsal linkler rel="nofollow" kullan'; +$lang['indexdelay'] = 'Indekslemeden evvel zaman gecikmesi (saniye)'; +$lang['mailguard'] = 'Email adreslerini karart'; +$lang['iexssprotect'] = 'Yüklenmiş dosyaları muhtemel kötu niyetli JavaScript veya HTML koduna kontrol et'; +$lang['htmlok'] = 'Gömülü HTML koduna izin ver'; +$lang['phpok'] = 'Gömülü PHP koduna izin ver'; +$lang['refcheck'] = 'Araç kaynak denetimi'; +$lang['refshow'] = 'Gösterilecek araç kaynağı sayısı'; $lang['gdlib'] = 'GD Lib sürümü'; $lang['jpg_quality'] = 'JPG sıkıştırma kalitesi [0-100]'; +$lang['mailfrom'] = 'Otomatik e-postalar için kullanılacak e-posta adresi'; $lang['sitemap'] = 'Google site haritası oluştur (gün)'; -$lang['renderer__core'] = '%s (dokuwiki çekirdeği)'; -$lang['renderer__plugin'] = '%s (eklenti)'; $lang['rss_content'] = 'XML beslemesinde ne gösterilsin?'; $lang['rss_update'] = 'XML beslemesini güncelleme aralığı'; $lang['rss_show_summary'] = 'XML beslemesinde özeti başlıkta göster'; +$lang['canonical'] = 'Tamolarak kurallara uygun URL\'leri kullan'; +$lang['renderer__core'] = '%s (dokuwiki çekirdeği)'; +$lang['renderer__plugin'] = '%s (eklenti)'; $lang['proxy____host'] = 'Proxy sunucu adı'; $lang['proxy____user'] = 'Proxy kullanıcı adı'; $lang['proxy____pass'] = 'Proxy şifresi'; diff --git a/lib/plugins/plugin/lang/tr/lang.php b/lib/plugins/plugin/lang/tr/lang.php index 9a655e400..9598ade7d 100644 --- a/lib/plugins/plugin/lang/tr/lang.php +++ b/lib/plugins/plugin/lang/tr/lang.php @@ -6,6 +6,7 @@ * @author Cihan Kahveci * @author Yavuz Selim * @author Caleb Maclennan + * @author farukerdemoncel@gmail.com */ $lang['menu'] = 'Eklenti Yönetimi'; $lang['download'] = 'Yeni bir eklenti indirip kur'; diff --git a/lib/plugins/popularity/lang/tr/lang.php b/lib/plugins/popularity/lang/tr/lang.php index fe87d1548..5339176bc 100644 --- a/lib/plugins/popularity/lang/tr/lang.php +++ b/lib/plugins/popularity/lang/tr/lang.php @@ -6,6 +6,8 @@ * @author Cihan Kahveci * @author Yavuz Selim * @author Caleb Maclennan + * @author farukerdemoncel@gmail.com */ $lang['name'] = 'Popülerlik Geribeslemesi (yüklemesi uzun sürebilir)'; $lang['submit'] = 'Verileri Gönder'; +$lang['lastSent'] = 'Bilgiler gönderildi'; diff --git a/lib/plugins/revert/lang/tr/lang.php b/lib/plugins/revert/lang/tr/lang.php index aa1458a95..9030c31e3 100644 --- a/lib/plugins/revert/lang/tr/lang.php +++ b/lib/plugins/revert/lang/tr/lang.php @@ -6,6 +6,7 @@ * @author Cihan Kahveci * @author Yavuz Selim * @author Caleb Maclennan + * @author farukerdemoncel@gmail.com */ $lang['menu'] = 'Eskiye Döndürme'; $lang['filter'] = 'Spam bulunan sayfaları ara'; diff --git a/lib/plugins/usermanager/lang/tr/lang.php b/lib/plugins/usermanager/lang/tr/lang.php index b9c9cfc52..7ddb7dd5d 100644 --- a/lib/plugins/usermanager/lang/tr/lang.php +++ b/lib/plugins/usermanager/lang/tr/lang.php @@ -6,6 +6,7 @@ * @author Cihan Kahveci * @author Yavuz Selim * @author Caleb Maclennan + * @author farukerdemoncel@gmail.com */ $lang['menu'] = 'Kullanıcı Yönetimi'; $lang['noauth'] = '(kullanıcı onaylaması yoktur)'; -- cgit v1.2.3 From 6686e3d1ac97a3c4d256f4e9df7f772102baed96 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:40:49 +0100 Subject: fixed tests --- _test/tests/inc/subscription.test.php | 31 ++++++++++++++++++++++++------- _test/tests/inc/subscription_set.test.php | 20 -------------------- 2 files changed, 24 insertions(+), 27 deletions(-) delete mode 100644 _test/tests/inc/subscription_set.test.php diff --git a/_test/tests/inc/subscription.test.php b/_test/tests/inc/subscription.test.php index c6f33dec7..333400576 100644 --- a/_test/tests/inc/subscription.test.php +++ b/_test/tests/inc/subscription.test.php @@ -120,7 +120,7 @@ class subscription_test extends DokuWikiTest { ); } - function test_bulkdigest(){ + function test_bulkdigest() { $sub = new MockupSubscription(); // let's start with nothing @@ -153,10 +153,10 @@ class subscription_test extends DokuWikiTest { // we now should get mails for three changes $this->assertEquals(3, $sub->send_bulk('sub1:test')); - $this->assertEquals(array('arthur@example.com','arthur@example.com','arthur@example.com'), $sub->mails); + $this->assertEquals(array('arthur@example.com', 'arthur@example.com', 'arthur@example.com'), $sub->mails); } - function test_bulklist(){ + function test_bulklist() { $sub = new MockupSubscription(); // let's start with nothing @@ -192,7 +192,24 @@ class subscription_test extends DokuWikiTest { $this->assertEquals(array('arthur@example.com'), $sub->mails); } + /** + * Tests, if overwriting subscriptions works even when subscriptions for the same + * user exist for two nested namespaces, this is a test for the bug described in FS#2580 + */ + function test_overwrite() { + $sub = new MockupSubscription(); + $sub->add(':', 'admin', 'digest', '123456789'); + $sub->add(':wiki:', 'admin', 'digest', '123456789'); + $sub->add(':', 'admin', 'digest', '1234'); + $sub->add(':wiki:', 'admin', 'digest', '1234'); + + $subscriptions = $sub->subscribers(':wiki:', 'admin'); + + $this->assertCount(1, $subscriptions[':'], 'More than one subscription saved for the root namespace even though the old one should have been overwritten.'); + $this->assertCount(1, $subscriptions[':wiki:'], 'More than one subscription saved for the wiki namespace even though the old one should have been overwritten.'); + $this->assertCount(2, $subscriptions, 'Didn\'t find the expected two subscriptions'); + } } /** @@ -201,18 +218,18 @@ class subscription_test extends DokuWikiTest { class MockupSubscription extends Subscription { public $mails; // we keep sent mails here - public function __construct(){ + public function __construct() { $this->reset(); } /** * resets the mail array */ - public function reset(){ + public function reset() { $this->mails = array(); } - public function isenabled(){ + public function isenabled() { return true; } @@ -220,7 +237,7 @@ class MockupSubscription extends Subscription { return parent::buildregex($user, $style, $data); } - protected function send($subscriber_mail, $subject, $id, $template, $trep, $hrep){ + protected function send($subscriber_mail, $subject, $id, $template, $trep, $hrep = null) { $this->mails[] = $subscriber_mail; return true; } diff --git a/_test/tests/inc/subscription_set.test.php b/_test/tests/inc/subscription_set.test.php deleted file mode 100644 index 5c0a6c816..000000000 --- a/_test/tests/inc/subscription_set.test.php +++ /dev/null @@ -1,20 +0,0 @@ - 'admin')); - $this->assertCount(1, $subscriptions[':'], 'More than one subscription saved for the root namespace even though the old one should have been overwritten.'); - $this->assertCount(1, $subscriptions[':wiki:'], 'More than one subscription saved for the wiki namespace even though the old one should have been overwritten.'); - $this->assertCount(2, $subscriptions, 'Didn\'t find the expected two subscriptions'); - } -} -- cgit v1.2.3 From 16c665d9fa1d3d1c5d82866a942ba8cb6db3a4ee Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:41:26 +0100 Subject: removed data parameter in subscription_handle_post() now the data parameter, which really is a timestamp is only handled internally of the subscription class --- inc/actions.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/inc/actions.php b/inc/actions.php index 911edf936..4083b0454 100644 --- a/inc/actions.php +++ b/inc/actions.php @@ -784,8 +784,7 @@ function subscription_handle_post(&$params) { $style = null; } - $data = in_array($style, array('list', 'digest')) ? time() : null; - $params = compact('target', 'style', 'data', 'action'); + $params = compact('target', 'style', 'action'); } //Setup VIM: ex: et ts=2 : -- cgit v1.2.3 From cfbb9916556595cd8987f6c79771883dde656185 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:47:21 +0100 Subject: removed unused vars --- inc/common.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/inc/common.php b/inc/common.php index 20e0af389..bc49e76b2 100644 --- a/inc/common.php +++ b/inc/common.php @@ -1105,10 +1105,7 @@ function saveOldRevision($id) { * @author Andreas Gohr */ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = array()) { - global $lang; global $conf; - global $INFO; - global $DIFF_INLINESTYLES; // decide if there is something to do, eg. whom to mail if($who == 'admin') { -- cgit v1.2.3 From edf986ad6271abac1f00055d3de4a9857cae1553 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:49:41 +0100 Subject: comment adjusted --- inc/subscription.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/subscription.php b/inc/subscription.php index 44248a39d..92c1e8579 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -381,7 +381,7 @@ class Subscription { * Send the diff for some page change * * @param string $subscriber_mail The target mail address - * @param string $template Mail template, should be 'subscr_digest' or 'subscr_single' + * @param string $template Mail template ('subscr_digest', 'subscr_single', 'mailtext', ...) * @param string $id Page for which the notification is * @param int|null $rev Old revision if any * @param string $summary Change summary if any -- cgit v1.2.3 From 004e7e6efb2e8da1d76f3959667ca0dbf8b0aaf6 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 10:52:26 +0100 Subject: simplified subscription->add() code a bit --- inc/subscription.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/inc/subscription.php b/inc/subscription.php index 92c1e8579..e888ee27f 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -204,20 +204,16 @@ class Subscription { // delete any existing subscription $this->remove($id, $user); - $user = auth_nameencode(trim($user)); + $user = auth_nameencode(trim($user)); $style = trim($style); - $data = trim($data); + $data = trim($data); if(!$user) throw new Exception('no subscription user given'); if(!$style) throw new Exception('no subscription style given'); if(!$data) $data = time(); //always add current time for new subscriptions - $line = "$user $style"; - if($data) $line .= " $data"; - $line .= "\n"; - + $line = "$user $style $data\n"; $file = $this->file($id); - return io_saveFile($file, $line, true); } -- cgit v1.2.3 From 8b87bc02a80bd1436f031d46f2d1e167b815323a Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 11:01:04 +0100 Subject: fixed lists in HTML mails --- inc/subscription.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/subscription.php b/inc/subscription.php index e888ee27f..fc26e42e8 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -503,7 +503,7 @@ class Subscription { $tlist .= '* '.$link.NL; $hlist .= '
  • '.hsc($id).'
  • '.NL; } - $hlist = ''; + $hlist .= ''; $id = prettyprint_id($ns_id); $trep = array( -- cgit v1.2.3 From 903e04c3aaaad8e237d8e50434aed40692672a43 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 11:07:46 +0100 Subject: correctly escape diffs in HTML mails --- inc/subscription.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/inc/subscription.php b/inc/subscription.php index fc26e42e8..e4cabffed 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -398,17 +398,22 @@ class Subscription { if($rev) { $subject = 'changed'; $trep['OLDPAGE'] = wl($id, "rev=$rev", true, '&'); - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id))); + + $old_content = rawWiki($id, $rev); + $new_content = rawWiki($id); + + $df = new Diff(explode("\n", $old_content), + explode("\n", $new_content)); $dformat = new UnifiedDiffFormatter(); $tdiff = $dformat->format($df); $DIFF_INLINESTYLES = true; + $df = new Diff(explode("\n", hsc($old_content)), + explode("\n", hsc($new_content))); $dformat = new InlineDiffFormatter(); $hdiff = $dformat->format($df); $hdiff = ''.$hdiff.'
    '; $DIFF_INLINESTYLES = false; - } else { $subject = 'newpage'; $trep['OLDPAGE'] = '---'; -- cgit v1.2.3 From 29c964eb1ccaac4204b31ac7409bd91e93e9ed0c Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 18 Jan 2013 11:16:53 +0100 Subject: readded mailfromnobody to subscription sending this was lost because the subscription branch, branched before this change in master --- inc/subscription.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inc/subscription.php b/inc/subscription.php index e4cabffed..dfb3533fd 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -546,6 +546,7 @@ class Subscription { */ protected function send($subscriber_mail, $subject, $context, $template, $trep, $hrep = null) { global $lang; + global $conf; $text = rawLocale($template); $subject = $lang['mail_'.$subject].' '.$context; @@ -553,6 +554,7 @@ class Subscription { $mail->bcc($subscriber_mail); $mail->subject($subject); $mail->setBody($text, $trep, $hrep); + $mail->from($conf['mailfromnobody']); if(isset($trep['SUBSCRIBE'])) { $mail->setHeader('List-Unsubscribe', '<'.$trep['SUBSCRIBE'].'>', false); } -- cgit v1.2.3 From 77e5adb1a4bff9e9dd43f7c10beaa235c6eb5398 Mon Sep 17 00:00:00 2001 From: Guillaume Turri Date: Sat, 19 Jan 2013 12:18:36 +0100 Subject: wiki.getAttachments returns 'perms' according to documentation --- inc/RemoteAPICore.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inc/RemoteAPICore.php b/inc/RemoteAPICore.php index c04a14f5c..72af65329 100644 --- a/inc/RemoteAPICore.php +++ b/inc/RemoteAPICore.php @@ -344,6 +344,8 @@ class RemoteAPICore { for($i=0; $i<$len; $i++) { unset($data[$i]['meta']); + $data[$i]['perms'] = $data[$i]['perm']; + unset($data[$i]['perm']); $data[$i]['lastModified'] = $this->api->toDate($data[$i]['mtime']); } return $data; -- cgit v1.2.3 From 9fd5ca2ec2955ee29404be1a39ddd9affcd0c78f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gro=CC=88nke?= Date: Sat, 19 Jan 2013 16:30:42 +0100 Subject: jQuery latest * jQuery 1.9.0 * jQuery-UI v1.9.2 * jQuery.fn.live > jQuery.fn.on * jQuery.fn.browser replacement (jquery.mb.browser.js) --- lib/exe/js.php | 1 + lib/scripts/behaviour.js | 74 +- .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../images/ui-bg_flat_75_ffffff_40x100.png | Bin .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin .../images/ui-bg_glass_65_ffffff_1x400.png | Bin .../images/ui-bg_glass_75_dadada_1x400.png | Bin .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../images/ui-icons_222222_256x240.png | Bin .../images/ui-icons_2e83ff_256x240.png | Bin .../images/ui-icons_454545_256x240.png | Bin .../images/ui-icons_888888_256x240.png | Bin .../images/ui-icons_cd0a0a_256x240.png | Bin .../jquery-ui-theme/jquery-ui-1.9.2.custom.css | 462 + .../jquery-ui-theme/jquery-ui-1.9.2.custom.min.css | 5 + lib/scripts/jquery/jquery-ui-theme/smoothness.css | 568 - lib/scripts/jquery/jquery-ui.js | 21842 +++++++++++-------- lib/scripts/jquery/jquery-ui.min.js | 420 +- lib/scripts/jquery/jquery.cookie.js | 107 +- lib/scripts/jquery/jquery.js | 9046 -------- lib/scripts/jquery/jquery.mb.browser.js | 104 + lib/scripts/jquery/jquery.mb.browser.min.js | 21 + lib/scripts/jquery/jquery.min.js | 8 +- lib/scripts/jquery/update.sh | 28 - 26 files changed, 13186 insertions(+), 19500 deletions(-) mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-bg_flat_0_aaaaaa_40x100.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-bg_flat_75_ffffff_40x100.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_55_fbf9ee_1x400.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_65_ffffff_1x400.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_75_dadada_1x400.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_75_e6e6e6_1x400.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_95_fef1ec_1x400.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-icons_222222_256x240.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-icons_2e83ff_256x240.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-icons_454545_256x240.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-icons_888888_256x240.png mode change 100644 => 100755 lib/scripts/jquery/jquery-ui-theme/images/ui-icons_cd0a0a_256x240.png create mode 100755 lib/scripts/jquery/jquery-ui-theme/jquery-ui-1.9.2.custom.css create mode 100755 lib/scripts/jquery/jquery-ui-theme/jquery-ui-1.9.2.custom.min.css delete mode 100644 lib/scripts/jquery/jquery-ui-theme/smoothness.css mode change 100644 => 100755 lib/scripts/jquery/jquery-ui.js mode change 100644 => 100755 lib/scripts/jquery/jquery-ui.min.js delete mode 100644 lib/scripts/jquery/jquery.js create mode 100644 lib/scripts/jquery/jquery.mb.browser.js create mode 100644 lib/scripts/jquery/jquery.mb.browser.min.js delete mode 100755 lib/scripts/jquery/update.sh diff --git a/lib/exe/js.php b/lib/exe/js.php index 42979eeed..7c1c27138 100644 --- a/lib/exe/js.php +++ b/lib/exe/js.php @@ -43,6 +43,7 @@ function js_out(){ DOKU_INC."lib/scripts/jquery/jquery$min.js", DOKU_INC.'lib/scripts/jquery/jquery.cookie.js', DOKU_INC."lib/scripts/jquery/jquery-ui$min.js", + DOKU_INC."lib/scripts/jquery/jquery.mb.browser.js", DOKU_INC."lib/scripts/fileuploader.js", DOKU_INC."lib/scripts/fileuploaderextended.js", DOKU_INC.'lib/scripts/helpers.js', diff --git a/lib/scripts/behaviour.js b/lib/scripts/behaviour.js index cffdde042..6878b0b96 100644 --- a/lib/scripts/behaviour.js +++ b/lib/scripts/behaviour.js @@ -1,3 +1,38 @@ +/** + * Hides elements with a slide animation + * + * @param fn optional callback to run after hiding + * @author Adrian Lang + */ +jQuery.fn.dw_hide = function(fn) { + return this.slideUp('fast', fn); +}; + +/** + * Unhides elements with a slide animation + * + * @param fn optional callback to run after hiding + * @author Adrian Lang + */ +jQuery.fn.dw_show = function(fn) { + return this.slideDown('fast', fn); +}; + +/** + * Toggles visibility of an element using a slide element + * + * @param bool the current state of the element (optional) + */ +jQuery.fn.dw_toggle = function(bool, fn) { + return this.each(function() { + var $this = jQuery(this); + if (typeof bool === 'undefined') { + bool = $this.is(':hidden'); + } + $this[bool ? "dw_show" : "dw_hide" ](fn); + }); +}; + /** * Automatic behaviours * @@ -16,7 +51,7 @@ var dw_behaviour = { dw_behaviour.subscription(); dw_behaviour.revisionBoxHandler(); - jQuery('#page__revisions input[type=checkbox]').live('click', + jQuery('#page__revisions input[type=checkbox]').on('click', dw_behaviour.revisionBoxHandler ); }, @@ -77,7 +112,7 @@ var dw_behaviour = { return; } - jQuery('a.windows').live('click', function(){ + jQuery('a.windows').on('click', function(){ alert(LANG.nosmblinks.replace(/\\n/,"\n")); }); }, @@ -142,39 +177,4 @@ var dw_behaviour = { }; -/** - * Hides elements with a slide animation - * - * @param fn optional callback to run after hiding - * @author Adrian Lang - */ -jQuery.fn.dw_hide = function(fn) { - return this.slideUp('fast', fn); -}; - -/** - * Unhides elements with a slide animation - * - * @param fn optional callback to run after hiding - * @author Adrian Lang - */ -jQuery.fn.dw_show = function(fn) { - return this.slideDown('fast', fn); -}; - -/** - * Toggles visibility of an element using a slide element - * - * @param bool the current state of the element (optional) - */ -jQuery.fn.dw_toggle = function(bool, fn) { - return this.each(function() { - var $this = jQuery(this); - if (typeof bool === 'undefined') { - bool = $this.is(':hidden'); - } - $this[bool ? "dw_show" : "dw_hide" ](fn); - }); -}; - jQuery(dw_behaviour.init); diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_flat_0_aaaaaa_40x100.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_flat_0_aaaaaa_40x100.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_flat_75_ffffff_40x100.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_flat_75_ffffff_40x100.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_55_fbf9ee_1x400.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_55_fbf9ee_1x400.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_65_ffffff_1x400.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_65_ffffff_1x400.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_75_dadada_1x400.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_75_dadada_1x400.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_75_e6e6e6_1x400.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_75_e6e6e6_1x400.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_95_fef1ec_1x400.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_glass_95_fef1ec_1x400.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_222222_256x240.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_222222_256x240.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_2e83ff_256x240.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_2e83ff_256x240.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_454545_256x240.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_454545_256x240.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_888888_256x240.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_888888_256x240.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_cd0a0a_256x240.png b/lib/scripts/jquery/jquery-ui-theme/images/ui-icons_cd0a0a_256x240.png old mode 100644 new mode 100755 diff --git a/lib/scripts/jquery/jquery-ui-theme/jquery-ui-1.9.2.custom.css b/lib/scripts/jquery/jquery-ui-theme/jquery-ui-1.9.2.custom.css new file mode 100755 index 000000000..9fa4a2d2a --- /dev/null +++ b/lib/scripts/jquery/jquery-ui-theme/jquery-ui-1.9.2.custom.css @@ -0,0 +1,462 @@ +/*! jQuery UI - v1.9.2 - 2012-11-23 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/ +* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; } +.ui-helper-clearfix:after { clear: both; } +.ui-helper-clearfix { zoom: 1; } +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } +.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; } +.ui-accordion .ui-accordion-icons { padding-left: 2.2em; } +.ui-accordion .ui-accordion-noicons { padding-left: .7em; } +.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; } +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; } +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}.ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; } +.ui-menu .ui-menu { margin-top: -3px; position: absolute; } +.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; } +.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; } +.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; } +.ui-menu .ui-menu-item a.ui-state-focus, +.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; } + +.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; } +.ui-menu .ui-state-disabled a { cursor: default; } + +/* icon support */ +.ui-menu-icons { position: relative; } +.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; } + +/* left-aligned */ +.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; } + +/* right-aligned */ +.ui-menu .ui-menu-icon { position: static; float: right; } +.ui-progressbar { height:2em; text-align: left; overflow: hidden; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; } +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; } +.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; } +.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; } +.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */ +.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */ +.ui-spinner-up { top: 0; } +.ui-spinner-down { bottom: 0; } + +/* TR overrides */ +.ui-spinner .ui-icon-triangle-1-s { + /* need to fix icons sprite */ + background-position:-65px -16px; +} +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tooltip { + padding: 8px; + position: absolute; + z-index: 9999; + max-width: 300px; + -webkit-box-shadow: 0 0 5px #aaa; + box-shadow: 0 0 5px #aaa; +} +/* Fades and background-images don't work well together in IE6, drop the image */ +* html .ui-tooltip { + background-image: none; +} +body .ui-tooltip { border-width: 2px; } + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */ + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; } \ No newline at end of file diff --git a/lib/scripts/jquery/jquery-ui-theme/jquery-ui-1.9.2.custom.min.css b/lib/scripts/jquery/jquery-ui-theme/jquery-ui-1.9.2.custom.min.css new file mode 100755 index 000000000..e96496989 --- /dev/null +++ b/lib/scripts/jquery/jquery-ui-theme/jquery-ui-1.9.2.custom.min.css @@ -0,0 +1,5 @@ +/*! jQuery UI - v1.9.2 - 2012-11-23 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/ +* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{zoom:1}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;zoom:1}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto;zoom:1}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}* html .ui-autocomplete{width:1px}.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0em}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .1em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus{padding:0}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;width:100%}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;zoom:1;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}* html .ui-tooltip{background-image:none}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px} \ No newline at end of file diff --git a/lib/scripts/jquery/jquery-ui-theme/smoothness.css b/lib/scripts/jquery/jquery-ui-theme/smoothness.css deleted file mode 100644 index 910d24b95..000000000 --- a/lib/scripts/jquery/jquery-ui-theme/smoothness.css +++ /dev/null @@ -1,568 +0,0 @@ -/* - * jQuery UI CSS Framework 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Theming/API - */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { display: none; } -.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } -.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } -.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -.ui-helper-clearfix { display: inline-block; } -/* required comment for clearfix to work in Opera \*/ -* html .ui-helper-clearfix { height:1%; } -.ui-helper-clearfix { display:block; } -/* end clearfix */ -.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { cursor: default !important; } - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } - - -/* - * jQuery UI CSS Framework 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Theming/API - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { font-size: 1.1em; } -.ui-widget .ui-widget { font-size: 1em; } -.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-size: 1em; } -.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } -.ui-widget-content a { color: #222222; } -.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } -.ui-widget-header a { color: #222222; } - -/* Interaction states -----------------------------------*/ -.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } -.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } -.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } -.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } -.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } -.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } -.ui-widget :active { outline: none; } - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } -.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } -.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } -.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } -.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } -.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } -.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } -.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } -.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } -.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } -.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } -.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } -.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } -.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } -.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } - -/* positioning */ -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-off { background-position: -96px -144px; } -.ui-icon-radio-on { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; } -.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; } -.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } -.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } - -/* Overlays */ -.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } -.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* - * jQuery UI Resizable 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Resizable#theming - */ -.ui-resizable { position: relative;} -.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; } -.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } -.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } -.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } -.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } -.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } -.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } -.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } -.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } -.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* - * jQuery UI Selectable 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Selectable#theming - */ -.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } -/* - * jQuery UI Accordion 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Accordion#theming - */ -/* IE/Win - Fix animation bug - #4615 */ -.ui-accordion { width: 100%; } -.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } -.ui-accordion .ui-accordion-li-fix { display: inline; } -.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } -.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } -.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } -.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } -.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } -.ui-accordion .ui-accordion-content-active { display: block; } -/* - * jQuery UI Autocomplete 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Autocomplete#theming - */ -.ui-autocomplete { position: absolute; cursor: default; } - -/* workarounds */ -* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ - -/* - * jQuery UI Menu 1.8.16 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Menu#theming - */ -.ui-menu { - list-style:none; - padding: 2px; - margin: 0; - display:block; - float: left; -} -.ui-menu .ui-menu { - margin-top: -3px; -} -.ui-menu .ui-menu-item { - margin:0; - padding: 0; - zoom: 1; - float: left; - clear: left; - width: 100%; -} -.ui-menu .ui-menu-item a { - text-decoration:none; - display:block; - padding:.2em .4em; - line-height:1.5; - zoom:1; -} -.ui-menu .ui-menu-item a.ui-state-hover, -.ui-menu .ui-menu-item a.ui-state-active { - font-weight: normal; - margin: -1px; -} -/* - * jQuery UI Button 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Button#theming - */ -.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ -.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ -button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ -.ui-button-icons-only { width: 3.4em; } -button.ui-button-icons-only { width: 3.7em; } - -/*button text element */ -.ui-button .ui-button-text { display: block; line-height: 1.4; } -.ui-button-text-only .ui-button-text { padding: .4em 1em; } -.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } -.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } -.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } -.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } -/* no icon support for input elements, provide padding by default */ -input.ui-button { padding: .4em 1em; } - -/*button icon element(s) */ -.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } -.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } -.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } -.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } -.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } - -/*button sets*/ -.ui-buttonset { margin-right: 7px; } -.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } - -/* workarounds */ -button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ -/* - * jQuery UI Dialog 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Dialog#theming - */ -.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } -.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } -.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } -.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } -.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } -.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } -.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } -.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } -.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } -.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } -.ui-draggable .ui-dialog-titlebar { cursor: move; } -/* - * jQuery UI Slider 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Slider#theming - */ -.ui-slider { position: relative; text-align: left; } -.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } -.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } - -.ui-slider-horizontal { height: .8em; } -.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } -.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } -.ui-slider-horizontal .ui-slider-range-min { left: 0; } -.ui-slider-horizontal .ui-slider-range-max { right: 0; } - -.ui-slider-vertical { width: .8em; height: 100px; } -.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } -.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } -.ui-slider-vertical .ui-slider-range-min { bottom: 0; } -.ui-slider-vertical .ui-slider-range-max { top: 0; }/* - * jQuery UI Tabs 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Tabs#theming - */ -.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ -.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } -.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } -.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } -.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ -.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } -.ui-tabs .ui-tabs-hide { display: none !important; } -/* - * jQuery UI Datepicker 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Datepicker#theming - */ -.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } -.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } -.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } -.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } -.ui-datepicker .ui-datepicker-prev { left:2px; } -.ui-datepicker .ui-datepicker-next { right:2px; } -.ui-datepicker .ui-datepicker-prev-hover { left:1px; } -.ui-datepicker .ui-datepicker-next-hover { right:1px; } -.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } -.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } -.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } -.ui-datepicker select.ui-datepicker-month-year {width: 100%;} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { width: 49%;} -.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } -.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } -.ui-datepicker td { border: 0; padding: 1px; } -.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } -.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } -.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { width:auto; } -.ui-datepicker-multi .ui-datepicker-group { float:left; } -.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } -.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } -.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } -.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } -.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; } - -/* RTL support */ -.ui-datepicker-rtl { direction: rtl; } -.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } -.ui-datepicker-rtl .ui-datepicker-group { float:right; } -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } - -/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ -.ui-datepicker-cover { - display: none; /*sorry for IE5*/ - display/**/: block; /*sorry for IE5*/ - position: absolute; /*must have*/ - z-index: -1; /*must have*/ - filter: mask(); /*must have*/ - top: -4px; /*must have*/ - left: -4px; /*must have*/ - width: 200px; /*must have*/ - height: 200px; /*must have*/ -}/* - * jQuery UI Progressbar 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Progressbar#theming - */ -.ui-progressbar { height:2em; text-align: left; } -.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/lib/scripts/jquery/jquery-ui.js b/lib/scripts/jquery/jquery-ui.js old mode 100644 new mode 100755 index cd515f361..6dc062e6a --- a/lib/scripts/jquery/jquery-ui.js +++ b/lib/scripts/jquery/jquery-ui.js @@ -1,14 +1,13 @@ -/*! - * jQuery UI 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI - */ +/*! jQuery UI - v1.9.2 - 2012-11-23 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.slider.js, jquery.ui.sortable.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js +* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */ + (function( $, undefined ) { +var uuid = 0, + runiqueId = /^ui-id-\d+$/; + // prevent duplicate loading // this is only a problem because we proxy existing functions // and we don't want to double proxy them @@ -18,26 +17,18 @@ if ( $.ui.version ) { } $.extend( $.ui, { - version: "1.8.16", + version: "1.9.2", keyCode: { - ALT: 18, BACKSPACE: 8, - CAPS_LOCK: 20, COMMA: 188, - COMMAND: 91, - COMMAND_LEFT: 91, // COMMAND - COMMAND_RIGHT: 93, - CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, - INSERT: 45, LEFT: 37, - MENU: 93, // COMMAND_RIGHT NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, @@ -48,18 +39,14 @@ $.extend( $.ui, { PAGE_UP: 33, PERIOD: 190, RIGHT: 39, - SHIFT: 16, SPACE: 32, TAB: 9, - UP: 38, - WINDOWS: 91 // COMMAND + UP: 38 } }); // plugins $.fn.extend({ - propAttr: $.fn.prop || $.fn.attr, - _focus: $.fn.focus, focus: function( delay, fn ) { return typeof delay === "number" ? @@ -77,13 +64,13 @@ $.fn.extend({ scrollParent: function() { var scrollParent; - if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { + if (($.ui.ie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { scrollParent = this.parents().filter(function() { - return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x')); }).eq(0); } else { scrollParent = this.parents().filter(function() { - return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x')); }).eq(0); } @@ -119,95 +106,63 @@ $.fn.extend({ return 0; }, - disableSelection: function() { - return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + - ".ui-disableSelection", function( event ) { - event.preventDefault(); - }); - }, - - enableSelection: function() { - return this.unbind( ".ui-disableSelection" ); - } -}); - -$.each( [ "Width", "Height" ], function( i, name ) { - var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], - type = name.toLowerCase(), - orig = { - innerWidth: $.fn.innerWidth, - innerHeight: $.fn.innerHeight, - outerWidth: $.fn.outerWidth, - outerHeight: $.fn.outerHeight - }; - - function reduce( elem, size, border, margin ) { - $.each( side, function() { - size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; - if ( border ) { - size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; - } - if ( margin ) { - size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; - } - }); - return size; - } - - $.fn[ "inner" + name ] = function( size ) { - if ( size === undefined ) { - return orig[ "inner" + name ].call( this ); - } - + uniqueId: function() { return this.each(function() { - $( this ).css( type, reduce( this, size ) + "px" ); + if ( !this.id ) { + this.id = "ui-id-" + (++uuid); + } }); - }; - - $.fn[ "outer" + name] = function( size, margin ) { - if ( typeof size !== "number" ) { - return orig[ "outer" + name ].call( this, size ); - } + }, + removeUniqueId: function() { return this.each(function() { - $( this).css( type, reduce( this, size, true, margin ) + "px" ); + if ( runiqueId.test( this.id ) ) { + $( this ).removeAttr( "id" ); + } }); - }; + } }); // selectors function focusable( element, isTabIndexNotNaN ) { - var nodeName = element.nodeName.toLowerCase(); + var map, mapName, img, + nodeName = element.nodeName.toLowerCase(); if ( "area" === nodeName ) { - var map = element.parentNode, - mapName = map.name, - img; + map = element.parentNode; + mapName = map.name; if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { return false; } img = $( "img[usemap=#" + mapName + "]" )[0]; return !!img && visible( img ); } - return ( /input|select|textarea|button|object/.test( nodeName ) - ? !element.disabled - : "a" == nodeName - ? element.href || isTabIndexNotNaN - : isTabIndexNotNaN) + return ( /input|select|textarea|button|object/.test( nodeName ) ? + !element.disabled : + "a" === nodeName ? + element.href || isTabIndexNotNaN : + isTabIndexNotNaN) && // the element and all of its ancestors must be visible - && visible( element ); + visible( element ); } function visible( element ) { - return !$( element ).parents().andSelf().filter(function() { - return $.curCSS( this, "visibility" ) === "hidden" || - $.expr.filters.hidden( this ); - }).length; + return $.expr.filters.visible( element ) && + !$( element ).parents().andSelf().filter(function() { + return $.css( this, "visibility" ) === "hidden"; + }).length; } $.extend( $.expr[ ":" ], { - data: function( elem, i, match ) { - return !!$.data( elem, match[ 3 ] ); - }, + data: $.expr.createPseudo ? + $.expr.createPseudo(function( dataName ) { + return function( elem ) { + return !!$.data( elem, dataName ); + }; + }) : + // support: jQuery <1.8 + function( elem, i, match ) { + return !!$.data( elem, match[ 3 ] ); + }, focusable: function( element ) { return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); @@ -225,6 +180,11 @@ $(function() { var body = document.body, div = body.appendChild( div = document.createElement( "div" ) ); + // access offsetHeight before setting the style to prevent a layout bug + // in IE 9 which causes the element to continue to take up space even + // after it is removed from the DOM (#8026) + div.offsetHeight; + $.extend( div.style, { minHeight: "100px", height: "auto", @@ -240,57 +200,134 @@ $(function() { body.removeChild( div ).style.display = "none"; }); +// support: jQuery <1.8 +if ( !$( "" ).outerWidth( 1 ).jquery ) { + $.each( [ "Width", "Height" ], function( i, name ) { + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], + type = name.toLowerCase(), + orig = { + innerWidth: $.fn.innerWidth, + innerHeight: $.fn.innerHeight, + outerWidth: $.fn.outerWidth, + outerHeight: $.fn.outerHeight + }; + + function reduce( elem, size, border, margin ) { + $.each( side, function() { + size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; + if ( border ) { + size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; + } + if ( margin ) { + size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; + } + }); + return size; + } + + $.fn[ "inner" + name ] = function( size ) { + if ( size === undefined ) { + return orig[ "inner" + name ].call( this ); + } + + return this.each(function() { + $( this ).css( type, reduce( this, size ) + "px" ); + }); + }; + + $.fn[ "outer" + name] = function( size, margin ) { + if ( typeof size !== "number" ) { + return orig[ "outer" + name ].call( this, size ); + } + + return this.each(function() { + $( this).css( type, reduce( this, size, true, margin ) + "px" ); + }); + }; + }); +} + +// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) +if ( $( "" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { + $.fn.removeData = (function( removeData ) { + return function( key ) { + if ( arguments.length ) { + return removeData.call( this, $.camelCase( key ) ); + } else { + return removeData.call( this ); + } + }; + })( $.fn.removeData ); +} + // deprecated + +(function() { + var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || []; + $.ui.ie = uaMatch.length ? true : false; + $.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6; +})(); + +$.fn.extend({ + disableSelection: function() { + return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + + ".ui-disableSelection", function( event ) { + event.preventDefault(); + }); + }, + + enableSelection: function() { + return this.unbind( ".ui-disableSelection" ); + } +}); + $.extend( $.ui, { // $.ui.plugin is deprecated. Use the proxy pattern instead. plugin: { add: function( module, option, set ) { - var proto = $.ui[ module ].prototype; - for ( var i in set ) { + var i, + proto = $.ui[ module ].prototype; + for ( i in set ) { proto.plugins[ i ] = proto.plugins[ i ] || []; proto.plugins[ i ].push( [ option, set[ i ] ] ); } }, call: function( instance, name, args ) { - var set = instance.plugins[ name ]; - if ( !set || !instance.element[ 0 ].parentNode ) { + var i, + set = instance.plugins[ name ]; + if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { return; } - - for ( var i = 0; i < set.length; i++ ) { + + for ( i = 0; i < set.length; i++ ) { if ( instance.options[ set[ i ][ 0 ] ] ) { set[ i ][ 1 ].apply( instance.element, args ); } } } }, - - // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() - contains: function( a, b ) { - return document.compareDocumentPosition ? - a.compareDocumentPosition( b ) & 16 : - a !== b && a.contains( b ); - }, - + + contains: $.contains, + // only used by resizable hasScroll: function( el, a ) { - + //If overflow is hidden, the element might have extra content, but the user wants to hide it if ( $( el ).css( "overflow" ) === "hidden") { return false; } - + var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", has = false; - + if ( el[ scroll ] > 0 ) { return true; } - + // TODO: determine which cases actually cause this to happen // if the element doesn't have the scroll set, see if it's possible to // set the scroll @@ -299,7 +336,7 @@ $.extend( $.ui, { el[ scroll ] = 0; return has; }, - + // these are odd functions, fix the API or move into individual plugins isOverAxis: function( x, reference, size ) { //Determines when x coordinate is over "b" element axis @@ -312,51 +349,25 @@ $.extend( $.ui, { }); })( jQuery ); -/*! - * jQuery UI Widget 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Widget - */ (function( $, undefined ) { -// jQuery 1.4+ -if ( $.cleanData ) { - var _cleanData = $.cleanData; - $.cleanData = function( elems ) { - for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { - try { - $( elem ).triggerHandler( "remove" ); - // http://bugs.jquery.com/ticket/8235 - } catch( e ) {} - } - _cleanData( elems ); - }; -} else { - var _remove = $.fn.remove; - $.fn.remove = function( selector, keepData ) { - return this.each(function() { - if ( !keepData ) { - if ( !selector || $.filter( selector, [ this ] ).length ) { - $( "*", this ).add( [ this ] ).each(function() { - try { - $( this ).triggerHandler( "remove" ); - // http://bugs.jquery.com/ticket/8235 - } catch( e ) {} - }); - } - } - return _remove.call( $(this), selector, keepData ); - }); - }; -} +var uuid = 0, + slice = Array.prototype.slice, + _cleanData = $.cleanData; +$.cleanData = function( elems ) { + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + try { + $( elem ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + } + _cleanData( elems ); +}; $.widget = function( name, base, prototype ) { - var namespace = name.split( "." )[ 0 ], - fullName; + var fullName, existingConstructor, constructor, basePrototype, + namespace = name.split( "." )[ 0 ]; + name = name.split( "." )[ 1 ]; fullName = namespace + "-" + name; @@ -366,81 +377,167 @@ $.widget = function( name, base, prototype ) { } // create selector for plugin - $.expr[ ":" ][ fullName ] = function( elem ) { - return !!$.data( elem, name ); + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); }; $[ namespace ] = $[ namespace ] || {}; - $[ namespace ][ name ] = function( options, element ) { + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new constructor( options, element ); + } + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) if ( arguments.length ) { this._createWidget( options, element ); } }; + // extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + // copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + // track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + }); - var basePrototype = new base(); + basePrototype = new base(); // we need to make the options hash a property directly on the new instance // otherwise we'll modify the options hash on the prototype that we're // inheriting from -// $.each( basePrototype, function( key, val ) { -// if ( $.isPlainObject(val) ) { -// basePrototype[ key ] = $.extend( {}, val ); -// } -// }); - basePrototype.options = $.extend( true, {}, basePrototype.options ); - $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( $.isFunction( value ) ) { + prototype[ prop ] = (function() { + var _super = function() { + return base.prototype[ prop ].apply( this, arguments ); + }, + _superApply = function( args ) { + return base.prototype[ prop ].apply( this, args ); + }; + return function() { + var __super = this._super, + __superApply = this._superApply, + returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply( this, arguments ); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + })(); + } + }); + constructor.prototype = $.widget.extend( basePrototype, { + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name + }, prototype, { + constructor: constructor, namespace: namespace, widgetName: name, - widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, - widgetBaseClass: fullName - }, prototype ); + // TODO remove widgetBaseClass, see #8155 + widgetBaseClass: fullName, + widgetFullName: fullName + }); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); + }); + // remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } - $.widget.bridge( name, $[ namespace ][ name ] ); + $.widget.bridge( name, constructor ); +}; + +$.widget.extend = function( target ) { + var input = slice.call( arguments, 1 ), + inputIndex = 0, + inputLength = input.length, + key, + value; + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; }; $.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; $.fn[ name ] = function( options ) { var isMethodCall = typeof options === "string", - args = Array.prototype.slice.call( arguments, 1 ), + args = slice.call( arguments, 1 ), returnValue = this; // allow multiple hashes to be passed on init options = !isMethodCall && args.length ? - $.extend.apply( null, [ true, options ].concat(args) ) : + $.widget.extend.apply( null, [ options ].concat(args) ) : options; - // prevent calls to internal methods - if ( isMethodCall && options.charAt( 0 ) === "_" ) { - return returnValue; - } - if ( isMethodCall ) { this.each(function() { - var instance = $.data( this, name ), - methodValue = instance && $.isFunction( instance[options] ) ? - instance[ options ].apply( instance, args ) : - instance; - // TODO: add this back in 1.9 and use $.error() (see #5972) -// if ( !instance ) { -// throw "cannot call methods on " + name + " prior to initialization; " + -// "attempted to call method '" + options + "'"; -// } -// if ( !$.isFunction( instance[options] ) ) { -// throw "no such method '" + options + "' for " + name + " widget instance"; -// } -// var methodValue = instance[ options ].apply( instance, args ); + var methodValue, + instance = $.data( this, fullName ); + if ( !instance ) { + return $.error( "cannot call methods on " + name + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + " widget instance" ); + } + methodValue = instance[ options ].apply( instance, args ); if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue; + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; return false; } }); } else { this.each(function() { - var instance = $.data( this, name ); + var instance = $.data( this, fullName ); if ( instance ) { instance.option( options || {} )._init(); } else { - $.data( this, name, new object( options, this ) ); + $.data( this, fullName, new object( options, this ) ); } }); } @@ -449,74 +546,126 @@ $.widget.bridge = function( name, object ) { }; }; -$.Widget = function( options, element ) { - // allow instantiation without initializing for simple inheritance - if ( arguments.length ) { - this._createWidget( options, element ); - } -}; +$.Widget = function( /* options, element */ ) {}; +$.Widget._childConstructors = []; $.Widget.prototype = { widgetName: "widget", widgetEventPrefix: "", + defaultElement: "
    ", options: { - disabled: false + disabled: false, + + // callbacks + create: null }, _createWidget: function( options, element ) { - // $.widget.bridge stores the plugin instance, but we do it anyway - // so that it's stored even before the _create function runs - $.data( element, this.widgetName, this ); + element = $( element || this.defaultElement || this )[ 0 ]; this.element = $( element ); - this.options = $.extend( true, {}, + this.uuid = uuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + this.options = $.widget.extend( {}, this.options, this._getCreateOptions(), options ); - var self = this; - this.element.bind( "remove." + this.widgetName, function() { - self.destroy(); - }); + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + + if ( element !== this ) { + // 1.9 BC for #7810 + // TODO remove dual storage + $.data( element, this.widgetName, this ); + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + }); + this.document = $( element.style ? + // element within the document + element.ownerDocument : + // element is window or document + element.document || element ); + this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); + } this._create(); - this._trigger( "create" ); + this._trigger( "create", null, this._getCreateEventData() ); this._init(); }, - _getCreateOptions: function() { - return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; - }, - _create: function() {}, - _init: function() {}, + _getCreateOptions: $.noop, + _getCreateEventData: $.noop, + _create: $.noop, + _init: $.noop, destroy: function() { + this._destroy(); + // we can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() this.element - .unbind( "." + this.widgetName ) - .removeData( this.widgetName ); + .unbind( this.eventNamespace ) + // 1.9 BC for #7810 + // TODO remove dual storage + .removeData( this.widgetName ) + .removeData( this.widgetFullName ) + // support: jquery <1.6.3 + // http://bugs.jquery.com/ticket/9413 + .removeData( $.camelCase( this.widgetFullName ) ); this.widget() - .unbind( "." + this.widgetName ) + .unbind( this.eventNamespace ) .removeAttr( "aria-disabled" ) .removeClass( - this.widgetBaseClass + "-disabled " + + this.widgetFullName + "-disabled " + "ui-state-disabled" ); + + // clean up events and states + this.bindings.unbind( this.eventNamespace ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); }, + _destroy: $.noop, widget: function() { return this.element; }, option: function( key, value ) { - var options = key; + var options = key, + parts, + curOption, + i; if ( arguments.length === 0 ) { // don't return a reference to the internal hash - return $.extend( {}, this.options ); + return $.widget.extend( {}, this.options ); } - if (typeof key === "string" ) { - if ( value === undefined ) { - return this.options[ key ]; - } + if ( typeof key === "string" ) { + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } options = {}; - options[ key ] = value; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( value === undefined ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( value === undefined ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } } this._setOptions( options ); @@ -524,10 +673,11 @@ $.Widget.prototype = { return this; }, _setOptions: function( options ) { - var self = this; - $.each( options, function( key, value ) { - self._setOption( key, value ); - }); + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } return this; }, @@ -536,10 +686,10 @@ $.Widget.prototype = { if ( key === "disabled" ) { this.widget() - [ value ? "addClass" : "removeClass"]( - this.widgetBaseClass + "-disabled" + " " + - "ui-state-disabled" ) + .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) .attr( "aria-disabled", value ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); } return this; @@ -552,46 +702,171 @@ $.Widget.prototype = { return this._setOption( "disabled", true ); }, + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement, + instance = this; + + // no suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // no element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + // accept selectors, DOM elements + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + // allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^(\w+)\s*(.*)$/ ), + eventName = match[1] + instance.eventNamespace, + selector = match[2]; + if ( selector ) { + delegateElement.delegate( selector, eventName, handlerProxy ); + } else { + element.bind( eventName, handlerProxy ); + } + }); + }, + + _off: function( element, eventName ) { + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; + element.unbind( eventName ).undelegate( eventName ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + $( event.currentTarget ).addClass( "ui-state-hover" ); + }, + mouseleave: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-hover" ); + } + }); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + $( event.currentTarget ).addClass( "ui-state-focus" ); + }, + focusout: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-focus" ); + } + }); + }, + _trigger: function( type, event, data ) { - var callback = this.options[ type ]; + var prop, orig, + callback = this.options[ type ]; + data = data || {}; event = $.Event( event ); event.type = ( type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type ).toLowerCase(); - data = data || {}; + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; // copy original event properties over to the new event - // this would happen if we could call $.event.fix instead of $.Event - // but we don't have a way to force an event to be fixed multiple times - if ( event.originalEvent ) { - for ( var i = $.event.props.length, prop; i; ) { - prop = $.event.props[ --i ]; - event[ prop ] = event.originalEvent[ prop ]; + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } } } this.element.trigger( event, data ); - - return !( $.isFunction(callback) && - callback.call( this.element[0], event, data ) === false || + return !( $.isFunction( callback ) && + callback.apply( this.element[0], [ event ].concat( data ) ) === false || event.isDefaultPrevented() ); } }; +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + var hasOptions, + effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + if ( options.delay ) { + element.delay( options.delay ); + } + if ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue(function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + }); + } + }; +}); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + $.Widget.prototype._getCreateOptions = function() { + return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; + }; +} + })( jQuery ); -/*! - * jQuery UI Mouse 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Mouse - * - * Depends: - * jquery.ui.widget.js - */ (function( $, undefined ) { var mouseHandled = false; @@ -600,21 +875,22 @@ $( document ).mouseup( function( e ) { }); $.widget("ui.mouse", { + version: "1.9.2", options: { - cancel: ':input,option', + cancel: 'input,textarea,button,select,option', distance: 1, delay: 0 }, _mouseInit: function() { - var self = this; + var that = this; this.element .bind('mousedown.'+this.widgetName, function(event) { - return self._mouseDown(event); + return that._mouseDown(event); }) .bind('click.'+this.widgetName, function(event) { - if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { - $.removeData(event.target, self.widgetName + '.preventClickEvent'); + if (true === $.data(event.target, that.widgetName + '.preventClickEvent')) { + $.removeData(event.target, that.widgetName + '.preventClickEvent'); event.stopImmediatePropagation(); return false; } @@ -627,22 +903,27 @@ $.widget("ui.mouse", { // other instances of mouse _mouseDestroy: function() { this.element.unbind('.'+this.widgetName); + if ( this._mouseMoveDelegate ) { + $(document) + .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); + } }, _mouseDown: function(event) { // don't let more than one widget handle mouseStart - if( mouseHandled ) { return }; + if( mouseHandled ) { return; } // we may have missed mouseup (out of window) (this._mouseStarted && this._mouseUp(event)); this._mouseDownEvent = event; - var self = this, - btnIsLeft = (event.which == 1), + var that = this, + btnIsLeft = (event.which === 1), // event.target.nodeName works around a bug in IE 8 with // disabled inputs (#7620) - elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); + elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { return true; } @@ -650,7 +931,7 @@ $.widget("ui.mouse", { this.mouseDelayMet = !this.options.delay; if (!this.mouseDelayMet) { this._mouseDelayTimer = setTimeout(function() { - self.mouseDelayMet = true; + that.mouseDelayMet = true; }, this.options.delay); } @@ -669,24 +950,24 @@ $.widget("ui.mouse", { // these delegates are required to keep context this._mouseMoveDelegate = function(event) { - return self._mouseMove(event); + return that._mouseMove(event); }; this._mouseUpDelegate = function(event) { - return self._mouseUp(event); + return that._mouseUp(event); }; $(document) .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); event.preventDefault(); - + mouseHandled = true; return true; }, _mouseMove: function(event) { // IE mouseup check - mouseup happened when mouse was out of window - if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { + if ($.ui.ie && !(document.documentMode >= 9) && !event.button) { return this._mouseUp(event); } @@ -712,8 +993,8 @@ $.widget("ui.mouse", { if (this._mouseStarted) { this._mouseStarted = false; - if (event.target == this._mouseDownEvent.target) { - $.data(event.target, this.widgetName + '.preventClickEvent', true); + if (event.target === this._mouseDownEvent.target) { + $.data(event.target, this.widgetName + '.preventClickEvent', true); } this._mouseStop(event); @@ -742,2370 +1023,4983 @@ $.widget("ui.mouse", { }); })(jQuery); -/* - * jQuery UI Draggable 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Draggables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ (function( $, undefined ) { -$.widget("ui.draggable", $.ui.mouse, { - widgetEventPrefix: "drag", - options: { - addClasses: true, - appendTo: "parent", - axis: false, - connectToSortable: false, - containment: false, - cursor: "auto", - cursorAt: false, - grid: false, - handle: false, - helper: "original", - iframeFix: false, - opacity: false, - refreshPositions: false, - revert: false, - revertDuration: 500, - scope: "default", - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - snap: false, - snapMode: "both", - snapTolerance: 20, - stack: false, - zIndex: false - }, - _create: function() { - - if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) - this.element[0].style.position = 'relative'; +$.ui = $.ui || {}; - (this.options.addClasses && this.element.addClass("ui-draggable")); - (this.options.disabled && this.element.addClass("ui-draggable-disabled")); - - this._mouseInit(); - - }, - - destroy: function() { - if(!this.element.data('draggable')) return; - this.element - .removeData("draggable") - .unbind(".draggable") - .removeClass("ui-draggable" - + " ui-draggable-dragging" - + " ui-draggable-disabled"); - this._mouseDestroy(); - - return this; - }, +var cachedScrollbarWidth, + max = Math.max, + abs = Math.abs, + round = Math.round, + rhorizontal = /left|center|right/, + rvertical = /top|center|bottom/, + roffset = /[\+\-]\d+%?/, + rposition = /^\w+/, + rpercent = /%$/, + _position = $.fn.position; + +function getOffsets( offsets, width, height ) { + return [ + parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), + parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) + ]; +} +function parseCss( element, property ) { + return parseInt( $.css( element, property ), 10 ) || 0; +} - _mouseCapture: function(event) { +$.position = { + scrollbarWidth: function() { + if ( cachedScrollbarWidth !== undefined ) { + return cachedScrollbarWidth; + } + var w1, w2, + div = $( "
    " ), + innerDiv = div.children()[0]; - var o = this.options; + $( "body" ).append( div ); + w1 = innerDiv.offsetWidth; + div.css( "overflow", "scroll" ); - // among others, prevent a drag on a resizable-handle - if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) - return false; + w2 = innerDiv.offsetWidth; - //Quit if we're not on a valid handle - this.handle = this._getHandle(event); - if (!this.handle) - return false; - - if ( o.iframeFix ) { - $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { - $('
    ') - .css({ - width: this.offsetWidth+"px", height: this.offsetHeight+"px", - position: "absolute", opacity: "0.001", zIndex: 1000 - }) - .css($(this).offset()) - .appendTo("body"); - }); + if ( w1 === w2 ) { + w2 = div[0].clientWidth; } - return true; + div.remove(); + return (cachedScrollbarWidth = w1 - w2); }, + getScrollInfo: function( within ) { + var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ), + overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ), + hasOverflowX = overflowX === "scroll" || + ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), + hasOverflowY = overflowY === "scroll" || + ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); + return { + width: hasOverflowX ? $.position.scrollbarWidth() : 0, + height: hasOverflowY ? $.position.scrollbarWidth() : 0 + }; + }, + getWithinInfo: function( element ) { + var withinElement = $( element || window ), + isWindow = $.isWindow( withinElement[0] ); + return { + element: withinElement, + isWindow: isWindow, + offset: withinElement.offset() || { left: 0, top: 0 }, + scrollLeft: withinElement.scrollLeft(), + scrollTop: withinElement.scrollTop(), + width: isWindow ? withinElement.width() : withinElement.outerWidth(), + height: isWindow ? withinElement.height() : withinElement.outerHeight() + }; + } +}; - _mouseStart: function(event) { - - var o = this.options; +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } - //Create and append the visible helper - this.helper = this._createHelper(event); + // make a copy, we don't want to modify arguments + options = $.extend( {}, options ); - //Cache the helper size - this._cacheHelperProportions(); + var atOffset, targetWidth, targetHeight, targetOffset, basePosition, + target = $( options.of ), + within = $.position.getWithinInfo( options.within ), + scrollInfo = $.position.getScrollInfo( within ), + targetElem = target[0], + collision = ( options.collision || "flip" ).split( " " ), + offsets = {}; - //If ddmanager is used for droppables, set the global draggable - if($.ui.ddmanager) - $.ui.ddmanager.current = this; + if ( targetElem.nodeType === 9 ) { + targetWidth = target.width(); + targetHeight = target.height(); + targetOffset = { top: 0, left: 0 }; + } else if ( $.isWindow( targetElem ) ) { + targetWidth = target.width(); + targetHeight = target.height(); + targetOffset = { top: target.scrollTop(), left: target.scrollLeft() }; + } else if ( targetElem.preventDefault ) { + // force left top to allow flipping + options.at = "left top"; + targetWidth = targetHeight = 0; + targetOffset = { top: targetElem.pageY, left: targetElem.pageX }; + } else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + targetOffset = target.offset(); + } + // clone to reuse original targetOffset later + basePosition = $.extend( {}, targetOffset ); - /* - * - Position generation - - * This block generates everything position related - it's the core of draggables. - */ + // force my and at to have valid horizontal and vertical positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[ this ] || "" ).split( " " ), + horizontalOffset, + verticalOffset; - //Cache the margins of the original element - this._cacheMargins(); + if ( pos.length === 1) { + pos = rhorizontal.test( pos[ 0 ] ) ? + pos.concat( [ "center" ] ) : + rvertical.test( pos[ 0 ] ) ? + [ "center" ].concat( pos ) : + [ "center", "center" ]; + } + pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; + pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; + + // calculate offsets + horizontalOffset = roffset.exec( pos[ 0 ] ); + verticalOffset = roffset.exec( pos[ 1 ] ); + offsets[ this ] = [ + horizontalOffset ? horizontalOffset[ 0 ] : 0, + verticalOffset ? verticalOffset[ 0 ] : 0 + ]; - //Store the helper's css position - this.cssPosition = this.helper.css("position"); - this.scrollParent = this.helper.scrollParent(); + // reduce to just the positions without the offsets + options[ this ] = [ + rposition.exec( pos[ 0 ] )[ 0 ], + rposition.exec( pos[ 1 ] )[ 0 ] + ]; + }); - //The element's absolute position on the page minus margins - this.offset = this.positionAbs = this.element.offset(); - this.offset = { - top: this.offset.top - this.margins.top, - left: this.offset.left - this.margins.left - }; + // normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } - $.extend(this.offset, { - click: { //Where the click happened, relative to the element - left: event.pageX - this.offset.left, - top: event.pageY - this.offset.top - }, - parent: this._getParentOffset(), - relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper - }); + if ( options.at[ 0 ] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[ 0 ] === "center" ) { + basePosition.left += targetWidth / 2; + } - //Generate the original position - this.originalPosition = this.position = this._generatePosition(event); - this.originalPageX = event.pageX; - this.originalPageY = event.pageY; + if ( options.at[ 1 ] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[ 1 ] === "center" ) { + basePosition.top += targetHeight / 2; + } - //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied - (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); + basePosition.left += atOffset[ 0 ]; + basePosition.top += atOffset[ 1 ]; - //Set a containment if given in the options - if(o.containment) - this._setContainment(); + return this.each(function() { + var collisionPosition, using, + elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseCss( this, "marginLeft" ), + marginTop = parseCss( this, "marginTop" ), + collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, + collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, + position = $.extend( {}, basePosition ), + myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); - //Trigger event + callbacks - if(this._trigger("start", event) === false) { - this._clear(); - return false; + if ( options.my[ 0 ] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[ 0 ] === "center" ) { + position.left -= elemWidth / 2; } - //Recache the helper size - this._cacheHelperProportions(); - - //Prepare the droppable offsets - if ($.ui.ddmanager && !o.dropBehaviour) - $.ui.ddmanager.prepareOffsets(this, event); - - this.helper.addClass("ui-draggable-dragging"); - this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position - - //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) - if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); - - return true; - }, - - _mouseDrag: function(event, noPropagation) { + if ( options.my[ 1 ] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[ 1 ] === "center" ) { + position.top -= elemHeight / 2; + } - //Compute the helpers position - this.position = this._generatePosition(event); - this.positionAbs = this._convertPositionTo("absolute"); + position.left += myOffset[ 0 ]; + position.top += myOffset[ 1 ]; - //Call plugins and callbacks and use the resulting position if something is returned - if (!noPropagation) { - var ui = this._uiHash(); - if(this._trigger('drag', event, ui) === false) { - this._mouseUp({}); - return false; - } - this.position = ui.position; + // if the browser doesn't support fractions, then round for consistent results + if ( !$.support.offsetFractions ) { + position.left = round( position.left ); + position.top = round( position.top ); } - if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; - if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; - if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); - - return false; - }, + collisionPosition = { + marginLeft: marginLeft, + marginTop: marginTop + }; - _mouseStop: function(event) { + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[ i ] ] ) { + $.ui.position[ collision[ i ] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], + my: options.my, + at: options.at, + within: within, + elem : elem + }); + } + }); - //If we are using droppables, inform the manager about the drop - var dropped = false; - if ($.ui.ddmanager && !this.options.dropBehaviour) - dropped = $.ui.ddmanager.drop(this, event); + if ( $.fn.bgiframe ) { + elem.bgiframe(); + } - //if a drop comes from outside (a sortable) - if(this.dropped) { - dropped = this.dropped; - this.dropped = false; + if ( options.using ) { + // adds feedback as second argument to using callback, if present + using = function( props ) { + var left = targetOffset.left - position.left, + right = left + targetWidth - elemWidth, + top = targetOffset.top - position.top, + bottom = top + targetHeight - elemHeight, + feedback = { + target: { + element: target, + left: targetOffset.left, + top: targetOffset.top, + width: targetWidth, + height: targetHeight + }, + element: { + element: elem, + left: position.left, + top: position.top, + width: elemWidth, + height: elemHeight + }, + horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", + vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" + }; + if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { + feedback.horizontal = "center"; + } + if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { + feedback.vertical = "middle"; + } + if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { + feedback.important = "horizontal"; + } else { + feedback.important = "vertical"; + } + options.using.call( this, props, feedback ); + }; } - - //if the original element is removed, don't bother to continue if helper is set to "original" - if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original") - return false; - if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { - var self = this; - $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { - if(self._trigger("stop", event) !== false) { - self._clear(); + elem.offset( $.extend( position, { using: using } ) ); + }); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, + outerWidth = within.width, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = withinOffset - collisionPosLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, + newOverRight; + + // element is wider than within + if ( data.collisionWidth > outerWidth ) { + // element is initially over the left side of within + if ( overLeft > 0 && overRight <= 0 ) { + newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; + position.left += overLeft - newOverRight; + // element is initially over right side of within + } else if ( overRight > 0 && overLeft <= 0 ) { + position.left = withinOffset; + // element is initially over both left and right sides of within + } else { + if ( overLeft > overRight ) { + position.left = withinOffset + outerWidth - data.collisionWidth; + } else { + position.left = withinOffset; + } } - }); - } else { - if(this._trigger("stop", event) !== false) { - this._clear(); + // too far left -> align with left edge + } else if ( overLeft > 0 ) { + position.left += overLeft; + // too far right -> align with right edge + } else if ( overRight > 0 ) { + position.left -= overRight; + // adjust based on position and margin + } else { + position.left = max( position.left - collisionPosLeft, position.left ); + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollTop : within.offset.top, + outerHeight = data.within.height, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = withinOffset - collisionPosTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, + newOverBottom; + + // element is taller than within + if ( data.collisionHeight > outerHeight ) { + // element is initially over the top of within + if ( overTop > 0 && overBottom <= 0 ) { + newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; + position.top += overTop - newOverBottom; + // element is initially over bottom of within + } else if ( overBottom > 0 && overTop <= 0 ) { + position.top = withinOffset; + // element is initially over both top and bottom of within + } else { + if ( overTop > overBottom ) { + position.top = withinOffset + outerHeight - data.collisionHeight; + } else { + position.top = withinOffset; + } + } + // too far up -> align with top + } else if ( overTop > 0 ) { + position.top += overTop; + // too far down -> align with bottom edge + } else if ( overBottom > 0 ) { + position.top -= overBottom; + // adjust based on position and margin + } else { + position.top = max( position.top - collisionPosTop, position.top ); } } - - return false; }, - - _mouseUp: function(event) { - if (this.options.iframeFix === true) { - $("div.ui-draggable-iframeFix").each(function() { - this.parentNode.removeChild(this); - }); //Remove frame helpers + flip: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.offset.left + within.scrollLeft, + outerWidth = within.width, + offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = collisionPosLeft - offsetLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + data.at[ 0 ] === "right" ? + -data.targetWidth : + 0, + offset = -2 * data.offset[ 0 ], + newOverRight, + newOverLeft; + + if ( overLeft < 0 ) { + newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; + if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { + position.left += myOffset + atOffset + offset; + } + } + else if ( overRight > 0 ) { + newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; + if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { + position.left += myOffset + atOffset + offset; + } + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.offset.top + within.scrollTop, + outerHeight = within.height, + offsetTop = within.isWindow ? within.scrollTop : within.offset.top, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = collisionPosTop - offsetTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, + top = data.my[ 1 ] === "top", + myOffset = top ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + data.at[ 1 ] === "bottom" ? + -data.targetHeight : + 0, + offset = -2 * data.offset[ 1 ], + newOverTop, + newOverBottom; + if ( overTop < 0 ) { + newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; + if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { + position.top += myOffset + atOffset + offset; + } + } + else if ( overBottom > 0 ) { + newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; + if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { + position.top += myOffset + atOffset + offset; + } + } } - - //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) - if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); - - return $.ui.mouse.prototype._mouseUp.call(this, event); }, - - cancel: function() { - - if(this.helper.is(".ui-draggable-dragging")) { - this._mouseUp({}); - } else { - this._clear(); + flipfit: { + left: function() { + $.ui.position.flip.left.apply( this, arguments ); + $.ui.position.fit.left.apply( this, arguments ); + }, + top: function() { + $.ui.position.flip.top.apply( this, arguments ); + $.ui.position.fit.top.apply( this, arguments ); } - - return this; - - }, + } +}; - _getHandle: function(event) { +// fraction support test +(function () { + var testElement, testElementParent, testElementStyle, offsetLeft, i, + body = document.getElementsByTagName( "body" )[ 0 ], + div = document.createElement( "div" ); + + //Create a "fake body" for testing based on method used in jQuery.support + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + $.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || document.documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + div.style.cssText = "position: absolute; left: 10.7432222px;"; + + offsetLeft = $( div ).offset().left; + $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; + + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); +})(); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + // offset option + (function( $ ) { + var _position = $.fn.position; + $.fn.position = function( options ) { + if ( !options || !options.offset ) { + return _position.call( this, options ); + } + var offset = options.offset.split( " " ), + at = options.at.split( " " ); + if ( offset.length === 1 ) { + offset[ 1 ] = offset[ 0 ]; + } + if ( /^\d/.test( offset[ 0 ] ) ) { + offset[ 0 ] = "+" + offset[ 0 ]; + } + if ( /^\d/.test( offset[ 1 ] ) ) { + offset[ 1 ] = "+" + offset[ 1 ]; + } + if ( at.length === 1 ) { + if ( /left|center|right/.test( at[ 0 ] ) ) { + at[ 1 ] = "center"; + } else { + at[ 1 ] = at[ 0 ]; + at[ 0 ] = "center"; + } + } + return _position.call( this, $.extend( options, { + at: at[ 0 ] + offset[ 0 ] + " " + at[ 1 ] + offset[ 1 ], + offset: undefined + } ) ); + }; + }( jQuery ) ); +} - var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; - $(this.options.handle, this.element) - .find("*") - .andSelf() - .each(function() { - if(this == event.target) handle = true; - }); +}( jQuery ) ); +(function( $, undefined ) { - return handle; +var uid = 0, + hideProps = {}, + showProps = {}; + +hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = + hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; +showProps.height = showProps.paddingTop = showProps.paddingBottom = + showProps.borderTopWidth = showProps.borderBottomWidth = "show"; + +$.widget( "ui.accordion", { + version: "1.9.2", + options: { + active: 0, + animate: {}, + collapsible: false, + event: "click", + header: "> li > :first-child,> :not(li):even", + heightStyle: "auto", + icons: { + activeHeader: "ui-icon-triangle-1-s", + header: "ui-icon-triangle-1-e" + }, + // callbacks + activate: null, + beforeActivate: null }, - _createHelper: function(event) { + _create: function() { + var accordionId = this.accordionId = "ui-accordion-" + + (this.element.attr( "id" ) || ++uid), + options = this.options; + + this.prevShow = this.prevHide = $(); + this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ); + + this.headers = this.element.find( options.header ) + .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); + this._hoverable( this.headers ); + this._focusable( this.headers ); + + this.headers.next() + .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) + .hide(); + + // don't allow collapsible: false and active: false / null + if ( !options.collapsible && (options.active === false || options.active == null) ) { + options.active = 0; + } + // handle negative values + if ( options.active < 0 ) { + options.active += this.headers.length; + } + this.active = this._findActive( options.active ) + .addClass( "ui-accordion-header-active ui-state-active" ) + .toggleClass( "ui-corner-all ui-corner-top" ); + this.active.next() + .addClass( "ui-accordion-content-active" ) + .show(); + + this._createIcons(); + this.refresh(); - var o = this.options; - var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); + // ARIA + this.element.attr( "role", "tablist" ); - if(!helper.parents('body').length) - helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); + this.headers + .attr( "role", "tab" ) + .each(function( i ) { + var header = $( this ), + headerId = header.attr( "id" ), + panel = header.next(), + panelId = panel.attr( "id" ); + if ( !headerId ) { + headerId = accordionId + "-header-" + i; + header.attr( "id", headerId ); + } + if ( !panelId ) { + panelId = accordionId + "-panel-" + i; + panel.attr( "id", panelId ); + } + header.attr( "aria-controls", panelId ); + panel.attr( "aria-labelledby", headerId ); + }) + .next() + .attr( "role", "tabpanel" ); - if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) - helper.css("position", "absolute"); + this.headers + .not( this.active ) + .attr({ + "aria-selected": "false", + tabIndex: -1 + }) + .next() + .attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }) + .hide(); - return helper; + // make sure at least one header is in the tab order + if ( !this.active.length ) { + this.headers.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active.attr({ + "aria-selected": "true", + tabIndex: 0 + }) + .next() + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); + } + this._on( this.headers, { keydown: "_keydown" }); + this._on( this.headers.next(), { keydown: "_panelKeyDown" }); + this._setupEvents( options.event ); }, - _adjustOffsetFromHelper: function(obj) { - if (typeof obj == 'string') { - obj = obj.split(' '); + _getCreateEventData: function() { + return { + header: this.active, + content: !this.active.length ? $() : this.active.next() + }; + }, + + _createIcons: function() { + var icons = this.options.icons; + if ( icons ) { + $( "" ) + .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) + .prependTo( this.headers ); + this.active.children( ".ui-accordion-header-icon" ) + .removeClass( icons.header ) + .addClass( icons.activeHeader ); + this.headers.addClass( "ui-accordion-icons" ); } - if ($.isArray(obj)) { - obj = {left: +obj[0], top: +obj[1] || 0}; + }, + + _destroyIcons: function() { + this.headers + .removeClass( "ui-accordion-icons" ) + .children( ".ui-accordion-header-icon" ) + .remove(); + }, + + _destroy: function() { + var contents; + + // clean up main element + this.element + .removeClass( "ui-accordion ui-widget ui-helper-reset" ) + .removeAttr( "role" ); + + // clean up headers + this.headers + .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) + .removeAttr( "role" ) + .removeAttr( "aria-selected" ) + .removeAttr( "aria-controls" ) + .removeAttr( "tabIndex" ) + .each(function() { + if ( /^ui-accordion/.test( this.id ) ) { + this.removeAttribute( "id" ); + } + }); + this._destroyIcons(); + + // clean up content panels + contents = this.headers.next() + .css( "display", "" ) + .removeAttr( "role" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-labelledby" ) + .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) + .each(function() { + if ( /^ui-accordion/.test( this.id ) ) { + this.removeAttribute( "id" ); + } + }); + if ( this.options.heightStyle !== "content" ) { + contents.css( "height", "" ); } - if ('left' in obj) { - this.offset.click.left = obj.left + this.margins.left; + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; } - if ('right' in obj) { - this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + + if ( key === "event" ) { + if ( this.options.event ) { + this._off( this.headers, this.options.event ); + } + this._setupEvents( value ); } - if ('top' in obj) { - this.offset.click.top = obj.top + this.margins.top; + + this._super( key, value ); + + // setting collapsible: false while collapsed; open first panel + if ( key === "collapsible" && !value && this.options.active === false ) { + this._activate( 0 ); } - if ('bottom' in obj) { - this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + + if ( key === "icons" ) { + this._destroyIcons(); + if ( value ) { + this._createIcons(); + } + } + + // #5332 - opacity doesn't cascade to positioned elements in IE + // so we need to add the disabled class to the headers and panels + if ( key === "disabled" ) { + this.headers.add( this.headers.next() ) + .toggleClass( "ui-state-disabled", !!value ); } }, - _getParentOffset: function() { + _keydown: function( event ) { + if ( event.altKey || event.ctrlKey ) { + return; + } - //Get the offsetParent and cache its position - this.offsetParent = this.helper.offsetParent(); - var po = this.offsetParent.offset(); + var keyCode = $.ui.keyCode, + length = this.headers.length, + currentIndex = this.headers.index( event.target ), + toFocus = false; - // This is a special case where we need to modify a offset calculated on start, since the following happened: - // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent - // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that - // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag - if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { - po.left += this.scrollParent.scrollLeft(); - po.top += this.scrollParent.scrollTop(); + switch ( event.keyCode ) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[ ( currentIndex + 1 ) % length ]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + this._eventHandler( event ); + break; + case keyCode.HOME: + toFocus = this.headers[ 0 ]; + break; + case keyCode.END: + toFocus = this.headers[ length - 1 ]; + break; } - if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information - || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix - po = { top: 0, left: 0 }; + if ( toFocus ) { + $( event.target ).attr( "tabIndex", -1 ); + $( toFocus ).attr( "tabIndex", 0 ); + toFocus.focus(); + event.preventDefault(); + } + }, - return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) - }; + _panelKeyDown : function( event ) { + if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { + $( event.currentTarget ).prev().focus(); + } + }, + + refresh: function() { + var maxHeight, overflow, + heightStyle = this.options.heightStyle, + parent = this.element.parent(); + + + if ( heightStyle === "fill" ) { + // IE 6 treats height like minHeight, so we need to turn off overflow + // in order to get a reliable height + // we use the minHeight support test because we assume that only + // browsers that don't support minHeight will treat height as minHeight + if ( !$.support.minHeight ) { + overflow = parent.css( "overflow" ); + parent.css( "overflow", "hidden"); + } + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each(function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + }); + if ( overflow ) { + parent.css( "overflow", overflow ); + } + + this.headers.each(function() { + maxHeight -= $( this ).outerHeight( true ); + }); + this.headers.next() + .each(function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + }) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.headers.next() + .each(function() { + maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); + }) + .height( maxHeight ); + } }, - _getRelativeOffset: function() { + _activate: function( index ) { + var active = this._findActive( index )[ 0 ]; - if(this.cssPosition == "relative") { - var p = this.element.position(); - return { - top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), - left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() - }; - } else { - return { top: 0, left: 0 }; + // trying to activate the already active panel + if ( active === this.active[ 0 ] ) { + return; } + // trying to collapse, simulate a click on the currently active header + active = active || this.active[ 0 ]; + + this._eventHandler({ + target: active, + currentTarget: active, + preventDefault: $.noop + }); }, - _cacheMargins: function() { - this.margins = { - left: (parseInt(this.element.css("marginLeft"),10) || 0), - top: (parseInt(this.element.css("marginTop"),10) || 0), - right: (parseInt(this.element.css("marginRight"),10) || 0), - bottom: (parseInt(this.element.css("marginBottom"),10) || 0) - }; + _findActive: function( selector ) { + return typeof selector === "number" ? this.headers.eq( selector ) : $(); }, - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() - }; + _setupEvents: function( event ) { + var events = {}; + if ( !event ) { + return; + } + $.each( event.split(" "), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + }); + this._on( this.headers, events ); }, - _setContainment: function() { + _eventHandler: function( event ) { + var options = this.options, + active = this.active, + clicked = $( event.currentTarget ), + clickedIsActive = clicked[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : clicked.next(), + toHide = active.next(), + eventData = { + oldHeader: active, + oldPanel: toHide, + newHeader: collapsing ? $() : clicked, + newPanel: toShow + }; - var o = this.options; - if(o.containment == 'parent') o.containment = this.helper[0].parentNode; - if(o.containment == 'document' || o.containment == 'window') this.containment = [ - o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, - o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, - (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, - (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top - ]; + event.preventDefault(); - if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { - var c = $(o.containment); - var ce = c[0]; if(!ce) return; - var co = c.offset(); - var over = ($(ce).css("overflow") != 'hidden'); + if ( + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } - this.containment = [ - (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), - (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), - (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, - (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom - ]; - this.relative_container = c; + options.active = collapsing ? false : this.headers.index( clicked ); - } else if(o.containment.constructor == Array) { - this.containment = o.containment; - } - - }, - - _convertPositionTo: function(d, pos) { + // when the call to ._toggle() comes after the class changes + // it causes a very odd bug in IE 8 (see #6720) + this.active = clickedIsActive ? $() : clicked; + this._toggle( eventData ); - if(!pos) pos = this.position; - var mod = d == "absolute" ? 1 : -1; - var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + // switch classes + // corner classes on the previously active header stay after the animation + active.removeClass( "ui-accordion-header-active ui-state-active" ); + if ( options.icons ) { + active.children( ".ui-accordion-header-icon" ) + .removeClass( options.icons.activeHeader ) + .addClass( options.icons.header ); + } - return { - top: ( - pos.top // The absolute mouse position - + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent - + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) - - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) - ), - left: ( - pos.left // The absolute mouse position - + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent - + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) - - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) - ) - }; + if ( !clickedIsActive ) { + clicked + .removeClass( "ui-corner-all" ) + .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); + if ( options.icons ) { + clicked.children( ".ui-accordion-header-icon" ) + .removeClass( options.icons.header ) + .addClass( options.icons.activeHeader ); + } + clicked + .next() + .addClass( "ui-accordion-content-active" ); + } }, - _generatePosition: function(event) { - - var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - var pageX = event.pageX; - var pageY = event.pageY; + _toggle: function( data ) { + var toShow = data.newPanel, + toHide = this.prevShow.length ? this.prevShow : data.oldPanel; - /* - * - Position constraining - - * Constrain the position to a mix of grid, containment. - */ + // handle activating a panel during the animation for another activation + this.prevShow.add( this.prevHide ).stop( true, true ); + this.prevShow = toShow; + this.prevHide = toHide; - if(this.originalPosition) { //If we are not dragging yet, we won't check for options - var containment; - if(this.containment) { - if (this.relative_container){ - var co = this.relative_container.offset(); - containment = [ this.containment[0] + co.left, - this.containment[1] + co.top, - this.containment[2] + co.left, - this.containment[3] + co.top ]; - } - else { - containment = this.containment; - } + if ( this.options.animate ) { + this._animate( toShow, toHide, data ); + } else { + toHide.hide(); + toShow.show(); + this._toggleComplete( data ); + } - if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; - if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; - if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; - if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; - } + toHide.attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + toHide.prev().attr( "aria-selected", "false" ); + // if we're switching panels, remove the old header from the tab order + // if we're opening from collapsed state, remove the previous header from the tab order + // if we're collapsing, then keep the collapsing header in the tab order + if ( toShow.length && toHide.length ) { + toHide.prev().attr( "tabIndex", -1 ); + } else if ( toShow.length ) { + this.headers.filter(function() { + return $( this ).attr( "tabIndex" ) === 0; + }) + .attr( "tabIndex", -1 ); + } - if(o.grid) { - //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) - var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; - pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + toShow + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }) + .prev() + .attr({ + "aria-selected": "true", + tabIndex: 0 + }); + }, - var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; - pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; - } + _animate: function( toShow, toHide, data ) { + var total, easing, duration, + that = this, + adjust = 0, + down = toShow.length && + ( !toHide.length || ( toShow.index() < toHide.index() ) ), + animate = this.options.animate || {}, + options = down && animate.down || animate, + complete = function() { + that._toggleComplete( data ); + }; + if ( typeof options === "number" ) { + duration = options; } + if ( typeof options === "string" ) { + easing = options; + } + // fall back from options to animation in case of partial down settings + easing = easing || options.easing || animate.easing; + duration = duration || options.duration || animate.duration; - return { - top: ( - pageY // The absolute mouse position - - this.offset.click.top // Click offset (relative to the element) - - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent - - this.offset.parent.top // The offsetParent's offset without borders (offset + border) - + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) - ), - left: ( - pageX // The absolute mouse position - - this.offset.click.left // Click offset (relative to the element) - - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent - - this.offset.parent.left // The offsetParent's offset without borders (offset + border) - + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) - ) - }; - - }, + if ( !toHide.length ) { + return toShow.animate( showProps, duration, easing, complete ); + } + if ( !toShow.length ) { + return toHide.animate( hideProps, duration, easing, complete ); + } - _clear: function() { - this.helper.removeClass("ui-draggable-dragging"); - if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); - //if($.ui.ddmanager) $.ui.ddmanager.current = null; - this.helper = null; - this.cancelHelperRemoval = false; + total = toShow.show().outerHeight(); + toHide.animate( hideProps, { + duration: duration, + easing: easing, + step: function( now, fx ) { + fx.now = Math.round( now ); + } + }); + toShow + .hide() + .animate( showProps, { + duration: duration, + easing: easing, + complete: complete, + step: function( now, fx ) { + fx.now = Math.round( now ); + if ( fx.prop !== "height" ) { + adjust += fx.now; + } else if ( that.options.heightStyle !== "content" ) { + fx.now = Math.round( total - toHide.outerHeight() - adjust ); + adjust = 0; + } + } + }); }, - // From now on bulk stuff - mainly helpers + _toggleComplete: function( data ) { + var toHide = data.oldPanel; - _trigger: function(type, event, ui) { - ui = ui || this._uiHash(); - $.ui.plugin.call(this, type, [event, ui]); - if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins - return $.Widget.prototype._trigger.call(this, type, event, ui); - }, + toHide + .removeClass( "ui-accordion-content-active" ) + .prev() + .removeClass( "ui-corner-top" ) + .addClass( "ui-corner-all" ); - plugins: {}, + // Work around for rendering bug in IE (#5421) + if ( toHide.length ) { + toHide.parent()[0].className = toHide.parent()[0].className; + } - _uiHash: function(event) { - return { - helper: this.helper, - position: this.position, - originalPosition: this.originalPosition, - offset: this.positionAbs - }; + this._trigger( "activate", null, data ); } - }); -$.extend($.ui.draggable, { - version: "1.8.16" -}); -$.ui.plugin.add("draggable", "connectToSortable", { - start: function(event, ui) { - var inst = $(this).data("draggable"), o = inst.options, - uiSortable = $.extend({}, ui, { item: inst.element }); - inst.sortables = []; - $(o.connectToSortable).each(function() { - var sortable = $.data(this, 'sortable'); - if (sortable && !sortable.options.disabled) { - inst.sortables.push({ - instance: sortable, - shouldRevert: sortable.options.revert - }); - sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). - sortable._trigger("activate", event, uiSortable); +// DEPRECATED +if ( $.uiBackCompat !== false ) { + // navigation options + (function( $, prototype ) { + $.extend( prototype.options, { + navigation: false, + navigationFilter: function() { + return this.href.toLowerCase() === location.href.toLowerCase(); } }); - }, - stop: function(event, ui) { - - //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper - var inst = $(this).data("draggable"), - uiSortable = $.extend({}, ui, { item: inst.element }); + var _create = prototype._create; + prototype._create = function() { + if ( this.options.navigation ) { + var that = this, + headers = this.element.find( this.options.header ), + content = headers.next(), + current = headers.add( content ) + .find( "a" ) + .filter( this.options.navigationFilter ) + [ 0 ]; + if ( current ) { + headers.add( content ).each( function( index ) { + if ( $.contains( this, current ) ) { + that.options.active = Math.floor( index / 2 ); + return false; + } + }); + } + } + _create.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // height options + (function( $, prototype ) { + $.extend( prototype.options, { + heightStyle: null, // remove default so we fall back to old values + autoHeight: true, // use heightStyle: "auto" + clearStyle: false, // use heightStyle: "content" + fillSpace: false // use heightStyle: "fill" + }); - $.each(inst.sortables, function() { - if(this.instance.isOver) { + var _create = prototype._create, + _setOption = prototype._setOption; - this.instance.isOver = 0; + $.extend( prototype, { + _create: function() { + this.options.heightStyle = this.options.heightStyle || + this._mergeHeightStyle(); - inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance - this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) + _create.call( this ); + }, - //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' - if(this.shouldRevert) this.instance.options.revert = true; + _setOption: function( key ) { + if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) { + this.options.heightStyle = this._mergeHeightStyle(); + } + _setOption.apply( this, arguments ); + }, - //Trigger the stop of the sortable - this.instance._mouseStop(event); + _mergeHeightStyle: function() { + var options = this.options; - this.instance.options.helper = this.instance.options._helper; + if ( options.fillSpace ) { + return "fill"; + } - //If the helper has been the original item, restore properties in the sortable - if(inst.options.helper == 'original') - this.instance.currentItem.css({ top: 'auto', left: 'auto' }); + if ( options.clearStyle ) { + return "content"; + } - } else { - this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance - this.instance._trigger("deactivate", event, uiSortable); + if ( options.autoHeight ) { + return "auto"; + } } - }); + }( jQuery, jQuery.ui.accordion.prototype ) ); - }, - drag: function(event, ui) { + // icon options + (function( $, prototype ) { + $.extend( prototype.options.icons, { + activeHeader: null, // remove default so we fall back to old values + headerSelected: "ui-icon-triangle-1-s" + }); - var inst = $(this).data("draggable"), self = this; + var _createIcons = prototype._createIcons; + prototype._createIcons = function() { + if ( this.options.icons ) { + this.options.icons.activeHeader = this.options.icons.activeHeader || + this.options.icons.headerSelected; + } + _createIcons.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); - var checkPos = function(o) { - var dyClick = this.offset.click.top, dxClick = this.offset.click.left; - var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; - var itemHeight = o.height, itemWidth = o.width; - var itemTop = o.top, itemLeft = o.left; + // expanded active option, activate method + (function( $, prototype ) { + prototype.activate = prototype._activate; - return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); + var _findActive = prototype._findActive; + prototype._findActive = function( index ) { + if ( index === -1 ) { + index = false; + } + if ( index && typeof index !== "number" ) { + index = this.headers.index( this.headers.filter( index ) ); + if ( index === -1 ) { + index = false; + } + } + return _findActive.call( this, index ); }; + }( jQuery, jQuery.ui.accordion.prototype ) ); - $.each(inst.sortables, function(i) { - - //Copy over some variables to allow calling the sortable's native _intersectsWith - this.instance.positionAbs = inst.positionAbs; - this.instance.helperProportions = inst.helperProportions; - this.instance.offset.click = inst.offset.click; - - if(this.instance._intersectsWith(this.instance.containerCache)) { + // resize method + jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh; - //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once - if(!this.instance.isOver) { + // change events + (function( $, prototype ) { + $.extend( prototype.options, { + change: null, + changestart: null + }); - this.instance.isOver = 1; - //Now we fake the start of dragging for the sortable instance, - //by cloning the list group item, appending it to the sortable and using it as inst.currentItem - //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) - this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); - this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it - this.instance.options.helper = function() { return ui.helper[0]; }; + var _trigger = prototype._trigger; + prototype._trigger = function( type, event, data ) { + var ret = _trigger.apply( this, arguments ); + if ( !ret ) { + return false; + } - event.target = this.instance.currentItem[0]; - this.instance._mouseCapture(event, true); - this.instance._mouseStart(event, true, true); + if ( type === "beforeActivate" ) { + ret = _trigger.call( this, "changestart", event, { + oldHeader: data.oldHeader, + oldContent: data.oldPanel, + newHeader: data.newHeader, + newContent: data.newPanel + }); + } else if ( type === "activate" ) { + ret = _trigger.call( this, "change", event, { + oldHeader: data.oldHeader, + oldContent: data.oldPanel, + newHeader: data.newHeader, + newContent: data.newPanel + }); + } + return ret; + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // animated option + // NOTE: this only provides support for "slide", "bounceslide", and easings + // not the full $.ui.accordion.animations API + (function( $, prototype ) { + $.extend( prototype.options, { + animate: null, + animated: "slide" + }); - //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes - this.instance.offset.click.top = inst.offset.click.top; - this.instance.offset.click.left = inst.offset.click.left; - this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; - this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; + var _create = prototype._create; + prototype._create = function() { + var options = this.options; + if ( options.animate === null ) { + if ( !options.animated ) { + options.animate = false; + } else if ( options.animated === "slide" ) { + options.animate = 300; + } else if ( options.animated === "bounceslide" ) { + options.animate = { + duration: 200, + down: { + easing: "easeOutBounce", + duration: 1000 + } + }; + } else { + options.animate = options.animated; + } + } - inst._trigger("toSortable", event); - inst.dropped = this.instance.element; //draggable revert needs that - //hack so receive/update callbacks work (mostly) - inst.currentItem = inst.element; - this.instance.fromOutside = inst; + _create.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); +} - } +})( jQuery ); +(function( $, undefined ) { - //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable - if(this.instance.currentItem) this.instance._mouseDrag(event); +// used to prevent race conditions with remote data sources +var requestIndex = 0; - } else { +$.widget( "ui.autocomplete", { + version: "1.9.2", + defaultElement: "", + options: { + appendTo: "body", + autoFocus: false, + delay: 300, + minLength: 1, + position: { + my: "left top", + at: "left bottom", + collision: "none" + }, + source: null, - //If it doesn't intersect with the sortable, and it intersected before, - //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval - if(this.instance.isOver) { + // callbacks + change: null, + close: null, + focus: null, + open: null, + response: null, + search: null, + select: null + }, - this.instance.isOver = 0; - this.instance.cancelHelperRemoval = true; - - //Prevent reverting on this forced stop - this.instance.options.revert = false; - - // The out event needs to be triggered independently - this.instance._trigger('out', event, this.instance._uiHash(this.instance)); - - this.instance._mouseStop(event, true); - this.instance.options.helper = this.instance.options._helper; + pending: 0, - //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size - this.instance.currentItem.remove(); - if(this.instance.placeholder) this.instance.placeholder.remove(); + _create: function() { + // Some browsers only repeat keydown events, not keypress events, + // so we use the suppressKeyPress flag to determine if we've already + // handled the keydown event. #7269 + // Unfortunately the code for & in keypress is the same as the up arrow, + // so we use the suppressKeyPressRepeat flag to avoid handling keypress + // events when we know the keydown event was used to modify the + // search term. #7799 + var suppressKeyPress, suppressKeyPressRepeat, suppressInput; + + this.isMultiLine = this._isMultiLine(); + this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ]; + this.isNewMenu = true; - inst._trigger("fromSortable", event); - inst.dropped = false; //draggable revert needs that + this.element + .addClass( "ui-autocomplete-input" ) + .attr( "autocomplete", "off" ); + + this._on( this.element, { + keydown: function( event ) { + if ( this.element.prop( "readOnly" ) ) { + suppressKeyPress = true; + suppressInput = true; + suppressKeyPressRepeat = true; + return; } - }; + suppressKeyPress = false; + suppressInput = false; + suppressKeyPressRepeat = false; + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + suppressKeyPress = true; + this._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + suppressKeyPress = true; + this._move( "nextPage", event ); + break; + case keyCode.UP: + suppressKeyPress = true; + this._keyEvent( "previous", event ); + break; + case keyCode.DOWN: + suppressKeyPress = true; + this._keyEvent( "next", event ); + break; + case keyCode.ENTER: + case keyCode.NUMPAD_ENTER: + // when menu is open and has focus + if ( this.menu.active ) { + // #6055 - Opera still allows the keypress to occur + // which causes forms to submit + suppressKeyPress = true; + event.preventDefault(); + this.menu.select( event ); + } + break; + case keyCode.TAB: + if ( this.menu.active ) { + this.menu.select( event ); + } + break; + case keyCode.ESCAPE: + if ( this.menu.element.is( ":visible" ) ) { + this._value( this.term ); + this.close( event ); + // Different browsers have different default behavior for escape + // Single press can mean undo or clear + // Double press in IE means clear the whole form + event.preventDefault(); + } + break; + default: + suppressKeyPressRepeat = true; + // search timeout should be triggered before the input value is changed + this._searchTimeout( event ); + break; + } + }, + keypress: function( event ) { + if ( suppressKeyPress ) { + suppressKeyPress = false; + event.preventDefault(); + return; + } + if ( suppressKeyPressRepeat ) { + return; + } + + // replicate some key handlers to allow them to repeat in Firefox and Opera + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + this._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + this._move( "nextPage", event ); + break; + case keyCode.UP: + this._keyEvent( "previous", event ); + break; + case keyCode.DOWN: + this._keyEvent( "next", event ); + break; + } + }, + input: function( event ) { + if ( suppressInput ) { + suppressInput = false; + event.preventDefault(); + return; + } + this._searchTimeout( event ); + }, + focus: function() { + this.selectedItem = null; + this.previous = this._value(); + }, + blur: function( event ) { + if ( this.cancelBlur ) { + delete this.cancelBlur; + return; + } + clearTimeout( this.searching ); + this.close( event ); + this._change( event ); + } }); - } -}); + this._initSource(); + this.menu = $( "
      " ) + .addClass( "ui-autocomplete" ) + .appendTo( this.document.find( this.options.appendTo || "body" )[ 0 ] ) + .menu({ + // custom key handling for now + input: $(), + // disable ARIA support, the live region takes care of that + role: null + }) + .zIndex( this.element.zIndex() + 1 ) + .hide() + .data( "menu" ); -$.ui.plugin.add("draggable", "cursor", { - start: function(event, ui) { - var t = $('body'), o = $(this).data('draggable').options; - if (t.css("cursor")) o._cursor = t.css("cursor"); - t.css("cursor", o.cursor); - }, - stop: function(event, ui) { - var o = $(this).data('draggable').options; - if (o._cursor) $('body').css("cursor", o._cursor); - } -}); + this._on( this.menu.element, { + mousedown: function( event ) { + // prevent moving focus out of the text field + event.preventDefault(); -$.ui.plugin.add("draggable", "opacity", { - start: function(event, ui) { - var t = $(ui.helper), o = $(this).data('draggable').options; - if(t.css("opacity")) o._opacity = t.css("opacity"); - t.css('opacity', o.opacity); - }, - stop: function(event, ui) { - var o = $(this).data('draggable').options; - if(o._opacity) $(ui.helper).css('opacity', o._opacity); - } -}); + // IE doesn't prevent moving focus even with event.preventDefault() + // so we set a flag to know when we should ignore the blur event + this.cancelBlur = true; + this._delay(function() { + delete this.cancelBlur; + }); -$.ui.plugin.add("draggable", "scroll", { - start: function(event, ui) { - var i = $(this).data("draggable"); - if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); - }, - drag: function(event, ui) { + // clicking on the scrollbar causes focus to shift to the body + // but we can't detect a mouseup or a click immediately afterward + // so we have to track the next mousedown and close the menu if + // the user clicks somewhere outside of the autocomplete + var menuElement = this.menu.element[ 0 ]; + if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { + this._delay(function() { + var that = this; + this.document.one( "mousedown", function( event ) { + if ( event.target !== that.element[ 0 ] && + event.target !== menuElement && + !$.contains( menuElement, event.target ) ) { + that.close(); + } + }); + }); + } + }, + menufocus: function( event, ui ) { + // #7024 - Prevent accidental activation of menu items in Firefox + if ( this.isNewMenu ) { + this.isNewMenu = false; + if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { + this.menu.blur(); + + this.document.one( "mousemove", function() { + $( event.target ).trigger( event.originalEvent ); + }); - var i = $(this).data("draggable"), o = i.options, scrolled = false; + return; + } + } - if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { + // back compat for _renderItem using item.autocomplete, via #7810 + // TODO remove the fallback, see #8156 + var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" ); + if ( false !== this._trigger( "focus", event, { item: item } ) ) { + // use value to match what will end up in the input, if it was a key event + if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { + this._value( item.value ); + } + } else { + // Normally the input is populated with the item's value as the + // menu is navigated, causing screen readers to notice a change and + // announce the item. Since the focus event was canceled, this doesn't + // happen, so we update the live region so that screen readers can + // still notice the change and announce it. + this.liveRegion.text( item.value ); + } + }, + menuselect: function( event, ui ) { + // back compat for _renderItem using item.autocomplete, via #7810 + // TODO remove the fallback, see #8156 + var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" ), + previous = this.previous; + + // only trigger when focus was lost (click on menu) + if ( this.element[0] !== this.document[0].activeElement ) { + this.element.focus(); + this.previous = previous; + // #6109 - IE triggers two focus events and the second + // is asynchronous, so we need to reset the previous + // term synchronously and asynchronously :-( + this._delay(function() { + this.previous = previous; + this.selectedItem = item; + }); + } - if(!o.axis || o.axis != 'x') { - if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) - i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; - else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) - i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; - } + if ( false !== this._trigger( "select", event, { item: item } ) ) { + this._value( item.value ); + } + // reset the term after the select event + // this allows custom select handling to work properly + this.term = this._value(); - if(!o.axis || o.axis != 'y') { - if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) - i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; - else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) - i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + this.close( event ); + this.selectedItem = item; } + }); - } else { + this.liveRegion = $( "", { + role: "status", + "aria-live": "polite" + }) + .addClass( "ui-helper-hidden-accessible" ) + .insertAfter( this.element ); - if(!o.axis || o.axis != 'x') { - if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) - scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); - else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) - scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); - } + if ( $.fn.bgiframe ) { + this.menu.element.bgiframe(); + } - if(!o.axis || o.axis != 'y') { - if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) - scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); - else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) - scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + // turning off autocomplete prevents the browser from remembering the + // value when navigating through history, so we re-enable autocomplete + // if the page is unloaded before the widget is destroyed. #7790 + this._on( this.window, { + beforeunload: function() { + this.element.removeAttr( "autocomplete" ); } + }); + }, + + _destroy: function() { + clearTimeout( this.searching ); + this.element + .removeClass( "ui-autocomplete-input" ) + .removeAttr( "autocomplete" ); + this.menu.element.remove(); + this.liveRegion.remove(); + }, + _setOption: function( key, value ) { + this._super( key, value ); + if ( key === "source" ) { + this._initSource(); + } + if ( key === "appendTo" ) { + this.menu.element.appendTo( this.document.find( value || "body" )[0] ); + } + if ( key === "disabled" && value && this.xhr ) { + this.xhr.abort(); } + }, - if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) - $.ui.ddmanager.prepareOffsets(i, event); + _isMultiLine: function() { + // Textareas are always multi-line + if ( this.element.is( "textarea" ) ) { + return true; + } + // Inputs are always single-line, even if inside a contentEditable element + // IE also treats inputs as contentEditable + if ( this.element.is( "input" ) ) { + return false; + } + // All other element types are determined by whether or not they're contentEditable + return this.element.prop( "isContentEditable" ); + }, - } -}); + _initSource: function() { + var array, url, + that = this; + if ( $.isArray(this.options.source) ) { + array = this.options.source; + this.source = function( request, response ) { + response( $.ui.autocomplete.filter( array, request.term ) ); + }; + } else if ( typeof this.options.source === "string" ) { + url = this.options.source; + this.source = function( request, response ) { + if ( that.xhr ) { + that.xhr.abort(); + } + that.xhr = $.ajax({ + url: url, + data: request, + dataType: "json", + success: function( data ) { + response( data ); + }, + error: function() { + response( [] ); + } + }); + }; + } else { + this.source = this.options.source; + } + }, -$.ui.plugin.add("draggable", "snap", { - start: function(event, ui) { + _searchTimeout: function( event ) { + clearTimeout( this.searching ); + this.searching = this._delay(function() { + // only search if the value has changed + if ( this.term !== this._value() ) { + this.selectedItem = null; + this.search( null, event ); + } + }, this.options.delay ); + }, - var i = $(this).data("draggable"), o = i.options; - i.snapElements = []; + search: function( value, event ) { + value = value != null ? value : this._value(); - $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { - var $t = $(this); var $o = $t.offset(); - if(this != i.element[0]) i.snapElements.push({ - item: this, - width: $t.outerWidth(), height: $t.outerHeight(), - top: $o.top, left: $o.left - }); - }); + // always save the actual value, not the one passed as an argument + this.term = this._value(); + + if ( value.length < this.options.minLength ) { + return this.close( event ); + } + + if ( this._trigger( "search", event ) === false ) { + return; + } + return this._search( value ); }, - drag: function(event, ui) { - var inst = $(this).data("draggable"), o = inst.options; - var d = o.snapTolerance; + _search: function( value ) { + this.pending++; + this.element.addClass( "ui-autocomplete-loading" ); + this.cancelSearch = false; - var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, - y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; + this.source( { term: value }, this._response() ); + }, - for (var i = inst.snapElements.length - 1; i >= 0; i--){ + _response: function() { + var that = this, + index = ++requestIndex; - var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, - t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; + return function( content ) { + if ( index === requestIndex ) { + that.__response( content ); + } - //Yes, I know, this is insane ;) - if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { - if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); - inst.snapElements[i].snapping = false; - continue; + that.pending--; + if ( !that.pending ) { + that.element.removeClass( "ui-autocomplete-loading" ); } + }; + }, - if(o.snapMode != 'inner') { - var ts = Math.abs(t - y2) <= d; - var bs = Math.abs(b - y1) <= d; - var ls = Math.abs(l - x2) <= d; - var rs = Math.abs(r - x1) <= d; - if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; - if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; - if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; - if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; - } - - var first = (ts || bs || ls || rs); - - if(o.snapMode != 'outer') { - var ts = Math.abs(t - y1) <= d; - var bs = Math.abs(b - y2) <= d; - var ls = Math.abs(l - x1) <= d; - var rs = Math.abs(r - x2) <= d; - if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; - if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; - if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; - if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; - } - - if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) - (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); - inst.snapElements[i].snapping = (ts || bs || ls || rs || first); - - }; + __response: function( content ) { + if ( content ) { + content = this._normalize( content ); + } + this._trigger( "response", null, { content: content } ); + if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { + this._suggest( content ); + this._trigger( "open" ); + } else { + // use ._close() instead of .close() so we don't cancel future searches + this._close(); + } + }, - } -}); + close: function( event ) { + this.cancelSearch = true; + this._close( event ); + }, -$.ui.plugin.add("draggable", "stack", { - start: function(event, ui) { + _close: function( event ) { + if ( this.menu.element.is( ":visible" ) ) { + this.menu.element.hide(); + this.menu.blur(); + this.isNewMenu = true; + this._trigger( "close", event ); + } + }, - var o = $(this).data("draggable").options; + _change: function( event ) { + if ( this.previous !== this._value() ) { + this._trigger( "change", event, { item: this.selectedItem } ); + } + }, - var group = $.makeArray($(o.stack)).sort(function(a,b) { - return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); - }); - if (!group.length) { return; } - - var min = parseInt(group[0].style.zIndex) || 0; - $(group).each(function(i) { - this.style.zIndex = min + i; + _normalize: function( items ) { + // assume all items have the right format when the first item is complete + if ( items.length && items[0].label && items[0].value ) { + return items; + } + return $.map( items, function( item ) { + if ( typeof item === "string" ) { + return { + label: item, + value: item + }; + } + return $.extend({ + label: item.label || item.value, + value: item.value || item.label + }, item ); }); + }, - this[0].style.zIndex = min + group.length; + _suggest: function( items ) { + var ul = this.menu.element + .empty() + .zIndex( this.element.zIndex() + 1 ); + this._renderMenu( ul, items ); + this.menu.refresh(); - } -}); + // size and position menu + ul.show(); + this._resizeMenu(); + ul.position( $.extend({ + of: this.element + }, this.options.position )); -$.ui.plugin.add("draggable", "zIndex", { - start: function(event, ui) { - var t = $(ui.helper), o = $(this).data("draggable").options; - if(t.css("zIndex")) o._zIndex = t.css("zIndex"); - t.css('zIndex', o.zIndex); + if ( this.options.autoFocus ) { + this.menu.next(); + } }, - stop: function(event, ui) { - var o = $(this).data("draggable").options; - if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); - } -}); - -})(jQuery); -/* - * jQuery UI Droppable 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Droppables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.mouse.js - * jquery.ui.draggable.js - */ -(function( $, undefined ) { -$.widget("ui.droppable", { - widgetEventPrefix: "drop", - options: { - accept: '*', - activeClass: false, - addClasses: true, - greedy: false, - hoverClass: false, - scope: 'default', - tolerance: 'intersect' + _resizeMenu: function() { + var ul = this.menu.element; + ul.outerWidth( Math.max( + // Firefox wraps long text (possibly a rounding bug) + // so we add 1px to avoid the wrapping (#7513) + ul.width( "" ).outerWidth() + 1, + this.element.outerWidth() + ) ); }, - _create: function() { - - var o = this.options, accept = o.accept; - this.isover = 0; this.isout = 1; - - this.accept = $.isFunction(accept) ? accept : function(d) { - return d.is(accept); - }; - - //Store the droppable's proportions - this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; - - // Add the reference and positions to the manager - $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; - $.ui.ddmanager.droppables[o.scope].push(this); - - (o.addClasses && this.element.addClass("ui-droppable")); + _renderMenu: function( ul, items ) { + var that = this; + $.each( items, function( index, item ) { + that._renderItemData( ul, item ); + }); }, - destroy: function() { - var drop = $.ui.ddmanager.droppables[this.options.scope]; - for ( var i = 0; i < drop.length; i++ ) - if ( drop[i] == this ) - drop.splice(i, 1); - - this.element - .removeClass("ui-droppable ui-droppable-disabled") - .removeData("droppable") - .unbind(".droppable"); - - return this; + _renderItemData: function( ul, item ) { + return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); }, - _setOption: function(key, value) { + _renderItem: function( ul, item ) { + return $( "
    • " ) + .append( $( "" ).text( item.label ) ) + .appendTo( ul ); + }, - if(key == 'accept') { - this.accept = $.isFunction(value) ? value : function(d) { - return d.is(value); - }; + _move: function( direction, event ) { + if ( !this.menu.element.is( ":visible" ) ) { + this.search( null, event ); + return; } - $.Widget.prototype._setOption.apply(this, arguments); + if ( this.menu.isFirstItem() && /^previous/.test( direction ) || + this.menu.isLastItem() && /^next/.test( direction ) ) { + this._value( this.term ); + this.menu.blur(); + return; + } + this.menu[ direction ]( event ); }, - _activate: function(event) { - var draggable = $.ui.ddmanager.current; - if(this.options.activeClass) this.element.addClass(this.options.activeClass); - (draggable && this._trigger('activate', event, this.ui(draggable))); + widget: function() { + return this.menu.element; }, - _deactivate: function(event) { - var draggable = $.ui.ddmanager.current; - if(this.options.activeClass) this.element.removeClass(this.options.activeClass); - (draggable && this._trigger('deactivate', event, this.ui(draggable))); + _value: function() { + return this.valueMethod.apply( this.element, arguments ); }, - _over: function(event) { - - var draggable = $.ui.ddmanager.current; - if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + _keyEvent: function( keyEvent, event ) { + if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { + this._move( keyEvent, event ); - if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { - if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); - this._trigger('over', event, this.ui(draggable)); + // prevents moving cursor to beginning/end of the text field in some browsers + event.preventDefault(); } + } +}); +$.extend( $.ui.autocomplete, { + escapeRegex: function( value ) { + return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); }, + filter: function(array, term) { + var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); + return $.grep( array, function(value) { + return matcher.test( value.label || value.value || value ); + }); + } +}); - _out: function(event) { - - var draggable = $.ui.ddmanager.current; - if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element - if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { - if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); - this._trigger('out', event, this.ui(draggable)); +// live region extension, adding a `messages` option +// NOTE: This is an experimental API. We are still investigating +// a full solution for string manipulation and internationalization. +$.widget( "ui.autocomplete", $.ui.autocomplete, { + options: { + messages: { + noResults: "No search results.", + results: function( amount ) { + return amount + ( amount > 1 ? " results are" : " result is" ) + + " available, use up and down arrow keys to navigate."; + } } - }, - _drop: function(event,custom) { - - var draggable = custom || $.ui.ddmanager.current; - if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element - - var childrenIntersection = false; - this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { - var inst = $.data(this, 'droppable'); - if( - inst.options.greedy - && !inst.options.disabled - && inst.options.scope == draggable.options.scope - && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) - && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) - ) { childrenIntersection = true; return false; } - }); - if(childrenIntersection) return false; - - if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { - if(this.options.activeClass) this.element.removeClass(this.options.activeClass); - if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); - this._trigger('drop', event, this.ui(draggable)); - return this.element; + __response: function( content ) { + var message; + this._superApply( arguments ); + if ( this.options.disabled || this.cancelSearch ) { + return; } - - return false; - - }, - - ui: function(c) { - return { - draggable: (c.currentItem || c.element), - helper: c.helper, - position: c.position, - offset: c.positionAbs - }; + if ( content && content.length ) { + message = this.options.messages.results( content.length ); + } else { + message = this.options.messages.noResults; + } + this.liveRegion.text( message ); } - -}); - -$.extend($.ui.droppable, { - version: "1.8.16" }); -$.ui.intersect = function(draggable, droppable, toleranceMode) { - - if (!droppable.offset) return false; - var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, - y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; - var l = droppable.offset.left, r = l + droppable.proportions.width, - t = droppable.offset.top, b = t + droppable.proportions.height; +}( jQuery )); +(function( $, undefined ) { - switch (toleranceMode) { - case 'fit': - return (l <= x1 && x2 <= r - && t <= y1 && y2 <= b); - break; - case 'intersect': - return (l < x1 + (draggable.helperProportions.width / 2) // Right Half - && x2 - (draggable.helperProportions.width / 2) < r // Left Half - && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half - && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half - break; - case 'pointer': - var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), - draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), - isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); - return isOver; - break; - case 'touch': - return ( - (y1 >= t && y1 <= b) || // Top edge touching - (y2 >= t && y2 <= b) || // Bottom edge touching - (y1 < t && y2 > b) // Surrounded vertically - ) && ( - (x1 >= l && x1 <= r) || // Left edge touching - (x2 >= l && x2 <= r) || // Right edge touching - (x1 < l && x2 > r) // Surrounded horizontally - ); - break; - default: - return false; - break; +var lastActive, startXPos, startYPos, clickDragged, + baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", + stateClasses = "ui-state-hover ui-state-active ", + typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", + formResetHandler = function() { + var buttons = $( this ).find( ":ui-button" ); + setTimeout(function() { + buttons.button( "refresh" ); + }, 1 ); + }, + radioGroup = function( radio ) { + var name = radio.name, + form = radio.form, + radios = $( [] ); + if ( name ) { + if ( form ) { + radios = $( form ).find( "[name='" + name + "']" ); + } else { + radios = $( "[name='" + name + "']", radio.ownerDocument ) + .filter(function() { + return !this.form; + }); + } } + return radios; + }; -}; +$.widget( "ui.button", { + version: "1.9.2", + defaultElement: "').addClass(this._triggerClass). + html(buttonImage == '' ? buttonText : $('').attr( + { src:buttonImage, alt:buttonText, title:buttonText }))); + input[isRTL ? 'before' : 'after'](inst.trigger); + inst.trigger.click(function() { + if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0]) + $.datepicker._hideDatepicker(); + else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) { + $.datepicker._hideDatepicker(); + $.datepicker._showDatepicker(input[0]); + } else + $.datepicker._showDatepicker(input[0]); + return false; + }); } - - //Store needed variables - this.offset = this.helper.offset(); - this.position = { left: curleft, top: curtop }; - this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; - this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; - this.originalPosition = { left: curleft, top: curtop }; - this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; - this.originalMousePosition = { left: event.pageX, top: event.pageY }; - - //Aspect Ratio - this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); - - var cursor = $('.ui-resizable-' + this.axis).css('cursor'); - $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); - - el.addClass("ui-resizable-resizing"); - this._propagate("start", event); - return true; }, - _mouseDrag: function(event) { - - //Increase performance, avoid regex - var el = this.helper, o = this.options, props = {}, - self = this, smp = this.originalMousePosition, a = this.axis; - - var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; - var trigger = this._change[a]; - if (!trigger) return false; - - // Calculate the attrs that will be change - var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; - - // Put this in the mouseDrag handler since the user can start pressing shift while resizing - this._updateVirtualBoundaries(event.shiftKey); - if (this._aspectRatio || event.shiftKey) - data = this._updateRatio(data, event); - - data = this._respectSize(data, event); - - // plugins callbacks need to be called first - this._propagate("resize", event); - - el.css({ - top: this.position.top + "px", left: this.position.left + "px", - width: this.size.width + "px", height: this.size.height + "px" - }); - - if (!this._helper && this._proportionallyResizeElements.length) - this._proportionallyResize(); - - this._updateCache(data); - - // calling the user callback at the end - this._trigger('resize', event, this.ui()); - - return false; + /* Apply the maximum length for the date format. */ + _autoSize: function(inst) { + if (this._get(inst, 'autoSize') && !inst.inline) { + var date = new Date(2009, 12 - 1, 20); // Ensure double digits + var dateFormat = this._get(inst, 'dateFormat'); + if (dateFormat.match(/[DM]/)) { + var findMax = function(names) { + var max = 0; + var maxI = 0; + for (var i = 0; i < names.length; i++) { + if (names[i].length > max) { + max = names[i].length; + maxI = i; + } + } + return maxI; + }; + date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? + 'monthNames' : 'monthNamesShort')))); + date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? + 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay()); + } + inst.input.attr('size', this._formatDate(inst, date).length); + } }, - _mouseStop: function(event) { - - this.resizing = false; - var o = this.options, self = this; - - if(this._helper) { - var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), - soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, - soffsetw = ista ? 0 : self.sizeDiff.width; - - var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) }, - left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, - top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; - - if (!o.animate) - this.element.css($.extend(s, { top: top, left: left })); - - self.helper.height(self.size.height); - self.helper.width(self.size.width); - - if (this._helper && !o.animate) this._proportionallyResize(); + /* Attach an inline date picker to a div. */ + _inlineDatepicker: function(target, inst) { + var divSpan = $(target); + if (divSpan.hasClass(this.markerClassName)) + return; + divSpan.addClass(this.markerClassName).append(inst.dpDiv). + bind("setData.datepicker", function(event, key, value){ + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key){ + return this._get(inst, key); + }); + $.data(target, PROP_NAME, inst); + this._setDate(inst, this._getDefaultDate(inst), true); + this._updateDatepicker(inst); + this._updateAlternate(inst); + //If disabled option is true, disable the datepicker before showing it (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); } - - $('body').css('cursor', 'auto'); - - this.element.removeClass("ui-resizable-resizing"); - - this._propagate("stop", event); - - if (this._helper) this.helper.remove(); - return false; - + // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements + // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height + inst.dpDiv.css( "display", "block" ); }, - _updateVirtualBoundaries: function(forceAspectRatio) { - var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b; - - b = { - minWidth: isNumber(o.minWidth) ? o.minWidth : 0, - maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, - minHeight: isNumber(o.minHeight) ? o.minHeight : 0, - maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity - }; - - if(this._aspectRatio || forceAspectRatio) { - // We want to create an enclosing box whose aspect ration is the requested one - // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension - pMinWidth = b.minHeight * this.aspectRatio; - pMinHeight = b.minWidth / this.aspectRatio; - pMaxWidth = b.maxHeight * this.aspectRatio; - pMaxHeight = b.maxWidth / this.aspectRatio; + /* Pop-up the date picker in a "dialog" box. + @param input element - ignored + @param date string or Date - the initial date to display + @param onSelect function - the function to call when a date is selected + @param settings object - update the dialog date picker instance's settings (anonymous object) + @param pos int[2] - coordinates for the dialog's position within the screen or + event - with x/y coordinates or + leave empty for default (screen centre) + @return the manager object */ + _dialogDatepicker: function(input, date, onSelect, settings, pos) { + var inst = this._dialogInst; // internal instance + if (!inst) { + this.uuid += 1; + var id = 'dp' + this.uuid; + this._dialogInput = $(''); + this._dialogInput.keydown(this._doKeyDown); + $('body').append(this._dialogInput); + inst = this._dialogInst = this._newInst(this._dialogInput, false); + inst.settings = {}; + $.data(this._dialogInput[0], PROP_NAME, inst); + } + extendRemove(inst.settings, settings || {}); + date = (date && date.constructor == Date ? this._formatDate(inst, date) : date); + this._dialogInput.val(date); - if(pMinWidth > b.minWidth) b.minWidth = pMinWidth; - if(pMinHeight > b.minHeight) b.minHeight = pMinHeight; - if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth; - if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight; - } - this._vBoundaries = b; - }, + this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); + if (!this._pos) { + var browserWidth = document.documentElement.clientWidth; + var browserHeight = document.documentElement.clientHeight; + var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; + var scrollY = document.documentElement.scrollTop || document.body.scrollTop; + this._pos = // should use actual width/height below + [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; + } - _updateCache: function(data) { - var o = this.options; - this.offset = this.helper.offset(); - if (isNumber(data.left)) this.position.left = data.left; - if (isNumber(data.top)) this.position.top = data.top; - if (isNumber(data.height)) this.size.height = data.height; - if (isNumber(data.width)) this.size.width = data.width; + // move input on screen for focus, but hidden behind dialog + this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px'); + inst.settings.onSelect = onSelect; + this._inDialog = true; + this.dpDiv.addClass(this._dialogClass); + this._showDatepicker(this._dialogInput[0]); + if ($.blockUI) + $.blockUI(this.dpDiv); + $.data(this._dialogInput[0], PROP_NAME, inst); + return this; }, - _updateRatio: function(data, event) { - - var o = this.options, cpos = this.position, csize = this.size, a = this.axis; - - if (isNumber(data.height)) data.width = (data.height * this.aspectRatio); - else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio); + /* Detach a datepicker from its control. + @param target element - the target input field or division or span */ + _destroyDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + $.removeData(target, PROP_NAME); + if (nodeName == 'input') { + inst.append.remove(); + inst.trigger.remove(); + $target.removeClass(this.markerClassName). + unbind('focus', this._showDatepicker). + unbind('keydown', this._doKeyDown). + unbind('keypress', this._doKeyPress). + unbind('keyup', this._doKeyUp); + } else if (nodeName == 'div' || nodeName == 'span') + $target.removeClass(this.markerClassName).empty(); + }, - if (a == 'sw') { - data.left = cpos.left + (csize.width - data.width); - data.top = null; + /* Enable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _enableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; } - if (a == 'nw') { - data.top = cpos.top + (csize.height - data.height); - data.left = cpos.left + (csize.width - data.width); + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = false; + inst.trigger.filter('button'). + each(function() { this.disabled = false; }).end(). + filter('img').css({opacity: '1.0', cursor: ''}); } - - return data; + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().removeClass('ui-state-disabled'); + inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). + prop("disabled", false); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry }, - _respectSize: function(data, event) { - - var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, - ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), - isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); - - if (isminw) data.width = o.minWidth; - if (isminh) data.height = o.minHeight; - if (ismaxw) data.width = o.maxWidth; - if (ismaxh) data.height = o.maxHeight; - - var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; - var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); - - if (isminw && cw) data.left = dw - o.minWidth; - if (ismaxw && cw) data.left = dw - o.maxWidth; - if (isminh && ch) data.top = dh - o.minHeight; - if (ismaxh && ch) data.top = dh - o.maxHeight; - - // fixing jump error on top/left - bug #2330 - var isNotwh = !data.width && !data.height; - if (isNotwh && !data.left && data.top) data.top = null; - else if (isNotwh && !data.top && data.left) data.left = null; - - return data; + /* Disable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _disableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = true; + inst.trigger.filter('button'). + each(function() { this.disabled = true; }).end(). + filter('img').css({opacity: '0.5', cursor: 'default'}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().addClass('ui-state-disabled'); + inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). + prop("disabled", true); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + this._disabledInputs[this._disabledInputs.length] = target; }, - _proportionallyResize: function() { - - var o = this.options; - if (!this._proportionallyResizeElements.length) return; - var element = this.helper || this.element; - - for (var i=0; i < this._proportionallyResizeElements.length; i++) { - - var prel = this._proportionallyResizeElements[i]; + /* Is the first field in a jQuery collection disabled as a datepicker? + @param target element - the target input field or division or span + @return boolean - true if disabled, false if enabled */ + _isDisabledDatepicker: function(target) { + if (!target) { + return false; + } + for (var i = 0; i < this._disabledInputs.length; i++) { + if (this._disabledInputs[i] == target) + return true; + } + return false; + }, - if (!this.borderDif) { - var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], - p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; + /* Retrieve the instance data for the target control. + @param target element - the target input field or division or span + @return object - the associated instance data + @throws error if a jQuery problem getting data */ + _getInst: function(target) { + try { + return $.data(target, PROP_NAME); + } + catch (err) { + throw 'Missing instance data for this datepicker'; + } + }, - this.borderDif = $.map(b, function(v, i) { - var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; - return border + padding; - }); + /* Update or retrieve the settings for a date picker attached to an input field or division. + @param target element - the target input field or division or span + @param name object - the new settings to update or + string - the name of the setting to change or retrieve, + when retrieving also 'all' for all instance settings or + 'defaults' for all global defaults + @param value any - the new value for the setting + (omit if above is an object or to retrieve a value) */ + _optionDatepicker: function(target, name, value) { + var inst = this._getInst(target); + if (arguments.length == 2 && typeof name == 'string') { + return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) : + (inst ? (name == 'all' ? $.extend({}, inst.settings) : + this._get(inst, name)) : null)); + } + var settings = name || {}; + if (typeof name == 'string') { + settings = {}; + settings[name] = value; + } + if (inst) { + if (this._curInst == inst) { + this._hideDatepicker(); } - - if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) - continue; - - prel.css({ - height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, - width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 - }); - - }; - + var date = this._getDateDatepicker(target, true); + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + extendRemove(inst.settings, settings); + // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided + if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined) + inst.settings.minDate = this._formatDate(inst, minDate); + if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined) + inst.settings.maxDate = this._formatDate(inst, maxDate); + this._attachments($(target), inst); + this._autoSize(inst); + this._setDate(inst, date); + this._updateAlternate(inst); + this._updateDatepicker(inst); + } }, - _renderProxy: function() { - - var el = this.element, o = this.options; - this.elementOffset = el.offset(); - - if(this._helper) { - - this.helper = this.helper || $('
      '); - - // fix ie6 offset TODO: This seems broken - var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), - pxyoffset = ( ie6 ? 2 : -1 ); - - this.helper.addClass(this._helper).css({ - width: this.element.outerWidth() + pxyoffset, - height: this.element.outerHeight() + pxyoffset, - position: 'absolute', - left: this.elementOffset.left - ie6offset +'px', - top: this.elementOffset.top - ie6offset +'px', - zIndex: ++o.zIndex //TODO: Don't modify option - }); - - this.helper - .appendTo("body") - .disableSelection(); + // change method deprecated + _changeDatepicker: function(target, name, value) { + this._optionDatepicker(target, name, value); + }, - } else { - this.helper = this.element; + /* Redraw the date picker attached to an input field or division. + @param target element - the target input field or division or span */ + _refreshDatepicker: function(target) { + var inst = this._getInst(target); + if (inst) { + this._updateDatepicker(inst); } - }, - _change: { - e: function(event, dx, dy) { - return { width: this.originalSize.width + dx }; - }, - w: function(event, dx, dy) { - var o = this.options, cs = this.originalSize, sp = this.originalPosition; - return { left: sp.left + dx, width: cs.width - dx }; - }, - n: function(event, dx, dy) { - var o = this.options, cs = this.originalSize, sp = this.originalPosition; - return { top: sp.top + dy, height: cs.height - dy }; - }, - s: function(event, dx, dy) { - return { height: this.originalSize.height + dy }; - }, - se: function(event, dx, dy) { - return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); - }, - sw: function(event, dx, dy) { - return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); - }, - ne: function(event, dx, dy) { - return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); - }, - nw: function(event, dx, dy) { - return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + /* Set the dates for a jQuery selection. + @param target element - the target input field or division or span + @param date Date - the new date */ + _setDateDatepicker: function(target, date) { + var inst = this._getInst(target); + if (inst) { + this._setDate(inst, date); + this._updateDatepicker(inst); + this._updateAlternate(inst); } }, - _propagate: function(n, event) { - $.ui.plugin.call(this, n, [event, this.ui()]); - (n != "resize" && this._trigger(n, event, this.ui())); + /* Get the date(s) for the first entry in a jQuery selection. + @param target element - the target input field or division or span + @param noDefault boolean - true if no default date is to be used + @return Date - the current date */ + _getDateDatepicker: function(target, noDefault) { + var inst = this._getInst(target); + if (inst && !inst.inline) + this._setDateFromField(inst, noDefault); + return (inst ? this._getDate(inst) : null); }, - plugins: {}, - - ui: function() { - return { - originalElement: this.originalElement, - element: this.element, - helper: this.helper, - position: this.position, - size: this.size, - originalSize: this.originalSize, - originalPosition: this.originalPosition - }; - } - -}); - -$.extend($.ui.resizable, { - version: "1.8.16" -}); - -/* - * Resizable Extensions - */ - -$.ui.plugin.add("resizable", "alsoResize", { + /* Handle keystrokes. */ + _doKeyDown: function(event) { + var inst = $.datepicker._getInst(event.target); + var handled = true; + var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); + inst._keyEvent = true; + if ($.datepicker._datepickerShowing) + switch (event.keyCode) { + case 9: $.datepicker._hideDatepicker(); + handled = false; + break; // hide on tab out + case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + + $.datepicker._currentClass + ')', inst.dpDiv); + if (sel[0]) + $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); + var onSelect = $.datepicker._get(inst, 'onSelect'); + if (onSelect) { + var dateStr = $.datepicker._formatDate(inst); - start: function (event, ui) { - var self = $(this).data("resizable"), o = self.options; - - var _store = function (exp) { - $(exp).each(function() { - var el = $(this); - el.data("resizable-alsoresize", { - width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), - left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10), - position: el.css('position') // to reset Opera on stop() - }); - }); - }; - - if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { - if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } - else { $.each(o.alsoResize, function (exp) { _store(exp); }); } - }else{ - _store(o.alsoResize); + // trigger custom callback + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); + } + else + $.datepicker._hideDatepicker(); + return false; // don't submit the form + break; // select the value on enter + case 27: $.datepicker._hideDatepicker(); + break; // hide on escape + case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // previous month/year on page up/+ ctrl + case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // next month/year on page down/+ ctrl + case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); + handled = event.ctrlKey || event.metaKey; + break; // clear on ctrl or command +end + case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); + handled = event.ctrlKey || event.metaKey; + break; // current on ctrl or command +home + case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); + handled = event.ctrlKey || event.metaKey; + // -1 day on ctrl or command +left + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +left on Mac + break; + case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // -1 week on ctrl or command +up + case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); + handled = event.ctrlKey || event.metaKey; + // +1 day on ctrl or command +right + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +right + break; + case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // +1 week on ctrl or command +down + default: handled = false; + } + else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home + $.datepicker._showDatepicker(this); + else { + handled = false; } - }, - - resize: function (event, ui) { - var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; - - var delta = { - height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, - top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 - }, - - _alsoResize = function (exp, c) { - $(exp).each(function() { - var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, - css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; - - $.each(css, function (i, prop) { - var sum = (start[prop]||0) + (delta[prop]||0); - if (sum && sum >= 0) - style[prop] = sum || null; - }); - - // Opera fixing relative position - if ($.browser.opera && /relative/.test(el.css('position'))) { - self._revertToRelativePosition = true; - el.css({ position: 'absolute', top: 'auto', left: 'auto' }); - } - - el.css(style); - }); - }; - - if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { - $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); - }else{ - _alsoResize(o.alsoResize); + if (handled) { + event.preventDefault(); + event.stopPropagation(); } }, - stop: function (event, ui) { - var self = $(this).data("resizable"), o = self.options; - - var _reset = function (exp) { - $(exp).each(function() { - var el = $(this); - // reset position for Opera - no need to verify it was changed - el.css({ position: el.data("resizable-alsoresize").position }); - }); - }; - - if (self._revertToRelativePosition) { - self._revertToRelativePosition = false; - if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { - $.each(o.alsoResize, function (exp) { _reset(exp); }); - }else{ - _reset(o.alsoResize); - } + /* Filter entered characters - based on date format. */ + _doKeyPress: function(event) { + var inst = $.datepicker._getInst(event.target); + if ($.datepicker._get(inst, 'constrainInput')) { + var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); + var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); + return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); } + }, - $(this).removeData("resizable-alsoresize"); - } -}); - -$.ui.plugin.add("resizable", "animate", { - - stop: function(event, ui) { - var self = $(this).data("resizable"), o = self.options; - - var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), - soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, - soffsetw = ista ? 0 : self.sizeDiff.width; - - var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, - left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, - top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; - - self.element.animate( - $.extend(style, top && left ? { top: top, left: left } : {}), { - duration: o.animateDuration, - easing: o.animateEasing, - step: function() { - - var data = { - width: parseInt(self.element.css('width'), 10), - height: parseInt(self.element.css('height'), 10), - top: parseInt(self.element.css('top'), 10), - left: parseInt(self.element.css('left'), 10) - }; - - if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); - - // propagating resize, and updating values for each animation step - self._updateCache(data); - self._propagate("resize", event); - + /* Synchronise manual entry and field/alternate field. */ + _doKeyUp: function(event) { + var inst = $.datepicker._getInst(event.target); + if (inst.input.val() != inst.lastVal) { + try { + var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), + (inst.input ? inst.input.val() : null), + $.datepicker._getFormatConfig(inst)); + if (date) { // only if valid + $.datepicker._setDateFromField(inst); + $.datepicker._updateAlternate(inst); + $.datepicker._updateDatepicker(inst); } } - ); - } - -}); - -$.ui.plugin.add("resizable", "containment", { - - start: function(event, ui) { - var self = $(this).data("resizable"), o = self.options, el = self.element; - var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; - if (!ce) return; - - self.containerElement = $(ce); - - if (/document/.test(oc) || oc == document) { - self.containerOffset = { left: 0, top: 0 }; - self.containerPosition = { left: 0, top: 0 }; - - self.parentData = { - element: $(document), left: 0, top: 0, - width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight - }; - } - - // i'm a node, so compute top, left, right, bottom - else { - var element = $(ce), p = []; - $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); - - self.containerOffset = element.offset(); - self.containerPosition = element.position(); - self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; - - var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, - width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); - - self.parentData = { - element: ce, left: co.left, top: co.top, width: width, height: height - }; + catch (err) { + $.datepicker.log(err); + } } + return true; }, - resize: function(event, ui) { - var self = $(this).data("resizable"), o = self.options, - ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, - pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement; - - if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; - - if (cp.left < (self._helper ? co.left : 0)) { - self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); - if (pRatio) self.size.height = self.size.width / o.aspectRatio; - self.position.left = o.helper ? co.left : 0; + /* Pop-up the date picker for a given input field. + If false returned from beforeShow event handler do not show. + @param input element - the input field attached to the date picker or + event - if triggered by focus */ + _showDatepicker: function(input) { + input = input.target || input; + if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger + input = $('input', input.parentNode)[0]; + if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here + return; + var inst = $.datepicker._getInst(input); + if ($.datepicker._curInst && $.datepicker._curInst != inst) { + $.datepicker._curInst.dpDiv.stop(true, true); + if ( inst && $.datepicker._datepickerShowing ) { + $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); + } } - - if (cp.top < (self._helper ? co.top : 0)) { - self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); - if (pRatio) self.size.width = self.size.height * o.aspectRatio; - self.position.top = self._helper ? co.top : 0; + var beforeShow = $.datepicker._get(inst, 'beforeShow'); + var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; + if(beforeShowSettings === false){ + //false + return; } - - self.offset.left = self.parentData.left+self.position.left; - self.offset.top = self.parentData.top+self.position.top; - - var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ), - hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height ); - - var isParent = self.containerElement.get(0) == self.element.parent().get(0), - isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); - - if(isParent && isOffsetRelative) woset -= self.parentData.left; - - if (woset + self.size.width >= self.parentData.width) { - self.size.width = self.parentData.width - woset; - if (pRatio) self.size.height = self.size.width / self.aspectRatio; + extendRemove(inst.settings, beforeShowSettings); + inst.lastVal = null; + $.datepicker._lastInput = input; + $.datepicker._setDateFromField(inst); + if ($.datepicker._inDialog) // hide cursor + input.value = ''; + if (!$.datepicker._pos) { // position below input + $.datepicker._pos = $.datepicker._findPos(input); + $.datepicker._pos[1] += input.offsetHeight; // add the height } + var isFixed = false; + $(input).parents().each(function() { + isFixed |= $(this).css('position') == 'fixed'; + return !isFixed; + }); + var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; + $.datepicker._pos = null; + //to avoid flashes on Firefox + inst.dpDiv.empty(); + // determine sizing offscreen + inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); + $.datepicker._updateDatepicker(inst); + // fix width for dynamic number of date pickers + // and adjust position before showing + offset = $.datepicker._checkOffset(inst, offset, isFixed); + inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? + 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', + left: offset.left + 'px', top: offset.top + 'px'}); + if (!inst.inline) { + var showAnim = $.datepicker._get(inst, 'showAnim'); + var duration = $.datepicker._get(inst, 'duration'); + var postProcess = function() { + var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only + if( !! cover.length ){ + var borders = $.datepicker._getBorders(inst.dpDiv); + cover.css({left: -borders[0], top: -borders[1], + width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); + } + }; + inst.dpDiv.zIndex($(input).zIndex()+1); + $.datepicker._datepickerShowing = true; - if (hoset + self.size.height >= self.parentData.height) { - self.size.height = self.parentData.height - hoset; - if (pRatio) self.size.width = self.size.height * self.aspectRatio; + // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed + if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) + inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess); + if (!showAnim || !duration) + postProcess(); + if (inst.input.is(':visible') && !inst.input.is(':disabled')) + inst.input.focus(); + $.datepicker._curInst = inst; } }, - stop: function(event, ui){ - var self = $(this).data("resizable"), o = self.options, cp = self.position, - co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; - - var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; - - if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) - $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + /* Generate the date picker content. */ + _updateDatepicker: function(inst) { + this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) + var borders = $.datepicker._getBorders(inst.dpDiv); + instActive = inst; // for delegate hover events + inst.dpDiv.empty().append(this._generateHTML(inst)); + this._attachHandlers(inst); + var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only + if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6 + cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}) + } + inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover(); + var numMonths = this._getNumberOfMonths(inst); + var cols = numMonths[1]; + var width = 17; + inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); + if (cols > 1) + inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); + inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + + 'Class']('ui-datepicker-multi'); + inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + + 'Class']('ui-datepicker-rtl'); + if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && + // #6694 - don't focus the input if it's already focused + // this breaks the change event in IE + inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement) + inst.input.focus(); + // deffered render of the years select (to avoid flashes on Firefox) + if( inst.yearshtml ){ + var origyearshtml = inst.yearshtml; + setTimeout(function(){ + //assure that inst.yearshtml didn't change. + if( origyearshtml === inst.yearshtml && inst.yearshtml ){ + inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml); + } + origyearshtml = inst.yearshtml = null; + }, 0); + } + }, - if (self._helper && !o.animate && (/static/).test(ce.css('position'))) - $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + /* Retrieve the size of left and top borders for an element. + @param elem (jQuery object) the element of interest + @return (number[2]) the left and top borders */ + _getBorders: function(elem) { + var convert = function(value) { + return {thin: 1, medium: 2, thick: 3}[value] || value; + }; + return [parseFloat(convert(elem.css('border-left-width'))), + parseFloat(convert(elem.css('border-top-width')))]; + }, - } -}); + /* Check positioning to remain on screen. */ + _checkOffset: function(inst, offset, isFixed) { + var dpWidth = inst.dpDiv.outerWidth(); + var dpHeight = inst.dpDiv.outerHeight(); + var inputWidth = inst.input ? inst.input.outerWidth() : 0; + var inputHeight = inst.input ? inst.input.outerHeight() : 0; + var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()); + var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); -$.ui.plugin.add("resizable", "ghost", { + offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); + offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; + offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; - start: function(event, ui) { + // now check if datepicker is showing outside window viewport - move to a better place if so. + offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? + Math.abs(offset.left + dpWidth - viewWidth) : 0); + offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? + Math.abs(dpHeight + inputHeight) : 0); - var self = $(this).data("resizable"), o = self.options, cs = self.size; + return offset; + }, - self.ghost = self.originalElement.clone(); - self.ghost - .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) - .addClass('ui-resizable-ghost') - .addClass(typeof o.ghost == 'string' ? o.ghost : ''); + /* Find an object's position on the screen. */ + _findPos: function(obj) { + var inst = this._getInst(obj); + var isRTL = this._get(inst, 'isRTL'); + while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) { + obj = obj[isRTL ? 'previousSibling' : 'nextSibling']; + } + var position = $(obj).offset(); + return [position.left, position.top]; + }, - self.ghost.appendTo(self.helper); + /* Hide the date picker from view. + @param input element - the input field attached to the date picker */ + _hideDatepicker: function(input) { + var inst = this._curInst; + if (!inst || (input && inst != $.data(input, PROP_NAME))) + return; + if (this._datepickerShowing) { + var showAnim = this._get(inst, 'showAnim'); + var duration = this._get(inst, 'duration'); + var postProcess = function() { + $.datepicker._tidyDialog(inst); + }; + // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed + if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) + inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' : + (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess); + if (!showAnim) + postProcess(); + this._datepickerShowing = false; + var onClose = this._get(inst, 'onClose'); + if (onClose) + onClose.apply((inst.input ? inst.input[0] : null), + [(inst.input ? inst.input.val() : ''), inst]); + this._lastInput = null; + if (this._inDialog) { + this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); + if ($.blockUI) { + $.unblockUI(); + $('body').append(this.dpDiv); + } + } + this._inDialog = false; + } }, - resize: function(event, ui){ - var self = $(this).data("resizable"), o = self.options; - if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); + /* Tidy up after a dialog display. */ + _tidyDialog: function(inst) { + inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); }, - stop: function(event, ui){ - var self = $(this).data("resizable"), o = self.options; - if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); - } - -}); + /* Close date picker if clicked elsewhere. */ + _checkExternalClick: function(event) { + if (!$.datepicker._curInst) + return; -$.ui.plugin.add("resizable", "grid", { + var $target = $(event.target), + inst = $.datepicker._getInst($target[0]); - resize: function(event, ui) { - var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey; - o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; - var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); + if ( ( ( $target[0].id != $.datepicker._mainDivId && + $target.parents('#' + $.datepicker._mainDivId).length == 0 && + !$target.hasClass($.datepicker.markerClassName) && + !$target.closest("." + $.datepicker._triggerClass).length && + $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || + ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) ) + $.datepicker._hideDatepicker(); + }, - if (/^(se|s|e)$/.test(a)) { - self.size.width = os.width + ox; - self.size.height = os.height + oy; - } - else if (/^(ne)$/.test(a)) { - self.size.width = os.width + ox; - self.size.height = os.height + oy; - self.position.top = op.top - oy; + /* Adjust one of the date sub-fields. */ + _adjustDate: function(id, offset, period) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._isDisabledDatepicker(target[0])) { + return; } - else if (/^(sw)$/.test(a)) { - self.size.width = os.width + ox; - self.size.height = os.height + oy; - self.position.left = op.left - ox; + this._adjustInstDate(inst, offset + + (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning + period); + this._updateDatepicker(inst); + }, + + /* Action for current link. */ + _gotoToday: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._get(inst, 'gotoCurrent') && inst.currentDay) { + inst.selectedDay = inst.currentDay; + inst.drawMonth = inst.selectedMonth = inst.currentMonth; + inst.drawYear = inst.selectedYear = inst.currentYear; } else { - self.size.width = os.width + ox; - self.size.height = os.height + oy; - self.position.top = op.top - oy; - self.position.left = op.left - ox; + var date = new Date(); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); } - } - -}); + this._notifyChange(inst); + this._adjustDate(target); + }, -var num = function(v) { - return parseInt(v, 10) || 0; -}; + /* Action for selecting a new month/year. */ + _selectMonthYear: function(id, select, period) { + var target = $(id); + var inst = this._getInst(target[0]); + inst['selected' + (period == 'M' ? 'Month' : 'Year')] = + inst['draw' + (period == 'M' ? 'Month' : 'Year')] = + parseInt(select.options[select.selectedIndex].value,10); + this._notifyChange(inst); + this._adjustDate(target); + }, -var isNumber = function(value) { - return !isNaN(parseInt(value, 10)); -}; + /* Action for selecting a day. */ + _selectDay: function(id, month, year, td) { + var target = $(id); + if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { + return; + } + var inst = this._getInst(target[0]); + inst.selectedDay = inst.currentDay = $('a', td).html(); + inst.selectedMonth = inst.currentMonth = month; + inst.selectedYear = inst.currentYear = year; + this._selectDate(id, this._formatDate(inst, + inst.currentDay, inst.currentMonth, inst.currentYear)); + }, -})(jQuery); -/* - * jQuery UI Selectable 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Selectables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ -(function( $, undefined ) { + /* Erase the input field and hide the date picker. */ + _clearDate: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + this._selectDate(target, ''); + }, -$.widget("ui.selectable", $.ui.mouse, { - options: { - appendTo: 'body', - autoRefresh: true, - distance: 0, - filter: '*', - tolerance: 'touch' + /* Update the input field with the selected date. */ + _selectDate: function(id, dateStr) { + var target = $(id); + var inst = this._getInst(target[0]); + dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); + if (inst.input) + inst.input.val(dateStr); + this._updateAlternate(inst); + var onSelect = this._get(inst, 'onSelect'); + if (onSelect) + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback + else if (inst.input) + inst.input.trigger('change'); // fire the change event + if (inst.inline) + this._updateDatepicker(inst); + else { + this._hideDatepicker(); + this._lastInput = inst.input[0]; + if (typeof(inst.input[0]) != 'object') + inst.input.focus(); // restore focus + this._lastInput = null; + } }, - _create: function() { - var self = this; - this.element.addClass("ui-selectable"); + /* Update any alternate field to synchronise with the main field. */ + _updateAlternate: function(inst) { + var altField = this._get(inst, 'altField'); + if (altField) { // update alternate field too + var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); + var date = this._getDate(inst); + var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); + $(altField).each(function() { $(this).val(dateStr); }); + } + }, - this.dragged = false; + /* Set as beforeShowDay function to prevent selection of weekends. + @param date Date - the date to customise + @return [boolean, string] - is this date selectable?, what is its CSS class? */ + noWeekends: function(date) { + var day = date.getDay(); + return [(day > 0 && day < 6), '']; + }, - // cache selectee children based on filter - var selectees; - this.refresh = function() { - selectees = $(self.options.filter, self.element[0]); - selectees.each(function() { - var $this = $(this); - var pos = $this.offset(); - $.data(this, "selectable-item", { - element: this, - $element: $this, - left: pos.left, - top: pos.top, - right: pos.left + $this.outerWidth(), - bottom: pos.top + $this.outerHeight(), - startselected: false, - selected: $this.hasClass('ui-selected'), - selecting: $this.hasClass('ui-selecting'), - unselecting: $this.hasClass('ui-unselecting') - }); + /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. + @param date Date - the date to get the week for + @return number - the number of the week within the year that contains this date */ + iso8601Week: function(date) { + var checkDate = new Date(date.getTime()); + // Find Thursday of this week starting on Monday + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + }, + + /* Parse a string value into a date object. + See formatDate below for the possible formats. + + @param format string - the expected format of the date + @param value string - the date in the above format + @param settings Object - attributes include: + shortYearCutoff number - the cutoff year for determining the century (optional) + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return Date - the extracted date value or null if value is blank */ + parseDate: function (format, value, settings) { + if (format == null || value == null) + throw 'Invalid arguments'; + value = (typeof value == 'object' ? value.toString() : value + ''); + if (value == '') + return null; + var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + var year = -1; + var month = -1; + var day = -1; + var doy = -1; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Extract a number from the string value + var getNumber = function(match) { + var isDoubled = lookAhead(match); + var size = (match == '@' ? 14 : (match == '!' ? 20 : + (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2)))); + var digits = new RegExp('^\\d{1,' + size + '}'); + var num = value.substring(iValue).match(digits); + if (!num) + throw 'Missing number at position ' + iValue; + iValue += num[0].length; + return parseInt(num[0], 10); + }; + // Extract a name from the string value and convert to an index + var getName = function(match, shortNames, longNames) { + var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { + return [ [k, v] ]; + }).sort(function (a, b) { + return -(a[1].length - b[1].length); + }); + var index = -1; + $.each(names, function (i, pair) { + var name = pair[1]; + if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) { + index = pair[0]; + iValue += name.length; + return false; + } + }); + if (index != -1) + return index + 1; + else + throw 'Unknown name at position ' + iValue; + }; + // Confirm that a literal character matches the string value + var checkLiteral = function() { + if (value.charAt(iValue) != format.charAt(iFormat)) + throw 'Unexpected literal at position ' + iValue; + iValue++; + }; + var iValue = 0; + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + checkLiteral(); + else + switch (format.charAt(iFormat)) { + case 'd': + day = getNumber('d'); + break; + case 'D': + getName('D', dayNamesShort, dayNames); + break; + case 'o': + doy = getNumber('o'); + break; + case 'm': + month = getNumber('m'); + break; + case 'M': + month = getName('M', monthNamesShort, monthNames); + break; + case 'y': + year = getNumber('y'); + break; + case '@': + var date = new Date(getNumber('@')); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case '!': + var date = new Date((getNumber('!') - this._ticksTo1970) / 10000); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case "'": + if (lookAhead("'")) + checkLiteral(); + else + literal = true; + break; + default: + checkLiteral(); + } + } + if (iValue < value.length){ + var extra = value.substr(iValue); + if (!/^\s+/.test(extra)) { + throw "Extra/unparsed characters found in date: " + extra; + } + } + if (year == -1) + year = new Date().getFullYear(); + else if (year < 100) + year += new Date().getFullYear() - new Date().getFullYear() % 100 + + (year <= shortYearCutoff ? 0 : -100); + if (doy > -1) { + month = 1; + day = doy; + do { + var dim = this._getDaysInMonth(year, month - 1); + if (day <= dim) + break; + month++; + day -= dim; + } while (true); + } + var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); + if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) + throw 'Invalid date'; // E.g. 31/02/00 + return date; + }, + + /* Standard date formats. */ + ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) + COOKIE: 'D, dd M yy', + ISO_8601: 'yy-mm-dd', + RFC_822: 'D, d M y', + RFC_850: 'DD, dd-M-y', + RFC_1036: 'D, d M y', + RFC_1123: 'D, d M yy', + RFC_2822: 'D, d M yy', + RSS: 'D, d M y', // RFC 822 + TICKS: '!', + TIMESTAMP: '@', + W3C: 'yy-mm-dd', // ISO 8601 + + _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + + Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), + + /* Format a date object into a string value. + The format can be combinations of the following: + d - day of month (no leading zero) + dd - day of month (two digit) + o - day of year (no leading zeros) + oo - day of year (three digit) + D - day name short + DD - day name long + m - month of year (no leading zero) + mm - month of year (two digit) + M - month name short + MM - month name long + y - year (two digit) + yy - year (four digit) + @ - Unix timestamp (ms since 01/01/1970) + ! - Windows ticks (100ns since 01/01/0001) + '...' - literal text + '' - single quote + + @param format string - the desired format of the date + @param date Date - the date value to format + @param settings Object - attributes include: + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return string - the date in the above format */ + formatDate: function (format, date, settings) { + if (!date) + return ''; + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Format a number, with leading zero if necessary + var formatNumber = function(match, value, len) { + var num = '' + value; + if (lookAhead(match)) + while (num.length < len) + num = '0' + num; + return num; + }; + // Format a name, short or long as requested + var formatName = function(match, value, shortNames, longNames) { + return (lookAhead(match) ? longNames[value] : shortNames[value]); + }; + var output = ''; + var literal = false; + if (date) + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + output += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': + output += formatNumber('d', date.getDate(), 2); + break; + case 'D': + output += formatName('D', date.getDay(), dayNamesShort, dayNames); + break; + case 'o': + output += formatNumber('o', + Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); + break; + case 'm': + output += formatNumber('m', date.getMonth() + 1, 2); + break; + case 'M': + output += formatName('M', date.getMonth(), monthNamesShort, monthNames); + break; + case 'y': + output += (lookAhead('y') ? date.getFullYear() : + (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); + break; + case '@': + output += date.getTime(); + break; + case '!': + output += date.getTime() * 10000 + this._ticksTo1970; + break; + case "'": + if (lookAhead("'")) + output += "'"; + else + literal = true; + break; + default: + output += format.charAt(iFormat); + } + } + return output; + }, + + /* Extract all possible characters from the date format. */ + _possibleChars: function (format) { + var chars = ''; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + for (var iFormat = 0; iFormat < format.length; iFormat++) + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + chars += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': case 'm': case 'y': case '@': + chars += '0123456789'; + break; + case 'D': case 'M': + return null; // Accept anything + case "'": + if (lookAhead("'")) + chars += "'"; + else + literal = true; + break; + default: + chars += format.charAt(iFormat); + } + return chars; + }, + + /* Get a setting value, defaulting if necessary. */ + _get: function(inst, name) { + return inst.settings[name] !== undefined ? + inst.settings[name] : this._defaults[name]; + }, + + /* Parse existing date and initialise date picker. */ + _setDateFromField: function(inst, noDefault) { + if (inst.input.val() == inst.lastVal) { + return; + } + var dateFormat = this._get(inst, 'dateFormat'); + var dates = inst.lastVal = inst.input ? inst.input.val() : null; + var date, defaultDate; + date = defaultDate = this._getDefaultDate(inst); + var settings = this._getFormatConfig(inst); + try { + date = this.parseDate(dateFormat, dates, settings) || defaultDate; + } catch (event) { + this.log(event); + dates = (noDefault ? '' : dates); + } + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + inst.currentDay = (dates ? date.getDate() : 0); + inst.currentMonth = (dates ? date.getMonth() : 0); + inst.currentYear = (dates ? date.getFullYear() : 0); + this._adjustInstDate(inst); + }, + + /* Retrieve the default date shown on opening. */ + _getDefaultDate: function(inst) { + return this._restrictMinMax(inst, + this._determineDate(inst, this._get(inst, 'defaultDate'), new Date())); + }, + + /* A date may be specified as an exact value or a relative one. */ + _determineDate: function(inst, date, defaultDate) { + var offsetNumeric = function(offset) { + var date = new Date(); + date.setDate(date.getDate() + offset); + return date; + }; + var offsetString = function(offset) { + try { + return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), + offset, $.datepicker._getFormatConfig(inst)); + } + catch (e) { + // Ignore + } + var date = (offset.toLowerCase().match(/^c/) ? + $.datepicker._getDate(inst) : null) || new Date(); + var year = date.getFullYear(); + var month = date.getMonth(); + var day = date.getDate(); + var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; + var matches = pattern.exec(offset); + while (matches) { + switch (matches[2] || 'd') { + case 'd' : case 'D' : + day += parseInt(matches[1],10); break; + case 'w' : case 'W' : + day += parseInt(matches[1],10) * 7; break; + case 'm' : case 'M' : + month += parseInt(matches[1],10); + day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); + break; + case 'y': case 'Y' : + year += parseInt(matches[1],10); + day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); + break; + } + matches = pattern.exec(offset); + } + return new Date(year, month, day); + }; + var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) : + (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); + newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate); + if (newDate) { + newDate.setHours(0); + newDate.setMinutes(0); + newDate.setSeconds(0); + newDate.setMilliseconds(0); + } + return this._daylightSavingAdjust(newDate); + }, + + /* Handle switch to/from daylight saving. + Hours may be non-zero on daylight saving cut-over: + > 12 when midnight changeover, but then cannot generate + midnight datetime, so jump to 1AM, otherwise reset. + @param date (Date) the date to check + @return (Date) the corrected date */ + _daylightSavingAdjust: function(date) { + if (!date) return null; + date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); + return date; + }, + + /* Set the date(s) directly. */ + _setDate: function(inst, date, noChange) { + var clear = !date; + var origMonth = inst.selectedMonth; + var origYear = inst.selectedYear; + var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); + inst.selectedDay = inst.currentDay = newDate.getDate(); + inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); + inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); + if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange) + this._notifyChange(inst); + this._adjustInstDate(inst); + if (inst.input) { + inst.input.val(clear ? '' : this._formatDate(inst)); + } + }, + + /* Retrieve the date(s) directly. */ + _getDate: function(inst) { + var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : + this._daylightSavingAdjust(new Date( + inst.currentYear, inst.currentMonth, inst.currentDay))); + return startDate; + }, + + /* Attach the onxxx handlers. These are declared statically so + * they work with static code transformers like Caja. + */ + _attachHandlers: function(inst) { + var stepMonths = this._get(inst, 'stepMonths'); + var id = '#' + inst.id.replace( /\\\\/g, "\\" ); + inst.dpDiv.find('[data-handler]').map(function () { + var handler = { + prev: function () { + window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M'); + }, + next: function () { + window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M'); + }, + hide: function () { + window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker(); + }, + today: function () { + window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id); + }, + selectDay: function () { + window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this); + return false; + }, + selectMonth: function () { + window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M'); + return false; + }, + selectYear: function () { + window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y'); + return false; + } + }; + $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]); + }); + }, + + /* Generate the HTML for the current state of the date picker. */ + _generateHTML: function(inst) { + var today = new Date(); + today = this._daylightSavingAdjust( + new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time + var isRTL = this._get(inst, 'isRTL'); + var showButtonPanel = this._get(inst, 'showButtonPanel'); + var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); + var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); + var numMonths = this._getNumberOfMonths(inst); + var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); + var stepMonths = this._get(inst, 'stepMonths'); + var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); + var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : + new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var drawMonth = inst.drawMonth - showCurrentAtPos; + var drawYear = inst.drawYear; + if (drawMonth < 0) { + drawMonth += 12; + drawYear--; + } + if (maxDate) { + var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), + maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); + maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); + while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { + drawMonth--; + if (drawMonth < 0) { + drawMonth = 11; + drawYear--; + } + } + } + inst.drawMonth = drawMonth; + inst.drawYear = drawYear; + var prevText = this._get(inst, 'prevText'); + prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), + this._getFormatConfig(inst))); + var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? + '
      ' + prevText + '' : + (hideIfNoPrevNext ? '' : '' + prevText + '')); + var nextText = this._get(inst, 'nextText'); + nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), + this._getFormatConfig(inst))); + var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? + '' + nextText + '' : + (hideIfNoPrevNext ? '' : '' + nextText + '')); + var currentText = this._get(inst, 'currentText'); + var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); + currentText = (!navigationAsDateFormat ? currentText : + this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); + var controls = (!inst.inline ? '' : ''); + var buttonPanel = (showButtonPanel) ? '
      ' + (isRTL ? controls : '') + + (this._isInRange(inst, gotoDate) ? '' : '') + (isRTL ? '' : controls) + '
      ' : ''; + var firstDay = parseInt(this._get(inst, 'firstDay'),10); + firstDay = (isNaN(firstDay) ? 0 : firstDay); + var showWeek = this._get(inst, 'showWeek'); + var dayNames = this._get(inst, 'dayNames'); + var dayNamesShort = this._get(inst, 'dayNamesShort'); + var dayNamesMin = this._get(inst, 'dayNamesMin'); + var monthNames = this._get(inst, 'monthNames'); + var monthNamesShort = this._get(inst, 'monthNamesShort'); + var beforeShowDay = this._get(inst, 'beforeShowDay'); + var showOtherMonths = this._get(inst, 'showOtherMonths'); + var selectOtherMonths = this._get(inst, 'selectOtherMonths'); + var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; + var defaultDate = this._getDefaultDate(inst); + var html = ''; + for (var row = 0; row < numMonths[0]; row++) { + var group = ''; + this.maxRows = 4; + for (var col = 0; col < numMonths[1]; col++) { + var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); + var cornerClass = ' ui-corner-all'; + var calender = ''; + if (isMultiMonth) { + calender += '
      '; + } + calender += '
      ' + + (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + + (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, + row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers + '
      ' + + ''; + var thead = (showWeek ? '' : ''); + for (var dow = 0; dow < 7; dow++) { // days of the week + var day = (dow + firstDay) % 7; + thead += '= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' + + '' + dayNamesMin[day] + ''; + } + calender += thead + ''; + var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); + if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) + inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); + var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; + var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate + var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) + this.maxRows = numRows; + var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); + for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows + calender += ''; + var tbody = (!showWeek ? '' : ''); + for (var dow = 0; dow < 7; dow++) { // create date picker days + var daySettings = (beforeShowDay ? + beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); + var otherMonth = (printDate.getMonth() != drawMonth); + var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || + (minDate && printDate < minDate) || (maxDate && printDate > maxDate); + tbody += ''; // display selectable date + printDate.setDate(printDate.getDate() + 1); + printDate = this._daylightSavingAdjust(printDate); + } + calender += tbody + ''; + } + drawMonth++; + if (drawMonth > 11) { + drawMonth = 0; + drawYear++; + } + calender += '
      ' + this._get(inst, 'weekHeader') + '
      ' + + this._get(inst, 'calculateWeek')(printDate) + '' + // actions + (otherMonth && !showOtherMonths ? ' ' : // display for other months + (unselectable ? '' + printDate.getDate() + '' : '' + printDate.getDate() + '')) + '
      ' + (isMultiMonth ? '
      ' + + ((numMonths[0] > 0 && col == numMonths[1]-1) ? '
      ' : '') : ''); + group += calender; + } + html += group; + } + html += buttonPanel + ($.ui.ie6 && !inst.inline ? + '' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, + secondary, monthNames, monthNamesShort) { + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '
      '; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '' + monthNames[drawMonth] + ''; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += ''; + } + if (!showMonthAfterYear) + html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); + // year selection + if ( !inst.yearshtml ) { + inst.yearshtml = ''; + if (secondary || !changeYear) + html += '' + drawYear + ''; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var thisYear = new Date().getFullYear(); + var determineYear = function(value) { + var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : + (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : + parseInt(value, 10))); + return (isNaN(year) ? thisYear : year); + }; + var year = determineYear(years[0]); + var endYear = Math.max(year, determineYear(years[1] || '')); + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + inst.yearshtml += ''; + + html += inst.yearshtml; + inst.yearshtml = null; + } + } + html += this._get(inst, 'yearSuffix'); + if (showMonthAfterYear) + html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; + html += '
      '; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate: function(inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._restrictMinMax(inst, + this._daylightSavingAdjust(new Date(year, month, day))); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Ensure a date is within any min/max bounds. */ + _restrictMinMax: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var newDate = (minDate && date < minDate ? minDate : date); + newDate = (maxDate && newDate > maxDate ? maxDate : newDate); + return newDate; + }, + + /* Notify change of month/year. */ + _notifyChange: function(inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths: function(inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set. */ + _getMinMaxDate: function(inst, minMax) { + return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date(curYear, + curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date.getTime() >= minDate.getTime()) && + (!maxDate || date.getTime() <= maxDate.getTime())); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig: function(inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff: shortYearCutoff, + dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), + monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate: function(inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } +}); + +/* + * Bind hover events for datepicker elements. + * Done via delegate so the binding only occurs once in the lifetime of the parent div. + * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. + */ +function bindHover(dpDiv) { + var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; + return dpDiv.delegate(selector, 'mouseout', function() { + $(this).removeClass('ui-state-hover'); + if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover'); + if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover'); + }) + .delegate(selector, 'mouseover', function(){ + if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { + $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + $(this).addClass('ui-state-hover'); + if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover'); + if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover'); + } + }); +} + +/* jQuery extend now ignores nulls! */ +function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; +}; + +/* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ +$.fn.datepicker = function(options){ + + /* Verify an empty collection wasn't passed - Fixes #6976 */ + if ( !this.length ) { + return this; + } + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find(document.body).append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function() { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); +}; + +$.datepicker = new Datepicker(); // singleton instance +$.datepicker.initialized = false; +$.datepicker.uuid = new Date().getTime(); +$.datepicker.version = "1.9.2"; + +// Workaround for #4055 +// Add another global to avoid noConflict issues with inline event handlers +window['DP_jQuery_' + dpuuid] = $; + +})(jQuery); +(function( $, undefined ) { + +var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ", + sizeRelatedOptions = { + buttons: true, + height: true, + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true, + width: true + }, + resizableRelatedOptions = { + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true + }; + +$.widget("ui.dialog", { + version: "1.9.2", + options: { + autoOpen: true, + buttons: {}, + closeOnEscape: true, + closeText: "close", + dialogClass: "", + draggable: true, + hide: null, + height: "auto", + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: { + my: "center", + at: "center", + of: window, + collision: "fit", + // ensure that the titlebar is never outside the document + using: function( pos ) { + var topOffset = $( this ).css( pos ).offset().top; + if ( topOffset < 0 ) { + $( this ).css( "top", pos.top - topOffset ); + } + } + }, + resizable: true, + show: null, + stack: true, + title: "", + width: 300, + zIndex: 1000 + }, + + _create: function() { + this.originalTitle = this.element.attr( "title" ); + // #5742 - .attr() might return a DOMElement + if ( typeof this.originalTitle !== "string" ) { + this.originalTitle = ""; + } + this.oldPosition = { + parent: this.element.parent(), + index: this.element.parent().children().index( this.element ) + }; + this.options.title = this.options.title || this.originalTitle; + var that = this, + options = this.options, + + title = options.title || " ", + uiDialog, + uiDialogTitlebar, + uiDialogTitlebarClose, + uiDialogTitle, + uiDialogButtonPane; + + uiDialog = ( this.uiDialog = $( "
      " ) ) + .addClass( uiDialogClasses + options.dialogClass ) + .css({ + display: "none", + outline: 0, // TODO: move to stylesheet + zIndex: options.zIndex + }) + // setting tabIndex makes the div focusable + .attr( "tabIndex", -1) + .keydown(function( event ) { + if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE ) { + that.close( event ); + event.preventDefault(); + } + }) + .mousedown(function( event ) { + that.moveToTop( false, event ); + }) + .appendTo( "body" ); + + this.element + .show() + .removeAttr( "title" ) + .addClass( "ui-dialog-content ui-widget-content" ) + .appendTo( uiDialog ); + + uiDialogTitlebar = ( this.uiDialogTitlebar = $( "
      " ) ) + .addClass( "ui-dialog-titlebar ui-widget-header " + + "ui-corner-all ui-helper-clearfix" ) + .bind( "mousedown", function() { + // Dialog isn't getting focus when dragging (#8063) + uiDialog.focus(); + }) + .prependTo( uiDialog ); + + uiDialogTitlebarClose = $( "" ) + .addClass( "ui-dialog-titlebar-close ui-corner-all" ) + .attr( "role", "button" ) + .click(function( event ) { + event.preventDefault(); + that.close( event ); + }) + .appendTo( uiDialogTitlebar ); + + ( this.uiDialogTitlebarCloseText = $( "" ) ) + .addClass( "ui-icon ui-icon-closethick" ) + .text( options.closeText ) + .appendTo( uiDialogTitlebarClose ); + + uiDialogTitle = $( "" ) + .uniqueId() + .addClass( "ui-dialog-title" ) + .html( title ) + .prependTo( uiDialogTitlebar ); + + uiDialogButtonPane = ( this.uiDialogButtonPane = $( "
      " ) ) + .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); + + ( this.uiButtonSet = $( "
      " ) ) + .addClass( "ui-dialog-buttonset" ) + .appendTo( uiDialogButtonPane ); + + uiDialog.attr({ + role: "dialog", + "aria-labelledby": uiDialogTitle.attr( "id" ) + }); + + uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection(); + this._hoverable( uiDialogTitlebarClose ); + this._focusable( uiDialogTitlebarClose ); + + if ( options.draggable && $.fn.draggable ) { + this._makeDraggable(); + } + if ( options.resizable && $.fn.resizable ) { + this._makeResizable(); + } + + this._createButtons( options.buttons ); + this._isOpen = false; + + if ( $.fn.bgiframe ) { + uiDialog.bgiframe(); + } + + // prevent tabbing out of modal dialogs + this._on( uiDialog, { keydown: function( event ) { + if ( !options.modal || event.keyCode !== $.ui.keyCode.TAB ) { + return; + } + + var tabbables = $( ":tabbable", uiDialog ), + first = tabbables.filter( ":first" ), + last = tabbables.filter( ":last" ); + + if ( event.target === last[0] && !event.shiftKey ) { + first.focus( 1 ); + return false; + } else if ( event.target === first[0] && event.shiftKey ) { + last.focus( 1 ); + return false; + } + }}); + }, + + _init: function() { + if ( this.options.autoOpen ) { + this.open(); + } + }, + + _destroy: function() { + var next, + oldPosition = this.oldPosition; + + if ( this.overlay ) { + this.overlay.destroy(); + } + this.uiDialog.hide(); + this.element + .removeClass( "ui-dialog-content ui-widget-content" ) + .hide() + .appendTo( "body" ); + this.uiDialog.remove(); + + if ( this.originalTitle ) { + this.element.attr( "title", this.originalTitle ); + } + + next = oldPosition.parent.children().eq( oldPosition.index ); + // Don't try to place the dialog next to itself (#8613) + if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { + next.before( this.element ); + } else { + oldPosition.parent.append( this.element ); + } + }, + + widget: function() { + return this.uiDialog; + }, + + close: function( event ) { + var that = this, + maxZ, thisZ; + + if ( !this._isOpen ) { + return; + } + + if ( false === this._trigger( "beforeClose", event ) ) { + return; + } + + this._isOpen = false; + + if ( this.overlay ) { + this.overlay.destroy(); + } + + if ( this.options.hide ) { + this._hide( this.uiDialog, this.options.hide, function() { + that._trigger( "close", event ); + }); + } else { + this.uiDialog.hide(); + this._trigger( "close", event ); + } + + $.ui.dialog.overlay.resize(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + if ( this.options.modal ) { + maxZ = 0; + $( ".ui-dialog" ).each(function() { + if ( this !== that.uiDialog[0] ) { + thisZ = $( this ).css( "z-index" ); + if ( !isNaN( thisZ ) ) { + maxZ = Math.max( maxZ, thisZ ); + } + } + }); + $.ui.dialog.maxZ = maxZ; + } + + return this; + }, + + isOpen: function() { + return this._isOpen; + }, + + // the force parameter allows us to move modal dialogs to their correct + // position on open + moveToTop: function( force, event ) { + var options = this.options, + saveScroll; + + if ( ( options.modal && !force ) || + ( !options.stack && !options.modal ) ) { + return this._trigger( "focus", event ); + } + + if ( options.zIndex > $.ui.dialog.maxZ ) { + $.ui.dialog.maxZ = options.zIndex; + } + if ( this.overlay ) { + $.ui.dialog.maxZ += 1; + $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ; + this.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ ); + } + + // Save and then restore scroll + // Opera 9.5+ resets when parent z-index is changed. + // http://bugs.jqueryui.com/ticket/3193 + saveScroll = { + scrollTop: this.element.scrollTop(), + scrollLeft: this.element.scrollLeft() + }; + $.ui.dialog.maxZ += 1; + this.uiDialog.css( "z-index", $.ui.dialog.maxZ ); + this.element.attr( saveScroll ); + this._trigger( "focus", event ); + + return this; + }, + + open: function() { + if ( this._isOpen ) { + return; + } + + var hasFocus, + options = this.options, + uiDialog = this.uiDialog; + + this._size(); + this._position( options.position ); + uiDialog.show( options.show ); + this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null; + this.moveToTop( true ); + + // set focus to the first tabbable element in the content area or the first button + // if there are no tabbable elements, set focus on the dialog itself + hasFocus = this.element.find( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = uiDialog; + } + } + hasFocus.eq( 0 ).focus(); + + this._isOpen = true; + this._trigger( "open" ); + + return this; + }, + + _createButtons: function( buttons ) { + var that = this, + hasButtons = false; + + // if we already have a button pane, remove it + this.uiDialogButtonPane.remove(); + this.uiButtonSet.empty(); + + if ( typeof buttons === "object" && buttons !== null ) { + $.each( buttons, function() { + return !(hasButtons = true); }); - }; - this.refresh(); + } + if ( hasButtons ) { + $.each( buttons, function( name, props ) { + var button, click; + props = $.isFunction( props ) ? + { click: props, text: name } : + props; + // Default to a non-submitting button + props = $.extend( { type: "button" }, props ); + // Change the context for the click callback to be the main element + click = props.click; + props.click = function() { + click.apply( that.element[0], arguments ); + }; + button = $( "", props ) + .appendTo( that.uiButtonSet ); + if ( $.fn.button ) { + button.button(); + } + }); + this.uiDialog.addClass( "ui-dialog-buttons" ); + this.uiDialogButtonPane.appendTo( this.uiDialog ); + } else { + this.uiDialog.removeClass( "ui-dialog-buttons" ); + } + }, - this.selectees = selectees.addClass("ui-selectee"); + _makeDraggable: function() { + var that = this, + options = this.options; - this._mouseInit(); + function filteredUi( ui ) { + return { + position: ui.position, + offset: ui.offset + }; + } - this.helper = $("
      "); + this.uiDialog.draggable({ + cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", + handle: ".ui-dialog-titlebar", + containment: "document", + start: function( event, ui ) { + $( this ) + .addClass( "ui-dialog-dragging" ); + that._trigger( "dragStart", event, filteredUi( ui ) ); + }, + drag: function( event, ui ) { + that._trigger( "drag", event, filteredUi( ui ) ); + }, + stop: function( event, ui ) { + options.position = [ + ui.position.left - that.document.scrollLeft(), + ui.position.top - that.document.scrollTop() + ]; + $( this ) + .removeClass( "ui-dialog-dragging" ); + that._trigger( "dragStop", event, filteredUi( ui ) ); + $.ui.dialog.overlay.resize(); + } + }); }, - destroy: function() { - this.selectees - .removeClass("ui-selectee") - .removeData("selectable-item"); - this.element - .removeClass("ui-selectable ui-selectable-disabled") - .removeData("selectable") - .unbind(".selectable"); - this._mouseDestroy(); + _makeResizable: function( handles ) { + handles = (handles === undefined ? this.options.resizable : handles); + var that = this, + options = this.options, + // .ui-resizable has position: relative defined in the stylesheet + // but dialogs have to use absolute or fixed positioning + position = this.uiDialog.css( "position" ), + resizeHandles = typeof handles === 'string' ? + handles : + "n,e,s,w,se,sw,ne,nw"; - return this; + function filteredUi( ui ) { + return { + originalPosition: ui.originalPosition, + originalSize: ui.originalSize, + position: ui.position, + size: ui.size + }; + } + + this.uiDialog.resizable({ + cancel: ".ui-dialog-content", + containment: "document", + alsoResize: this.element, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + minWidth: options.minWidth, + minHeight: this._minHeight(), + handles: resizeHandles, + start: function( event, ui ) { + $( this ).addClass( "ui-dialog-resizing" ); + that._trigger( "resizeStart", event, filteredUi( ui ) ); + }, + resize: function( event, ui ) { + that._trigger( "resize", event, filteredUi( ui ) ); + }, + stop: function( event, ui ) { + $( this ).removeClass( "ui-dialog-resizing" ); + options.height = $( this ).height(); + options.width = $( this ).width(); + that._trigger( "resizeStop", event, filteredUi( ui ) ); + $.ui.dialog.overlay.resize(); + } + }) + .css( "position", position ) + .find( ".ui-resizable-se" ) + .addClass( "ui-icon ui-icon-grip-diagonal-se" ); }, - _mouseStart: function(event) { - var self = this; + _minHeight: function() { + var options = this.options; - this.opos = [event.pageX, event.pageY]; + if ( options.height === "auto" ) { + return options.minHeight; + } else { + return Math.min( options.minHeight, options.height ); + } + }, - if (this.options.disabled) - return; + _position: function( position ) { + var myAt = [], + offset = [ 0, 0 ], + isVisible; - var options = this.options; + if ( position ) { + // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( + // if (typeof position == 'string' || $.isArray(position)) { + // myAt = $.isArray(position) ? position : position.split(' '); - this.selectees = $(options.filter, this.element[0]); + if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { + myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ]; + if ( myAt.length === 1 ) { + myAt[ 1 ] = myAt[ 0 ]; + } - this._trigger("start", event); + $.each( [ "left", "top" ], function( i, offsetPosition ) { + if ( +myAt[ i ] === myAt[ i ] ) { + offset[ i ] = myAt[ i ]; + myAt[ i ] = offsetPosition; + } + }); - $(options.appendTo).append(this.helper); - // position helper (lasso) - this.helper.css({ - "left": event.clientX, - "top": event.clientY, - "width": 0, - "height": 0 - }); + position = { + my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + + myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), + at: myAt.join( " " ) + }; + } - if (options.autoRefresh) { - this.refresh(); + position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); + } else { + position = $.ui.dialog.prototype.options.position; } - this.selectees.filter('.ui-selected').each(function() { - var selectee = $.data(this, "selectable-item"); - selectee.startselected = true; - if (!event.metaKey) { - selectee.$element.removeClass('ui-selected'); - selectee.selected = false; - selectee.$element.addClass('ui-unselecting'); - selectee.unselecting = true; - // selectable UNSELECTING callback - self._trigger("unselecting", event, { - unselecting: selectee.element - }); + // need to show the dialog to get the actual offset in the position plugin + isVisible = this.uiDialog.is( ":visible" ); + if ( !isVisible ) { + this.uiDialog.show(); + } + this.uiDialog.position( position ); + if ( !isVisible ) { + this.uiDialog.hide(); + } + }, + + _setOptions: function( options ) { + var that = this, + resizableOptions = {}, + resize = false; + + $.each( options, function( key, value ) { + that._setOption( key, value ); + + if ( key in sizeRelatedOptions ) { + resize = true; + } + if ( key in resizableRelatedOptions ) { + resizableOptions[ key ] = value; } }); - $(event.target).parents().andSelf().each(function() { - var selectee = $.data(this, "selectable-item"); - if (selectee) { - var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected'); - selectee.$element - .removeClass(doSelect ? "ui-unselecting" : "ui-selected") - .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); - selectee.unselecting = !doSelect; - selectee.selecting = doSelect; - selectee.selected = doSelect; - // selectable (UN)SELECTING callback - if (doSelect) { - self._trigger("selecting", event, { - selecting: selectee.element - }); + if ( resize ) { + this._size(); + } + if ( this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", resizableOptions ); + } + }, + + _setOption: function( key, value ) { + var isDraggable, isResizable, + uiDialog = this.uiDialog; + + switch ( key ) { + case "buttons": + this._createButtons( value ); + break; + case "closeText": + // ensure that we always pass a string + this.uiDialogTitlebarCloseText.text( "" + value ); + break; + case "dialogClass": + uiDialog + .removeClass( this.options.dialogClass ) + .addClass( uiDialogClasses + value ); + break; + case "disabled": + if ( value ) { + uiDialog.addClass( "ui-dialog-disabled" ); } else { - self._trigger("unselecting", event, { - unselecting: selectee.element + uiDialog.removeClass( "ui-dialog-disabled" ); + } + break; + case "draggable": + isDraggable = uiDialog.is( ":data(draggable)" ); + if ( isDraggable && !value ) { + uiDialog.draggable( "destroy" ); + } + + if ( !isDraggable && value ) { + this._makeDraggable(); + } + break; + case "position": + this._position( value ); + break; + case "resizable": + // currently resizable, becoming non-resizable + isResizable = uiDialog.is( ":data(resizable)" ); + if ( isResizable && !value ) { + uiDialog.resizable( "destroy" ); + } + + // currently resizable, changing handles + if ( isResizable && typeof value === "string" ) { + uiDialog.resizable( "option", "handles", value ); + } + + // currently non-resizable, becoming resizable + if ( !isResizable && value !== false ) { + this._makeResizable( value ); + } + break; + case "title": + // convert whatever was passed in o a string, for html() to not throw up + $( ".ui-dialog-title", this.uiDialogTitlebar ) + .html( "" + ( value || " " ) ); + break; + } + + this._super( key, value ); + }, + + _size: function() { + /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content + * divs will both have width and height set, so we need to reset them + */ + var nonContentHeight, minContentHeight, autoHeight, + options = this.options, + isVisible = this.uiDialog.is( ":visible" ); + + // reset content sizing + this.element.show().css({ + width: "auto", + minHeight: 0, + height: 0 + }); + + if ( options.minWidth > options.width ) { + options.width = options.minWidth; + } + + // reset wrapper sizing + // determine the height of all the non-content elements + nonContentHeight = this.uiDialog.css({ + height: "auto", + width: options.width + }) + .outerHeight(); + minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); + + if ( options.height === "auto" ) { + // only needed for IE6 support + if ( $.support.minHeight ) { + this.element.css({ + minHeight: minContentHeight, + height: "auto" + }); + } else { + this.uiDialog.show(); + autoHeight = this.element.css( "height", "auto" ).height(); + if ( !isVisible ) { + this.uiDialog.hide(); + } + this.element.height( Math.max( autoHeight, minContentHeight ) ); + } + } else { + this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); + } + + if (this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); + } + } +}); + +$.extend($.ui.dialog, { + uuid: 0, + maxZ: 0, + + getTitleId: function($el) { + var id = $el.attr( "id" ); + if ( !id ) { + this.uuid += 1; + id = this.uuid; + } + return "ui-dialog-title-" + id; + }, + + overlay: function( dialog ) { + this.$el = $.ui.dialog.overlay.create( dialog ); + } +}); + +$.extend( $.ui.dialog.overlay, { + instances: [], + // reuse old instances due to IE memory leak with alpha transparency (see #5185) + oldInstances: [], + maxZ: 0, + events: $.map( + "focus,mousedown,mouseup,keydown,keypress,click".split( "," ), + function( event ) { + return event + ".dialog-overlay"; + } + ).join( " " ), + create: function( dialog ) { + if ( this.instances.length === 0 ) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ( $.ui.dialog.overlay.instances.length ) { + $( document ).bind( $.ui.dialog.overlay.events, function( event ) { + // stop events if the z-index of the target is < the z-index of the overlay + // we cannot return true when we don't want to cancel the event (#3523) + if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) { + return false; + } }); } - return false; + }, 1 ); + + // handle window resize + $( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize ); + } + + var $el = ( this.oldInstances.pop() || $( "
      " ).addClass( "ui-widget-overlay" ) ); + + // allow closing by pressing the escape key + $( document ).bind( "keydown.dialog-overlay", function( event ) { + var instances = $.ui.dialog.overlay.instances; + // only react to the event if we're the top overlay + if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el && + dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE ) { + + dialog.close( event ); + event.preventDefault(); } }); - }, + $el.appendTo( document.body ).css({ + width: this.width(), + height: this.height() + }); - _mouseDrag: function(event) { - var self = this; - this.dragged = true; + if ( $.fn.bgiframe ) { + $el.bgiframe(); + } - if (this.options.disabled) - return; + this.instances.push( $el ); + return $el; + }, - var options = this.options; + destroy: function( $el ) { + var indexOf = $.inArray( $el, this.instances ), + maxZ = 0; - var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; - if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } - if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } - this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + if ( indexOf !== -1 ) { + this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] ); + } - this.selectees.each(function() { - var selectee = $.data(this, "selectable-item"); - //prevent helper from being selected if appendTo: selectable - if (!selectee || selectee.element == self.element[0]) - return; - var hit = false; - if (options.tolerance == 'touch') { - hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); - } else if (options.tolerance == 'fit') { - hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); - } + if ( this.instances.length === 0 ) { + $( [ document, window ] ).unbind( ".dialog-overlay" ); + } - if (hit) { - // SELECT - if (selectee.selected) { - selectee.$element.removeClass('ui-selected'); - selectee.selected = false; - } - if (selectee.unselecting) { - selectee.$element.removeClass('ui-unselecting'); - selectee.unselecting = false; - } - if (!selectee.selecting) { - selectee.$element.addClass('ui-selecting'); - selectee.selecting = true; - // selectable SELECTING callback - self._trigger("selecting", event, { - selecting: selectee.element - }); - } - } else { - // UNSELECT - if (selectee.selecting) { - if (event.metaKey && selectee.startselected) { - selectee.$element.removeClass('ui-selecting'); - selectee.selecting = false; - selectee.$element.addClass('ui-selected'); - selectee.selected = true; - } else { - selectee.$element.removeClass('ui-selecting'); - selectee.selecting = false; - if (selectee.startselected) { - selectee.$element.addClass('ui-unselecting'); - selectee.unselecting = true; - } - // selectable UNSELECTING callback - self._trigger("unselecting", event, { - unselecting: selectee.element - }); - } - } - if (selectee.selected) { - if (!event.metaKey && !selectee.startselected) { - selectee.$element.removeClass('ui-selected'); - selectee.selected = false; + $el.height( 0 ).width( 0 ).remove(); - selectee.$element.addClass('ui-unselecting'); - selectee.unselecting = true; - // selectable UNSELECTING callback - self._trigger("unselecting", event, { - unselecting: selectee.element - }); - } - } - } + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + $.each( this.instances, function() { + maxZ = Math.max( maxZ, this.css( "z-index" ) ); }); - - return false; + this.maxZ = maxZ; }, - _mouseStop: function(event) { - var self = this; + height: function() { + var scrollHeight, + offsetHeight; + // handle IE + if ( $.ui.ie ) { + scrollHeight = Math.max( + document.documentElement.scrollHeight, + document.body.scrollHeight + ); + offsetHeight = Math.max( + document.documentElement.offsetHeight, + document.body.offsetHeight + ); - this.dragged = false; + if ( scrollHeight < offsetHeight ) { + return $( window ).height() + "px"; + } else { + return scrollHeight + "px"; + } + // handle "good" browsers + } else { + return $( document ).height() + "px"; + } + }, - var options = this.options; + width: function() { + var scrollWidth, + offsetWidth; + // handle IE + if ( $.ui.ie ) { + scrollWidth = Math.max( + document.documentElement.scrollWidth, + document.body.scrollWidth + ); + offsetWidth = Math.max( + document.documentElement.offsetWidth, + document.body.offsetWidth + ); - $('.ui-unselecting', this.element[0]).each(function() { - var selectee = $.data(this, "selectable-item"); - selectee.$element.removeClass('ui-unselecting'); - selectee.unselecting = false; - selectee.startselected = false; - self._trigger("unselected", event, { - unselected: selectee.element - }); - }); - $('.ui-selecting', this.element[0]).each(function() { - var selectee = $.data(this, "selectable-item"); - selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); - selectee.selecting = false; - selectee.selected = true; - selectee.startselected = true; - self._trigger("selected", event, { - selected: selectee.element - }); - }); - this._trigger("stop", event); + if ( scrollWidth < offsetWidth ) { + return $( window ).width() + "px"; + } else { + return scrollWidth + "px"; + } + // handle "good" browsers + } else { + return $( document ).width() + "px"; + } + }, - this.helper.remove(); + resize: function() { + /* If the dialog is draggable and the user drags it past the + * right edge of the window, the document becomes wider so we + * need to stretch the overlay. If the user then drags the + * dialog back to the left, the document will become narrower, + * so we need to shrink the overlay to the appropriate size. + * This is handled by shrinking the overlay before setting it + * to the full document size. + */ + var $overlays = $( [] ); + $.each( $.ui.dialog.overlay.instances, function() { + $overlays = $overlays.add( this ); + }); - return false; + $overlays.css({ + width: 0, + height: 0 + }).css({ + width: $.ui.dialog.overlay.width(), + height: $.ui.dialog.overlay.height() + }); } - }); -$.extend($.ui.selectable, { - version: "1.8.16" +$.extend( $.ui.dialog.overlay.prototype, { + destroy: function() { + $.ui.dialog.overlay.destroy( this.$el ); + } }); -})(jQuery); -/* - * jQuery UI Sortable 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Sortables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ +}( jQuery ) ); (function( $, undefined ) { -$.widget("ui.sortable", $.ui.mouse, { - widgetEventPrefix: "sort", +$.widget("ui.draggable", $.ui.mouse, { + version: "1.9.2", + widgetEventPrefix: "drag", options: { + addClasses: true, appendTo: "parent", axis: false, - connectWith: false, + connectToSortable: false, containment: false, - cursor: 'auto', + cursor: "auto", cursorAt: false, - dropOnEmpty: true, - forcePlaceholderSize: false, - forceHelperSize: false, grid: false, handle: false, helper: "original", - items: '> *', + iframeFix: false, opacity: false, - placeholder: false, + refreshPositions: false, revert: false, + revertDuration: 500, + scope: "default", scroll: true, scrollSensitivity: 20, scrollSpeed: 20, - scope: "default", - tolerance: "intersect", - zIndex: 1000 + snap: false, + snapMode: "both", + snapTolerance: 20, + stack: false, + zIndex: false }, _create: function() { - var o = this.options; - this.containerCache = {}; - this.element.addClass("ui-sortable"); - - //Get the items - this.refresh(); - - //Let's determine if the items are being displayed horizontally - this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false; + if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) + this.element[0].style.position = 'relative'; - //Let's determine the parent's offset - this.offset = this.element.offset(); + (this.options.addClasses && this.element.addClass("ui-draggable")); + (this.options.disabled && this.element.addClass("ui-draggable-disabled")); - //Initialize mouse events for interaction this._mouseInit(); }, - destroy: function() { - this.element - .removeClass("ui-sortable ui-sortable-disabled") - .removeData("sortable") - .unbind(".sortable"); + _destroy: function() { + this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); this._mouseDestroy(); - - for ( var i = this.items.length - 1; i >= 0; i-- ) - this.items[i].item.removeData("sortable-item"); - - return this; }, - _setOption: function(key, value){ - if ( key === "disabled" ) { - this.options[ key ] = value; - - this.widget() - [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" ); - } else { - // Don't call widget base _setOption for disable as it adds ui-state-disabled class - $.Widget.prototype._setOption.apply(this, arguments); - } - }, - - _mouseCapture: function(event, overrideHandle) { - - if (this.reverting) { - return false; - } - - if(this.options.disabled || this.options.type == 'static') return false; - - //We have to refresh the items data once first - this._refreshItems(event); + _mouseCapture: function(event) { - //Find out if the clicked node (or one of its parents) is a actual item in this.items - var currentItem = null, self = this, nodes = $(event.target).parents().each(function() { - if($.data(this, 'sortable-item') == self) { - currentItem = $(this); - return false; - } - }); - if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target); + var o = this.options; - if(!currentItem) return false; - if(this.options.handle && !overrideHandle) { - var validHandle = false; + // among others, prevent a drag on a resizable-handle + if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) + return false; - $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); - if(!validHandle) return false; - } + //Quit if we're not on a valid handle + this.handle = this._getHandle(event); + if (!this.handle) + return false; + + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { + $('
      ') + .css({ + width: this.offsetWidth+"px", height: this.offsetHeight+"px", + position: "absolute", opacity: "0.001", zIndex: 1000 + }) + .css($(this).offset()) + .appendTo("body"); + }); - this.currentItem = currentItem; - this._removeCurrentsFromItems(); return true; }, - _mouseStart: function(event, overrideHandle, noActivation) { - - var o = this.options, self = this; - this.currentContainer = this; + _mouseStart: function(event) { - //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture - this.refreshPositions(); + var o = this.options; //Create and append the visible helper this.helper = this._createHelper(event); + this.helper.addClass("ui-draggable-dragging"); + //Cache the helper size this._cacheHelperProportions(); + //If ddmanager is used for droppables, set the global draggable + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + /* * - Position generation - * This block generates everything position related - it's the core of draggables. @@ -3114,21 +6008,17 @@ $.widget("ui.sortable", $.ui.mouse, { //Cache the margins of the original element this._cacheMargins(); - //Get the next scrolling parent + //Store the helper's css position + this.cssPosition = this.helper.css("position"); this.scrollParent = this.helper.scrollParent(); //The element's absolute position on the page minus margins - this.offset = this.currentItem.offset(); + this.offset = this.positionAbs = this.element.offset(); this.offset = { top: this.offset.top - this.margins.top, left: this.offset.left - this.margins.left }; - // Only after we got the offset, we can change the helper's position to absolute - // TODO: Still need to figure out a way to make relative sorting possible - this.helper.css("position", "absolute"); - this.cssPosition = this.helper.css("position"); - $.extend(this.offset, { click: { //Where the click happened, relative to the element left: event.pageX - this.offset.left, @@ -3139,1062 +6029,1658 @@ $.widget("ui.sortable", $.ui.mouse, { }); //Generate the original position - this.originalPosition = this._generatePosition(event); + this.originalPosition = this.position = this._generatePosition(event); this.originalPageX = event.pageX; this.originalPageY = event.pageY; //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); - //Cache the former DOM position - this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; + //Set a containment if given in the options + if(o.containment) + this._setContainment(); - //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way - if(this.helper[0] != this.currentItem[0]) { - this.currentItem.hide(); + //Trigger event + callbacks + if(this._trigger("start", event) === false) { + this._clear(); + return false; } - //Create the placeholder - this._createPlaceholder(); + //Recache the helper size + this._cacheHelperProportions(); - //Set a containment if given in the options - if(o.containment) - this._setContainment(); + //Prepare the droppable offsets + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position + + //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) + if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); + + return true; + }, + + _mouseDrag: function(event, noPropagation) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + //Call plugins and callbacks and use the resulting position if something is returned + if (!noPropagation) { + var ui = this._uiHash(); + if(this._trigger('drag', event, ui) === false) { + this._mouseUp({}); + return false; + } + this.position = ui.position; + } + + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + return false; + }, + + _mouseStop: function(event) { + + //If we are using droppables, inform the manager about the drop + var dropped = false; + if ($.ui.ddmanager && !this.options.dropBehaviour) + dropped = $.ui.ddmanager.drop(this, event); + + //if a drop comes from outside (a sortable) + if(this.dropped) { + dropped = this.dropped; + this.dropped = false; + } + + //if the original element is no longer in the DOM don't bother to continue (see #8269) + var element = this.element[0], elementInDom = false; + while ( element && (element = element.parentNode) ) { + if (element == document ) { + elementInDom = true; + } + } + if ( !elementInDom && this.options.helper === "original" ) + return false; + + if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { + var that = this; + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { + if(that._trigger("stop", event) !== false) { + that._clear(); + } + }); + } else { + if(this._trigger("stop", event) !== false) { + this._clear(); + } + } + + return false; + }, + + _mouseUp: function(event) { + //Remove frame helpers + $("div.ui-draggable-iframeFix").each(function() { + this.parentNode.removeChild(this); + }); + + //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) + if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); + + return $.ui.mouse.prototype._mouseUp.call(this, event); + }, + + cancel: function() { + + if(this.helper.is(".ui-draggable-dragging")) { + this._mouseUp({}); + } else { + this._clear(); + } + + return this; + + }, + + _getHandle: function(event) { + + var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; + $(this.options.handle, this.element) + .find("*") + .andSelf() + .each(function() { + if(this == event.target) handle = true; + }); + + return handle; + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); + + if(!helper.parents('body').length) + helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); + + if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) + helper.css("position", "absolute"); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.element.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.element.css("marginLeft"),10) || 0), + top: (parseInt(this.element.css("marginTop"),10) || 0), + right: (parseInt(this.element.css("marginRight"),10) || 0), + bottom: (parseInt(this.element.css("marginBottom"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, + o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, + (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; - if(o.cursor) { // cursor option - if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); - $('body').css("cursor", o.cursor); - } + if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { + var c = $(o.containment); + var ce = c[0]; if(!ce) return; + var co = c.offset(); + var over = ($(ce).css("overflow") != 'hidden'); - if(o.opacity) { // opacity option - if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); - this.helper.css("opacity", o.opacity); - } + this.containment = [ + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), + (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, + (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom + ]; + this.relative_container = c; - if(o.zIndex) { // zIndex option - if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); - this.helper.css("zIndex", o.zIndex); + } else if(o.containment.constructor == Array) { + this.containment = o.containment; } - //Prepare scrolling - if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') - this.overflowOffset = this.scrollParent.offset(); + }, - //Call callbacks - this._trigger("start", event, this._uiHash()); + _convertPositionTo: function(d, pos) { - //Recache the helper size - if(!this._preserveHelperProportions) - this._cacheHelperProportions(); + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; - //Post 'activate' events to possible containers - if(!noActivation) { - for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); } - } + }, - //Prepare possible droppables - if($.ui.ddmanager) - $.ui.ddmanager.current = this; + _generatePosition: function(event) { - if ($.ui.ddmanager && !o.dropBehaviour) - $.ui.ddmanager.prepareOffsets(this, event); + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + var pageX = event.pageX; + var pageY = event.pageY; - this.dragging = true; + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ - this.helper.addClass("ui-sortable-helper"); - this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position - return true; + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + var containment; + if(this.containment) { + if (this.relative_container){ + var co = this.relative_container.offset(); + containment = [ this.containment[0] + co.left, + this.containment[1] + co.top, + this.containment[2] + co.left, + this.containment[3] + co.top ]; + } + else { + containment = this.containment; + } - }, + if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; + } - _mouseDrag: function(event) { + if(o.grid) { + //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) + var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; + pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; - //Compute the helpers position - this.position = this._generatePosition(event); - this.positionAbs = this._convertPositionTo("absolute"); + var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; + pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } - if (!this.lastPositionAbs) { - this.lastPositionAbs = this.positionAbs; } - //Do scrolling - if(this.options.scroll) { - var o = this.options, scrolled = false; - if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; - if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) - this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; - else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) - this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + }, - if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) - this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; - else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) - this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + _clear: function() { + this.helper.removeClass("ui-draggable-dragging"); + if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); + //if($.ui.ddmanager) $.ui.ddmanager.current = null; + this.helper = null; + this.cancelHelperRemoval = false; + }, - } else { + // From now on bulk stuff - mainly helpers - if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) - scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); - else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) - scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + _trigger: function(type, event, ui) { + ui = ui || this._uiHash(); + $.ui.plugin.call(this, type, [event, ui]); + if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins + return $.Widget.prototype._trigger.call(this, type, event, ui); + }, - if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) - scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); - else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) - scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + plugins: {}, - } + _uiHash: function(event) { + return { + helper: this.helper, + position: this.position, + originalPosition: this.originalPosition, + offset: this.positionAbs + }; + } - if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) - $.ui.ddmanager.prepareOffsets(this, event); - } +}); - //Regenerate the absolute position used for position checks - this.positionAbs = this._convertPositionTo("absolute"); +$.ui.plugin.add("draggable", "connectToSortable", { + start: function(event, ui) { - //Set the helper position - if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; - if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + var inst = $(this).data("draggable"), o = inst.options, + uiSortable = $.extend({}, ui, { item: inst.element }); + inst.sortables = []; + $(o.connectToSortable).each(function() { + var sortable = $.data(this, 'sortable'); + if (sortable && !sortable.options.disabled) { + inst.sortables.push({ + instance: sortable, + shouldRevert: sortable.options.revert + }); + sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). + sortable._trigger("activate", event, uiSortable); + } + }); - //Rearrange - for (var i = this.items.length - 1; i >= 0; i--) { + }, + stop: function(event, ui) { - //Cache variables and intersection, continue if no intersection - var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); - if (!intersection) continue; + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper + var inst = $(this).data("draggable"), + uiSortable = $.extend({}, ui, { item: inst.element }); - if(itemElement != this.currentItem[0] //cannot intersect with itself - && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before - && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked - && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) - //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container - ) { + $.each(inst.sortables, function() { + if(this.instance.isOver) { - this.direction = intersection == 1 ? "down" : "up"; + this.instance.isOver = 0; - if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { - this._rearrange(event, item); - } else { - break; - } + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) - this._trigger("change", event, this._uiHash()); - break; - } - } + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' + if(this.shouldRevert) this.instance.options.revert = true; - //Post events to containers - this._contactContainers(event); + //Trigger the stop of the sortable + this.instance._mouseStop(event); - //Interconnect with droppables - if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + this.instance.options.helper = this.instance.options._helper; - //Call callbacks - this._trigger('sort', event, this._uiHash()); + //If the helper has been the original item, restore properties in the sortable + if(inst.options.helper == 'original') + this.instance.currentItem.css({ top: 'auto', left: 'auto' }); - this.lastPositionAbs = this.positionAbs; - return false; + } else { + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance + this.instance._trigger("deactivate", event, uiSortable); + } - }, + }); - _mouseStop: function(event, noPropagation) { + }, + drag: function(event, ui) { - if(!event) return; + var inst = $(this).data("draggable"), that = this; - //If we are using droppables, inform the manager about the drop - if ($.ui.ddmanager && !this.options.dropBehaviour) - $.ui.ddmanager.drop(this, event); + var checkPos = function(o) { + var dyClick = this.offset.click.top, dxClick = this.offset.click.left; + var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; + var itemHeight = o.height, itemWidth = o.width; + var itemTop = o.top, itemLeft = o.left; - if(this.options.revert) { - var self = this; - var cur = self.placeholder.offset(); + return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); + }; - self.reverting = true; + $.each(inst.sortables, function(i) { - $(this.helper).animate({ - left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), - top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) - }, parseInt(this.options.revert, 10) || 500, function() { - self._clear(event); - }); - } else { - this._clear(event, noPropagation); - } + var innermostIntersecting = false; + var thisSortable = this; + //Copy over some variables to allow calling the sortable's native _intersectsWith + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; - return false; + if(this.instance._intersectsWith(this.instance.containerCache)) { + innermostIntersecting = true; + $.each(inst.sortables, function () { + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + if (this != thisSortable + && this.instance._intersectsWith(this.instance.containerCache) + && $.ui.contains(thisSortable.instance.element[0], this.instance.element[0])) + innermostIntersecting = false; + return innermostIntersecting; + }); + } - }, - cancel: function() { + if(innermostIntersecting) { + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once + if(!this.instance.isOver) { - var self = this; + this.instance.isOver = 1; + //Now we fake the start of dragging for the sortable instance, + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem + //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) + this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it + this.instance.options.helper = function() { return ui.helper[0]; }; - if(this.dragging) { + event.target = this.instance.currentItem[0]; + this.instance._mouseCapture(event, true); + this.instance._mouseStart(event, true, true); - this._mouseUp({ target: null }); + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes + this.instance.offset.click.top = inst.offset.click.top; + this.instance.offset.click.left = inst.offset.click.left; + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; - if(this.options.helper == "original") - this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); - else - this.currentItem.show(); + inst._trigger("toSortable", event); + inst.dropped = this.instance.element; //draggable revert needs that + //hack so receive/update callbacks work (mostly) + inst.currentItem = inst.element; + this.instance.fromOutside = inst; - //Post deactivating events to containers - for (var i = this.containers.length - 1; i >= 0; i--){ - this.containers[i]._trigger("deactivate", null, self._uiHash(this)); - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", null, self._uiHash(this)); - this.containers[i].containerCache.over = 0; } - } - - } - if (this.placeholder) { - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); - if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); - - $.extend(this, { - helper: null, - dragging: false, - reverting: false, - _noFinalSort: null - }); + //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable + if(this.instance.currentItem) this.instance._mouseDrag(event); - if(this.domPosition.prev) { - $(this.domPosition.prev).after(this.currentItem); } else { - $(this.domPosition.parent).prepend(this.currentItem); - } - } - return this; + //If it doesn't intersect with the sortable, and it intersected before, + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval + if(this.instance.isOver) { - }, + this.instance.isOver = 0; + this.instance.cancelHelperRemoval = true; - serialize: function(o) { + //Prevent reverting on this forced stop + this.instance.options.revert = false; - var items = this._getItemsAsjQuery(o && o.connected); - var str = []; o = o || {}; + // The out event needs to be triggered independently + this.instance._trigger('out', event, this.instance._uiHash(this.instance)); - $(items).each(function() { - var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); - if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); - }); + this.instance._mouseStop(event, true); + this.instance.options.helper = this.instance.options._helper; - if(!str.length && o.key) { - str.push(o.key + '='); - } + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size + this.instance.currentItem.remove(); + if(this.instance.placeholder) this.instance.placeholder.remove(); - return str.join('&'); + inst._trigger("fromSortable", event); + inst.dropped = false; //draggable revert needs that + } - }, + }; - toArray: function(o) { + }); - var items = this._getItemsAsjQuery(o && o.connected); - var ret = []; o = o || {}; + } +}); - items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); - return ret; +$.ui.plugin.add("draggable", "cursor", { + start: function(event, ui) { + var t = $('body'), o = $(this).data('draggable').options; + if (t.css("cursor")) o._cursor = t.css("cursor"); + t.css("cursor", o.cursor); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if (o._cursor) $('body').css("cursor", o._cursor); + } +}); +$.ui.plugin.add("draggable", "opacity", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data('draggable').options; + if(t.css("opacity")) o._opacity = t.css("opacity"); + t.css('opacity', o.opacity); }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if(o._opacity) $(ui.helper).css('opacity', o._opacity); + } +}); - /* Be careful with the following core functions */ - _intersectsWith: function(item) { +$.ui.plugin.add("draggable", "scroll", { + start: function(event, ui) { + var i = $(this).data("draggable"); + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); + }, + drag: function(event, ui) { - var x1 = this.positionAbs.left, - x2 = x1 + this.helperProportions.width, - y1 = this.positionAbs.top, - y2 = y1 + this.helperProportions.height; + var i = $(this).data("draggable"), o = i.options, scrolled = false; - var l = item.left, - r = l + item.width, - t = item.top, - b = t + item.height; + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { - var dyClick = this.offset.click.top, - dxClick = this.offset.click.left; + if(!o.axis || o.axis != 'x') { + if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; + } - var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + if(!o.axis || o.axis != 'y') { + if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + } - if( this.options.tolerance == "pointer" - || this.options.forcePointerForContainers - || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) - ) { - return isOverElement; } else { - return (l < x1 + (this.helperProportions.width / 2) // Right Half - && x2 - (this.helperProportions.width / 2) < r // Left Half - && t < y1 + (this.helperProportions.height / 2) // Bottom Half - && y2 - (this.helperProportions.height / 2) < b ); // Top Half + if(!o.axis || o.axis != 'x') { + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + + if(!o.axis || o.axis != 'y') { + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } } - }, - _intersectsWithPointer: function(item) { + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(i, event); - var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), - isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), - isOverElement = isOverElementHeight && isOverElementWidth, - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); + } +}); - if (!isOverElement) - return false; +$.ui.plugin.add("draggable", "snap", { + start: function(event, ui) { - return this.floating ? - ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) - : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); + var i = $(this).data("draggable"), o = i.options; + i.snapElements = []; + + $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { + var $t = $(this); var $o = $t.offset(); + if(this != i.element[0]) i.snapElements.push({ + item: this, + width: $t.outerWidth(), height: $t.outerHeight(), + top: $o.top, left: $o.left + }); + }); }, + drag: function(event, ui) { - _intersectsWithSides: function(item) { + var inst = $(this).data("draggable"), o = inst.options; + var d = o.snapTolerance; - var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), - isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); + var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; - if (this.floating && horizontalDirection) { - return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); - } else { - return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); - } + for (var i = inst.snapElements.length - 1; i >= 0; i--){ - }, + var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, + t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; + + //Yes, I know, this is insane ;) + if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { + if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = false; + continue; + } + + if(o.snapMode != 'inner') { + var ts = Math.abs(t - y2) <= d; + var bs = Math.abs(b - y1) <= d; + var ls = Math.abs(l - x2) <= d; + var rs = Math.abs(r - x1) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; + } + + var first = (ts || bs || ls || rs); + + if(o.snapMode != 'outer') { + var ts = Math.abs(t - y1) <= d; + var bs = Math.abs(b - y2) <= d; + var ls = Math.abs(l - x1) <= d; + var rs = Math.abs(r - x2) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; + } + + if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); + + }; - _getDragVerticalDirection: function() { - var delta = this.positionAbs.top - this.lastPositionAbs.top; - return delta != 0 && (delta > 0 ? "down" : "up"); - }, + } +}); - _getDragHorizontalDirection: function() { - var delta = this.positionAbs.left - this.lastPositionAbs.left; - return delta != 0 && (delta > 0 ? "right" : "left"); - }, +$.ui.plugin.add("draggable", "stack", { + start: function(event, ui) { - refresh: function(event) { - this._refreshItems(event); - this.refreshPositions(); - return this; - }, + var o = $(this).data("draggable").options; - _connectWith: function() { - var options = this.options; - return options.connectWith.constructor == String - ? [options.connectWith] - : options.connectWith; - }, - - _getItemsAsjQuery: function(connected) { + var group = $.makeArray($(o.stack)).sort(function(a,b) { + return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); + }); + if (!group.length) { return; } - var self = this; - var items = []; - var queries = []; - var connectWith = this._connectWith(); + var min = parseInt(group[0].style.zIndex) || 0; + $(group).each(function(i) { + this.style.zIndex = min + i; + }); - if(connectWith && connected) { - for (var i = connectWith.length - 1; i >= 0; i--){ - var cur = $(connectWith[i]); - for (var j = cur.length - 1; j >= 0; j--){ - var inst = $.data(cur[j], 'sortable'); - if(inst && inst != this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); - } - }; - }; - } + this[0].style.zIndex = min + group.length; - queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); + } +}); - for (var i = queries.length - 1; i >= 0; i--){ - queries[i][0].each(function() { - items.push(this); - }); - }; +$.ui.plugin.add("draggable", "zIndex", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data("draggable").options; + if(t.css("zIndex")) o._zIndex = t.css("zIndex"); + t.css('zIndex', o.zIndex); + }, + stop: function(event, ui) { + var o = $(this).data("draggable").options; + if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); + } +}); - return $(items); +})(jQuery); +(function( $, undefined ) { +$.widget("ui.droppable", { + version: "1.9.2", + widgetEventPrefix: "drop", + options: { + accept: '*', + activeClass: false, + addClasses: true, + greedy: false, + hoverClass: false, + scope: 'default', + tolerance: 'intersect' }, + _create: function() { - _removeCurrentsFromItems: function() { + var o = this.options, accept = o.accept; + this.isover = 0; this.isout = 1; - var list = this.currentItem.find(":data(sortable-item)"); + this.accept = $.isFunction(accept) ? accept : function(d) { + return d.is(accept); + }; - for (var i=0; i < this.items.length; i++) { + //Store the droppable's proportions + this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; - for (var j=0; j < list.length; j++) { - if(list[j] == this.items[i].item[0]) - this.items.splice(i,1); - }; + // Add the reference and positions to the manager + $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; + $.ui.ddmanager.droppables[o.scope].push(this); - }; + (o.addClasses && this.element.addClass("ui-droppable")); }, - _refreshItems: function(event) { + _destroy: function() { + var drop = $.ui.ddmanager.droppables[this.options.scope]; + for ( var i = 0; i < drop.length; i++ ) + if ( drop[i] == this ) + drop.splice(i, 1); - this.items = []; - this.containers = [this]; - var items = this.items; - var self = this; - var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; - var connectWith = this._connectWith(); + this.element.removeClass("ui-droppable ui-droppable-disabled"); + }, - if(connectWith) { - for (var i = connectWith.length - 1; i >= 0; i--){ - var cur = $(connectWith[i]); - for (var j = cur.length - 1; j >= 0; j--){ - var inst = $.data(cur[j], 'sortable'); - if(inst && inst != this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); - this.containers.push(inst); - } - }; + _setOption: function(key, value) { + + if(key == 'accept') { + this.accept = $.isFunction(value) ? value : function(d) { + return d.is(value); }; } + $.Widget.prototype._setOption.apply(this, arguments); + }, - for (var i = queries.length - 1; i >= 0; i--) { - var targetData = queries[i][1]; - var _queries = queries[i][0]; + _activate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.addClass(this.options.activeClass); + (draggable && this._trigger('activate', event, this.ui(draggable))); + }, - for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { - var item = $(_queries[j]); + _deactivate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + (draggable && this._trigger('deactivate', event, this.ui(draggable))); + }, - item.data('sortable-item', targetData); // Data for target checking (mouse manager) + _over: function(event) { - items.push({ - item: item, - instance: targetData, - width: 0, height: 0, - left: 0, top: 0 - }); - }; - }; + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); + this._trigger('over', event, this.ui(draggable)); + } }, - refreshPositions: function(fast) { + _out: function(event) { - //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change - if(this.offsetParent && this.helper) { - this.offset.parent = this._getParentOffset(); - } + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element - for (var i = this.items.length - 1; i >= 0; i--){ - var item = this.items[i]; + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('out', event, this.ui(draggable)); + } - //We ignore calculating positions of all connected containers when we're not over them - if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) - continue; + }, - var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; + _drop: function(event,custom) { - if (!fast) { - item.width = t.outerWidth(); - item.height = t.outerHeight(); - } + var draggable = custom || $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element - var p = t.offset(); - item.left = p.left; - item.top = p.top; - }; + var childrenIntersection = false; + this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { + var inst = $.data(this, 'droppable'); + if( + inst.options.greedy + && !inst.options.disabled + && inst.options.scope == draggable.options.scope + && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) + && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) + ) { childrenIntersection = true; return false; } + }); + if(childrenIntersection) return false; - if(this.options.custom && this.options.custom.refreshContainers) { - this.options.custom.refreshContainers.call(this); - } else { - for (var i = this.containers.length - 1; i >= 0; i--){ - var p = this.containers[i].element.offset(); - this.containers[i].containerCache.left = p.left; - this.containers[i].containerCache.top = p.top; - this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); - this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); - }; + if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('drop', event, this.ui(draggable)); + return this.element; } - return this; - }, - - _createPlaceholder: function(that) { + return false; - var self = that || this, o = self.options; + }, - if(!o.placeholder || o.placeholder.constructor == String) { - var className = o.placeholder; - o.placeholder = { - element: function() { + ui: function(c) { + return { + draggable: (c.currentItem || c.element), + helper: c.helper, + position: c.position, + offset: c.positionAbs + }; + } - var el = $(document.createElement(self.currentItem[0].nodeName)) - .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder") - .removeClass("ui-sortable-helper")[0]; +}); - if(!className) - el.style.visibility = "hidden"; +$.ui.intersect = function(draggable, droppable, toleranceMode) { - return el; - }, - update: function(container, p) { + if (!droppable.offset) return false; - // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that - // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified - if(className && !o.forcePlaceholderSize) return; + var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, + y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; + var l = droppable.offset.left, r = l + droppable.proportions.width, + t = droppable.offset.top, b = t + droppable.proportions.height; - //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item - if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); }; - if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); }; - } - }; + switch (toleranceMode) { + case 'fit': + return (l <= x1 && x2 <= r + && t <= y1 && y2 <= b); + break; + case 'intersect': + return (l < x1 + (draggable.helperProportions.width / 2) // Right Half + && x2 - (draggable.helperProportions.width / 2) < r // Left Half + && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half + && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half + break; + case 'pointer': + var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), + draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), + isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); + return isOver; + break; + case 'touch': + return ( + (y1 >= t && y1 <= b) || // Top edge touching + (y2 >= t && y2 <= b) || // Bottom edge touching + (y1 < t && y2 > b) // Surrounded vertically + ) && ( + (x1 >= l && x1 <= r) || // Left edge touching + (x2 >= l && x2 <= r) || // Right edge touching + (x1 < l && x2 > r) // Surrounded horizontally + ); + break; + default: + return false; + break; } - //Create the placeholder - self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); - - //Append it after the actual current item - self.currentItem.after(self.placeholder); - - //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) - o.placeholder.update(self, self.placeholder); +}; - }, +/* + This manager tracks offsets of draggables and droppables +*/ +$.ui.ddmanager = { + current: null, + droppables: { 'default': [] }, + prepareOffsets: function(t, event) { - _contactContainers: function(event) { - - // get innermost container that intersects with item - var innermostContainer = null, innermostIndex = null; - - - for (var i = this.containers.length - 1; i >= 0; i--){ + var m = $.ui.ddmanager.droppables[t.options.scope] || []; + var type = event ? event.type : null; // workaround for #2317 + var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); - // never consider a container that's located within the item itself - if($.ui.contains(this.currentItem[0], this.containers[i].element[0])) - continue; + droppablesLoop: for (var i = 0; i < m.length; i++) { - if(this._intersectsWith(this.containers[i].containerCache)) { + if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted + for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item + m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue - // if we've already found a container and it's more "inner" than this, then continue - if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0])) - continue; + if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables - innermostContainer = this.containers[i]; - innermostIndex = i; - - } else { - // container doesn't intersect. trigger "out" event if necessary - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", event, this._uiHash(this)); - this.containers[i].containerCache.over = 0; - } - } + m[i].offset = m[i].element.offset(); + m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; } - - // if no intersecting containers found, return - if(!innermostContainer) return; - // move the item into the container if it's not there already - if(this.containers.length === 1) { - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; - } else if(this.currentContainer != this.containers[innermostIndex]) { - - //When entering a new container, we will find the item with the least distance and append our item near it - var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; - for (var j = this.items.length - 1; j >= 0; j--) { - if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; - var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; - if(Math.abs(cur - base) < dist) { - dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; - } - } - - if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled - return; - - this.currentContainer = this.containers[innermostIndex]; - itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); - this._trigger("change", event, this._uiHash()); - this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); - - //Update the placeholder - this.options.placeholder.update(this.currentContainer, this.placeholder); - - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; - } - - }, + drop: function(draggable, event) { - _createHelper: function(event) { - - var o = this.options; - var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); - - if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already - $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); + var dropped = false; + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { - if(helper[0] == this.currentItem[0]) - this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; + if(!this.options) return; + if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) + dropped = this._drop.call(this, event) || dropped; - if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); - if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); + if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + this.isout = 1; this.isover = 0; + this._deactivate.call(this, event); + } - return helper; + }); + return dropped; }, - - _adjustOffsetFromHelper: function(obj) { - if (typeof obj == 'string') { - obj = obj.split(' '); - } - if ($.isArray(obj)) { - obj = {left: +obj[0], top: +obj[1] || 0}; - } - if ('left' in obj) { - this.offset.click.left = obj.left + this.margins.left; - } - if ('right' in obj) { - this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; - } - if ('top' in obj) { - this.offset.click.top = obj.top + this.margins.top; - } - if ('bottom' in obj) { - this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; - } + dragStart: function( draggable, event ) { + //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) + draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { + if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); + }); }, + drag: function(draggable, event) { - _getParentOffset: function() { - + //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. + if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); - //Get the offsetParent and cache its position - this.offsetParent = this.helper.offsetParent(); - var po = this.offsetParent.offset(); + //Run through all droppables and check their positions based on specific tolerance options + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { - // This is a special case where we need to modify a offset calculated on start, since the following happened: - // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent - // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that - // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag - if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { - po.left += this.scrollParent.scrollLeft(); - po.top += this.scrollParent.scrollTop(); - } + if(this.options.disabled || this.greedyChild || !this.visible) return; + var intersects = $.ui.intersect(draggable, this, this.options.tolerance); - if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information - || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix - po = { top: 0, left: 0 }; + var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); + if(!c) return; - return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) - }; + var parentInstance; + if (this.options.greedy) { + // find droppable parents with same scope + var scope = this.options.scope; + var parent = this.element.parents(':data(droppable)').filter(function () { + return $.data(this, 'droppable').options.scope === scope; + }); - }, + if (parent.length) { + parentInstance = $.data(parent[0], 'droppable'); + parentInstance.greedyChild = (c == 'isover' ? 1 : 0); + } + } - _getRelativeOffset: function() { + // we just moved into a greedy child + if (parentInstance && c == 'isover') { + parentInstance['isover'] = 0; + parentInstance['isout'] = 1; + parentInstance._out.call(parentInstance, event); + } - if(this.cssPosition == "relative") { - var p = this.currentItem.position(); - return { - top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), - left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() - }; - } else { - return { top: 0, left: 0 }; - } + this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; + this[c == "isover" ? "_over" : "_out"].call(this, event); - }, + // we just moved out of a greedy child + if (parentInstance && c == 'isout') { + parentInstance['isout'] = 0; + parentInstance['isover'] = 1; + parentInstance._over.call(parentInstance, event); + } + }); - _cacheMargins: function() { - this.margins = { - left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), - top: (parseInt(this.currentItem.css("marginTop"),10) || 0) - }; }, + dragStop: function( draggable, event ) { + draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); + //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) + if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); + } +}; - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() - }; - }, +})(jQuery); +;(jQuery.effects || (function($, undefined) { - _setContainment: function() { +var backCompat = $.uiBackCompat !== false, + // prefix used for storing data on .data() + dataSpace = "ui-effects-"; - var o = this.options; - if(o.containment == 'parent') o.containment = this.helper[0].parentNode; - if(o.containment == 'document' || o.containment == 'window') this.containment = [ - 0 - this.offset.relative.left - this.offset.parent.left, - 0 - this.offset.relative.top - this.offset.parent.top, - $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, - ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top - ]; +$.effects = { + effect: {} +}; - if(!(/^(document|window|parent)$/).test(o.containment)) { - var ce = $(o.containment)[0]; - var co = $(o.containment).offset(); - var over = ($(ce).css("overflow") != 'hidden'); +/*! + * jQuery Color Animations v2.0.0 + * http://jquery.com/ + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * Date: Mon Aug 13 13:41:02 2012 -0500 + */ +(function( jQuery, undefined ) { + + var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "), + + // plusequals test for += 100 -= 100 + rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, + // a set of RE's that can match strings and generate color tuples. + stringParsers = [{ + re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ], + execResult[ 3 ], + execResult[ 4 ] + ]; + } + }, { + re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ] * 2.55, + execResult[ 2 ] * 2.55, + execResult[ 3 ] * 2.55, + execResult[ 4 ] + ]; + } + }, { + // this regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ], 16 ) + ]; + } + }, { + // this regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) + ]; + } + }, { + re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + space: "hsla", + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ] / 100, + execResult[ 3 ] / 100, + execResult[ 4 ] + ]; + } + }], + + // jQuery.Color( ) + color = jQuery.Color = function( color, green, blue, alpha ) { + return new jQuery.Color.fn.parse( color, green, blue, alpha ); + }, + spaces = { + rgba: { + props: { + red: { + idx: 0, + type: "byte" + }, + green: { + idx: 1, + type: "byte" + }, + blue: { + idx: 2, + type: "byte" + } + } + }, - this.containment = [ - co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, - co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, - co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, - co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - ]; + hsla: { + props: { + hue: { + idx: 0, + type: "degrees" + }, + saturation: { + idx: 1, + type: "percent" + }, + lightness: { + idx: 2, + type: "percent" + } + } } - }, + propTypes = { + "byte": { + floor: true, + max: 255 + }, + "percent": { + max: 1 + }, + "degrees": { + mod: 360, + floor: true + } + }, + support = color.support = {}, - _convertPositionTo: function(d, pos) { - - if(!pos) pos = this.position; - var mod = d == "absolute" ? 1 : -1; - var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - return { - top: ( - pos.top // The absolute mouse position - + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent - + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) - - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) - ), - left: ( - pos.left // The absolute mouse position - + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent - + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) - - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) - ) - }; + // element for support tests + supportElem = jQuery( "

      " )[ 0 ], - }, + // colors = jQuery.Color.names + colors, - _generatePosition: function(event) { + // local aliases of functions called often + each = jQuery.each; - var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); +// determine rgba support immediately +supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; +support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; - // This is another very weird special case that only happens for relative elements: - // 1. If the css position is relative - // 2. and the scroll parent is the document or similar to the offset parent - // we have to refresh the relative offset during the scroll so there are no jumps - if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { - this.offset.relative = this._getRelativeOffset(); - } +// define cache name and alpha properties +// for rgba and hsla spaces +each( spaces, function( spaceName, space ) { + space.cache = "_" + spaceName; + space.props.alpha = { + idx: 3, + type: "percent", + def: 1 + }; +}); - var pageX = event.pageX; - var pageY = event.pageY; +function clamp( value, prop, allowEmpty ) { + var type = propTypes[ prop.type ] || {}; - /* - * - Position constraining - - * Constrain the position to a mix of grid, containment. - */ + if ( value == null ) { + return (allowEmpty || !prop.def) ? null : prop.def; + } - if(this.originalPosition) { //If we are not dragging yet, we won't check for options + // ~~ is an short way of doing floor for positive numbers + value = type.floor ? ~~value : parseFloat( value ); - if(this.containment) { - if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; - if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; - if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; - if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; - } + // IE will pass in empty strings as value for alpha, + // which will hit this case + if ( isNaN( value ) ) { + return prop.def; + } - if(o.grid) { - var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; - pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + if ( type.mod ) { + // we add mod before modding to make sure that negatives values + // get converted properly: -10 -> 350 + return (value + type.mod) % type.mod; + } - var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; - pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; - } + // for now all property types without mod have min and max + return 0 > value ? 0 : type.max < value ? type.max : value; +} - } +function stringParse( string ) { + var inst = color(), + rgba = inst._rgba = []; - return { - top: ( - pageY // The absolute mouse position - - this.offset.click.top // Click offset (relative to the element) - - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent - - this.offset.parent.top // The offsetParent's offset without borders (offset + border) - + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) - ), - left: ( - pageX // The absolute mouse position - - this.offset.click.left // Click offset (relative to the element) - - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent - - this.offset.parent.left // The offsetParent's offset without borders (offset + border) - + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) - ) - }; + string = string.toLowerCase(); - }, + each( stringParsers, function( i, parser ) { + var parsed, + match = parser.re.exec( string ), + values = match && parser.parse( match ), + spaceName = parser.space || "rgba"; - _rearrange: function(event, i, a, hardRefresh) { + if ( values ) { + parsed = inst[ spaceName ]( values ); - a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); + // if this was an rgba parse the assignment might happen twice + // oh well.... + inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; + rgba = inst._rgba = parsed._rgba; - //Various things done here to improve the performance: - // 1. we create a setTimeout, that calls refreshPositions - // 2. on the instance, we have a counter variable, that get's higher after every append - // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same - // 4. this lets only the last addition to the timeout stack through - this.counter = this.counter ? ++this.counter : 1; - var self = this, counter = this.counter; + // exit each( stringParsers ) here because we matched + return false; + } + }); - window.setTimeout(function() { - if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove - },0); + // Found a stringParser that handled it + if ( rgba.length ) { - }, + // if this came from a parsed string, force "transparent" when alpha is 0 + // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) + if ( rgba.join() === "0,0,0,0" ) { + jQuery.extend( rgba, colors.transparent ); + } + return inst; + } - _clear: function(event, noPropagation) { + // named colors + return colors[ string ]; +} - this.reverting = false; - // We delay all events that have to be triggered to after the point where the placeholder has been removed and - // everything else normalized again - var delayedTriggers = [], self = this; +color.fn = jQuery.extend( color.prototype, { + parse: function( red, green, blue, alpha ) { + if ( red === undefined ) { + this._rgba = [ null, null, null, null ]; + return this; + } + if ( red.jquery || red.nodeType ) { + red = jQuery( red ).css( green ); + green = undefined; + } - // We first have to update the dom position of the actual currentItem - // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) - if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); - this._noFinalSort = null; + var inst = this, + type = jQuery.type( red ), + rgba = this._rgba = []; - if(this.helper[0] == this.currentItem[0]) { - for(var i in this._storedCSS) { - if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; - } - this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); - } else { - this.currentItem.show(); + // more than 1 argument specified - assume ( red, green, blue, alpha ) + if ( green !== undefined ) { + red = [ red, green, blue, alpha ]; + type = "array"; } - if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); - if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed - if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element - if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); - for (var i = this.containers.length - 1; i >= 0; i--){ - if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) { - delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - } - }; - }; + if ( type === "string" ) { + return this.parse( stringParse( red ) || colors._default ); + } - //Post events to containers - for (var i = this.containers.length - 1; i >= 0; i--){ - if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - if(this.containers[i].containerCache.over) { - delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - this.containers[i].containerCache.over = 0; - } + if ( type === "array" ) { + each( spaces.rgba.props, function( key, prop ) { + rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); + }); + return this; } - //Do what was originally in plugins - if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor - if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity - if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index + if ( type === "object" ) { + if ( red instanceof color ) { + each( spaces, function( spaceName, space ) { + if ( red[ space.cache ] ) { + inst[ space.cache ] = red[ space.cache ].slice(); + } + }); + } else { + each( spaces, function( spaceName, space ) { + var cache = space.cache; + each( space.props, function( key, prop ) { - this.dragging = false; - if(this.cancelHelperRemoval) { - if(!noPropagation) { - this._trigger("beforeStop", event, this._uiHash()); - for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); + // if the cache doesn't exist, and we know how to convert + if ( !inst[ cache ] && space.to ) { + + // if the value was null, we don't need to copy it + // if the key was alpha, we don't need to copy it either + if ( key === "alpha" || red[ key ] == null ) { + return; + } + inst[ cache ] = space.to( inst._rgba ); + } + + // this is the only case where we allow nulls for ALL properties. + // call clamp with alwaysAllowEmpty + inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); + }); + + // everything defined but alpha? + if ( inst[ cache ] && $.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { + // use the default of 1 + inst[ cache ][ 3 ] = 1; + if ( space.from ) { + inst._rgba = space.from( inst[ cache ] ); + } + } + }); } - return false; + return this; } + }, + is: function( compare ) { + var is = color( compare ), + same = true, + inst = this; - if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); + each( spaces, function( _, space ) { + var localCache, + isCache = is[ space.cache ]; + if (isCache) { + localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; + each( space.props, function( _, prop ) { + if ( isCache[ prop.idx ] != null ) { + same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); + return same; + } + }); + } + return same; + }); + return same; + }, + _space: function() { + var used = [], + inst = this; + each( spaces, function( spaceName, space ) { + if ( inst[ space.cache ] ) { + used.push( spaceName ); + } + }); + return used.pop(); + }, + transition: function( other, distance ) { + var end = color( other ), + spaceName = end._space(), + space = spaces[ spaceName ], + startColor = this.alpha() === 0 ? color( "transparent" ) : this, + start = startColor[ space.cache ] || space.to( startColor._rgba ), + result = start.slice(); + + end = end[ space.cache ]; + each( space.props, function( key, prop ) { + var index = prop.idx, + startValue = start[ index ], + endValue = end[ index ], + type = propTypes[ prop.type ] || {}; + + // if null, don't override start value + if ( endValue === null ) { + return; + } + // if null - use end + if ( startValue === null ) { + result[ index ] = endValue; + } else { + if ( type.mod ) { + if ( endValue - startValue > type.mod / 2 ) { + startValue += type.mod; + } else if ( startValue - endValue > type.mod / 2 ) { + startValue -= type.mod; + } + } + result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); + } + }); + return this[ spaceName ]( result ); + }, + blend: function( opaque ) { + // if we are already opaque - return ourself + if ( this._rgba[ 3 ] === 1 ) { + return this; + } - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + var rgb = this._rgba.slice(), + a = rgb.pop(), + blend = color( opaque )._rgba; - if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; + return color( jQuery.map( rgb, function( v, i ) { + return ( 1 - a ) * blend[ i ] + a * v; + })); + }, + toRgbaString: function() { + var prefix = "rgba(", + rgba = jQuery.map( this._rgba, function( v, i ) { + return v == null ? ( i > 2 ? 1 : 0 ) : v; + }); - if(!noPropagation) { - for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); + if ( rgba[ 3 ] === 1 ) { + rgba.pop(); + prefix = "rgb("; } - this.fromOutside = false; - return true; - + return prefix + rgba.join() + ")"; }, + toHslaString: function() { + var prefix = "hsla(", + hsla = jQuery.map( this.hsla(), function( v, i ) { + if ( v == null ) { + v = i > 2 ? 1 : 0; + } - _trigger: function() { - if ($.Widget.prototype._trigger.apply(this, arguments) === false) { - this.cancel(); + // catch 1 and 2 + if ( i && i < 3 ) { + v = Math.round( v * 100 ) + "%"; + } + return v; + }); + + if ( hsla[ 3 ] === 1 ) { + hsla.pop(); + prefix = "hsl("; } + return prefix + hsla.join() + ")"; }, + toHexString: function( includeAlpha ) { + var rgba = this._rgba.slice(), + alpha = rgba.pop(); - _uiHash: function(inst) { - var self = inst || this; - return { - helper: self.helper, - placeholder: self.placeholder || $([]), - position: self.position, - originalPosition: self.originalPosition, - offset: self.positionAbs, - item: self.currentItem, - sender: inst ? inst.element : null - }; - } + if ( includeAlpha ) { + rgba.push( ~~( alpha * 255 ) ); + } -}); + return "#" + jQuery.map( rgba, function( v ) { -$.extend($.ui.sortable, { - version: "1.8.16" + // default to 0 when nulls exist + v = ( v || 0 ).toString( 16 ); + return v.length === 1 ? "0" + v : v; + }).join(""); + }, + toString: function() { + return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); + } }); +color.fn.parse.prototype = color.fn; -})(jQuery); -/* - * jQuery UI Effects 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/ - */ -;jQuery.effects || (function($, undefined) { - -$.effects = {}; +// hsla conversions adapted from: +// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 +function hue2rgb( p, q, h ) { + h = ( h + 1 ) % 1; + if ( h * 6 < 1 ) { + return p + (q - p) * h * 6; + } + if ( h * 2 < 1) { + return q; + } + if ( h * 3 < 2 ) { + return p + (q - p) * ((2/3) - h) * 6; + } + return p; +} +spaces.hsla.to = function ( rgba ) { + if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { + return [ null, null, null, rgba[ 3 ] ]; + } + var r = rgba[ 0 ] / 255, + g = rgba[ 1 ] / 255, + b = rgba[ 2 ] / 255, + a = rgba[ 3 ], + max = Math.max( r, g, b ), + min = Math.min( r, g, b ), + diff = max - min, + add = max + min, + l = add * 0.5, + h, s; + + if ( min === max ) { + h = 0; + } else if ( r === max ) { + h = ( 60 * ( g - b ) / diff ) + 360; + } else if ( g === max ) { + h = ( 60 * ( b - r ) / diff ) + 120; + } else { + h = ( 60 * ( r - g ) / diff ) + 240; + } -/******************************************************************************/ -/****************************** COLOR ANIMATIONS ******************************/ -/******************************************************************************/ + if ( l === 0 || l === 1 ) { + s = l; + } else if ( l <= 0.5 ) { + s = diff / add; + } else { + s = diff / ( 2 - add ); + } + return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; +}; -// override the animation for color styles -$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', - 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'], -function(i, attr) { - $.fx.step[attr] = function(fx) { - if (!fx.colorInit) { - fx.start = getColor(fx.elem, attr); - fx.end = getRGB(fx.end); - fx.colorInit = true; - } +spaces.hsla.from = function ( hsla ) { + if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { + return [ null, null, null, hsla[ 3 ] ]; + } + var h = hsla[ 0 ] / 360, + s = hsla[ 1 ], + l = hsla[ 2 ], + a = hsla[ 3 ], + q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, + p = 2 * l - q; + + return [ + Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), + Math.round( hue2rgb( p, q, h ) * 255 ), + Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), + a + ]; +}; - fx.elem.style[attr] = 'rgb(' + - Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' + - Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' + - Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')'; - }; -}); -// Color Conversion functions from highlightFade -// By Blair Mitchelmore -// http://jquery.offput.ca/highlightFade/ +each( spaces, function( spaceName, space ) { + var props = space.props, + cache = space.cache, + to = space.to, + from = space.from; -// Parse strings looking for color tuples [255,255,255] -function getRGB(color) { - var result; + // makes rgba() and hsla() + color.fn[ spaceName ] = function( value ) { - // Check if we're already dealing with an array of colors - if ( color && color.constructor == Array && color.length == 3 ) - return color; + // generate a cache for this space if it doesn't exist + if ( to && !this[ cache ] ) { + this[ cache ] = to( this._rgba ); + } + if ( value === undefined ) { + return this[ cache ].slice(); + } - // Look for rgb(num,num,num) - if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) - return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)]; + var ret, + type = jQuery.type( value ), + arr = ( type === "array" || type === "object" ) ? value : arguments, + local = this[ cache ].slice(); - // Look for rgb(num%,num%,num%) - if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) - return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; + each( props, function( key, prop ) { + var val = arr[ type === "object" ? key : prop.idx ]; + if ( val == null ) { + val = local[ prop.idx ]; + } + local[ prop.idx ] = clamp( val, prop ); + }); - // Look for #a0b1c2 - if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) - return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; + if ( from ) { + ret = color( from( local ) ); + ret[ cache ] = local; + return ret; + } else { + return color( local ); + } + }; - // Look for #fff - if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) - return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; + // makes red() green() blue() alpha() hue() saturation() lightness() + each( props, function( key, prop ) { + // alpha is included in more than one space + if ( color.fn[ key ] ) { + return; + } + color.fn[ key ] = function( value ) { + var vtype = jQuery.type( value ), + fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), + local = this[ fn ](), + cur = local[ prop.idx ], + match; - // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 - if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) - return colors['transparent']; + if ( vtype === "undefined" ) { + return cur; + } - // Otherwise, we're most likely dealing with a named color - return colors[$.trim(color).toLowerCase()]; -} + if ( vtype === "function" ) { + value = value.call( this, cur ); + vtype = jQuery.type( value ); + } + if ( value == null && prop.empty ) { + return this; + } + if ( vtype === "string" ) { + match = rplusequals.exec( value ); + if ( match ) { + value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); + } + } + local[ prop.idx ] = value; + return this[ fn ]( local ); + }; + }); +}); -function getColor(elem, attr) { - var color; +// add .fx.step functions +each( stepHooks, function( i, hook ) { + jQuery.cssHooks[ hook ] = { + set: function( elem, value ) { + var parsed, curElem, + backgroundColor = ""; + + if ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) { + value = color( parsed || value ); + if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { + curElem = hook === "backgroundColor" ? elem.parentNode : elem; + while ( + (backgroundColor === "" || backgroundColor === "transparent") && + curElem && curElem.style + ) { + try { + backgroundColor = jQuery.css( curElem, "backgroundColor" ); + curElem = curElem.parentNode; + } catch ( e ) { + } + } - do { - color = $.curCSS(elem, attr); + value = value.blend( backgroundColor && backgroundColor !== "transparent" ? + backgroundColor : + "_default" ); + } - // Keep going until we find an element that has color, or we hit the body - if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") ) - break; + value = value.toRgbaString(); + } + try { + elem.style[ hook ] = value; + } catch( error ) { + // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' + } + } + }; + jQuery.fx.step[ hook ] = function( fx ) { + if ( !fx.colorInit ) { + fx.start = color( fx.elem, hook ); + fx.end = color( fx.end ); + fx.colorInit = true; + } + jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); + }; +}); - attr = "backgroundColor"; - } while ( elem = elem.parentNode ); +jQuery.cssHooks.borderColor = { + expand: function( value ) { + var expanded = {}; - return getRGB(color); + each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { + expanded[ "border" + part + "Color" ] = value; + }); + return expanded; + } }; -// Some named colors to work with -// From Interface by Stefan Petre -// http://interface.eyecon.ro/ - -var colors = { - aqua:[0,255,255], - azure:[240,255,255], - beige:[245,245,220], - black:[0,0,0], - blue:[0,0,255], - brown:[165,42,42], - cyan:[0,255,255], - darkblue:[0,0,139], - darkcyan:[0,139,139], - darkgrey:[169,169,169], - darkgreen:[0,100,0], - darkkhaki:[189,183,107], - darkmagenta:[139,0,139], - darkolivegreen:[85,107,47], - darkorange:[255,140,0], - darkorchid:[153,50,204], - darkred:[139,0,0], - darksalmon:[233,150,122], - darkviolet:[148,0,211], - fuchsia:[255,0,255], - gold:[255,215,0], - green:[0,128,0], - indigo:[75,0,130], - khaki:[240,230,140], - lightblue:[173,216,230], - lightcyan:[224,255,255], - lightgreen:[144,238,144], - lightgrey:[211,211,211], - lightpink:[255,182,193], - lightyellow:[255,255,224], - lime:[0,255,0], - magenta:[255,0,255], - maroon:[128,0,0], - navy:[0,0,128], - olive:[128,128,0], - orange:[255,165,0], - pink:[255,192,203], - purple:[128,0,128], - violet:[128,0,128], - red:[255,0,0], - silver:[192,192,192], - white:[255,255,255], - yellow:[255,255,0], - transparent: [255,255,255] +// Basic color names only. +// Usage of any of the other color names requires adding yourself or including +// jquery.color.svg-names.js. +colors = jQuery.Color.names = { + // 4.1. Basic color keywords + aqua: "#00ffff", + black: "#000000", + blue: "#0000ff", + fuchsia: "#ff00ff", + gray: "#808080", + green: "#008000", + lime: "#00ff00", + maroon: "#800000", + navy: "#000080", + olive: "#808000", + purple: "#800080", + red: "#ff0000", + silver: "#c0c0c0", + teal: "#008080", + white: "#ffffff", + yellow: "#ffff00", + + // 4.2.3. "transparent" color keyword + transparent: [ null, null, null, 0 ], + + _default: "#ffffff" }; +})( jQuery ); + /******************************************************************************/ /****************************** CLASS ANIMATIONS ******************************/ /******************************************************************************/ +(function() { -var classAnimationActions = ['add', 'remove', 'toggle'], +var classAnimationActions = [ "add", "remove", "toggle" ], shorthandStyles = { border: 1, borderBottom: 1, @@ -4207,199 +7693,253 @@ var classAnimationActions = ['add', 'remove', 'toggle'], padding: 1 }; +$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { + $.fx.step[ prop ] = function( fx ) { + if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { + jQuery.style( fx.elem, prop, fx.end ); + fx.setAttr = true; + } + }; +}); + function getElementStyles() { - var style = document.defaultView - ? document.defaultView.getComputedStyle(this, null) - : this.currentStyle, + var style = this.ownerDocument.defaultView ? + this.ownerDocument.defaultView.getComputedStyle( this, null ) : + this.currentStyle, newStyle = {}, key, - camelCase; + len; // webkit enumerates style porperties - if (style && style.length && style[0] && style[style[0]]) { - var len = style.length; - while (len--) { - key = style[len]; - if (typeof style[key] == 'string') { - camelCase = key.replace(/\-(\w)/g, function(all, letter){ - return letter.toUpperCase(); - }); - newStyle[camelCase] = style[key]; + if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { + len = style.length; + while ( len-- ) { + key = style[ len ]; + if ( typeof style[ key ] === "string" ) { + newStyle[ $.camelCase( key ) ] = style[ key ]; } } } else { - for (key in style) { - if (typeof style[key] === 'string') { - newStyle[key] = style[key]; + for ( key in style ) { + if ( typeof style[ key ] === "string" ) { + newStyle[ key ] = style[ key ]; } } } - + return newStyle; } -function filterStyles(styles) { - var name, value; - for (name in styles) { - value = styles[name]; - if ( - // ignore null and undefined values - value == null || - // ignore functions (when does this occur?) - $.isFunction(value) || - // shorthand styles that need to be expanded - name in shorthandStyles || - // ignore scrollbars (break in IE) - (/scrollbar/).test(name) || - - // only colors or values that can be converted to numbers - (!(/color/i).test(name) && isNaN(parseFloat(value))) - ) { - delete styles[name]; - } - } - - return styles; -} -function styleDifference(oldStyle, newStyle) { - var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459 - name; +function styleDifference( oldStyle, newStyle ) { + var diff = {}, + name, value; - for (name in newStyle) { - if (oldStyle[name] != newStyle[name]) { - diff[name] = newStyle[name]; + for ( name in newStyle ) { + value = newStyle[ name ]; + if ( oldStyle[ name ] !== value ) { + if ( !shorthandStyles[ name ] ) { + if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { + diff[ name ] = value; + } + } } } return diff; } -$.effects.animateClass = function(value, duration, easing, callback) { - if ($.isFunction(easing)) { - callback = easing; - easing = null; - } +$.effects.animateClass = function( value, duration, easing, callback ) { + var o = $.speed( duration, easing, callback ); - return this.queue(function() { - var that = $(this), - originalStyleAttr = that.attr('style') || ' ', - originalStyle = filterStyles(getElementStyles.call(this)), - newStyle, - className = that.attr('class'); + return this.queue( function() { + var animated = $( this ), + baseClass = animated.attr( "class" ) || "", + applyClassChange, + allAnimations = o.children ? animated.find( "*" ).andSelf() : animated; - $.each(classAnimationActions, function(i, action) { - if (value[action]) { - that[action + 'Class'](value[action]); - } + // map the animated objects to store the original styles. + allAnimations = allAnimations.map(function() { + var el = $( this ); + return { + el: el, + start: getElementStyles.call( this ) + }; }); - newStyle = filterStyles(getElementStyles.call(this)); - that.attr('class', className); - that.animate(styleDifference(originalStyle, newStyle), { - queue: false, - duration: duration, - easing: easing, - complete: function() { - $.each(classAnimationActions, function(i, action) { - if (value[action]) { that[action + 'Class'](value[action]); } - }); - // work around bug in IE by clearing the cssText before setting it - if (typeof that.attr('style') == 'object') { - that.attr('style').cssText = ''; - that.attr('style').cssText = originalStyleAttr; - } else { - that.attr('style', originalStyleAttr); + // apply class change + applyClassChange = function() { + $.each( classAnimationActions, function(i, action) { + if ( value[ action ] ) { + animated[ action + "Class" ]( value[ action ] ); } - if (callback) { callback.apply(this, arguments); } - $.dequeue( this ); - } + }); + }; + applyClassChange(); + + // map all animated objects again - calculate new styles and diff + allAnimations = allAnimations.map(function() { + this.end = getElementStyles.call( this.el[ 0 ] ); + this.diff = styleDifference( this.start, this.end ); + return this; + }); + + // apply original class + animated.attr( "class", baseClass ); + + // map all animated objects again - this time collecting a promise + allAnimations = allAnimations.map(function() { + var styleInfo = this, + dfd = $.Deferred(), + opts = jQuery.extend({}, o, { + queue: false, + complete: function() { + dfd.resolve( styleInfo ); + } + }); + + this.el.animate( this.diff, opts ); + return dfd.promise(); + }); + + // once all animations have completed: + $.when.apply( $, allAnimations.get() ).done(function() { + + // set the final class + applyClassChange(); + + // for each animated element, + // clear all css properties that were animated + $.each( arguments, function() { + var el = this.el; + $.each( this.diff, function(key) { + el.css( key, '' ); + }); + }); + + // this is guarnteed to be there if you use jQuery.speed() + // it also handles dequeuing the next anim... + o.complete.call( animated[ 0 ] ); }); }); }; $.fn.extend({ _addClass: $.fn.addClass, - addClass: function(classNames, speed, easing, callback) { - return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames); + addClass: function( classNames, speed, easing, callback ) { + return speed ? + $.effects.animateClass.call( this, + { add: classNames }, speed, easing, callback ) : + this._addClass( classNames ); }, _removeClass: $.fn.removeClass, - removeClass: function(classNames,speed,easing,callback) { - return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames); + removeClass: function( classNames, speed, easing, callback ) { + return speed ? + $.effects.animateClass.call( this, + { remove: classNames }, speed, easing, callback ) : + this._removeClass( classNames ); }, _toggleClass: $.fn.toggleClass, - toggleClass: function(classNames, force, speed, easing, callback) { - if ( typeof force == "boolean" || force === undefined ) { + toggleClass: function( classNames, force, speed, easing, callback ) { + if ( typeof force === "boolean" || force === undefined ) { if ( !speed ) { - // without speed parameter; - return this._toggleClass(classNames, force); + // without speed parameter + return this._toggleClass( classNames, force ); } else { - return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]); + return $.effects.animateClass.call( this, + (force ? { add: classNames } : { remove: classNames }), + speed, easing, callback ); } } else { - // without switch parameter; - return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]); + // without force parameter + return $.effects.animateClass.call( this, + { toggle: classNames }, force, speed, easing ); } }, - switchClass: function(remove,add,speed,easing,callback) { - return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]); + switchClass: function( remove, add, speed, easing, callback) { + return $.effects.animateClass.call( this, { + add: add, + remove: remove + }, speed, easing, callback ); } }); - +})(); /******************************************************************************/ /*********************************** EFFECTS **********************************/ /******************************************************************************/ -$.extend($.effects, { - version: "1.8.16", +(function() { + +$.extend( $.effects, { + version: "1.9.2", // Saves a set of properties in a data storage - save: function(element, set) { - for(var i=0; i < set.length; i++) { - if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]); + save: function( element, set ) { + for( var i=0; i < set.length; i++ ) { + if ( set[ i ] !== null ) { + element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); + } } }, // Restores a set of previously saved properties from a data storage - restore: function(element, set) { - for(var i=0; i < set.length; i++) { - if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i])); + restore: function( element, set ) { + var val, i; + for( i=0; i < set.length; i++ ) { + if ( set[ i ] !== null ) { + val = element.data( dataSpace + set[ i ] ); + // support: jQuery 1.6.2 + // http://bugs.jquery.com/ticket/9917 + // jQuery 1.6.2 incorrectly returns undefined for any falsy value. + // We can't differentiate between "" and 0 here, so we just assume + // empty string since it's likely to be a more common value... + if ( val === undefined ) { + val = ""; + } + element.css( set[ i ], val ); + } } }, - setMode: function(el, mode) { - if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle + setMode: function( el, mode ) { + if (mode === "toggle") { + mode = el.is( ":hidden" ) ? "show" : "hide"; + } return mode; }, - getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value - // this should be a little more flexible in the future to handle a string & hash + // Translates a [top,left] array into a baseline value + // this should be a little more flexible in the future to handle a string & hash + getBaseline: function( origin, original ) { var y, x; - switch (origin[0]) { - case 'top': y = 0; break; - case 'middle': y = 0.5; break; - case 'bottom': y = 1; break; - default: y = origin[0] / original.height; - }; - switch (origin[1]) { - case 'left': x = 0; break; - case 'center': x = 0.5; break; - case 'right': x = 1; break; - default: x = origin[1] / original.width; + switch ( origin[ 0 ] ) { + case "top": y = 0; break; + case "middle": y = 0.5; break; + case "bottom": y = 1; break; + default: y = origin[ 0 ] / original.height; + } + switch ( origin[ 1 ] ) { + case "left": x = 0; break; + case "center": x = 0.5; break; + case "right": x = 1; break; + default: x = origin[ 1 ] / original.width; + } + return { + x: x, + y: y }; - return {x: x, y: y}; }, // Wraps the element around a wrapper that copies position properties - createWrapper: function(element) { + createWrapper: function( element ) { // if the element is already wrapped, return it - if (element.parent().is('.ui-effects-wrapper')) { + if ( element.parent().is( ".ui-effects-wrapper" )) { return element.parent(); } @@ -4407,108 +7947,149 @@ $.extend($.effects, { var props = { width: element.outerWidth(true), height: element.outerHeight(true), - 'float': element.css('float') + "float": element.css( "float" ) }, - wrapper = $('

      ') - .addClass('ui-effects-wrapper') + wrapper = $( "
      " ) + .addClass( "ui-effects-wrapper" ) .css({ - fontSize: '100%', - background: 'transparent', - border: 'none', + fontSize: "100%", + background: "transparent", + border: "none", margin: 0, padding: 0 }), + // Store the size in case width/height are defined in % - Fixes #5245 + size = { + width: element.width(), + height: element.height() + }, active = document.activeElement; - element.wrap(wrapper); + // support: Firefox + // Firefox incorrectly exposes anonymous content + // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 + try { + active.id; + } catch( e ) { + active = document.body; + } + + element.wrap( wrapper ); // Fixes #7595 - Elements lose focus when wrapped. if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { $( active ).focus(); } - - wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element + + wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element // transfer positioning properties to the wrapper - if (element.css('position') == 'static') { - wrapper.css({ position: 'relative' }); - element.css({ position: 'relative' }); + if ( element.css( "position" ) === "static" ) { + wrapper.css({ position: "relative" }); + element.css({ position: "relative" }); } else { - $.extend(props, { - position: element.css('position'), - zIndex: element.css('z-index') + $.extend( props, { + position: element.css( "position" ), + zIndex: element.css( "z-index" ) }); - $.each(['top', 'left', 'bottom', 'right'], function(i, pos) { - props[pos] = element.css(pos); - if (isNaN(parseInt(props[pos], 10))) { - props[pos] = 'auto'; + $.each([ "top", "left", "bottom", "right" ], function(i, pos) { + props[ pos ] = element.css( pos ); + if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { + props[ pos ] = "auto"; } }); - element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' }); + element.css({ + position: "relative", + top: 0, + left: 0, + right: "auto", + bottom: "auto" + }); } + element.css(size); - return wrapper.css(props).show(); + return wrapper.css( props ).show(); }, - removeWrapper: function(element) { - var parent, - active = document.activeElement; - - if (element.parent().is('.ui-effects-wrapper')) { - parent = element.parent().replaceWith(element); + removeWrapper: function( element ) { + var active = document.activeElement; + + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + element.parent().replaceWith( element ); + // Fixes #7595 - Elements lose focus when wrapped. if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { $( active ).focus(); } - return parent; } - + + return element; }, - setTransition: function(element, list, factor, value) { + setTransition: function( element, list, factor, value ) { value = value || {}; - $.each(list, function(i, x){ - unit = element.cssUnit(x); - if (unit[0] > 0) value[x] = unit[0] * factor + unit[1]; + $.each( list, function( i, x ) { + var unit = element.cssUnit( x ); + if ( unit[ 0 ] > 0 ) { + value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; + } }); return value; } }); +// return an effect options object for the given parameters: +function _normalizeArguments( effect, options, speed, callback ) { -function _normalizeArguments(effect, options, speed, callback) { - // shift params for method overloading - if (typeof effect == 'object') { - callback = options; - speed = null; + // allow passing all options as the first parameter + if ( $.isPlainObject( effect ) ) { options = effect; - effect = options.effect; + effect = effect.effect; + } + + // convert to an object + effect = { effect: effect }; + + // catch (effect, null, ...) + if ( options == null ) { + options = {}; } - if ($.isFunction(options)) { + + // catch (effect, callback) + if ( $.isFunction( options ) ) { callback = options; speed = null; options = {}; } - if (typeof options == 'number' || $.fx.speeds[options]) { + + // catch (effect, speed, ?) + if ( typeof options === "number" || $.fx.speeds[ options ] ) { callback = speed; speed = options; options = {}; } - if ($.isFunction(speed)) { + + // catch (effect, options, callback) + if ( $.isFunction( speed ) ) { callback = speed; speed = null; } - options = options || {}; + // add options to effect + if ( options ) { + $.extend( effect, options ); + } speed = speed || options.duration; - speed = $.fx.off ? 0 : typeof speed == 'number' - ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default; + effect.duration = $.fx.off ? 0 : + typeof speed === "number" ? speed : + speed in $.fx.speeds ? $.fx.speeds[ speed ] : + $.fx.speeds._default; - callback = callback || options.complete; + effect.complete = callback || options.complete; - return [effect, options, speed, callback]; + return effect; } function standardSpeed( speed ) { @@ -4516,7252 +8097,6783 @@ function standardSpeed( speed ) { if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { return true; } - + // invalid strings - treat as "normal" speed - if ( typeof speed === "string" && !$.effects[ speed ] ) { + if ( typeof speed === "string" && !$.effects.effect[ speed ] ) { + // TODO: remove in 2.0 (#7115) + if ( backCompat && $.effects[ speed ] ) { + return false; + } return true; } - + return false; } $.fn.extend({ - effect: function(effect, options, speed, callback) { - var args = _normalizeArguments.apply(this, arguments), - // TODO: make effects take actual parameters instead of a hash - args2 = { - options: args[1], - duration: args[2], - callback: args[3] - }, - mode = args2.options.mode, - effectMethod = $.effects[effect]; - - if ( $.fx.off || !effectMethod ) { + effect: function( /* effect, options, speed, callback */ ) { + var args = _normalizeArguments.apply( this, arguments ), + mode = args.mode, + queue = args.queue, + effectMethod = $.effects.effect[ args.effect ], + + // DEPRECATED: remove in 2.0 (#7115) + oldEffectMethod = !effectMethod && backCompat && $.effects[ args.effect ]; + + if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) { // delegate to the original method (e.g., .show()) if possible if ( mode ) { - return this[ mode ]( args2.duration, args2.callback ); + return this[ mode ]( args.duration, args.complete ); } else { - return this.each(function() { - if ( args2.callback ) { - args2.callback.call( this ); + return this.each( function() { + if ( args.complete ) { + args.complete.call( this ); } }); } } - - return effectMethod.call(this, args2); + + function run( next ) { + var elem = $( this ), + complete = args.complete, + mode = args.mode; + + function done() { + if ( $.isFunction( complete ) ) { + complete.call( elem[0] ); + } + if ( $.isFunction( next ) ) { + next(); + } + } + + // if the element is hiddden and mode is hide, + // or element is visible and mode is show + if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { + done(); + } else { + effectMethod.call( elem[0], args, done ); + } + } + + // TODO: remove this check in 2.0, effectMethod will always be true + if ( effectMethod ) { + return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); + } else { + // DEPRECATED: remove in 2.0 (#7115) + return oldEffectMethod.call(this, { + options: args, + duration: args.duration, + callback: args.complete, + mode: args.mode + }); + } }, _show: $.fn.show, - show: function(speed) { + show: function( speed ) { if ( standardSpeed( speed ) ) { - return this._show.apply(this, arguments); + return this._show.apply( this, arguments ); } else { - var args = _normalizeArguments.apply(this, arguments); - args[1].mode = 'show'; - return this.effect.apply(this, args); + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "show"; + return this.effect.call( this, args ); } }, _hide: $.fn.hide, - hide: function(speed) { + hide: function( speed ) { if ( standardSpeed( speed ) ) { - return this._hide.apply(this, arguments); + return this._hide.apply( this, arguments ); } else { - var args = _normalizeArguments.apply(this, arguments); - args[1].mode = 'hide'; - return this.effect.apply(this, args); + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "hide"; + return this.effect.call( this, args ); } }, // jQuery core overloads toggle and creates _toggle __toggle: $.fn.toggle, - toggle: function(speed) { + toggle: function( speed ) { if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) { - return this.__toggle.apply(this, arguments); + return this.__toggle.apply( this, arguments ); } else { - var args = _normalizeArguments.apply(this, arguments); - args[1].mode = 'toggle'; - return this.effect.apply(this, args); + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "toggle"; + return this.effect.call( this, args ); } }, // helper functions cssUnit: function(key) { - var style = this.css(key), val = []; - $.each( ['em','px','%','pt'], function(i, unit){ - if(style.indexOf(unit) > 0) - val = [parseFloat(style), unit]; + var style = this.css( key ), + val = []; + + $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { + if ( style.indexOf( unit ) > 0 ) { + val = [ parseFloat( style ), unit ]; + } }); return val; } }); - +})(); /******************************************************************************/ /*********************************** EASING ***********************************/ /******************************************************************************/ -/* - * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ - * - * Uses the built in easing capabilities added In jQuery 1.1 - * to offer multiple easing options - * - * TERMS OF USE - jQuery Easing - * - * Open source under the BSD License. - * - * Copyright 2008 George McGinley Smith - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * Neither the name of the author nor the names of contributors may be used to endorse - * or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ +(function() { -// t: current time, b: begInnIng value, c: change In value, d: duration -$.easing.jswing = $.easing.swing; +// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) -$.extend($.easing, -{ - def: 'easeOutQuad', - swing: function (x, t, b, c, d) { - //alert($.easing.default); - return $.easing[$.easing.def](x, t, b, c, d); - }, - easeInQuad: function (x, t, b, c, d) { - return c*(t/=d)*t + b; - }, - easeOutQuad: function (x, t, b, c, d) { - return -c *(t/=d)*(t-2) + b; - }, - easeInOutQuad: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t + b; - return -c/2 * ((--t)*(t-2) - 1) + b; - }, - easeInCubic: function (x, t, b, c, d) { - return c*(t/=d)*t*t + b; - }, - easeOutCubic: function (x, t, b, c, d) { - return c*((t=t/d-1)*t*t + 1) + b; - }, - easeInOutCubic: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t*t + b; - return c/2*((t-=2)*t*t + 2) + b; - }, - easeInQuart: function (x, t, b, c, d) { - return c*(t/=d)*t*t*t + b; - }, - easeOutQuart: function (x, t, b, c, d) { - return -c * ((t=t/d-1)*t*t*t - 1) + b; - }, - easeInOutQuart: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t*t*t + b; - return -c/2 * ((t-=2)*t*t*t - 2) + b; - }, - easeInQuint: function (x, t, b, c, d) { - return c*(t/=d)*t*t*t*t + b; - }, - easeOutQuint: function (x, t, b, c, d) { - return c*((t=t/d-1)*t*t*t*t + 1) + b; - }, - easeInOutQuint: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; - return c/2*((t-=2)*t*t*t*t + 2) + b; - }, - easeInSine: function (x, t, b, c, d) { - return -c * Math.cos(t/d * (Math.PI/2)) + c + b; - }, - easeOutSine: function (x, t, b, c, d) { - return c * Math.sin(t/d * (Math.PI/2)) + b; - }, - easeInOutSine: function (x, t, b, c, d) { - return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; - }, - easeInExpo: function (x, t, b, c, d) { - return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; - }, - easeOutExpo: function (x, t, b, c, d) { - return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; - }, - easeInOutExpo: function (x, t, b, c, d) { - if (t==0) return b; - if (t==d) return b+c; - if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; - return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; - }, - easeInCirc: function (x, t, b, c, d) { - return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; - }, - easeOutCirc: function (x, t, b, c, d) { - return c * Math.sqrt(1 - (t=t/d-1)*t) + b; - }, - easeInOutCirc: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; - return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; - }, - easeInElastic: function (x, t, b, c, d) { - var s=1.70158;var p=0;var a=c; - if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; - if (a < Math.abs(c)) { a=c; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (c/a); - return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; +var baseEasings = {}; + +$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { + baseEasings[ name ] = function( p ) { + return Math.pow( p, i + 2 ); + }; +}); + +$.extend( baseEasings, { + Sine: function ( p ) { + return 1 - Math.cos( p * Math.PI / 2 ); }, - easeOutElastic: function (x, t, b, c, d) { - var s=1.70158;var p=0;var a=c; - if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; - if (a < Math.abs(c)) { a=c; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (c/a); - return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; + Circ: function ( p ) { + return 1 - Math.sqrt( 1 - p * p ); }, - easeInOutElastic: function (x, t, b, c, d) { - var s=1.70158;var p=0;var a=c; - if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); - if (a < Math.abs(c)) { a=c; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (c/a); - if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; - return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; - }, - easeInBack: function (x, t, b, c, d, s) { - if (s == undefined) s = 1.70158; - return c*(t/=d)*t*((s+1)*t - s) + b; - }, - easeOutBack: function (x, t, b, c, d, s) { - if (s == undefined) s = 1.70158; - return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; - }, - easeInOutBack: function (x, t, b, c, d, s) { - if (s == undefined) s = 1.70158; - if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; - return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; + Elastic: function( p ) { + return p === 0 || p === 1 ? p : + -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); }, - easeInBounce: function (x, t, b, c, d) { - return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b; - }, - easeOutBounce: function (x, t, b, c, d) { - if ((t/=d) < (1/2.75)) { - return c*(7.5625*t*t) + b; - } else if (t < (2/2.75)) { - return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; - } else if (t < (2.5/2.75)) { - return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; - } else { - return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; - } + Back: function( p ) { + return p * p * ( 3 * p - 2 ); }, - easeInOutBounce: function (x, t, b, c, d) { - if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; - return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; + Bounce: function ( p ) { + var pow2, + bounce = 4; + + while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} + return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); } }); -/* - * - * TERMS OF USE - EASING EQUATIONS - * - * Open source under the BSD License. - * - * Copyright 2001 Robert Penner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * Neither the name of the author nor the names of contributors may be used to endorse - * or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ +$.each( baseEasings, function( name, easeIn ) { + $.easing[ "easeIn" + name ] = easeIn; + $.easing[ "easeOut" + name ] = function( p ) { + return 1 - easeIn( 1 - p ); + }; + $.easing[ "easeInOut" + name ] = function( p ) { + return p < 0.5 ? + easeIn( p * 2 ) / 2 : + 1 - easeIn( p * -2 + 2 ) / 2; + }; +}); + +})(); + +})(jQuery)); +(function( $, undefined ) { + +var rvertical = /up|down|vertical/, + rpositivemotion = /up|left|vertical|horizontal/; + +$.effects.effect.blind = function( o, done ) { + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + direction = o.direction || "up", + vertical = rvertical.test( direction ), + ref = vertical ? "height" : "width", + ref2 = vertical ? "top" : "left", + motion = rpositivemotion.test( direction ), + animation = {}, + show = mode === "show", + wrapper, distance, margin; + + // if already wrapped, the wrapper's properties are my property. #6245 + if ( el.parent().is( ".ui-effects-wrapper" ) ) { + $.effects.save( el.parent(), props ); + } else { + $.effects.save( el, props ); + } + el.show(); + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + + distance = wrapper[ ref ](); + margin = parseFloat( wrapper.css( ref2 ) ) || 0; + + animation[ ref ] = show ? distance : 0; + if ( !motion ) { + el + .css( vertical ? "bottom" : "right", 0 ) + .css( vertical ? "top" : "left", "auto" ) + .css({ position: "absolute" }); + + animation[ ref2 ] = show ? margin : distance + margin; + } + + // start at 0 if we are showing + if ( show ) { + wrapper.css( ref, 0 ); + if ( ! motion ) { + wrapper.css( ref2, margin + distance ); + } + } + + // Animate + wrapper.animate( animation, { + duration: o.duration, + easing: o.easing, + queue: false, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); + +}; })(jQuery); -/* - * jQuery UI Effects Blind 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Blind - * - * Depends: - * jquery.effects.core.js - */ (function( $, undefined ) { -$.effects.blind = function(o) { +$.effects.effect.bounce = function( o, done ) { + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + + // defaults: + mode = $.effects.setMode( el, o.mode || "effect" ), + hide = mode === "hide", + show = mode === "show", + direction = o.direction || "up", + distance = o.distance, + times = o.times || 5, + + // number of internal animations + anims = times * 2 + ( show || hide ? 1 : 0 ), + speed = o.duration / anims, + easing = o.easing, + + // utility: + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ), + i, + upAnim, + downAnim, + + // we will need to re-assemble the queue to stack our animations in place + queue = el.queue(), + queuelen = queue.length; + + // Avoid touching opacity to prevent clearType and PNG issues in IE + if ( show || hide ) { + props.push( "opacity" ); + } + + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); // Create Wrapper - return this.queue(function() { + // default distance for the BIGGEST bounce is the outer Distance / 3 + if ( !distance ) { + distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; + } - // Create element - var el = $(this), props = ['position','top','bottom','left','right']; + if ( show ) { + downAnim = { opacity: 1 }; + downAnim[ ref ] = 0; - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode - var direction = o.options.direction || 'vertical'; // Default direction - - // Adjust - $.effects.save(el, props); el.show(); // Save & Show - var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper - var ref = (direction == 'vertical') ? 'height' : 'width'; - var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width(); - if(mode == 'show') wrapper.css(ref, 0); // Shift - - // Animation - var animation = {}; - animation[ref] = mode == 'show' ? distance : 0; - - // Animate - wrapper.animate(animation, o.duration, o.options.easing, function() { - if(mode == 'hide') el.hide(); // Hide - $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(el[0], arguments); // Callback - el.dequeue(); - }); + // if we are showing, force opacity 0 and set the initial position + // then do the "first" animation + el.css( "opacity", 0 ) + .css( ref, motion ? -distance * 2 : distance * 2 ) + .animate( downAnim, speed, easing ); + } + + // start at the smallest distance if we are hiding + if ( hide ) { + distance = distance / Math.pow( 2, times - 1 ); + } + + downAnim = {}; + downAnim[ ref ] = 0; + // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here + for ( i = 0; i < times; i++ ) { + upAnim = {}; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + el.animate( upAnim, speed, easing ) + .animate( downAnim, speed, easing ); + + distance = hide ? distance * 2 : distance / 2; + } + + // Last Bounce when Hiding + if ( hide ) { + upAnim = { opacity: 0 }; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + el.animate( upAnim, speed, easing ); + } + + el.queue(function() { + if ( hide ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); }); + // inject all the animations we just queued to be first in line (after "inprogress") + if ( queuelen > 1) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + el.dequeue(); + }; })(jQuery); -/* - * jQuery UI Effects Bounce 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Bounce - * - * Depends: - * jquery.effects.core.js - */ (function( $, undefined ) { -$.effects.bounce = function(o) { +$.effects.effect.clip = function( o, done ) { + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + direction = o.direction || "vertical", + vert = direction === "vertical", + size = vert ? "height" : "width", + position = vert ? "top" : "left", + animation = {}, + wrapper, animate, distance; + + // Save & Show + $.effects.save( el, props ); + el.show(); + + // Create Wrapper + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + animate = ( el[0].tagName === "IMG" ) ? wrapper : el; + distance = animate[ size ](); - return this.queue(function() { + // Shift + if ( show ) { + animate.css( size, 0 ); + animate.css( position, distance / 2 ); + } - // Create element - var el = $(this), props = ['position','top','bottom','left','right']; + // Create Animation Object: + animation[ size ] = show ? distance : 0; + animation[ position ] = show ? 0 : distance / 2; - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode - var direction = o.options.direction || 'up'; // Default direction - var distance = o.options.distance || 20; // Default distance - var times = o.options.times || 5; // Default # of times - var speed = o.duration || 250; // Default speed per bounce - if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE - - // Adjust - $.effects.save(el, props); el.show(); // Save & Show - $.effects.createWrapper(el); // Create Wrapper - var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; - var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; - var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3); - if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift - if (mode == 'hide') distance = distance / (times * 2); - if (mode != 'hide') times--; - - // Animate - if (mode == 'show') { // Show Bounce - var animation = {opacity: 1}; - animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance; - el.animate(animation, speed / 2, o.options.easing); - distance = distance / 2; - times--; - }; - for (var i = 0; i < times; i++) { // Bounces - var animation1 = {}, animation2 = {}; - animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; - animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; - el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing); - distance = (mode == 'hide') ? distance * 2 : distance / 2; - }; - if (mode == 'hide') { // Last Bounce - var animation = {opacity: 0}; - animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; - el.animate(animation, speed / 2, o.options.easing, function(){ - el.hide(); // Hide - $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(this, arguments); // Callback - }); - } else { - var animation1 = {}, animation2 = {}; - animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; - animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; - el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){ - $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(this, arguments); // Callback - }); - }; - el.queue('fx', function() { el.dequeue(); }); - el.dequeue(); + // Animate + animate.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( !show ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } }); }; })(jQuery); -/* - * jQuery UI Effects Clip 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Clip - * - * Depends: - * jquery.effects.core.js - */ (function( $, undefined ) { -$.effects.clip = function(o) { +$.effects.effect.drop = function( o, done ) { + + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + direction = o.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", + animation = { + opacity: show ? 1 : 0 + }, + distance; + + // Adjust + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + + distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; + + if ( show ) { + el + .css( "opacity", 0 ) + .css( ref, motion === "pos" ? -distance : distance ); + } + + // Animation + animation[ ref ] = ( show ? + ( motion === "pos" ? "+=" : "-=" ) : + ( motion === "pos" ? "-=" : "+=" ) ) + + distance; + + // Animate + el.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); +}; + +})(jQuery); +(function( $, undefined ) { + +$.effects.effect.explode = function( o, done ) { + + var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, + cells = rows, + el = $( this ), + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + + // show and then visibility:hidden the element before calculating offset + offset = el.show().css( "visibility", "hidden" ).offset(), + + // width and height of a piece + width = Math.ceil( el.outerWidth() / cells ), + height = Math.ceil( el.outerHeight() / rows ), + pieces = [], + + // loop + i, j, left, top, mx, my; + + // children animate complete: + function childComplete() { + pieces.push( this ); + if ( pieces.length === rows * cells ) { + animComplete(); + } + } + + // clone the element for each row and cell. + for( i = 0; i < rows ; i++ ) { // ===> + top = offset.top + i * height; + my = i - ( rows - 1 ) / 2 ; + + for( j = 0; j < cells ; j++ ) { // ||| + left = offset.left + j * width; + mx = j - ( cells - 1 ) / 2 ; + + // Create a clone of the now hidden main element that will be absolute positioned + // within a wrapper div off the -left and -top equal to size of our pieces + el + .clone() + .appendTo( "body" ) + .wrap( "
      " ) + .css({ + position: "absolute", + visibility: "visible", + left: -j * width, + top: -i * height + }) + + // select the wrapper - make it overflow: hidden and absolute positioned based on + // where the original was located +left and +top equal to the size of pieces + .parent() + .addClass( "ui-effects-explode" ) + .css({ + position: "absolute", + overflow: "hidden", + width: width, + height: height, + left: left + ( show ? mx * width : 0 ), + top: top + ( show ? my * height : 0 ), + opacity: show ? 0 : 1 + }).animate({ + left: left + ( show ? 0 : mx * width ), + top: top + ( show ? 0 : my * height ), + opacity: show ? 1 : 0 + }, o.duration || 500, o.easing, childComplete ); + } + } + + function animComplete() { + el.css({ + visibility: "visible" + }); + $( pieces ).remove(); + if ( !show ) { + el.hide(); + } + done(); + } +}; + +})(jQuery); +(function( $, undefined ) { + +$.effects.effect.fade = function( o, done ) { + var el = $( this ), + mode = $.effects.setMode( el, o.mode || "toggle" ); + + el.animate({ + opacity: mode + }, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: done + }); +}; + +})( jQuery ); +(function( $, undefined ) { + +$.effects.effect.fold = function( o, done ) { + + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + hide = mode === "hide", + size = o.size || 15, + percent = /([0-9]+)%/.exec( size ), + horizFirst = !!o.horizFirst, + widthFirst = show !== horizFirst, + ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], + duration = o.duration / 2, + wrapper, distance, + animation1 = {}, + animation2 = {}; + + $.effects.save( el, props ); + el.show(); + + // Create Wrapper + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + distance = widthFirst ? + [ wrapper.width(), wrapper.height() ] : + [ wrapper.height(), wrapper.width() ]; + + if ( percent ) { + size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; + } + if ( show ) { + wrapper.css( horizFirst ? { + height: 0, + width: size + } : { + height: size, + width: 0 + }); + } + + // Animation + animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; + animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; + + // Animate + wrapper + .animate( animation1, duration, o.easing ) + .animate( animation2, duration, o.easing, function() { + if ( hide ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + }); + +}; + +})(jQuery); +(function( $, undefined ) { + +$.effects.effect.highlight = function( o, done ) { + var elem = $( this ), + props = [ "backgroundImage", "backgroundColor", "opacity" ], + mode = $.effects.setMode( elem, o.mode || "show" ), + animation = { + backgroundColor: elem.css( "backgroundColor" ) + }; + + if (mode === "hide") { + animation.opacity = 0; + } + + $.effects.save( elem, props ); + + elem + .show() + .css({ + backgroundImage: "none", + backgroundColor: o.color || "#ffff99" + }) + .animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + elem.hide(); + } + $.effects.restore( elem, props ); + done(); + } + }); +}; + +})(jQuery); +(function( $, undefined ) { + +$.effects.effect.pulsate = function( o, done ) { + var elem = $( this ), + mode = $.effects.setMode( elem, o.mode || "show" ), + show = mode === "show", + hide = mode === "hide", + showhide = ( show || mode === "hide" ), + + // showing or hiding leaves of the "last" animation + anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), + duration = o.duration / anims, + animateTo = 0, + queue = elem.queue(), + queuelen = queue.length, + i; + + if ( show || !elem.is(":visible")) { + elem.css( "opacity", 0 ).show(); + animateTo = 1; + } + + // anims - 1 opacity "toggles" + for ( i = 1; i < anims; i++ ) { + elem.animate({ + opacity: animateTo + }, duration, o.easing ); + animateTo = 1 - animateTo; + } + + elem.animate({ + opacity: animateTo + }, duration, o.easing); - return this.queue(function() { + elem.queue(function() { + if ( hide ) { + elem.hide(); + } + done(); + }); - // Create element - var el = $(this), props = ['position','top','bottom','left','right','height','width']; + // We just queued up "anims" animations, we need to put them next in the queue + if ( queuelen > 1 ) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + elem.dequeue(); +}; - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode - var direction = o.options.direction || 'vertical'; // Default direction - - // Adjust - $.effects.save(el, props); el.show(); // Save & Show - var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper - var animate = el[0].tagName == 'IMG' ? wrapper : el; - var ref = { - size: (direction == 'vertical') ? 'height' : 'width', - position: (direction == 'vertical') ? 'top' : 'left' +})(jQuery); +(function( $, undefined ) { + +$.effects.effect.puff = function( o, done ) { + var elem = $( this ), + mode = $.effects.setMode( elem, o.mode || "hide" ), + hide = mode === "hide", + percent = parseInt( o.percent, 10 ) || 150, + factor = percent / 100, + original = { + height: elem.height(), + width: elem.width(), + outerHeight: elem.outerHeight(), + outerWidth: elem.outerWidth() }; - var distance = (direction == 'vertical') ? animate.height() : animate.width(); - if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift - - // Animation - var animation = {}; - animation[ref.size] = mode == 'show' ? distance : 0; - animation[ref.position] = mode == 'show' ? 0 : distance / 2; - - // Animate - animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { - if(mode == 'hide') el.hide(); // Hide - $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(el[0], arguments); // Callback - el.dequeue(); - }}); + $.extend( o, { + effect: "scale", + queue: false, + fade: true, + mode: mode, + complete: done, + percent: hide ? percent : 100, + from: hide ? + original : + { + height: original.height * factor, + width: original.width * factor, + outerHeight: original.outerHeight * factor, + outerWidth: original.outerWidth * factor + } }); + elem.effect( o ); }; -})(jQuery); -/* - * jQuery UI Effects Drop 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Drop - * - * Depends: - * jquery.effects.core.js - */ -(function( $, undefined ) { +$.effects.effect.scale = function( o, done ) { + + // Create element + var el = $( this ), + options = $.extend( true, {}, o ), + mode = $.effects.setMode( el, o.mode || "effect" ), + percent = parseInt( o.percent, 10 ) || + ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), + direction = o.direction || "both", + origin = o.origin, + original = { + height: el.height(), + width: el.width(), + outerHeight: el.outerHeight(), + outerWidth: el.outerWidth() + }, + factor = { + y: direction !== "horizontal" ? (percent / 100) : 1, + x: direction !== "vertical" ? (percent / 100) : 1 + }; -$.effects.drop = function(o) { + // We are going to pass this effect to the size effect: + options.effect = "size"; + options.queue = false; + options.complete = done; - return this.queue(function() { + // Set default origin and restore for show/hide + if ( mode !== "effect" ) { + options.origin = origin || ["middle","center"]; + options.restore = true; + } - // Create element - var el = $(this), props = ['position','top','bottom','left','right','opacity']; + options.from = o.from || ( mode === "show" ? { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + } : original ); + options.to = { + height: original.height * factor.y, + width: original.width * factor.x, + outerHeight: original.outerHeight * factor.y, + outerWidth: original.outerWidth * factor.x + }; - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode - var direction = o.options.direction || 'left'; // Default Direction - - // Adjust - $.effects.save(el, props); el.show(); // Save & Show - $.effects.createWrapper(el); // Create Wrapper - var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; - var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; - var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2); - if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift - - // Animation - var animation = {opacity: mode == 'show' ? 1 : 0}; - animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; - - // Animate - el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { - if(mode == 'hide') el.hide(); // Hide - $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(this, arguments); // Callback - el.dequeue(); - }}); + // Fade option to support puff + if ( options.fade ) { + if ( mode === "show" ) { + options.from.opacity = 0; + options.to.opacity = 1; + } + if ( mode === "hide" ) { + options.from.opacity = 1; + options.to.opacity = 0; + } + } - }); + // Animate + el.effect( options ); }; -})(jQuery); -/* - * jQuery UI Effects Explode 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Explode - * - * Depends: - * jquery.effects.core.js - */ -(function( $, undefined ) { +$.effects.effect.size = function( o, done ) { -$.effects.explode = function(o) { + // Create element + var original, baseline, factor, + el = $( this ), + props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], - return this.queue(function() { + // Always restore + props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], - var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; - var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; + // Copy for children + props2 = [ "width", "height", "overflow" ], + cProps = [ "fontSize" ], + vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], + hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], - o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode; - var el = $(this).show().css('visibility', 'hidden'); - var offset = el.offset(); + // Set options + mode = $.effects.setMode( el, o.mode || "effect" ), + restore = o.restore || mode !== "effect", + scale = o.scale || "both", + origin = o.origin || [ "middle", "center" ], + position = el.css( "position" ), + props = restore ? props0 : props1, + zero = { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + }; - //Substract the margins - not fixing the problem yet. - offset.top -= parseInt(el.css("marginTop"),10) || 0; - offset.left -= parseInt(el.css("marginLeft"),10) || 0; + if ( mode === "show" ) { + el.show(); + } + original = { + height: el.height(), + width: el.width(), + outerHeight: el.outerHeight(), + outerWidth: el.outerWidth() + }; - var width = el.outerWidth(true); - var height = el.outerHeight(true); + if ( o.mode === "toggle" && mode === "show" ) { + el.from = o.to || zero; + el.to = o.from || original; + } else { + el.from = o.from || ( mode === "show" ? zero : original ); + el.to = o.to || ( mode === "hide" ? zero : original ); + } - for(var i=0;i
      ') - .css({ - position: 'absolute', - visibility: 'visible', - left: -j*(width/cells), - top: -i*(height/rows) - }) - .parent() - .addClass('ui-effects-explode') - .css({ - position: 'absolute', - overflow: 'hidden', - width: width/cells, - height: height/rows, - left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0), - top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0), - opacity: o.options.mode == 'show' ? 0 : 1 - }).animate({ - left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)), - top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)), - opacity: o.options.mode == 'show' ? 1 : 0 - }, o.duration || 500); + // Set scaling factor + factor = { + from: { + y: el.from.height / original.height, + x: el.from.width / original.width + }, + to: { + y: el.to.height / original.height, + x: el.to.width / original.width + } + }; + + // Scale the css box + if ( scale === "box" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + props = props.concat( vProps ); + el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); + el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + props = props.concat( hProps ); + el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); + el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); } } - // Set a timeout, to call the callback approx. when the other animations have finished - setTimeout(function() { + // Scale the content + if ( scale === "content" || scale === "both" ) { - o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide(); - if(o.callback) o.callback.apply(el[0]); // Callback - el.dequeue(); + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + props = props.concat( cProps ).concat( props2 ); + el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); + el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); + } + } - $('div.ui-effects-explode').remove(); + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + el.css( "overflow", "hidden" ).css( el.from ); + + // Adjust + if (origin) { // Calculate baseline shifts + baseline = $.effects.getBaseline( origin, original ); + el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; + el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; + el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; + el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; + } + el.css( el.from ); // set top & left + + // Animate + if ( scale === "content" || scale === "both" ) { // Scale the children + + // Add margins/font-size + vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); + hProps = hProps.concat([ "marginLeft", "marginRight" ]); + props2 = props0.concat(vProps).concat(hProps); + + el.find( "*[width]" ).each( function(){ + var child = $( this ), + c_original = { + height: child.height(), + width: child.width(), + outerHeight: child.outerHeight(), + outerWidth: child.outerWidth() + }; + if (restore) { + $.effects.save(child, props2); + } - }, o.duration || 500); + child.from = { + height: c_original.height * factor.from.y, + width: c_original.width * factor.from.x, + outerHeight: c_original.outerHeight * factor.from.y, + outerWidth: c_original.outerWidth * factor.from.x + }; + child.to = { + height: c_original.height * factor.to.y, + width: c_original.width * factor.to.x, + outerHeight: c_original.height * factor.to.y, + outerWidth: c_original.width * factor.to.x + }; + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); + child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); + } - }); + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); + child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); + } -}; + // Animate children + child.css( child.from ); + child.animate( child.to, o.duration, o.easing, function() { -})(jQuery); -/* - * jQuery UI Effects Fade 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Fade - * - * Depends: - * jquery.effects.core.js - */ -(function( $, undefined ) { + // Restore children + if ( restore ) { + $.effects.restore( child, props2 ); + } + }); + }); + } -$.effects.fade = function(o) { - return this.queue(function() { - var elem = $(this), - mode = $.effects.setMode(elem, o.options.mode || 'hide'); + // Animate + el.animate( el.to, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( el.to.opacity === 0 ) { + el.css( "opacity", el.from.opacity ); + } + if( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + if ( !restore ) { + + // we need to calculate our new positioning based on the scaling + if ( position === "static" ) { + el.css({ + position: "relative", + top: el.to.top, + left: el.to.left + }); + } else { + $.each([ "top", "left" ], function( idx, pos ) { + el.css( pos, function( _, str ) { + var val = parseInt( str, 10 ), + toRef = idx ? el.to.left : el.to.top; + + // if original was "auto", recalculate the new value from wrapper + if ( str === "auto" ) { + return toRef + "px"; + } - elem.animate({ opacity: mode }, { - queue: false, - duration: o.duration, - easing: o.options.easing, - complete: function() { - (o.callback && o.callback.apply(this, arguments)); - elem.dequeue(); + return val + toRef + "px"; + }); + }); + } } - }); + + $.effects.removeWrapper( el ); + done(); + } }); + }; })(jQuery); -/* - * jQuery UI Effects Fold 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Fold - * - * Depends: - * jquery.effects.core.js - */ (function( $, undefined ) { -$.effects.fold = function(o) { - - return this.queue(function() { - - // Create element - var el = $(this), props = ['position','top','bottom','left','right']; - - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode - var size = o.options.size || 15; // Default fold size - var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value - var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2; - - // Adjust - $.effects.save(el, props); el.show(); // Save & Show - var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper - var widthFirst = ((mode == 'show') != horizFirst); - var ref = widthFirst ? ['width', 'height'] : ['height', 'width']; - var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()]; - var percent = /([0-9]+)%/.exec(size); - if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1]; - if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift - - // Animation - var animation1 = {}, animation2 = {}; - animation1[ref[0]] = mode == 'show' ? distance[0] : size; - animation2[ref[1]] = mode == 'show' ? distance[1] : 0; - - // Animate - wrapper.animate(animation1, duration, o.options.easing) - .animate(animation2, duration, o.options.easing, function() { - if(mode == 'hide') el.hide(); // Hide - $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(el[0], arguments); // Callback - el.dequeue(); +$.effects.effect.shake = function( o, done ) { + + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "effect" ), + direction = o.direction || "left", + distance = o.distance || 20, + times = o.times || 3, + anims = times * 2 + 1, + speed = Math.round(o.duration/anims), + ref = (direction === "up" || direction === "down") ? "top" : "left", + positiveMotion = (direction === "up" || direction === "left"), + animation = {}, + animation1 = {}, + animation2 = {}, + i, + + // we will need to re-assemble the queue to stack our animations in place + queue = el.queue(), + queuelen = queue.length; + + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + + // Animation + animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; + animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; + animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; + + // Animate + el.animate( animation, speed, o.easing ); + + // Shakes + for ( i = 1; i < times; i++ ) { + el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); + } + el + .animate( animation1, speed, o.easing ) + .animate( animation, speed / 2, o.easing ) + .queue(function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); }); - }); + // inject all the animations we just queued to be first in line (after "inprogress") + if ( queuelen > 1) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + el.dequeue(); }; })(jQuery); -/* - * jQuery UI Effects Highlight 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Highlight - * - * Depends: - * jquery.effects.core.js - */ (function( $, undefined ) { -$.effects.highlight = function(o) { - return this.queue(function() { - var elem = $(this), - props = ['backgroundImage', 'backgroundColor', 'opacity'], - mode = $.effects.setMode(elem, o.options.mode || 'show'), - animation = { - backgroundColor: elem.css('backgroundColor') - }; +$.effects.effect.slide = function( o, done ) { + + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "width", "height" ], + mode = $.effects.setMode( el, o.mode || "show" ), + show = mode === "show", + direction = o.direction || "left", + ref = (direction === "up" || direction === "down") ? "top" : "left", + positiveMotion = (direction === "up" || direction === "left"), + distance, + animation = {}; + + // Adjust + $.effects.save( el, props ); + el.show(); + distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); + + $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + + if ( show ) { + el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); + } - if (mode == 'hide') { - animation.opacity = 0; + // Animation + animation[ ref ] = ( show ? + ( positiveMotion ? "+=" : "-=") : + ( positiveMotion ? "-=" : "+=")) + + distance; + + // Animate + el.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); } + }); +}; - $.effects.save(elem, props); - elem - .show() +})(jQuery); +(function( $, undefined ) { + +$.effects.effect.transfer = function( o, done ) { + var elem = $( this ), + target = $( o.to ), + targetFixed = target.css( "position" ) === "fixed", + body = $("body"), + fixTop = targetFixed ? body.scrollTop() : 0, + fixLeft = targetFixed ? body.scrollLeft() : 0, + endPosition = target.offset(), + animation = { + top: endPosition.top - fixTop , + left: endPosition.left - fixLeft , + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = elem.offset(), + transfer = $( '
      ' ) + .appendTo( document.body ) + .addClass( o.className ) .css({ - backgroundImage: 'none', - backgroundColor: o.options.color || '#ffff99' + top: startPosition.top - fixTop , + left: startPosition.left - fixLeft , + height: elem.innerHeight(), + width: elem.innerWidth(), + position: targetFixed ? "fixed" : "absolute" }) - .animate(animation, { - queue: false, - duration: o.duration, - easing: o.options.easing, - complete: function() { - (mode == 'hide' && elem.hide()); - $.effects.restore(elem, props); - (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter')); - (o.callback && o.callback.apply(this, arguments)); - elem.dequeue(); - } + .animate( animation, o.duration, o.easing, function() { + transfer.remove(); + done(); }); - }); }; })(jQuery); -/* - * jQuery UI Effects Pulsate 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Pulsate - * - * Depends: - * jquery.effects.core.js - */ (function( $, undefined ) { -$.effects.pulsate = function(o) { - return this.queue(function() { - var elem = $(this), - mode = $.effects.setMode(elem, o.options.mode || 'show'); - times = ((o.options.times || 5) * 2) - 1; - duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2, - isVisible = elem.is(':visible'), - animateTo = 0; - - if (!isVisible) { - elem.css('opacity', 0).show(); - animateTo = 1; - } - - if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) { - times--; - } +var mouseHandled = false; - for (var i = 0; i < times; i++) { - elem.animate({ opacity: animateTo }, duration, o.options.easing); - animateTo = (animateTo + 1) % 2; - } +$.widget( "ui.menu", { + version: "1.9.2", + defaultElement: "
        ", + delay: 300, + options: { + icons: { + submenu: "ui-icon-carat-1-e" + }, + menus: "ul", + position: { + my: "left top", + at: "right top" + }, + role: "menu", - elem.animate({ opacity: animateTo }, duration, o.options.easing, function() { - if (animateTo == 0) { - elem.hide(); - } - (o.callback && o.callback.apply(this, arguments)); - }); + // callbacks + blur: null, + focus: null, + select: null + }, - elem - .queue('fx', function() { elem.dequeue(); }) - .dequeue(); - }); -}; + _create: function() { + this.activeMenu = this.element; + this.element + .uniqueId() + .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) + .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) + .attr({ + role: this.options.role, + tabIndex: 0 + }) + // need to catch all clicks on disabled menu + // not possible through _on + .bind( "click" + this.eventNamespace, $.proxy(function( event ) { + if ( this.options.disabled ) { + event.preventDefault(); + } + }, this )); -})(jQuery); -/* - * jQuery UI Effects Scale 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Scale - * - * Depends: - * jquery.effects.core.js - */ -(function( $, undefined ) { + if ( this.options.disabled ) { + this.element + .addClass( "ui-state-disabled" ) + .attr( "aria-disabled", "true" ); + } -$.effects.puff = function(o) { - return this.queue(function() { - var elem = $(this), - mode = $.effects.setMode(elem, o.options.mode || 'hide'), - percent = parseInt(o.options.percent, 10) || 150, - factor = percent / 100, - original = { height: elem.height(), width: elem.width() }; - - $.extend(o.options, { - fade: true, - mode: mode, - percent: mode == 'hide' ? percent : 100, - from: mode == 'hide' - ? original - : { - height: original.height * factor, - width: original.width * factor + this._on({ + // Prevent focus from sticking to links inside menu after clicking + // them (focus should always stay on UL during navigation). + "mousedown .ui-menu-item > a": function( event ) { + event.preventDefault(); + }, + "click .ui-state-disabled > a": function( event ) { + event.preventDefault(); + }, + "click .ui-menu-item:has(a)": function( event ) { + var target = $( event.target ).closest( ".ui-menu-item" ); + if ( !mouseHandled && target.not( ".ui-state-disabled" ).length ) { + mouseHandled = true; + + this.select( event ); + // Open submenu on click + if ( target.has( ".ui-menu" ).length ) { + this.expand( event ); + } else if ( !this.element.is( ":focus" ) ) { + // Redirect focus to the menu + this.element.trigger( "focus", [ true ] ); + + // If the active item is on the top level, let it stay active. + // Otherwise, blur the active item since it is no longer visible. + if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { + clearTimeout( this.timer ); + } + } + } + }, + "mouseenter .ui-menu-item": function( event ) { + var target = $( event.currentTarget ); + // Remove ui-state-active class from siblings of the newly focused menu item + // to avoid a jump caused by adjacent elements both having a class with a border + target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); + this.focus( event, target ); + }, + mouseleave: "collapseAll", + "mouseleave .ui-menu": "collapseAll", + focus: function( event, keepActiveItem ) { + // If there's already an active item, keep it active + // If not, activate the first item + var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); + + if ( !keepActiveItem ) { + this.focus( event, item ); } + }, + blur: function( event ) { + this._delay(function() { + if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { + this.collapseAll( event ); + } + }); + }, + keydown: "_keydown" }); - elem.effect('scale', o.options, o.duration, o.callback); - elem.dequeue(); - }); -}; - -$.effects.scale = function(o) { - - return this.queue(function() { + this.refresh(); - // Create element - var el = $(this); + // Clicks outside of a menu collapse any open menus + this._on( this.document, { + click: function( event ) { + if ( !$( event.target ).closest( ".ui-menu" ).length ) { + this.collapseAll( event ); + } - // Set options - var options = $.extend(true, {}, o.options); - var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode - var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent - var direction = o.options.direction || 'both'; // Set default axis - var origin = o.options.origin; // The origin of the scaling - if (mode != 'effect') { // Set default origin and restore for show/hide - options.origin = origin || ['middle','center']; - options.restore = true; - } - var original = {height: el.height(), width: el.width()}; // Save original - el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state - - // Adjust - var factor = { // Set scaling factor - y: direction != 'horizontal' ? (percent / 100) : 1, - x: direction != 'vertical' ? (percent / 100) : 1 - }; - el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state + // Reset the mouseHandled flag + mouseHandled = false; + } + }); + }, - if (o.options.fade) { // Fade option to support puff - if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;}; - if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;}; - }; + _destroy: function() { + // Destroy (sub)menus + this.element + .removeAttr( "aria-activedescendant" ) + .find( ".ui-menu" ).andSelf() + .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) + .removeAttr( "role" ) + .removeAttr( "tabIndex" ) + .removeAttr( "aria-labelledby" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-disabled" ) + .removeUniqueId() + .show(); + + // Destroy menu items + this.element.find( ".ui-menu-item" ) + .removeClass( "ui-menu-item" ) + .removeAttr( "role" ) + .removeAttr( "aria-disabled" ) + .children( "a" ) + .removeUniqueId() + .removeClass( "ui-corner-all ui-state-hover" ) + .removeAttr( "tabIndex" ) + .removeAttr( "role" ) + .removeAttr( "aria-haspopup" ) + .children().each( function() { + var elem = $( this ); + if ( elem.data( "ui-menu-submenu-carat" ) ) { + elem.remove(); + } + }); - // Animation - options.from = el.from; options.to = el.to; options.mode = mode; + // Destroy menu dividers + this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); + }, - // Animate - el.effect('size', options, o.duration, o.callback); - el.dequeue(); - }); + _keydown: function( event ) { + var match, prev, character, skip, regex, + preventDefault = true; -}; + function escape( value ) { + return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); + } -$.effects.size = function(o) { + switch ( event.keyCode ) { + case $.ui.keyCode.PAGE_UP: + this.previousPage( event ); + break; + case $.ui.keyCode.PAGE_DOWN: + this.nextPage( event ); + break; + case $.ui.keyCode.HOME: + this._move( "first", "first", event ); + break; + case $.ui.keyCode.END: + this._move( "last", "last", event ); + break; + case $.ui.keyCode.UP: + this.previous( event ); + break; + case $.ui.keyCode.DOWN: + this.next( event ); + break; + case $.ui.keyCode.LEFT: + this.collapse( event ); + break; + case $.ui.keyCode.RIGHT: + if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { + this.expand( event ); + } + break; + case $.ui.keyCode.ENTER: + case $.ui.keyCode.SPACE: + this._activate( event ); + break; + case $.ui.keyCode.ESCAPE: + this.collapse( event ); + break; + default: + preventDefault = false; + prev = this.previousFilter || ""; + character = String.fromCharCode( event.keyCode ); + skip = false; - return this.queue(function() { + clearTimeout( this.filterTimer ); - // Create element - var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity']; - var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore - var props2 = ['width','height','overflow']; // Copy for children - var cProps = ['fontSize']; - var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom']; - var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight']; + if ( character === prev ) { + skip = true; + } else { + character = prev + character; + } - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode - var restore = o.options.restore || false; // Default restore - var scale = o.options.scale || 'both'; // Default scale mode - var origin = o.options.origin; // The origin of the sizing - var original = {height: el.height(), width: el.width()}; // Save original - el.from = o.options.from || original; // Default from state - el.to = o.options.to || original; // Default to state - // Adjust - if (origin) { // Calculate baseline shifts - var baseline = $.effects.getBaseline(origin, original); - el.from.top = (original.height - el.from.height) * baseline.y; - el.from.left = (original.width - el.from.width) * baseline.x; - el.to.top = (original.height - el.to.height) * baseline.y; - el.to.left = (original.width - el.to.width) * baseline.x; - }; - var factor = { // Set scaling factor - from: {y: el.from.height / original.height, x: el.from.width / original.width}, - to: {y: el.to.height / original.height, x: el.to.width / original.width} - }; - if (scale == 'box' || scale == 'both') { // Scale the css box - if (factor.from.y != factor.to.y) { // Vertical props scaling - props = props.concat(vProps); - el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from); - el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to); - }; - if (factor.from.x != factor.to.x) { // Horizontal props scaling - props = props.concat(hProps); - el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from); - el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to); - }; - }; - if (scale == 'content' || scale == 'both') { // Scale the content - if (factor.from.y != factor.to.y) { // Vertical props scaling - props = props.concat(cProps); - el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from); - el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to); - }; - }; - $.effects.save(el, restore ? props : props1); el.show(); // Save & Show - $.effects.createWrapper(el); // Create Wrapper - el.css('overflow','hidden').css(el.from); // Shift - - // Animate - if (scale == 'content' || scale == 'both') { // Scale the children - vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size - hProps = hProps.concat(['marginLeft','marginRight']); // Add margins - props2 = props.concat(vProps).concat(hProps); // Concat - el.find("*[width]").each(function(){ - child = $(this); - if (restore) $.effects.save(child, props2); - var c_original = {height: child.height(), width: child.width()}; // Save original - child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x}; - child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x}; - if (factor.from.y != factor.to.y) { // Vertical props scaling - child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from); - child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to); - }; - if (factor.from.x != factor.to.x) { // Horizontal props scaling - child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from); - child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to); - }; - child.css(child.from); // Shift children - child.animate(child.to, o.duration, o.options.easing, function(){ - if (restore) $.effects.restore(child, props2); // Restore children - }); // Animate children + regex = new RegExp( "^" + escape( character ), "i" ); + match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { + return regex.test( $( this ).children( "a" ).text() ); }); - }; + match = skip && match.index( this.active.next() ) !== -1 ? + this.active.nextAll( ".ui-menu-item" ) : + match; + + // If no matches on the current filter, reset to the last character pressed + // to move down the menu to the first item that starts with that character + if ( !match.length ) { + character = String.fromCharCode( event.keyCode ); + regex = new RegExp( "^" + escape( character ), "i" ); + match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { + return regex.test( $( this ).children( "a" ).text() ); + }); + } - // Animate - el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { - if (el.to.opacity === 0) { - el.css('opacity', el.from.opacity); + if ( match.length ) { + this.focus( event, match ); + if ( match.length > 1 ) { + this.previousFilter = character; + this.filterTimer = this._delay(function() { + delete this.previousFilter; + }, 1000 ); + } else { + delete this.previousFilter; + } + } else { + delete this.previousFilter; } - if(mode == 'hide') el.hide(); // Hide - $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(this, arguments); // Callback - el.dequeue(); - }}); + } - }); + if ( preventDefault ) { + event.preventDefault(); + } + }, -}; + _activate: function( event ) { + if ( !this.active.is( ".ui-state-disabled" ) ) { + if ( this.active.children( "a[aria-haspopup='true']" ).length ) { + this.expand( event ); + } else { + this.select( event ); + } + } + }, -})(jQuery); -/* - * jQuery UI Effects Shake 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Shake - * - * Depends: - * jquery.effects.core.js - */ -(function( $, undefined ) { + refresh: function() { + var menus, + icon = this.options.icons.submenu, + submenus = this.element.find( this.options.menus ); -$.effects.shake = function(o) { + // Initialize nested menus + submenus.filter( ":not(.ui-menu)" ) + .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) + .hide() + .attr({ + role: this.options.role, + "aria-hidden": "true", + "aria-expanded": "false" + }) + .each(function() { + var menu = $( this ), + item = menu.prev( "a" ), + submenuCarat = $( "" ) + .addClass( "ui-menu-icon ui-icon " + icon ) + .data( "ui-menu-submenu-carat", true ); + + item + .attr( "aria-haspopup", "true" ) + .prepend( submenuCarat ); + menu.attr( "aria-labelledby", item.attr( "id" ) ); + }); - return this.queue(function() { + menus = submenus.add( this.element ); - // Create element - var el = $(this), props = ['position','top','bottom','left','right']; + // Don't refresh list items that are already adapted + menus.children( ":not(.ui-menu-item):has(a)" ) + .addClass( "ui-menu-item" ) + .attr( "role", "presentation" ) + .children( "a" ) + .uniqueId() + .addClass( "ui-corner-all" ) + .attr({ + tabIndex: -1, + role: this._itemRole() + }); - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode - var direction = o.options.direction || 'left'; // Default direction - var distance = o.options.distance || 20; // Default distance - var times = o.options.times || 3; // Default # of times - var speed = o.duration || o.options.duration || 140; // Default speed per shake - - // Adjust - $.effects.save(el, props); el.show(); // Save & Show - $.effects.createWrapper(el); // Create Wrapper - var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; - var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; - - // Animation - var animation = {}, animation1 = {}, animation2 = {}; - animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; - animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2; - animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2; - - // Animate - el.animate(animation, speed, o.options.easing); - for (var i = 1; i < times; i++) { // Shakes - el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing); - }; - el.animate(animation1, speed, o.options.easing). - animate(animation, speed / 2, o.options.easing, function(){ // Last shake - $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(this, arguments); // Callback + // Initialize unlinked menu-items containing spaces and/or dashes only as dividers + menus.children( ":not(.ui-menu-item)" ).each(function() { + var item = $( this ); + // hyphen, em dash, en dash + if ( !/[^\-—–\s]/.test( item.text() ) ) { + item.addClass( "ui-widget-content ui-menu-divider" ); + } }); - el.queue('fx', function() { el.dequeue(); }); - el.dequeue(); - }); -}; + // Add aria-disabled attribute to any disabled menu item + menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); -})(jQuery); -/* - * jQuery UI Effects Slide 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Slide - * - * Depends: - * jquery.effects.core.js - */ -(function( $, undefined ) { + // If the active item has been removed, blur the menu + if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { + this.blur(); + } + }, -$.effects.slide = function(o) { + _itemRole: function() { + return { + menu: "menuitem", + listbox: "option" + }[ this.options.role ]; + }, - return this.queue(function() { + focus: function( event, item ) { + var nested, focused; + this.blur( event, event && event.type === "focus" ); - // Create element - var el = $(this), props = ['position','top','bottom','left','right']; + this._scrollIntoView( item ); - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode - var direction = o.options.direction || 'left'; // Default Direction - - // Adjust - $.effects.save(el, props); el.show(); // Save & Show - $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper - var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; - var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; - var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true})); - if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift - - // Animation - var animation = {}; - animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; - - // Animate - el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { - if(mode == 'hide') el.hide(); // Hide - $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore - if(o.callback) o.callback.apply(this, arguments); // Callback - el.dequeue(); - }}); + this.active = item.first(); + focused = this.active.children( "a" ).addClass( "ui-state-focus" ); + // Only update aria-activedescendant if there's a role + // otherwise we assume focus is managed elsewhere + if ( this.options.role ) { + this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); + } - }); + // Highlight active parent menu item, if any + this.active + .parent() + .closest( ".ui-menu-item" ) + .children( "a:first" ) + .addClass( "ui-state-active" ); -}; + if ( event && event.type === "keydown" ) { + this._close(); + } else { + this.timer = this._delay(function() { + this._close(); + }, this.delay ); + } -})(jQuery); -/* - * jQuery UI Effects Transfer 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Transfer - * - * Depends: - * jquery.effects.core.js - */ -(function( $, undefined ) { + nested = item.children( ".ui-menu" ); + if ( nested.length && ( /^mouse/.test( event.type ) ) ) { + this._startOpening(nested); + } + this.activeMenu = item.parent(); -$.effects.transfer = function(o) { - return this.queue(function() { - var elem = $(this), - target = $(o.options.to), - endPosition = target.offset(), - animation = { - top: endPosition.top, - left: endPosition.left, - height: target.innerHeight(), - width: target.innerWidth() - }, - startPosition = elem.offset(), - transfer = $('
        ') - .appendTo(document.body) - .addClass(o.options.className) - .css({ - top: startPosition.top, - left: startPosition.left, - height: elem.innerHeight(), - width: elem.innerWidth(), - position: 'absolute' - }) - .animate(animation, o.duration, o.options.easing, function() { - transfer.remove(); - (o.callback && o.callback.apply(elem[0], arguments)); - elem.dequeue(); - }); - }); -}; + this._trigger( "focus", event, { item: item } ); + }, -})(jQuery); -/* - * jQuery UI Accordion 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Accordion - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function( $, undefined ) { + _scrollIntoView: function( item ) { + var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; + if ( this._hasScroll() ) { + borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; + paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; + offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; + scroll = this.activeMenu.scrollTop(); + elementHeight = this.activeMenu.height(); + itemHeight = item.height(); -$.widget( "ui.accordion", { - options: { - active: 0, - animated: "slide", - autoHeight: true, - clearStyle: false, - collapsible: false, - event: "click", - fillSpace: false, - header: "> li > :first-child,> :not(li):even", - icons: { - header: "ui-icon-triangle-1-e", - headerSelected: "ui-icon-triangle-1-s" - }, - navigation: false, - navigationFilter: function() { - return this.href.toLowerCase() === location.href.toLowerCase(); + if ( offset < 0 ) { + this.activeMenu.scrollTop( scroll + offset ); + } else if ( offset + itemHeight > elementHeight ) { + this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); + } } }, - _create: function() { - var self = this, - options = self.options; + blur: function( event, fromFocus ) { + if ( !fromFocus ) { + clearTimeout( this.timer ); + } - self.running = 0; + if ( !this.active ) { + return; + } - self.element - .addClass( "ui-accordion ui-widget ui-helper-reset" ) - // in lack of child-selectors in CSS - // we need to mark top-LIs in a UL-accordion for some IE-fix - .children( "li" ) - .addClass( "ui-accordion-li-fix" ); + this.active.children( "a" ).removeClass( "ui-state-focus" ); + this.active = null; - self.headers = self.element.find( options.header ) - .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ) - .bind( "mouseenter.accordion", function() { - if ( options.disabled ) { - return; - } - $( this ).addClass( "ui-state-hover" ); - }) - .bind( "mouseleave.accordion", function() { - if ( options.disabled ) { - return; - } - $( this ).removeClass( "ui-state-hover" ); - }) - .bind( "focus.accordion", function() { - if ( options.disabled ) { - return; - } - $( this ).addClass( "ui-state-focus" ); - }) - .bind( "blur.accordion", function() { - if ( options.disabled ) { - return; - } - $( this ).removeClass( "ui-state-focus" ); - }); + this._trigger( "blur", event, { item: this.active } ); + }, - self.headers.next() - .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); + _startOpening: function( submenu ) { + clearTimeout( this.timer ); - if ( options.navigation ) { - var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 ); - if ( current.length ) { - var header = current.closest( ".ui-accordion-header" ); - if ( header.length ) { - // anchor within header - self.active = header; - } else { - // anchor within content - self.active = current.closest( ".ui-accordion-content" ).prev(); - } - } + // Don't open if already open fixes a Firefox bug that caused a .5 pixel + // shift in the submenu position when mousing over the carat icon + if ( submenu.attr( "aria-hidden" ) !== "true" ) { + return; } - self.active = self._findActive( self.active || options.active ) - .addClass( "ui-state-default ui-state-active" ) - .toggleClass( "ui-corner-all" ) - .toggleClass( "ui-corner-top" ); - self.active.next().addClass( "ui-accordion-content-active" ); + this.timer = this._delay(function() { + this._close(); + this._open( submenu ); + }, this.delay ); + }, - self._createIcons(); - self.resize(); - - // ARIA - self.element.attr( "role", "tablist" ); + _open: function( submenu ) { + var position = $.extend({ + of: this.active + }, this.options.position ); - self.headers - .attr( "role", "tab" ) - .bind( "keydown.accordion", function( event ) { - return self._keydown( event ); - }) - .next() - .attr( "role", "tabpanel" ); + clearTimeout( this.timer ); + this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) + .hide() + .attr( "aria-hidden", "true" ); - self.headers - .not( self.active || "" ) - .attr({ - "aria-expanded": "false", - "aria-selected": "false", - tabIndex: -1 - }) - .next() - .hide(); + submenu + .show() + .removeAttr( "aria-hidden" ) + .attr( "aria-expanded", "true" ) + .position( position ); + }, - // make sure at least one header is in the tab order - if ( !self.active.length ) { - self.headers.eq( 0 ).attr( "tabIndex", 0 ); - } else { - self.active - .attr({ - "aria-expanded": "true", - "aria-selected": "true", - tabIndex: 0 - }); - } + collapseAll: function( event, all ) { + clearTimeout( this.timer ); + this.timer = this._delay(function() { + // If we were passed an event, look for the submenu that contains the event + var currentMenu = all ? this.element : + $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); - // only need links in tab order for Safari - if ( !$.browser.safari ) { - self.headers.find( "a" ).attr( "tabIndex", -1 ); + // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway + if ( !currentMenu.length ) { + currentMenu = this.element; + } + + this._close( currentMenu ); + + this.blur( event ); + this.activeMenu = currentMenu; + }, this.delay ); + }, + + // With no arguments, closes the currently active menu - if nothing is active + // it closes all menus. If passed an argument, it will search for menus BELOW + _close: function( startMenu ) { + if ( !startMenu ) { + startMenu = this.active ? this.active.parent() : this.element; } - if ( options.event ) { - self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) { - self._clickHandler.call( self, event, this ); - event.preventDefault(); - }); + startMenu + .find( ".ui-menu" ) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ) + .end() + .find( "a.ui-state-active" ) + .removeClass( "ui-state-active" ); + }, + + collapse: function( event ) { + var newItem = this.active && + this.active.parent().closest( ".ui-menu-item", this.element ); + if ( newItem && newItem.length ) { + this._close(); + this.focus( event, newItem ); } }, - _createIcons: function() { - var options = this.options; - if ( options.icons ) { - $( "" ) - .addClass( "ui-icon " + options.icons.header ) - .prependTo( this.headers ); - this.active.children( ".ui-icon" ) - .toggleClass(options.icons.header) - .toggleClass(options.icons.headerSelected); - this.element.addClass( "ui-accordion-icons" ); + expand: function( event ) { + var newItem = this.active && + this.active + .children( ".ui-menu " ) + .children( ".ui-menu-item" ) + .first(); + + if ( newItem && newItem.length ) { + this._open( newItem.parent() ); + + // Delay so Firefox will not hide activedescendant change in expanding submenu from AT + this._delay(function() { + this.focus( event, newItem ); + }); } }, - _destroyIcons: function() { - this.headers.children( ".ui-icon" ).remove(); - this.element.removeClass( "ui-accordion-icons" ); + next: function( event ) { + this._move( "next", "first", event ); }, - destroy: function() { - var options = this.options; + previous: function( event ) { + this._move( "prev", "last", event ); + }, - this.element - .removeClass( "ui-accordion ui-widget ui-helper-reset" ) - .removeAttr( "role" ); + isFirstItem: function() { + return this.active && !this.active.prevAll( ".ui-menu-item" ).length; + }, - this.headers - .unbind( ".accordion" ) - .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) - .removeAttr( "role" ) - .removeAttr( "aria-expanded" ) - .removeAttr( "aria-selected" ) - .removeAttr( "tabIndex" ); + isLastItem: function() { + return this.active && !this.active.nextAll( ".ui-menu-item" ).length; + }, - this.headers.find( "a" ).removeAttr( "tabIndex" ); - this._destroyIcons(); - var contents = this.headers.next() - .css( "display", "" ) - .removeAttr( "role" ) - .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" ); - if ( options.autoHeight || options.fillHeight ) { - contents.css( "height", "" ); + _move: function( direction, filter, event ) { + var next; + if ( this.active ) { + if ( direction === "first" || direction === "last" ) { + next = this.active + [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) + .eq( -1 ); + } else { + next = this.active + [ direction + "All" ]( ".ui-menu-item" ) + .eq( 0 ); + } + } + if ( !next || !next.length || !this.active ) { + next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); } - return $.Widget.prototype.destroy.call( this ); + this.focus( event, next ); }, - _setOption: function( key, value ) { - $.Widget.prototype._setOption.apply( this, arguments ); - - if ( key == "active" ) { - this.activate( value ); + nextPage: function( event ) { + var item, base, height; + + if ( !this.active ) { + this.next( event ); + return; } - if ( key == "icons" ) { - this._destroyIcons(); - if ( value ) { - this._createIcons(); - } + if ( this.isLastItem() ) { + return; } - // #5332 - opacity doesn't cascade to positioned elements in IE - // so we need to add the disabled class to the headers and panels - if ( key == "disabled" ) { - this.headers.add(this.headers.next()) - [ value ? "addClass" : "removeClass" ]( - "ui-accordion-disabled ui-state-disabled" ); + if ( this._hasScroll() ) { + base = this.active.offset().top; + height = this.element.height(); + this.active.nextAll( ".ui-menu-item" ).each(function() { + item = $( this ); + return item.offset().top - base - height < 0; + }); + + this.focus( event, item ); + } else { + this.focus( event, this.activeMenu.children( ".ui-menu-item" ) + [ !this.active ? "first" : "last" ]() ); } }, - _keydown: function( event ) { - if ( this.options.disabled || event.altKey || event.ctrlKey ) { + previousPage: function( event ) { + var item, base, height; + if ( !this.active ) { + this.next( event ); return; } - - var keyCode = $.ui.keyCode, - length = this.headers.length, - currentIndex = this.headers.index( event.target ), - toFocus = false; - - switch ( event.keyCode ) { - case keyCode.RIGHT: - case keyCode.DOWN: - toFocus = this.headers[ ( currentIndex + 1 ) % length ]; - break; - case keyCode.LEFT: - case keyCode.UP: - toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; - break; - case keyCode.SPACE: - case keyCode.ENTER: - this._clickHandler( { target: event.target }, event.target ); - event.preventDefault(); + if ( this.isFirstItem() ) { + return; } + if ( this._hasScroll() ) { + base = this.active.offset().top; + height = this.element.height(); + this.active.prevAll( ".ui-menu-item" ).each(function() { + item = $( this ); + return item.offset().top - base + height > 0; + }); - if ( toFocus ) { - $( event.target ).attr( "tabIndex", -1 ); - $( toFocus ).attr( "tabIndex", 0 ); - toFocus.focus(); - return false; + this.focus( event, item ); + } else { + this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); } + }, - return true; + _hasScroll: function() { + return this.element.outerHeight() < this.element.prop( "scrollHeight" ); }, - resize: function() { - var options = this.options, - maxHeight; + select: function( event ) { + // TODO: It should never be possible to not have an active item at this + // point, but the tests don't trigger mouseenter before click. + this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); + var ui = { item: this.active }; + if ( !this.active.has( ".ui-menu" ).length ) { + this.collapseAll( event, true ); + } + this._trigger( "select", event, ui ); + } +}); - if ( options.fillSpace ) { - if ( $.browser.msie ) { - var defOverflow = this.element.parent().css( "overflow" ); - this.element.parent().css( "overflow", "hidden"); - } - maxHeight = this.element.parent().height(); - if ($.browser.msie) { - this.element.parent().css( "overflow", defOverflow ); - } +}( jQuery )); +(function( $, undefined ) { - this.headers.each(function() { - maxHeight -= $( this ).outerHeight( true ); - }); +$.widget( "ui.progressbar", { + version: "1.9.2", + options: { + value: 0, + max: 100 + }, - this.headers.next() - .each(function() { - $( this ).height( Math.max( 0, maxHeight - - $( this ).innerHeight() + $( this ).height() ) ); - }) - .css( "overflow", "auto" ); - } else if ( options.autoHeight ) { - maxHeight = 0; - this.headers.next() - .each(function() { - maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); - }) - .height( maxHeight ); - } + min: 0, - return this; - }, + _create: function() { + this.element + .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .attr({ + role: "progressbar", + "aria-valuemin": this.min, + "aria-valuemax": this.options.max, + "aria-valuenow": this._value() + }); - activate: function( index ) { - // TODO this gets called on init, changing the option without an explicit call for that - this.options.active = index; - // call clickHandler with custom event - var active = this._findActive( index )[ 0 ]; - this._clickHandler( { target: active }, active ); + this.valueDiv = $( "
        " ) + .appendTo( this.element ); - return this; + this.oldValue = this._value(); + this._refreshValue(); }, - _findActive: function( selector ) { - return selector - ? typeof selector === "number" - ? this.headers.filter( ":eq(" + selector + ")" ) - : this.headers.not( this.headers.not( selector ) ) - : selector === false - ? $( [] ) - : this.headers.filter( ":eq(0)" ); + _destroy: function() { + this.element + .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); + + this.valueDiv.remove(); }, - // TODO isn't event.target enough? why the separate target argument? - _clickHandler: function( event, target ) { - var options = this.options; - if ( options.disabled ) { - return; + value: function( newValue ) { + if ( newValue === undefined ) { + return this._value(); } - // called only when using activate(false) to close all parts programmatically - if ( !event.target ) { - if ( !options.collapsible ) { - return; + this._setOption( "value", newValue ); + return this; + }, + + _setOption: function( key, value ) { + if ( key === "value" ) { + this.options.value = value; + this._refreshValue(); + if ( this._value() === this.options.max ) { + this._trigger( "complete" ); } - this.active - .removeClass( "ui-state-active ui-corner-top" ) - .addClass( "ui-state-default ui-corner-all" ) - .children( ".ui-icon" ) - .removeClass( options.icons.headerSelected ) - .addClass( options.icons.header ); - this.active.next().addClass( "ui-accordion-content-active" ); - var toHide = this.active.next(), - data = { - options: options, - newHeader: $( [] ), - oldHeader: options.active, - newContent: $( [] ), - oldContent: toHide - }, - toShow = ( this.active = $( [] ) ); - this._toggle( toShow, toHide, data ); - return; } - // get the click target - var clicked = $( event.currentTarget || target ), - clickedIsActive = clicked[0] === this.active[0]; - - // TODO the option is changed, is that correct? - // TODO if it is correct, shouldn't that happen after determining that the click is valid? - options.active = options.collapsible && clickedIsActive ? - false : - this.headers.index( clicked ); + this._super( key, value ); + }, - // if animations are still active, or the active header is the target, ignore click - if ( this.running || ( !options.collapsible && clickedIsActive ) ) { - return; + _value: function() { + var val = this.options.value; + // normalize invalid value + if ( typeof val !== "number" ) { + val = 0; } + return Math.min( this.options.max, Math.max( this.min, val ) ); + }, - // find elements to show and hide - var active = this.active, - toShow = clicked.next(), - toHide = this.active.next(), - data = { - options: options, - newHeader: clickedIsActive && options.collapsible ? $([]) : clicked, - oldHeader: this.active, - newContent: clickedIsActive && options.collapsible ? $([]) : toShow, - oldContent: toHide - }, - down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); + _percentage: function() { + return 100 * this._value() / this.options.max; + }, - // when the call to ._toggle() comes after the class changes - // it causes a very odd bug in IE 8 (see #6720) - this.active = clickedIsActive ? $([]) : clicked; - this._toggle( toShow, toHide, data, clickedIsActive, down ); + _refreshValue: function() { + var value = this.value(), + percentage = this._percentage(); - // switch classes - active - .removeClass( "ui-state-active ui-corner-top" ) - .addClass( "ui-state-default ui-corner-all" ) - .children( ".ui-icon" ) - .removeClass( options.icons.headerSelected ) - .addClass( options.icons.header ); - if ( !clickedIsActive ) { - clicked - .removeClass( "ui-state-default ui-corner-all" ) - .addClass( "ui-state-active ui-corner-top" ) - .children( ".ui-icon" ) - .removeClass( options.icons.header ) - .addClass( options.icons.headerSelected ); - clicked - .next() - .addClass( "ui-accordion-content-active" ); + if ( this.oldValue !== value ) { + this.oldValue = value; + this._trigger( "change" ); } - return; - }, - - _toggle: function( toShow, toHide, data, clickedIsActive, down ) { - var self = this, - options = self.options; + this.valueDiv + .toggle( value > this.min ) + .toggleClass( "ui-corner-right", value === this.options.max ) + .width( percentage.toFixed(0) + "%" ); + this.element.attr( "aria-valuenow", value ); + } +}); - self.toShow = toShow; - self.toHide = toHide; - self.data = data; +})( jQuery ); +(function( $, undefined ) { - var complete = function() { - if ( !self ) { - return; - } - return self._completed.apply( self, arguments ); - }; +$.widget("ui.resizable", $.ui.mouse, { + version: "1.9.2", + widgetEventPrefix: "resize", + options: { + alsoResize: false, + animate: false, + animateDuration: "slow", + animateEasing: "swing", + aspectRatio: false, + autoHide: false, + containment: false, + ghost: false, + grid: false, + handles: "e,s,se", + helper: false, + maxHeight: null, + maxWidth: null, + minHeight: 10, + minWidth: 10, + zIndex: 1000 + }, + _create: function() { - // trigger changestart event - self._trigger( "changestart", null, self.data ); + var that = this, o = this.options; + this.element.addClass("ui-resizable"); - // count elements to animate - self.running = toHide.size() === 0 ? toShow.size() : toHide.size(); + $.extend(this, { + _aspectRatio: !!(o.aspectRatio), + aspectRatio: o.aspectRatio, + originalElement: this.element, + _proportionallyResizeElements: [], + _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null + }); - if ( options.animated ) { - var animOptions = {}; + //Wrap the element if it cannot hold child nodes + if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { - if ( options.collapsible && clickedIsActive ) { - animOptions = { - toShow: $( [] ), - toHide: toHide, - complete: complete, - down: down, - autoHeight: options.autoHeight || options.fillSpace - }; - } else { - animOptions = { - toShow: toShow, - toHide: toHide, - complete: complete, - down: down, - autoHeight: options.autoHeight || options.fillSpace - }; - } + //Create a wrapper element and set the wrapper to the new current internal element + this.element.wrap( + $('
        ').css({ + position: this.element.css('position'), + width: this.element.outerWidth(), + height: this.element.outerHeight(), + top: this.element.css('top'), + left: this.element.css('left') + }) + ); - if ( !options.proxied ) { - options.proxied = options.animated; - } + //Overwrite the original this.element + this.element = this.element.parent().data( + "resizable", this.element.data('resizable') + ); - if ( !options.proxiedDuration ) { - options.proxiedDuration = options.duration; - } + this.elementIsWrapper = true; - options.animated = $.isFunction( options.proxied ) ? - options.proxied( animOptions ) : - options.proxied; + //Move margins to the wrapper + this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); + this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); - options.duration = $.isFunction( options.proxiedDuration ) ? - options.proxiedDuration( animOptions ) : - options.proxiedDuration; + //Prevent Safari textarea resize + this.originalResizeStyle = this.originalElement.css('resize'); + this.originalElement.css('resize', 'none'); - var animations = $.ui.accordion.animations, - duration = options.duration, - easing = options.animated; + //Push the actual element to our proportionallyResize internal array + this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); - if ( easing && !animations[ easing ] && !$.easing[ easing ] ) { - easing = "slide"; - } - if ( !animations[ easing ] ) { - animations[ easing ] = function( options ) { - this.slide( options, { - easing: easing, - duration: duration || 700 - }); - }; - } + // avoid IE jump (hard set the margin) + this.originalElement.css({ margin: this.originalElement.css('margin') }); - animations[ easing ]( animOptions ); - } else { - if ( options.collapsible && clickedIsActive ) { - toShow.toggle(); - } else { - toHide.hide(); - toShow.show(); - } + // fix handlers offset + this._proportionallyResize(); - complete( true ); } - // TODO assert that the blur and focus triggers are really necessary, remove otherwise - toHide.prev() - .attr({ - "aria-expanded": "false", - "aria-selected": "false", - tabIndex: -1 - }) - .blur(); - toShow.prev() - .attr({ - "aria-expanded": "true", - "aria-selected": "true", - tabIndex: 0 - }) - .focus(); - }, + this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }); + if(this.handles.constructor == String) { - _completed: function( cancel ) { - this.running = cancel ? 0 : --this.running; - if ( this.running ) { - return; - } + if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; + var n = this.handles.split(","); this.handles = {}; - if ( this.options.clearStyle ) { - this.toShow.add( this.toHide ).css({ - height: "", - overflow: "" - }); - } + for(var i = 0; i < n.length; i++) { - // other classes are removed before the animation; this one needs to stay until completed - this.toHide.removeClass( "ui-accordion-content-active" ); - // Work around for rendering bug in IE (#5421) - if ( this.toHide.length ) { - this.toHide.parent()[0].className = this.toHide.parent()[0].className; - } + var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; + var axis = $('
        '); - this._trigger( "change", null, this.data ); - } -}); + // Apply zIndex to all handles - see #7960 + axis.css({ zIndex: o.zIndex }); -$.extend( $.ui.accordion, { - version: "1.8.16", - animations: { - slide: function( options, additions ) { - options = $.extend({ - easing: "swing", - duration: 300 - }, options, additions ); - if ( !options.toHide.size() ) { - options.toShow.animate({ - height: "show", - paddingTop: "show", - paddingBottom: "show" - }, options ); - return; - } - if ( !options.toShow.size() ) { - options.toHide.animate({ - height: "hide", - paddingTop: "hide", - paddingBottom: "hide" - }, options ); - return; - } - var overflow = options.toShow.css( "overflow" ), - percentDone = 0, - showProps = {}, - hideProps = {}, - fxAttrs = [ "height", "paddingTop", "paddingBottom" ], - originalWidth; - // fix width before calculating height of hidden element - var s = options.toShow; - originalWidth = s[0].style.width; - s.width( parseInt( s.parent().width(), 10 ) - - parseInt( s.css( "paddingLeft" ), 10 ) - - parseInt( s.css( "paddingRight" ), 10 ) - - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 ) - - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) ); - - $.each( fxAttrs, function( i, prop ) { - hideProps[ prop ] = "hide"; - - var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ); - showProps[ prop ] = { - value: parts[ 1 ], - unit: parts[ 2 ] || "px" + //TODO : What's going on here? + if ('se' == handle) { + axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); }; - }); - options.toShow.css({ height: 0, overflow: "hidden" }).show(); - options.toHide - .filter( ":hidden" ) - .each( options.complete ) - .end() - .filter( ":visible" ) - .animate( hideProps, { - step: function( now, settings ) { - // only calculate the percent when animating height - // IE gets very inconsistent results when animating elements - // with small values, which is common for padding - if ( settings.prop == "height" ) { - percentDone = ( settings.end - settings.start === 0 ) ? 0 : - ( settings.now - settings.start ) / ( settings.end - settings.start ); - } - - options.toShow[ 0 ].style[ settings.prop ] = - ( percentDone * showProps[ settings.prop ].value ) - + showProps[ settings.prop ].unit; - }, - duration: options.duration, - easing: options.easing, - complete: function() { - if ( !options.autoHeight ) { - options.toShow.css( "height", "" ); - } - options.toShow.css({ - width: originalWidth, - overflow: overflow - }); - options.complete(); - } - }); - }, - bounceslide: function( options ) { - this.slide( options, { - easing: options.down ? "easeOutBounce" : "swing", - duration: options.down ? 1000 : 200 - }); - } - } -}); -})( jQuery ); -/* - * jQuery UI Autocomplete 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Autocomplete - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.position.js - */ -(function( $, undefined ) { + //Insert into internal handles object and append to element + this.handles[handle] = '.ui-resizable-'+handle; + this.element.append(axis); + } -// used to prevent race conditions with remote data sources -var requestIndex = 0; + } -$.widget( "ui.autocomplete", { - options: { - appendTo: "body", - autoFocus: false, - delay: 300, - minLength: 1, - position: { - my: "left top", - at: "left bottom", - collision: "none" - }, - source: null - }, + this._renderAxis = function(target) { - pending: 0, + target = target || this.element; - _create: function() { - var self = this, - doc = this.element[ 0 ].ownerDocument, - suppressKeyPress; + for(var i in this.handles) { - this.element - .addClass( "ui-autocomplete-input" ) - .attr( "autocomplete", "off" ) - // TODO verify these actually work as intended - .attr({ - role: "textbox", - "aria-autocomplete": "list", - "aria-haspopup": "true" - }) - .bind( "keydown.autocomplete", function( event ) { - if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) { - return; - } + if(this.handles[i].constructor == String) + this.handles[i] = $(this.handles[i], this.element).show(); - suppressKeyPress = false; - var keyCode = $.ui.keyCode; - switch( event.keyCode ) { - case keyCode.PAGE_UP: - self._move( "previousPage", event ); - break; - case keyCode.PAGE_DOWN: - self._move( "nextPage", event ); - break; - case keyCode.UP: - self._move( "previous", event ); - // prevent moving cursor to beginning of text field in some browsers - event.preventDefault(); - break; - case keyCode.DOWN: - self._move( "next", event ); - // prevent moving cursor to end of text field in some browsers - event.preventDefault(); - break; - case keyCode.ENTER: - case keyCode.NUMPAD_ENTER: - // when menu is open and has focus - if ( self.menu.active ) { - // #6055 - Opera still allows the keypress to occur - // which causes forms to submit - suppressKeyPress = true; - event.preventDefault(); - } - //passthrough - ENTER and TAB both select the current element - case keyCode.TAB: - if ( !self.menu.active ) { - return; - } - self.menu.select( event ); - break; - case keyCode.ESCAPE: - self.element.val( self.term ); - self.close( event ); - break; - default: - // keypress is triggered before the input value is changed - clearTimeout( self.searching ); - self.searching = setTimeout(function() { - // only search if the value has changed - if ( self.term != self.element.val() ) { - self.selectedItem = null; - self.search( null, event ); - } - }, self.options.delay ); - break; - } - }) - .bind( "keypress.autocomplete", function( event ) { - if ( suppressKeyPress ) { - suppressKeyPress = false; - event.preventDefault(); - } - }) - .bind( "focus.autocomplete", function() { - if ( self.options.disabled ) { - return; - } + //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { + + var axis = $(this.handles[i], this.element), padWrapper = 0; + + //Checking the correct pad and border + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); + + //The padding type i have to apply... + var padPos = [ 'padding', + /ne|nw|n/.test(i) ? 'Top' : + /se|sw|s/.test(i) ? 'Bottom' : + /^e$/.test(i) ? 'Right' : 'Left' ].join(""); + + target.css(padPos, padWrapper); + + this._proportionallyResize(); - self.selectedItem = null; - self.previous = self.element.val(); - }) - .bind( "blur.autocomplete", function( event ) { - if ( self.options.disabled ) { - return; } - clearTimeout( self.searching ); - // clicks on the menu (or a button to trigger a search) will cause a blur event - self.closing = setTimeout(function() { - self.close( event ); - self._change( event ); - }, 150 ); - }); - this._initSource(); - this.response = function() { - return self._response.apply( self, arguments ); + //TODO: What's that good for? There's not anything to be executed left + if(!$(this.handles[i]).length) + continue; + + } }; - this.menu = $( "
          " ) - .addClass( "ui-autocomplete" ) - .appendTo( $( this.options.appendTo || "body", doc )[0] ) - // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) - .mousedown(function( event ) { - // clicking on the scrollbar causes focus to shift to the body - // but we can't detect a mouseup or a click immediately afterward - // so we have to track the next mousedown and close the menu if - // the user clicks somewhere outside of the autocomplete - var menuElement = self.menu.element[ 0 ]; - if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { - setTimeout(function() { - $( document ).one( 'mousedown', function( event ) { - if ( event.target !== self.element[ 0 ] && - event.target !== menuElement && - !$.ui.contains( menuElement, event.target ) ) { - self.close(); - } - }); - }, 1 ); - } - // use another timeout to make sure the blur-event-handler on the input was already triggered - setTimeout(function() { - clearTimeout( self.closing ); - }, 13); - }) - .menu({ - focus: function( event, ui ) { - var item = ui.item.data( "item.autocomplete" ); - if ( false !== self._trigger( "focus", event, { item: item } ) ) { - // use value to match what will end up in the input, if it was a key event - if ( /^key/.test(event.originalEvent.type) ) { - self.element.val( item.value ); - } - } - }, - selected: function( event, ui ) { - var item = ui.item.data( "item.autocomplete" ), - previous = self.previous; - - // only trigger when focus was lost (click on menu) - if ( self.element[0] !== doc.activeElement ) { - self.element.focus(); - self.previous = previous; - // #6109 - IE triggers two focus events and the second - // is asynchronous, so we need to reset the previous - // term synchronously and asynchronously :-( - setTimeout(function() { - self.previous = previous; - self.selectedItem = item; - }, 1); - } + //TODO: make renderAxis a prototype function + this._renderAxis(this.element); - if ( false !== self._trigger( "select", event, { item: item } ) ) { - self.element.val( item.value ); - } - // reset the term after the select event - // this allows custom select handling to work properly - self.term = self.element.val(); + this._handles = $('.ui-resizable-handle', this.element) + .disableSelection(); - self.close( event ); - self.selectedItem = item; - }, - blur: function( event, ui ) { - // don't set the value of the text field if it's already correct - // this prevents moving the cursor unnecessarily - if ( self.menu.element.is(":visible") && - ( self.element.val() !== self.term ) ) { - self.element.val( self.term ); + //Matching axis name + this._handles.mouseover(function() { + if (!that.resizing) { + if (this.className) + var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); + //Axis, default = se + that.axis = axis && axis[1] ? axis[1] : 'se'; + } + }); + + //If we want to auto hide the elements + if (o.autoHide) { + this._handles.hide(); + $(this.element) + .addClass("ui-resizable-autohide") + .mouseenter(function() { + if (o.disabled) return; + $(this).removeClass("ui-resizable-autohide"); + that._handles.show(); + }) + .mouseleave(function(){ + if (o.disabled) return; + if (!that.resizing) { + $(this).addClass("ui-resizable-autohide"); + that._handles.hide(); } - } - }) - .zIndex( this.element.zIndex() + 1 ) - // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 - .css({ top: 0, left: 0 }) - .hide() - .data( "menu" ); - if ( $.fn.bgiframe ) { - this.menu.element.bgiframe(); + }); } - }, - destroy: function() { - this.element - .removeClass( "ui-autocomplete-input" ) - .removeAttr( "autocomplete" ) - .removeAttr( "role" ) - .removeAttr( "aria-autocomplete" ) - .removeAttr( "aria-haspopup" ); - this.menu.element.remove(); - $.Widget.prototype.destroy.call( this ); + //Initialize the mouse interaction + this._mouseInit(); + }, - _setOption: function( key, value ) { - $.Widget.prototype._setOption.apply( this, arguments ); - if ( key === "source" ) { - this._initSource(); - } - if ( key === "appendTo" ) { - this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) - } - if ( key === "disabled" && value && this.xhr ) { - this.xhr.abort(); + _destroy: function() { + + this._mouseDestroy(); + + var _destroy = function(exp) { + $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") + .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); + }; + + //TODO: Unwrap at same DOM position + if (this.elementIsWrapper) { + _destroy(this.element); + var wrapper = this.element; + this.originalElement.css({ + position: wrapper.css('position'), + width: wrapper.outerWidth(), + height: wrapper.outerHeight(), + top: wrapper.css('top'), + left: wrapper.css('left') + }).insertAfter( wrapper ); + wrapper.remove(); } + + this.originalElement.css('resize', this.originalResizeStyle); + _destroy(this.originalElement); + + return this; }, - _initSource: function() { - var self = this, - array, - url; - if ( $.isArray(this.options.source) ) { - array = this.options.source; - this.source = function( request, response ) { - response( $.ui.autocomplete.filter(array, request.term) ); - }; - } else if ( typeof this.options.source === "string" ) { - url = this.options.source; - this.source = function( request, response ) { - if ( self.xhr ) { - self.xhr.abort(); - } - self.xhr = $.ajax({ - url: url, - data: request, - dataType: "json", - autocompleteRequest: ++requestIndex, - success: function( data, status ) { - if ( this.autocompleteRequest === requestIndex ) { - response( data ); - } - }, - error: function() { - if ( this.autocompleteRequest === requestIndex ) { - response( [] ); - } - } - }); - }; - } else { - this.source = this.options.source; + _mouseCapture: function(event) { + var handle = false; + for (var i in this.handles) { + if ($(this.handles[i])[0] == event.target) { + handle = true; + } } + + return !this.options.disabled && handle; }, - search: function( value, event ) { - value = value != null ? value : this.element.val(); + _mouseStart: function(event) { - // always save the actual value, not the one passed as an argument - this.term = this.element.val(); + var o = this.options, iniPos = this.element.position(), el = this.element; - if ( value.length < this.options.minLength ) { - return this.close( event ); + this.resizing = true; + this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; + + // bugfix for http://dev.jquery.com/ticket/1749 + if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { + el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); } - clearTimeout( this.closing ); - if ( this._trigger( "search", event ) === false ) { - return; + this._renderProxy(); + + var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); + + if (o.containment) { + curleft += $(o.containment).scrollLeft() || 0; + curtop += $(o.containment).scrollTop() || 0; } - return this._search( value ); - }, + //Store needed variables + this.offset = this.helper.offset(); + this.position = { left: curleft, top: curtop }; + this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalPosition = { left: curleft, top: curtop }; + this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; + this.originalMousePosition = { left: event.pageX, top: event.pageY }; - _search: function( value ) { - this.pending++; - this.element.addClass( "ui-autocomplete-loading" ); + //Aspect Ratio + this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); - this.source( { term: value }, this.response ); - }, + var cursor = $('.ui-resizable-' + this.axis).css('cursor'); + $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); - _response: function( content ) { - if ( !this.options.disabled && content && content.length ) { - content = this._normalize( content ); - this._suggest( content ); - this._trigger( "open" ); - } else { - this.close(); - } - this.pending--; - if ( !this.pending ) { - this.element.removeClass( "ui-autocomplete-loading" ); - } + el.addClass("ui-resizable-resizing"); + this._propagate("start", event); + return true; }, - close: function( event ) { - clearTimeout( this.closing ); - if ( this.menu.element.is(":visible") ) { - this.menu.element.hide(); - this.menu.deactivate(); - this._trigger( "close", event ); - } - }, - - _change: function( event ) { - if ( this.previous !== this.element.val() ) { - this._trigger( "change", event, { item: this.selectedItem } ); - } + _mouseDrag: function(event) { + + //Increase performance, avoid regex + var el = this.helper, o = this.options, props = {}, + that = this, smp = this.originalMousePosition, a = this.axis; + + var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; + var trigger = this._change[a]; + if (!trigger) return false; + + // Calculate the attrs that will be change + var data = trigger.apply(this, [event, dx, dy]); + + // Put this in the mouseDrag handler since the user can start pressing shift while resizing + this._updateVirtualBoundaries(event.shiftKey); + if (this._aspectRatio || event.shiftKey) + data = this._updateRatio(data, event); + + data = this._respectSize(data, event); + + // plugins callbacks need to be called first + this._propagate("resize", event); + + el.css({ + top: this.position.top + "px", left: this.position.left + "px", + width: this.size.width + "px", height: this.size.height + "px" + }); + + if (!this._helper && this._proportionallyResizeElements.length) + this._proportionallyResize(); + + this._updateCache(data); + + // calling the user callback at the end + this._trigger('resize', event, this.ui()); + + return false; }, - _normalize: function( items ) { - // assume all items have the right format when the first item is complete - if ( items.length && items[0].label && items[0].value ) { - return items; + _mouseStop: function(event) { + + this.resizing = false; + var o = this.options, that = this; + + if(this._helper) { + var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height, + soffsetw = ista ? 0 : that.sizeDiff.width; + + var s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }, + left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null, + top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null; + + if (!o.animate) + this.element.css($.extend(s, { top: top, left: left })); + + that.helper.height(that.size.height); + that.helper.width(that.size.width); + + if (this._helper && !o.animate) this._proportionallyResize(); } - return $.map( items, function(item) { - if ( typeof item === "string" ) { - return { - label: item, - value: item - }; - } - return $.extend({ - label: item.label || item.value, - value: item.value || item.label - }, item ); - }); + + $('body').css('cursor', 'auto'); + + this.element.removeClass("ui-resizable-resizing"); + + this._propagate("stop", event); + + if (this._helper) this.helper.remove(); + return false; + }, - _suggest: function( items ) { - var ul = this.menu.element - .empty() - .zIndex( this.element.zIndex() + 1 ); - this._renderMenu( ul, items ); - // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate - this.menu.deactivate(); - this.menu.refresh(); + _updateVirtualBoundaries: function(forceAspectRatio) { + var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b; - // size and position menu - ul.show(); - this._resizeMenu(); - ul.position( $.extend({ - of: this.element - }, this.options.position )); + b = { + minWidth: isNumber(o.minWidth) ? o.minWidth : 0, + maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, + minHeight: isNumber(o.minHeight) ? o.minHeight : 0, + maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity + }; - if ( this.options.autoFocus ) { - this.menu.next( new $.Event("mouseover") ); + if(this._aspectRatio || forceAspectRatio) { + // We want to create an enclosing box whose aspect ration is the requested one + // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension + pMinWidth = b.minHeight * this.aspectRatio; + pMinHeight = b.minWidth / this.aspectRatio; + pMaxWidth = b.maxHeight * this.aspectRatio; + pMaxHeight = b.maxWidth / this.aspectRatio; + + if(pMinWidth > b.minWidth) b.minWidth = pMinWidth; + if(pMinHeight > b.minHeight) b.minHeight = pMinHeight; + if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth; + if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight; } + this._vBoundaries = b; }, - _resizeMenu: function() { - var ul = this.menu.element; - ul.outerWidth( Math.max( - ul.width( "" ).outerWidth(), - this.element.outerWidth() - ) ); + _updateCache: function(data) { + var o = this.options; + this.offset = this.helper.offset(); + if (isNumber(data.left)) this.position.left = data.left; + if (isNumber(data.top)) this.position.top = data.top; + if (isNumber(data.height)) this.size.height = data.height; + if (isNumber(data.width)) this.size.width = data.width; }, - _renderMenu: function( ul, items ) { - var self = this; - $.each( items, function( index, item ) { - self._renderItem( ul, item ); - }); - }, + _updateRatio: function(data, event) { - _renderItem: function( ul, item) { - return $( "
        • " ) - .data( "item.autocomplete", item ) - .append( $( "" ).text( item.label ) ) - .appendTo( ul ); - }, + var o = this.options, cpos = this.position, csize = this.size, a = this.axis; - _move: function( direction, event ) { - if ( !this.menu.element.is(":visible") ) { - this.search( null, event ); - return; + if (isNumber(data.height)) data.width = (data.height * this.aspectRatio); + else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio); + + if (a == 'sw') { + data.left = cpos.left + (csize.width - data.width); + data.top = null; } - if ( this.menu.first() && /^previous/.test(direction) || - this.menu.last() && /^next/.test(direction) ) { - this.element.val( this.term ); - this.menu.deactivate(); - return; + if (a == 'nw') { + data.top = cpos.top + (csize.height - data.height); + data.left = cpos.left + (csize.width - data.width); } - this.menu[ direction ]( event ); - }, - - widget: function() { - return this.menu.element; - } -}); -$.extend( $.ui.autocomplete, { - escapeRegex: function( value ) { - return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + return data; }, - filter: function(array, term) { - var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); - return $.grep( array, function(value) { - return matcher.test( value.label || value.value || value ); - }); - } -}); -}( jQuery )); + _respectSize: function(data, event) { -/* - * jQuery UI Menu (not officially released) - * - * This widget isn't yet finished and the API is subject to change. We plan to finish - * it for the next release. You're welcome to give it a try anyway and give us feedback, - * as long as you're okay with migrating your code later on. We can help with that, too. - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Menu - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function($) { + var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, + ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), + isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); -$.widget("ui.menu", { - _create: function() { - var self = this; - this.element - .addClass("ui-menu ui-widget ui-widget-content ui-corner-all") - .attr({ - role: "listbox", - "aria-activedescendant": "ui-active-menuitem" - }) - .click(function( event ) { - if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) { - return; - } - // temporary - event.preventDefault(); - self.select( event ); - }); - this.refresh(); - }, - - refresh: function() { - var self = this; - - // don't refresh list items that are already adapted - var items = this.element.children("li:not(.ui-menu-item):has(a)") - .addClass("ui-menu-item") - .attr("role", "menuitem"); - - items.children("a") - .addClass("ui-corner-all") - .attr("tabindex", -1) - // mouseenter doesn't work with event delegation - .mouseenter(function( event ) { - self.activate( event, $(this).parent() ); - }) - .mouseleave(function() { - self.deactivate(); - }); - }, + if (isminw) data.width = o.minWidth; + if (isminh) data.height = o.minHeight; + if (ismaxw) data.width = o.maxWidth; + if (ismaxh) data.height = o.maxHeight; - activate: function( event, item ) { - this.deactivate(); - if (this.hasScroll()) { - var offset = item.offset().top - this.element.offset().top, - scroll = this.element.scrollTop(), - elementHeight = this.element.height(); - if (offset < 0) { - this.element.scrollTop( scroll + offset); - } else if (offset >= elementHeight) { - this.element.scrollTop( scroll + offset - elementHeight + item.height()); - } - } - this.active = item.eq(0) - .children("a") - .addClass("ui-state-hover") - .attr("id", "ui-active-menuitem") - .end(); - this._trigger("focus", event, { item: item }); - }, + var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; + var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); - deactivate: function() { - if (!this.active) { return; } + if (isminw && cw) data.left = dw - o.minWidth; + if (ismaxw && cw) data.left = dw - o.maxWidth; + if (isminh && ch) data.top = dh - o.minHeight; + if (ismaxh && ch) data.top = dh - o.maxHeight; - this.active.children("a") - .removeClass("ui-state-hover") - .removeAttr("id"); - this._trigger("blur"); - this.active = null; - }, + // fixing jump error on top/left - bug #2330 + var isNotwh = !data.width && !data.height; + if (isNotwh && !data.left && data.top) data.top = null; + else if (isNotwh && !data.top && data.left) data.left = null; - next: function(event) { - this.move("next", ".ui-menu-item:first", event); + return data; }, - previous: function(event) { - this.move("prev", ".ui-menu-item:last", event); - }, + _proportionallyResize: function() { - first: function() { - return this.active && !this.active.prevAll(".ui-menu-item").length; - }, + var o = this.options; + if (!this._proportionallyResizeElements.length) return; + var element = this.helper || this.element; - last: function() { - return this.active && !this.active.nextAll(".ui-menu-item").length; - }, + for (var i=0; i < this._proportionallyResizeElements.length; i++) { - move: function(direction, edge, event) { - if (!this.active) { - this.activate(event, this.element.children(edge)); - return; - } - var next = this.active[direction + "All"](".ui-menu-item").eq(0); - if (next.length) { - this.activate(event, next); - } else { - this.activate(event, this.element.children(edge)); - } - }, + var prel = this._proportionallyResizeElements[i]; - // TODO merge with previousPage - nextPage: function(event) { - if (this.hasScroll()) { - // TODO merge with no-scroll-else - if (!this.active || this.last()) { - this.activate(event, this.element.children(".ui-menu-item:first")); - return; - } - var base = this.active.offset().top, - height = this.element.height(), - result = this.element.children(".ui-menu-item").filter(function() { - var close = $(this).offset().top - base - height + $(this).height(); - // TODO improve approximation - return close < 10 && close > -10; - }); + if (!this.borderDif) { + var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], + p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; - // TODO try to catch this earlier when scrollTop indicates the last page anyway - if (!result.length) { - result = this.element.children(".ui-menu-item:last"); + this.borderDif = $.map(b, function(v, i) { + var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; + return border + padding; + }); } - this.activate(event, result); - } else { - this.activate(event, this.element.children(".ui-menu-item") - .filter(!this.active || this.last() ? ":first" : ":last")); - } - }, - // TODO merge with nextPage - previousPage: function(event) { - if (this.hasScroll()) { - // TODO merge with no-scroll-else - if (!this.active || this.first()) { - this.activate(event, this.element.children(".ui-menu-item:last")); - return; - } + prel.css({ + height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, + width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 + }); - var base = this.active.offset().top, - height = this.element.height(); - result = this.element.children(".ui-menu-item").filter(function() { - var close = $(this).offset().top - base + height - $(this).height(); - // TODO improve approximation - return close < 10 && close > -10; - }); + }; - // TODO try to catch this earlier when scrollTop indicates the last page anyway - if (!result.length) { - result = this.element.children(".ui-menu-item:first"); - } - this.activate(event, result); - } else { - this.activate(event, this.element.children(".ui-menu-item") - .filter(!this.active || this.first() ? ":last" : ":first")); - } }, - hasScroll: function() { - return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight"); - }, + _renderProxy: function() { - select: function( event ) { - this._trigger("selected", event, { item: this.active }); - } -}); + var el = this.element, o = this.options; + this.elementOffset = el.offset(); -}(jQuery)); -/* - * jQuery UI Button 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Button - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function( $, undefined ) { + if(this._helper) { -var lastActive, startXPos, startYPos, clickDragged, - baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", - stateClasses = "ui-state-hover ui-state-active ", - typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", - formResetHandler = function() { - var buttons = $( this ).find( ":ui-button" ); - setTimeout(function() { - buttons.button( "refresh" ); - }, 1 ); - }, - radioGroup = function( radio ) { - var name = radio.name, - form = radio.form, - radios = $( [] ); - if ( name ) { - if ( form ) { - radios = $( form ).find( "[name='" + name + "']" ); - } else { - radios = $( "[name='" + name + "']", radio.ownerDocument ) - .filter(function() { - return !this.form; - }); - } + this.helper = this.helper || $('
          '); + + // fix ie6 offset TODO: This seems broken + var ie6offset = ($.ui.ie6 ? 1 : 0), + pxyoffset = ( $.ui.ie6 ? 2 : -1 ); + + this.helper.addClass(this._helper).css({ + width: this.element.outerWidth() + pxyoffset, + height: this.element.outerHeight() + pxyoffset, + position: 'absolute', + left: this.elementOffset.left - ie6offset +'px', + top: this.elementOffset.top - ie6offset +'px', + zIndex: ++o.zIndex //TODO: Don't modify option + }); + + this.helper + .appendTo("body") + .disableSelection(); + + } else { + this.helper = this.element; } - return radios; - }; -$.widget( "ui.button", { - options: { - disabled: null, - text: true, - label: null, - icons: { - primary: null, - secondary: null + }, + + _change: { + e: function(event, dx, dy) { + return { width: this.originalSize.width + dx }; + }, + w: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { left: sp.left + dx, width: cs.width - dx }; + }, + n: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { top: sp.top + dy, height: cs.height - dy }; + }, + s: function(event, dx, dy) { + return { height: this.originalSize.height + dy }; + }, + se: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + sw: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + }, + ne: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + nw: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); } }, - _create: function() { - this.element.closest( "form" ) - .unbind( "reset.button" ) - .bind( "reset.button", formResetHandler ); - if ( typeof this.options.disabled !== "boolean" ) { - this.options.disabled = this.element.propAttr( "disabled" ); - } + _propagate: function(n, event) { + $.ui.plugin.call(this, n, [event, this.ui()]); + (n != "resize" && this._trigger(n, event, this.ui())); + }, - this._determineButtonType(); - this.hasTitle = !!this.buttonElement.attr( "title" ); + plugins: {}, - var self = this, - options = this.options, - toggleButton = this.type === "checkbox" || this.type === "radio", - hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ), - focusClass = "ui-state-focus"; + ui: function() { + return { + originalElement: this.originalElement, + element: this.element, + helper: this.helper, + position: this.position, + size: this.size, + originalSize: this.originalSize, + originalPosition: this.originalPosition + }; + } - if ( options.label === null ) { - options.label = this.buttonElement.html(); - } +}); - if ( this.element.is( ":disabled" ) ) { - options.disabled = true; - } +/* + * Resizable Extensions + */ - this.buttonElement - .addClass( baseClasses ) - .attr( "role", "button" ) - .bind( "mouseenter.button", function() { - if ( options.disabled ) { - return; - } - $( this ).addClass( "ui-state-hover" ); - if ( this === lastActive ) { - $( this ).addClass( "ui-state-active" ); - } - }) - .bind( "mouseleave.button", function() { - if ( options.disabled ) { - return; - } - $( this ).removeClass( hoverClass ); - }) - .bind( "click.button", function( event ) { - if ( options.disabled ) { - event.preventDefault(); - event.stopImmediatePropagation(); - } - }); +$.ui.plugin.add("resizable", "alsoResize", { - this.element - .bind( "focus.button", function() { - // no need to check disabled, focus won't be triggered anyway - self.buttonElement.addClass( focusClass ); - }) - .bind( "blur.button", function() { - self.buttonElement.removeClass( focusClass ); - }); + start: function (event, ui) { + var that = $(this).data("resizable"), o = that.options; - if ( toggleButton ) { - this.element.bind( "change.button", function() { - if ( clickDragged ) { - return; - } - self.refresh(); - }); - // if mouse moves between mousedown and mouseup (drag) set clickDragged flag - // prevents issue where button state changes but checkbox/radio checked state - // does not in Firefox (see ticket #6970) - this.buttonElement - .bind( "mousedown.button", function( event ) { - if ( options.disabled ) { - return; - } - clickDragged = false; - startXPos = event.pageX; - startYPos = event.pageY; - }) - .bind( "mouseup.button", function( event ) { - if ( options.disabled ) { - return; - } - if ( startXPos !== event.pageX || startYPos !== event.pageY ) { - clickDragged = true; - } + var _store = function (exp) { + $(exp).each(function() { + var el = $(this); + el.data("resizable-alsoresize", { + width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), + left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10) + }); }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { + if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } + else { $.each(o.alsoResize, function (exp) { _store(exp); }); } + }else{ + _store(o.alsoResize); } + }, - if ( this.type === "checkbox" ) { - this.buttonElement.bind( "click.button", function() { - if ( options.disabled || clickDragged ) { - return false; - } - $( this ).toggleClass( "ui-state-active" ); - self.buttonElement.attr( "aria-pressed", self.element[0].checked ); - }); - } else if ( this.type === "radio" ) { - this.buttonElement.bind( "click.button", function() { - if ( options.disabled || clickDragged ) { - return false; - } - $( this ).addClass( "ui-state-active" ); - self.buttonElement.attr( "aria-pressed", "true" ); + resize: function (event, ui) { + var that = $(this).data("resizable"), o = that.options, os = that.originalSize, op = that.originalPosition; - var radio = self.element[ 0 ]; - radioGroup( radio ) - .not( radio ) - .map(function() { - return $( this ).button( "widget" )[ 0 ]; - }) - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - }); - } else { - this.buttonElement - .bind( "mousedown.button", function() { - if ( options.disabled ) { - return false; - } - $( this ).addClass( "ui-state-active" ); - lastActive = this; - $( document ).one( "mouseup", function() { - lastActive = null; - }); - }) - .bind( "mouseup.button", function() { - if ( options.disabled ) { - return false; - } - $( this ).removeClass( "ui-state-active" ); - }) - .bind( "keydown.button", function(event) { - if ( options.disabled ) { - return false; - } - if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) { - $( this ).addClass( "ui-state-active" ); - } - }) - .bind( "keyup.button", function() { - $( this ).removeClass( "ui-state-active" ); - }); + var delta = { + height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, + top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 + }, - if ( this.buttonElement.is("a") ) { - this.buttonElement.keyup(function(event) { - if ( event.keyCode === $.ui.keyCode.SPACE ) { - // TODO pass through original event correctly (just as 2nd argument doesn't work) - $( this ).click(); - } + _alsoResize = function (exp, c) { + $(exp).each(function() { + var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, + css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; + + $.each(css, function (i, prop) { + var sum = (start[prop]||0) + (delta[prop]||0); + if (sum && sum >= 0) + style[prop] = sum || null; }); - } - } - // TODO: pull out $.Widget's handling for the disabled option into - // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can - // be overridden by individual plugins - this._setOption( "disabled", options.disabled ); - this._resetButton(); + el.css(style); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { + $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); + }else{ + _alsoResize(o.alsoResize); + } }, - _determineButtonType: function() { + stop: function (event, ui) { + $(this).removeData("resizable-alsoresize"); + } +}); - if ( this.element.is(":checkbox") ) { - this.type = "checkbox"; - } else if ( this.element.is(":radio") ) { - this.type = "radio"; - } else if ( this.element.is("input") ) { - this.type = "input"; - } else { - this.type = "button"; - } +$.ui.plugin.add("resizable", "animate", { + + stop: function(event, ui) { + var that = $(this).data("resizable"), o = that.options; + + var pr = that._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height, + soffsetw = ista ? 0 : that.sizeDiff.width; + + var style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, + left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null, + top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null; + + that.element.animate( + $.extend(style, top && left ? { top: top, left: left } : {}), { + duration: o.animateDuration, + easing: o.animateEasing, + step: function() { + + var data = { + width: parseInt(that.element.css('width'), 10), + height: parseInt(that.element.css('height'), 10), + top: parseInt(that.element.css('top'), 10), + left: parseInt(that.element.css('left'), 10) + }; + + if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); + + // propagating resize, and updating values for each animation step + that._updateCache(data); + that._propagate("resize", event); - if ( this.type === "checkbox" || this.type === "radio" ) { - // we don't search against the document in case the element - // is disconnected from the DOM - var ancestor = this.element.parents().filter(":last"), - labelSelector = "label[for='" + this.element.attr("id") + "']"; - this.buttonElement = ancestor.find( labelSelector ); - if ( !this.buttonElement.length ) { - ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); - this.buttonElement = ancestor.filter( labelSelector ); - if ( !this.buttonElement.length ) { - this.buttonElement = ancestor.find( labelSelector ); } } - this.element.addClass( "ui-helper-hidden-accessible" ); + ); + } - var checked = this.element.is( ":checked" ); - if ( checked ) { - this.buttonElement.addClass( "ui-state-active" ); - } - this.buttonElement.attr( "aria-pressed", checked ); - } else { - this.buttonElement = this.element; - } - }, +}); - widget: function() { - return this.buttonElement; - }, +$.ui.plugin.add("resizable", "containment", { - destroy: function() { - this.element - .removeClass( "ui-helper-hidden-accessible" ); - this.buttonElement - .removeClass( baseClasses + " " + stateClasses + " " + typeClasses ) - .removeAttr( "role" ) - .removeAttr( "aria-pressed" ) - .html( this.buttonElement.find(".ui-button-text").html() ); + start: function(event, ui) { + var that = $(this).data("resizable"), o = that.options, el = that.element; + var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; + if (!ce) return; - if ( !this.hasTitle ) { - this.buttonElement.removeAttr( "title" ); + that.containerElement = $(ce); + + if (/document/.test(oc) || oc == document) { + that.containerOffset = { left: 0, top: 0 }; + that.containerPosition = { left: 0, top: 0 }; + + that.parentData = { + element: $(document), left: 0, top: 0, + width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight + }; } - $.Widget.prototype.destroy.call( this ); - }, + // i'm a node, so compute top, left, right, bottom + else { + var element = $(ce), p = []; + $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); - _setOption: function( key, value ) { - $.Widget.prototype._setOption.apply( this, arguments ); - if ( key === "disabled" ) { - if ( value ) { - this.element.propAttr( "disabled", true ); - } else { - this.element.propAttr( "disabled", false ); - } - return; + that.containerOffset = element.offset(); + that.containerPosition = element.position(); + that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; + + var co = that.containerOffset, ch = that.containerSize.height, cw = that.containerSize.width, + width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); + + that.parentData = { + element: ce, left: co.left, top: co.top, width: width, height: height + }; } - this._resetButton(); }, - refresh: function() { - var isDisabled = this.element.is( ":disabled" ); - if ( isDisabled !== this.options.disabled ) { - this._setOption( "disabled", isDisabled ); - } - if ( this.type === "radio" ) { - radioGroup( this.element[0] ).each(function() { - if ( $( this ).is( ":checked" ) ) { - $( this ).button( "widget" ) - .addClass( "ui-state-active" ) - .attr( "aria-pressed", "true" ); - } else { - $( this ).button( "widget" ) - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - } - }); - } else if ( this.type === "checkbox" ) { - if ( this.element.is( ":checked" ) ) { - this.buttonElement - .addClass( "ui-state-active" ) - .attr( "aria-pressed", "true" ); - } else { - this.buttonElement - .removeClass( "ui-state-active" ) - .attr( "aria-pressed", "false" ); - } + resize: function(event, ui) { + var that = $(this).data("resizable"), o = that.options, + ps = that.containerSize, co = that.containerOffset, cs = that.size, cp = that.position, + pRatio = that._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = that.containerElement; + + if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; + + if (cp.left < (that._helper ? co.left : 0)) { + that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); + if (pRatio) that.size.height = that.size.width / that.aspectRatio; + that.position.left = o.helper ? co.left : 0; } - }, - _resetButton: function() { - if ( this.type === "input" ) { - if ( this.options.label ) { - this.element.val( this.options.label ); - } - return; + if (cp.top < (that._helper ? co.top : 0)) { + that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); + if (pRatio) that.size.width = that.size.height * that.aspectRatio; + that.position.top = that._helper ? co.top : 0; } - var buttonElement = this.buttonElement.removeClass( typeClasses ), - buttonText = $( "" ) - .addClass( "ui-button-text" ) - .html( this.options.label ) - .appendTo( buttonElement.empty() ) - .text(), - icons = this.options.icons, - multipleIcons = icons.primary && icons.secondary, - buttonClasses = []; - if ( icons.primary || icons.secondary ) { - if ( this.options.text ) { - buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); - } + that.offset.left = that.parentData.left+that.position.left; + that.offset.top = that.parentData.top+that.position.top; - if ( icons.primary ) { - buttonElement.prepend( "" ); - } + var woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ), + hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); - if ( icons.secondary ) { - buttonElement.append( "" ); - } + var isParent = that.containerElement.get(0) == that.element.parent().get(0), + isOffsetRelative = /relative|absolute/.test(that.containerElement.css('position')); - if ( !this.options.text ) { - buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); + if(isParent && isOffsetRelative) woset -= that.parentData.left; - if ( !this.hasTitle ) { - buttonElement.attr( "title", buttonText ); - } - } - } else { - buttonClasses.push( "ui-button-text-only" ); + if (woset + that.size.width >= that.parentData.width) { + that.size.width = that.parentData.width - woset; + if (pRatio) that.size.height = that.size.width / that.aspectRatio; } - buttonElement.addClass( buttonClasses.join( " " ) ); + + if (hoset + that.size.height >= that.parentData.height) { + that.size.height = that.parentData.height - hoset; + if (pRatio) that.size.width = that.size.height * that.aspectRatio; + } + }, + + stop: function(event, ui){ + var that = $(this).data("resizable"), o = that.options, cp = that.position, + co = that.containerOffset, cop = that.containerPosition, ce = that.containerElement; + + var helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height; + + if (that._helper && !o.animate && (/relative/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + if (that._helper && !o.animate && (/static/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + } }); -$.widget( "ui.buttonset", { - options: { - items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" - }, +$.ui.plugin.add("resizable", "ghost", { - _create: function() { - this.element.addClass( "ui-buttonset" ); - }, - - _init: function() { - this.refresh(); - }, + start: function(event, ui) { - _setOption: function( key, value ) { - if ( key === "disabled" ) { - this.buttons.button( "option", key, value ); - } + var that = $(this).data("resizable"), o = that.options, cs = that.size; + + that.ghost = that.originalElement.clone(); + that.ghost + .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) + .addClass('ui-resizable-ghost') + .addClass(typeof o.ghost == 'string' ? o.ghost : ''); + + that.ghost.appendTo(that.helper); - $.Widget.prototype._setOption.apply( this, arguments ); - }, - - refresh: function() { - var ltr = this.element.css( "direction" ) === "ltr"; - - this.buttons = this.element.find( this.options.items ) - .filter( ":ui-button" ) - .button( "refresh" ) - .end() - .not( ":ui-button" ) - .button() - .end() - .map(function() { - return $( this ).button( "widget" )[ 0 ]; - }) - .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) - .filter( ":first" ) - .addClass( ltr ? "ui-corner-left" : "ui-corner-right" ) - .end() - .filter( ":last" ) - .addClass( ltr ? "ui-corner-right" : "ui-corner-left" ) - .end() - .end(); }, - destroy: function() { - this.element.removeClass( "ui-buttonset" ); - this.buttons - .map(function() { - return $( this ).button( "widget" )[ 0 ]; - }) - .removeClass( "ui-corner-left ui-corner-right" ) - .end() - .button( "destroy" ); + resize: function(event, ui){ + var that = $(this).data("resizable"), o = that.options; + if (that.ghost) that.ghost.css({ position: 'relative', height: that.size.height, width: that.size.width }); + }, - $.Widget.prototype.destroy.call( this ); + stop: function(event, ui){ + var that = $(this).data("resizable"), o = that.options; + if (that.ghost && that.helper) that.helper.get(0).removeChild(that.ghost.get(0)); } + }); -}( jQuery ) ); -/* - * jQuery UI Datepicker 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Datepicker - * - * Depends: - * jquery.ui.core.js - */ -(function( $, undefined ) { +$.ui.plugin.add("resizable", "grid", { -$.extend($.ui, { datepicker: { version: "1.8.16" } }); + resize: function(event, ui) { + var that = $(this).data("resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis, ratio = o._aspectRatio || event.shiftKey; + o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; + var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); -var PROP_NAME = 'datepicker'; -var dpuuid = new Date().getTime(); -var instActive; + if (/^(se|s|e)$/.test(a)) { + that.size.width = os.width + ox; + that.size.height = os.height + oy; + } + else if (/^(ne)$/.test(a)) { + that.size.width = os.width + ox; + that.size.height = os.height + oy; + that.position.top = op.top - oy; + } + else if (/^(sw)$/.test(a)) { + that.size.width = os.width + ox; + that.size.height = os.height + oy; + that.position.left = op.left - ox; + } + else { + that.size.width = os.width + ox; + that.size.height = os.height + oy; + that.position.top = op.top - oy; + that.position.left = op.left - ox; + } + } -/* Date picker manager. - Use the singleton instance of this class, $.datepicker, to interact with the date picker. - Settings for (groups of) date pickers are maintained in an instance object, - allowing multiple different settings on the same page. */ +}); -function Datepicker() { - this.debug = false; // Change this to true to start debugging - this._curInst = null; // The current instance in use - this._keyEvent = false; // If the last event was a key event - this._disabledInputs = []; // List of date picker inputs that have been disabled - this._datepickerShowing = false; // True if the popup picker is showing , false if not - this._inDialog = false; // True if showing within a "dialog", false if not - this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division - this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class - this._appendClass = 'ui-datepicker-append'; // The name of the append marker class - this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class - this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class - this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class - this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class - this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class - this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class - this.regional = []; // Available regional settings, indexed by language code - this.regional[''] = { // Default regional settings - closeText: 'Done', // Display text for close link - prevText: 'Prev', // Display text for previous month link - nextText: 'Next', // Display text for next month link - currentText: 'Today', // Display text for current month link - monthNames: ['January','February','March','April','May','June', - 'July','August','September','October','November','December'], // Names of months for drop-down and formatting - monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting - dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting - dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting - dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday - weekHeader: 'Wk', // Column header for week of the year - dateFormat: 'mm/dd/yy', // See format options on parseDate - firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... - isRTL: false, // True if right-to-left language, false if left-to-right - showMonthAfterYear: false, // True if the year select precedes month, false for month then year - yearSuffix: '' // Additional text to append to the year in the month headers - }; - this._defaults = { // Global defaults for all the date picker instances - showOn: 'focus', // 'focus' for popup on focus, - // 'button' for trigger button, or 'both' for either - showAnim: 'fadeIn', // Name of jQuery animation for popup - showOptions: {}, // Options for enhanced animations - defaultDate: null, // Used when field is blank: actual date, - // +/-number for offset from today, null for today - appendText: '', // Display text following the input box, e.g. showing the format - buttonText: '...', // Text for trigger button - buttonImage: '', // URL for trigger button image - buttonImageOnly: false, // True if the image appears alone, false if it appears on a button - hideIfNoPrevNext: false, // True to hide next/previous month links - // if not applicable, false to just disable them - navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links - gotoCurrent: false, // True if today link goes back to current selection instead - changeMonth: false, // True if month can be selected directly, false if only prev/next - changeYear: false, // True if year can be selected directly, false if only prev/next - yearRange: 'c-10:c+10', // Range of years to display in drop-down, - // either relative to today's year (-nn:+nn), relative to currently displayed year - // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) - showOtherMonths: false, // True to show dates in other months, false to leave blank - selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable - showWeek: false, // True to show week of the year, false to not show it - calculateWeek: this.iso8601Week, // How to calculate the week of the year, - // takes a Date and returns the number of the week for it - shortYearCutoff: '+10', // Short year values < this are in the current century, - // > this are in the previous century, - // string value starting with '+' for current year + value - minDate: null, // The earliest selectable date, or null for no limit - maxDate: null, // The latest selectable date, or null for no limit - duration: 'fast', // Duration of display/closure - beforeShowDay: null, // Function that takes a date and returns an array with - // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', - // [2] = cell title (optional), e.g. $.datepicker.noWeekends - beforeShow: null, // Function that takes an input field and - // returns a set of custom settings for the date picker - onSelect: null, // Define a callback function when a date is selected - onChangeMonthYear: null, // Define a callback function when the month or year is changed - onClose: null, // Define a callback function when the datepicker is closed - numberOfMonths: 1, // Number of months to show at a time - showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) - stepMonths: 1, // Number of months to step back/forward - stepBigMonths: 12, // Number of months to step back/forward for the big links - altField: '', // Selector for an alternate field to store selected dates into - altFormat: '', // The date format to use for the alternate field - constrainInput: true, // The input is constrained by the current date format - showButtonPanel: false, // True to show button panel, false to not show it - autoSize: false, // True to size the input for the date format, false to leave as is - disabled: false // The initial disabled state - }; - $.extend(this._defaults, this.regional['']); - this.dpDiv = bindHover($('
          ')); -} +var num = function(v) { + return parseInt(v, 10) || 0; +}; -$.extend(Datepicker.prototype, { - /* Class name added to elements to indicate already configured with a date picker. */ - markerClassName: 'hasDatepicker', - - //Keep track of the maximum number of rows displayed (see #7043) - maxRows: 4, +var isNumber = function(value) { + return !isNaN(parseInt(value, 10)); +}; - /* Debug logging (if enabled). */ - log: function () { - if (this.debug) - console.log.apply('', arguments); - }, - - // TODO rename to "widget" when switching to widget factory - _widgetDatepicker: function() { - return this.dpDiv; - }, +})(jQuery); +(function( $, undefined ) { - /* Override the default settings for all instances of the date picker. - @param settings object - the new settings to use as defaults (anonymous object) - @return the manager object */ - setDefaults: function(settings) { - extendRemove(this._defaults, settings || {}); - return this; +$.widget("ui.selectable", $.ui.mouse, { + version: "1.9.2", + options: { + appendTo: 'body', + autoRefresh: true, + distance: 0, + filter: '*', + tolerance: 'touch' }, + _create: function() { + var that = this; - /* Attach the date picker to a jQuery selection. - @param target element - the target input field or division or span - @param settings object - the new settings to use for this date picker instance (anonymous) */ - _attachDatepicker: function(target, settings) { - // check for settings on the control itself - in namespace 'date:' - var inlineSettings = null; - for (var attrName in this._defaults) { - var attrValue = target.getAttribute('date:' + attrName); - if (attrValue) { - inlineSettings = inlineSettings || {}; - try { - inlineSettings[attrName] = eval(attrValue); - } catch (err) { - inlineSettings[attrName] = attrValue; - } - } - } - var nodeName = target.nodeName.toLowerCase(); - var inline = (nodeName == 'div' || nodeName == 'span'); - if (!target.id) { - this.uuid += 1; - target.id = 'dp' + this.uuid; - } - var inst = this._newInst($(target), inline); - inst.settings = $.extend({}, settings || {}, inlineSettings || {}); - if (nodeName == 'input') { - this._connectDatepicker(target, inst); - } else if (inline) { - this._inlineDatepicker(target, inst); - } + this.element.addClass("ui-selectable"); + + this.dragged = false; + + // cache selectee children based on filter + var selectees; + this.refresh = function() { + selectees = $(that.options.filter, that.element[0]); + selectees.addClass("ui-selectee"); + selectees.each(function() { + var $this = $(this); + var pos = $this.offset(); + $.data(this, "selectable-item", { + element: this, + $element: $this, + left: pos.left, + top: pos.top, + right: pos.left + $this.outerWidth(), + bottom: pos.top + $this.outerHeight(), + startselected: false, + selected: $this.hasClass('ui-selected'), + selecting: $this.hasClass('ui-selecting'), + unselecting: $this.hasClass('ui-unselecting') + }); + }); + }; + this.refresh(); + + this.selectees = selectees.addClass("ui-selectee"); + + this._mouseInit(); + + this.helper = $("
          "); }, - /* Create a new instance object. */ - _newInst: function(target, inline) { - var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars - return {id: id, input: target, // associated target - selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection - drawMonth: 0, drawYear: 0, // month being drawn - inline: inline, // is datepicker inline or not - dpDiv: (!inline ? this.dpDiv : // presentation div - bindHover($('
          ')))}; + _destroy: function() { + this.selectees + .removeClass("ui-selectee") + .removeData("selectable-item"); + this.element + .removeClass("ui-selectable ui-selectable-disabled"); + this._mouseDestroy(); }, - /* Attach the date picker to an input field. */ - _connectDatepicker: function(target, inst) { - var input = $(target); - inst.append = $([]); - inst.trigger = $([]); - if (input.hasClass(this.markerClassName)) + _mouseStart: function(event) { + var that = this; + + this.opos = [event.pageX, event.pageY]; + + if (this.options.disabled) return; - this._attachments(input, inst); - input.addClass(this.markerClassName).keydown(this._doKeyDown). - keypress(this._doKeyPress).keyup(this._doKeyUp). - bind("setData.datepicker", function(event, key, value) { - inst.settings[key] = value; - }).bind("getData.datepicker", function(event, key) { - return this._get(inst, key); - }); - this._autoSize(inst); - $.data(target, PROP_NAME, inst); - //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) - if( inst.settings.disabled ) { - this._disableDatepicker( target ); - } - }, - /* Make attachments based on settings. */ - _attachments: function(input, inst) { - var appendText = this._get(inst, 'appendText'); - var isRTL = this._get(inst, 'isRTL'); - if (inst.append) - inst.append.remove(); - if (appendText) { - inst.append = $('' + appendText + ''); - input[isRTL ? 'before' : 'after'](inst.append); + var options = this.options; + + this.selectees = $(options.filter, this.element[0]); + + this._trigger("start", event); + + $(options.appendTo).append(this.helper); + // position helper (lasso) + this.helper.css({ + "left": event.clientX, + "top": event.clientY, + "width": 0, + "height": 0 + }); + + if (options.autoRefresh) { + this.refresh(); } - input.unbind('focus', this._showDatepicker); - if (inst.trigger) - inst.trigger.remove(); - var showOn = this._get(inst, 'showOn'); - if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field - input.focus(this._showDatepicker); - if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked - var buttonText = this._get(inst, 'buttonText'); - var buttonImage = this._get(inst, 'buttonImage'); - inst.trigger = $(this._get(inst, 'buttonImageOnly') ? - $('').addClass(this._triggerClass). - attr({ src: buttonImage, alt: buttonText, title: buttonText }) : - $('').addClass(this._triggerClass). - html(buttonImage == '' ? buttonText : $('').attr( - { src:buttonImage, alt:buttonText, title:buttonText }))); - input[isRTL ? 'before' : 'after'](inst.trigger); - inst.trigger.click(function() { - if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0]) - $.datepicker._hideDatepicker(); - else - $.datepicker._showDatepicker(input[0]); + + this.selectees.filter('.ui-selected').each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.startselected = true; + if (!event.metaKey && !event.ctrlKey) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + }); + + $(event.target).parents().andSelf().each(function() { + var selectee = $.data(this, "selectable-item"); + if (selectee) { + var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected'); + selectee.$element + .removeClass(doSelect ? "ui-unselecting" : "ui-selected") + .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); + selectee.unselecting = !doSelect; + selectee.selecting = doSelect; + selectee.selected = doSelect; + // selectable (UN)SELECTING callback + if (doSelect) { + that._trigger("selecting", event, { + selecting: selectee.element + }); + } else { + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } return false; - }); - } + } + }); + }, - /* Apply the maximum length for the date format. */ - _autoSize: function(inst) { - if (this._get(inst, 'autoSize') && !inst.inline) { - var date = new Date(2009, 12 - 1, 20); // Ensure double digits - var dateFormat = this._get(inst, 'dateFormat'); - if (dateFormat.match(/[DM]/)) { - var findMax = function(names) { - var max = 0; - var maxI = 0; - for (var i = 0; i < names.length; i++) { - if (names[i].length > max) { - max = names[i].length; - maxI = i; + _mouseDrag: function(event) { + var that = this; + this.dragged = true; + + if (this.options.disabled) + return; + + var options = this.options; + + var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; + if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } + if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } + this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + + this.selectees.each(function() { + var selectee = $.data(this, "selectable-item"); + //prevent helper from being selected if appendTo: selectable + if (!selectee || selectee.element == that.element[0]) + return; + var hit = false; + if (options.tolerance == 'touch') { + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); + } else if (options.tolerance == 'fit') { + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); + } + + if (hit) { + // SELECT + if (selectee.selected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + } + if (selectee.unselecting) { + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + } + if (!selectee.selecting) { + selectee.$element.addClass('ui-selecting'); + selectee.selecting = true; + // selectable SELECTING callback + that._trigger("selecting", event, { + selecting: selectee.element + }); + } + } else { + // UNSELECT + if (selectee.selecting) { + if ((event.metaKey || event.ctrlKey) && selectee.startselected) { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + selectee.$element.addClass('ui-selected'); + selectee.selected = true; + } else { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + if (selectee.startselected) { + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; } + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); } - return maxI; - }; - date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? - 'monthNames' : 'monthNamesShort')))); - date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? - 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay()); + } + if (selectee.selected) { + if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } } - inst.input.attr('size', this._formatDate(inst, date).length); - } + }); + + return false; }, - /* Attach an inline date picker to a div. */ - _inlineDatepicker: function(target, inst) { - var divSpan = $(target); - if (divSpan.hasClass(this.markerClassName)) - return; - divSpan.addClass(this.markerClassName).append(inst.dpDiv). - bind("setData.datepicker", function(event, key, value){ - inst.settings[key] = value; - }).bind("getData.datepicker", function(event, key){ - return this._get(inst, key); + _mouseStop: function(event) { + var that = this; + + this.dragged = false; + + var options = this.options; + + $('.ui-unselecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + selectee.startselected = false; + that._trigger("unselected", event, { + unselected: selectee.element }); - $.data(target, PROP_NAME, inst); - this._setDate(inst, this._getDefaultDate(inst), true); - this._updateDatepicker(inst); - this._updateAlternate(inst); - //If disabled option is true, disable the datepicker before showing it (see ticket #5665) - if( inst.settings.disabled ) { - this._disableDatepicker( target ); - } - // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements - // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height - inst.dpDiv.css( "display", "block" ); - }, + }); + $('.ui-selecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); + selectee.selecting = false; + selectee.selected = true; + selectee.startselected = true; + that._trigger("selected", event, { + selected: selectee.element + }); + }); + this._trigger("stop", event); - /* Pop-up the date picker in a "dialog" box. - @param input element - ignored - @param date string or Date - the initial date to display - @param onSelect function - the function to call when a date is selected - @param settings object - update the dialog date picker instance's settings (anonymous object) - @param pos int[2] - coordinates for the dialog's position within the screen or - event - with x/y coordinates or - leave empty for default (screen centre) - @return the manager object */ - _dialogDatepicker: function(input, date, onSelect, settings, pos) { - var inst = this._dialogInst; // internal instance - if (!inst) { - this.uuid += 1; - var id = 'dp' + this.uuid; - this._dialogInput = $(''); - this._dialogInput.keydown(this._doKeyDown); - $('body').append(this._dialogInput); - inst = this._dialogInst = this._newInst(this._dialogInput, false); - inst.settings = {}; - $.data(this._dialogInput[0], PROP_NAME, inst); - } - extendRemove(inst.settings, settings || {}); - date = (date && date.constructor == Date ? this._formatDate(inst, date) : date); - this._dialogInput.val(date); + this.helper.remove(); - this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); - if (!this._pos) { - var browserWidth = document.documentElement.clientWidth; - var browserHeight = document.documentElement.clientHeight; - var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; - var scrollY = document.documentElement.scrollTop || document.body.scrollTop; - this._pos = // should use actual width/height below - [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; - } + return false; + } - // move input on screen for focus, but hidden behind dialog - this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px'); - inst.settings.onSelect = onSelect; - this._inDialog = true; - this.dpDiv.addClass(this._dialogClass); - this._showDatepicker(this._dialogInput[0]); - if ($.blockUI) - $.blockUI(this.dpDiv); - $.data(this._dialogInput[0], PROP_NAME, inst); - return this; - }, +}); - /* Detach a datepicker from its control. - @param target element - the target input field or division or span */ - _destroyDatepicker: function(target) { - var $target = $(target); - var inst = $.data(target, PROP_NAME); - if (!$target.hasClass(this.markerClassName)) { - return; - } - var nodeName = target.nodeName.toLowerCase(); - $.removeData(target, PROP_NAME); - if (nodeName == 'input') { - inst.append.remove(); - inst.trigger.remove(); - $target.removeClass(this.markerClassName). - unbind('focus', this._showDatepicker). - unbind('keydown', this._doKeyDown). - unbind('keypress', this._doKeyPress). - unbind('keyup', this._doKeyUp); - } else if (nodeName == 'div' || nodeName == 'span') - $target.removeClass(this.markerClassName).empty(); - }, +})(jQuery); +(function( $, undefined ) { - /* Enable the date picker to a jQuery selection. - @param target element - the target input field or division or span */ - _enableDatepicker: function(target) { - var $target = $(target); - var inst = $.data(target, PROP_NAME); - if (!$target.hasClass(this.markerClassName)) { - return; - } - var nodeName = target.nodeName.toLowerCase(); - if (nodeName == 'input') { - target.disabled = false; - inst.trigger.filter('button'). - each(function() { this.disabled = false; }).end(). - filter('img').css({opacity: '1.0', cursor: ''}); - } - else if (nodeName == 'div' || nodeName == 'span') { - var inline = $target.children('.' + this._inlineClass); - inline.children().removeClass('ui-state-disabled'); - inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). - removeAttr("disabled"); - } - this._disabledInputs = $.map(this._disabledInputs, - function(value) { return (value == target ? null : value); }); // delete entry - }, +// number of pages in a slider +// (how many times can you page up/down to go through the whole range) +var numPages = 5; - /* Disable the date picker to a jQuery selection. - @param target element - the target input field or division or span */ - _disableDatepicker: function(target) { - var $target = $(target); - var inst = $.data(target, PROP_NAME); - if (!$target.hasClass(this.markerClassName)) { - return; - } - var nodeName = target.nodeName.toLowerCase(); - if (nodeName == 'input') { - target.disabled = true; - inst.trigger.filter('button'). - each(function() { this.disabled = true; }).end(). - filter('img').css({opacity: '0.5', cursor: 'default'}); - } - else if (nodeName == 'div' || nodeName == 'span') { - var inline = $target.children('.' + this._inlineClass); - inline.children().addClass('ui-state-disabled'); - inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). - attr("disabled", "disabled"); - } - this._disabledInputs = $.map(this._disabledInputs, - function(value) { return (value == target ? null : value); }); // delete entry - this._disabledInputs[this._disabledInputs.length] = target; - }, +$.widget( "ui.slider", $.ui.mouse, { + version: "1.9.2", + widgetEventPrefix: "slide", - /* Is the first field in a jQuery collection disabled as a datepicker? - @param target element - the target input field or division or span - @return boolean - true if disabled, false if enabled */ - _isDisabledDatepicker: function(target) { - if (!target) { - return false; - } - for (var i = 0; i < this._disabledInputs.length; i++) { - if (this._disabledInputs[i] == target) - return true; - } - return false; + options: { + animate: false, + distance: 0, + max: 100, + min: 0, + orientation: "horizontal", + range: false, + step: 1, + value: 0, + values: null }, - /* Retrieve the instance data for the target control. - @param target element - the target input field or division or span - @return object - the associated instance data - @throws error if a jQuery problem getting data */ - _getInst: function(target) { - try { - return $.data(target, PROP_NAME); - } - catch (err) { - throw 'Missing instance data for this datepicker'; - } - }, + _create: function() { + var i, handleCount, + o = this.options, + existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), + handle = "", + handles = []; + + this._keySliding = false; + this._mouseSliding = false; + this._animateOff = true; + this._handleIndex = null; + this._detectOrientation(); + this._mouseInit(); + + this.element + .addClass( "ui-slider" + + " ui-slider-" + this.orientation + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" + + ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); + + this.range = $([]); - /* Update or retrieve the settings for a date picker attached to an input field or division. - @param target element - the target input field or division or span - @param name object - the new settings to update or - string - the name of the setting to change or retrieve, - when retrieving also 'all' for all instance settings or - 'defaults' for all global defaults - @param value any - the new value for the setting - (omit if above is an object or to retrieve a value) */ - _optionDatepicker: function(target, name, value) { - var inst = this._getInst(target); - if (arguments.length == 2 && typeof name == 'string') { - return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) : - (inst ? (name == 'all' ? $.extend({}, inst.settings) : - this._get(inst, name)) : null)); - } - var settings = name || {}; - if (typeof name == 'string') { - settings = {}; - settings[name] = value; - } - if (inst) { - if (this._curInst == inst) { - this._hideDatepicker(); + if ( o.range ) { + if ( o.range === true ) { + if ( !o.values ) { + o.values = [ this._valueMin(), this._valueMin() ]; + } + if ( o.values.length && o.values.length !== 2 ) { + o.values = [ o.values[0], o.values[0] ]; + } } - var date = this._getDateDatepicker(target, true); - var minDate = this._getMinMaxDate(inst, 'min'); - var maxDate = this._getMinMaxDate(inst, 'max'); - extendRemove(inst.settings, settings); - // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided - if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined) - inst.settings.minDate = this._formatDate(inst, minDate); - if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined) - inst.settings.maxDate = this._formatDate(inst, maxDate); - this._attachments($(target), inst); - this._autoSize(inst); - this._setDate(inst, date); - this._updateAlternate(inst); - this._updateDatepicker(inst); + + this.range = $( "
          " ) + .appendTo( this.element ) + .addClass( "ui-slider-range" + + // note: this isn't the most fittingly semantic framework class for this element, + // but worked best visually with a variety of themes + " ui-widget-header" + + ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); } - }, - // change method deprecated - _changeDatepicker: function(target, name, value) { - this._optionDatepicker(target, name, value); - }, + handleCount = ( o.values && o.values.length ) || 1; - /* Redraw the date picker attached to an input field or division. - @param target element - the target input field or division or span */ - _refreshDatepicker: function(target) { - var inst = this._getInst(target); - if (inst) { - this._updateDatepicker(inst); + for ( i = existingHandles.length; i < handleCount; i++ ) { + handles.push( handle ); } - }, - /* Set the dates for a jQuery selection. - @param target element - the target input field or division or span - @param date Date - the new date */ - _setDateDatepicker: function(target, date) { - var inst = this._getInst(target); - if (inst) { - this._setDate(inst, date); - this._updateDatepicker(inst); - this._updateAlternate(inst); - } - }, + this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); - /* Get the date(s) for the first entry in a jQuery selection. - @param target element - the target input field or division or span - @param noDefault boolean - true if no default date is to be used - @return Date - the current date */ - _getDateDatepicker: function(target, noDefault) { - var inst = this._getInst(target); - if (inst && !inst.inline) - this._setDateFromField(inst, noDefault); - return (inst ? this._getDate(inst) : null); - }, + this.handle = this.handles.eq( 0 ); - /* Handle keystrokes. */ - _doKeyDown: function(event) { - var inst = $.datepicker._getInst(event.target); - var handled = true; - var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); - inst._keyEvent = true; - if ($.datepicker._datepickerShowing) - switch (event.keyCode) { - case 9: $.datepicker._hideDatepicker(); - handled = false; - break; // hide on tab out - case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + - $.datepicker._currentClass + ')', inst.dpDiv); - if (sel[0]) - $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); - var onSelect = $.datepicker._get(inst, 'onSelect'); - if (onSelect) { - var dateStr = $.datepicker._formatDate(inst); + this.handles.add( this.range ).filter( "a" ) + .click(function( event ) { + event.preventDefault(); + }) + .mouseenter(function() { + if ( !o.disabled ) { + $( this ).addClass( "ui-state-hover" ); + } + }) + .mouseleave(function() { + $( this ).removeClass( "ui-state-hover" ); + }) + .focus(function() { + if ( !o.disabled ) { + $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); + $( this ).addClass( "ui-state-focus" ); + } else { + $( this ).blur(); + } + }) + .blur(function() { + $( this ).removeClass( "ui-state-focus" ); + }); - // trigger custom callback - onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); + this.handles.each(function( i ) { + $( this ).data( "ui-slider-handle-index", i ); + }); + + this._on( this.handles, { + keydown: function( event ) { + var allowed, curVal, newVal, step, + index = $( event.target ).data( "ui-slider-handle-index" ); + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + case $.ui.keyCode.END: + case $.ui.keyCode.PAGE_UP: + case $.ui.keyCode.PAGE_DOWN: + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + event.preventDefault(); + if ( !this._keySliding ) { + this._keySliding = true; + $( event.target ).addClass( "ui-state-active" ); + allowed = this._start( event, index ); + if ( allowed === false ) { + return; } - else - $.datepicker._hideDatepicker(); - return false; // don't submit the form - break; // select the value on enter - case 27: $.datepicker._hideDatepicker(); - break; // hide on escape - case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? - -$.datepicker._get(inst, 'stepBigMonths') : - -$.datepicker._get(inst, 'stepMonths')), 'M'); - break; // previous month/year on page up/+ ctrl - case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? - +$.datepicker._get(inst, 'stepBigMonths') : - +$.datepicker._get(inst, 'stepMonths')), 'M'); - break; // next month/year on page down/+ ctrl - case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); - handled = event.ctrlKey || event.metaKey; - break; // clear on ctrl or command +end - case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); - handled = event.ctrlKey || event.metaKey; - break; // current on ctrl or command +home - case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); - handled = event.ctrlKey || event.metaKey; - // -1 day on ctrl or command +left - if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? - -$.datepicker._get(inst, 'stepBigMonths') : - -$.datepicker._get(inst, 'stepMonths')), 'M'); - // next month/year on alt +left on Mac + } break; - case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); - handled = event.ctrlKey || event.metaKey; - break; // -1 week on ctrl or command +up - case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); - handled = event.ctrlKey || event.metaKey; - // +1 day on ctrl or command +right - if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? - +$.datepicker._get(inst, 'stepBigMonths') : - +$.datepicker._get(inst, 'stepMonths')), 'M'); - // next month/year on alt +right + } + + step = this.options.step; + if ( this.options.values && this.options.values.length ) { + curVal = newVal = this.values( index ); + } else { + curVal = newVal = this.value(); + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + newVal = this._valueMin(); break; - case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); - handled = event.ctrlKey || event.metaKey; - break; // +1 week on ctrl or command +down - default: handled = false; + case $.ui.keyCode.END: + newVal = this._valueMax(); + break; + case $.ui.keyCode.PAGE_UP: + newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.PAGE_DOWN: + newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + if ( curVal === this._valueMax() ) { + return; + } + newVal = this._trimAlignValue( curVal + step ); + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + if ( curVal === this._valueMin() ) { + return; + } + newVal = this._trimAlignValue( curVal - step ); + break; + } + + this._slide( event, index, newVal ); + }, + keyup: function( event ) { + var index = $( event.target ).data( "ui-slider-handle-index" ); + + if ( this._keySliding ) { + this._keySliding = false; + this._stop( event, index ); + this._change( event, index ); + $( event.target ).removeClass( "ui-state-active" ); + } + } + }); + + this._refreshValue(); + + this._animateOff = false; + }, + + _destroy: function() { + this.handles.remove(); + this.range.remove(); + + this.element + .removeClass( "ui-slider" + + " ui-slider-horizontal" + + " ui-slider-vertical" + + " ui-slider-disabled" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" ); + + this._mouseDestroy(); + }, + + _mouseCapture: function( event ) { + var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, + that = this, + o = this.options; + + if ( o.disabled ) { + return false; + } + + this.elementSize = { + width: this.element.outerWidth(), + height: this.element.outerHeight() + }; + this.elementOffset = this.element.offset(); + + position = { x: event.pageX, y: event.pageY }; + normValue = this._normValueFromMouse( position ); + distance = this._valueMax() - this._valueMin() + 1; + this.handles.each(function( i ) { + var thisDistance = Math.abs( normValue - that.values(i) ); + if ( distance > thisDistance ) { + distance = thisDistance; + closestHandle = $( this ); + index = i; } - else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home - $.datepicker._showDatepicker(this); - else { - handled = false; + }); + + // workaround for bug #3736 (if both handles of a range are at 0, + // the first is always used as the one with least distance, + // and moving it is obviously prevented by preventing negative ranges) + if( o.range === true && this.values(1) === o.min ) { + index += 1; + closestHandle = $( this.handles[index] ); } - if (handled) { - event.preventDefault(); - event.stopPropagation(); + + allowed = this._start( event, index ); + if ( allowed === false ) { + return false; } - }, + this._mouseSliding = true; - /* Filter entered characters - based on date format. */ - _doKeyPress: function(event) { - var inst = $.datepicker._getInst(event.target); - if ($.datepicker._get(inst, 'constrainInput')) { - var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); - var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); - return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); + this._handleIndex = index; + + closestHandle + .addClass( "ui-state-active" ) + .focus(); + + offset = closestHandle.offset(); + mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); + this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { + left: event.pageX - offset.left - ( closestHandle.width() / 2 ), + top: event.pageY - offset.top - + ( closestHandle.height() / 2 ) - + ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - + ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + + ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) + }; + + if ( !this.handles.hasClass( "ui-state-hover" ) ) { + this._slide( event, index, normValue ); } + this._animateOff = true; + return true; }, - /* Synchronise manual entry and field/alternate field. */ - _doKeyUp: function(event) { - var inst = $.datepicker._getInst(event.target); - if (inst.input.val() != inst.lastVal) { - try { - var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), - (inst.input ? inst.input.val() : null), - $.datepicker._getFormatConfig(inst)); - if (date) { // only if valid - $.datepicker._setDateFromField(inst); - $.datepicker._updateAlternate(inst); - $.datepicker._updateDatepicker(inst); - } - } - catch (event) { - $.datepicker.log(event); - } - } + _mouseStart: function() { return true; }, - /* Pop-up the date picker for a given input field. - If false returned from beforeShow event handler do not show. - @param input element - the input field attached to the date picker or - event - if triggered by focus */ - _showDatepicker: function(input) { - input = input.target || input; - if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger - input = $('input', input.parentNode)[0]; - if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here - return; - var inst = $.datepicker._getInst(input); - if ($.datepicker._curInst && $.datepicker._curInst != inst) { - if ( $.datepicker._datepickerShowing ) { - $.datepicker._triggerOnClose($.datepicker._curInst); - } - $.datepicker._curInst.dpDiv.stop(true, true); - } - var beforeShow = $.datepicker._get(inst, 'beforeShow'); - var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; - if(beforeShowSettings === false){ - //false - return; + _mouseDrag: function( event ) { + var position = { x: event.pageX, y: event.pageY }, + normValue = this._normValueFromMouse( position ); + + this._slide( event, this._handleIndex, normValue ); + + return false; + }, + + _mouseStop: function( event ) { + this.handles.removeClass( "ui-state-active" ); + this._mouseSliding = false; + + this._stop( event, this._handleIndex ); + this._change( event, this._handleIndex ); + + this._handleIndex = null; + this._clickOffset = null; + this._animateOff = false; + + return false; + }, + + _detectOrientation: function() { + this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; + }, + + _normValueFromMouse: function( position ) { + var pixelTotal, + pixelMouse, + percentMouse, + valueTotal, + valueMouse; + + if ( this.orientation === "horizontal" ) { + pixelTotal = this.elementSize.width; + pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); + } else { + pixelTotal = this.elementSize.height; + pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); } - extendRemove(inst.settings, beforeShowSettings); - inst.lastVal = null; - $.datepicker._lastInput = input; - $.datepicker._setDateFromField(inst); - if ($.datepicker._inDialog) // hide cursor - input.value = ''; - if (!$.datepicker._pos) { // position below input - $.datepicker._pos = $.datepicker._findPos(input); - $.datepicker._pos[1] += input.offsetHeight; // add the height + + percentMouse = ( pixelMouse / pixelTotal ); + if ( percentMouse > 1 ) { + percentMouse = 1; } - var isFixed = false; - $(input).parents().each(function() { - isFixed |= $(this).css('position') == 'fixed'; - return !isFixed; - }); - if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled - $.datepicker._pos[0] -= document.documentElement.scrollLeft; - $.datepicker._pos[1] -= document.documentElement.scrollTop; + if ( percentMouse < 0 ) { + percentMouse = 0; } - var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; - $.datepicker._pos = null; - //to avoid flashes on Firefox - inst.dpDiv.empty(); - // determine sizing offscreen - inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); - $.datepicker._updateDatepicker(inst); - // fix width for dynamic number of date pickers - // and adjust position before showing - offset = $.datepicker._checkOffset(inst, offset, isFixed); - inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? - 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', - left: offset.left + 'px', top: offset.top + 'px'}); - if (!inst.inline) { - var showAnim = $.datepicker._get(inst, 'showAnim'); - var duration = $.datepicker._get(inst, 'duration'); - var postProcess = function() { - var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only - if( !! cover.length ){ - var borders = $.datepicker._getBorders(inst.dpDiv); - cover.css({left: -borders[0], top: -borders[1], - width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); - } - }; - inst.dpDiv.zIndex($(input).zIndex()+1); - $.datepicker._datepickerShowing = true; - if ($.effects && $.effects[showAnim]) - inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); - else - inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess); - if (!showAnim || !duration) - postProcess(); - if (inst.input.is(':visible') && !inst.input.is(':disabled')) - inst.input.focus(); - $.datepicker._curInst = inst; + if ( this.orientation === "vertical" ) { + percentMouse = 1 - percentMouse; } + + valueTotal = this._valueMax() - this._valueMin(); + valueMouse = this._valueMin() + percentMouse * valueTotal; + + return this._trimAlignValue( valueMouse ); }, - /* Generate the date picker content. */ - _updateDatepicker: function(inst) { - var self = this; - self.maxRows = 4; //Reset the max number of rows being displayed (see #7043) - var borders = $.datepicker._getBorders(inst.dpDiv); - instActive = inst; // for delegate hover events - inst.dpDiv.empty().append(this._generateHTML(inst)); - var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only - if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6 - cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}) + _start: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); } - inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover(); - var numMonths = this._getNumberOfMonths(inst); - var cols = numMonths[1]; - var width = 17; - inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); - if (cols > 1) - inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); - inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + - 'Class']('ui-datepicker-multi'); - inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + - 'Class']('ui-datepicker-rtl'); - if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && - // #6694 - don't focus the input if it's already focused - // this breaks the change event in IE - inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement) - inst.input.focus(); - // deffered render of the years select (to avoid flashes on Firefox) - if( inst.yearshtml ){ - var origyearshtml = inst.yearshtml; - setTimeout(function(){ - //assure that inst.yearshtml didn't change. - if( origyearshtml === inst.yearshtml && inst.yearshtml ){ - inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml); + return this._trigger( "start", event, uiHash ); + }, + + _slide: function( event, index, newVal ) { + var otherVal, + newValues, + allowed; + + if ( this.options.values && this.options.values.length ) { + otherVal = this.values( index ? 0 : 1 ); + + if ( ( this.options.values.length === 2 && this.options.range === true ) && + ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) + ) { + newVal = otherVal; + } + + if ( newVal !== this.values( index ) ) { + newValues = this.values(); + newValues[ index ] = newVal; + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal, + values: newValues + } ); + otherVal = this.values( index ? 0 : 1 ); + if ( allowed !== false ) { + this.values( index, newVal, true ); } - origyearshtml = inst.yearshtml = null; - }, 0); + } + } else { + if ( newVal !== this.value() ) { + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal + } ); + if ( allowed !== false ) { + this.value( newVal ); + } + } } }, - /* Retrieve the size of left and top borders for an element. - @param elem (jQuery object) the element of interest - @return (number[2]) the left and top borders */ - _getBorders: function(elem) { - var convert = function(value) { - return {thin: 1, medium: 2, thick: 3}[value] || value; + _stop: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() }; - return [parseFloat(convert(elem.css('border-left-width'))), - parseFloat(convert(elem.css('border-top-width')))]; - }, - - /* Check positioning to remain on screen. */ - _checkOffset: function(inst, offset, isFixed) { - var dpWidth = inst.dpDiv.outerWidth(); - var dpHeight = inst.dpDiv.outerHeight(); - var inputWidth = inst.input ? inst.input.outerWidth() : 0; - var inputHeight = inst.input ? inst.input.outerHeight() : 0; - var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft(); - var viewHeight = document.documentElement.clientHeight + $(document).scrollTop(); - - offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); - offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; - offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; - - // now check if datepicker is showing outside window viewport - move to a better place if so. - offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? - Math.abs(offset.left + dpWidth - viewWidth) : 0); - offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? - Math.abs(dpHeight + inputHeight) : 0); + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } - return offset; + this._trigger( "stop", event, uiHash ); }, - /* Find an object's position on the screen. */ - _findPos: function(obj) { - var inst = this._getInst(obj); - var isRTL = this._get(inst, 'isRTL'); - while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) { - obj = obj[isRTL ? 'previousSibling' : 'nextSibling']; - } - var position = $(obj).offset(); - return [position.left, position.top]; - }, + _change: function( event, index ) { + if ( !this._keySliding && !this._mouseSliding ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } - /* Trigger custom callback of onClose. */ - _triggerOnClose: function(inst) { - var onClose = this._get(inst, 'onClose'); - if (onClose) - onClose.apply((inst.input ? inst.input[0] : null), - [(inst.input ? inst.input.val() : ''), inst]); + this._trigger( "change", event, uiHash ); + } }, - /* Hide the date picker from view. - @param input element - the input field attached to the date picker */ - _hideDatepicker: function(input) { - var inst = this._curInst; - if (!inst || (input && inst != $.data(input, PROP_NAME))) + value: function( newValue ) { + if ( arguments.length ) { + this.options.value = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, 0 ); return; - if (this._datepickerShowing) { - var showAnim = this._get(inst, 'showAnim'); - var duration = this._get(inst, 'duration'); - var postProcess = function() { - $.datepicker._tidyDialog(inst); - this._curInst = null; - }; - if ($.effects && $.effects[showAnim]) - inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); - else - inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' : - (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess); - if (!showAnim) - postProcess(); - $.datepicker._triggerOnClose(inst); - this._datepickerShowing = false; - this._lastInput = null; - if (this._inDialog) { - this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); - if ($.blockUI) { - $.unblockUI(); - $('body').append(this.dpDiv); - } - } - this._inDialog = false; } - }, - /* Tidy up after a dialog display. */ - _tidyDialog: function(inst) { - inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); + return this._value(); }, - /* Close date picker if clicked elsewhere. */ - _checkExternalClick: function(event) { - if (!$.datepicker._curInst) - return; - var $target = $(event.target); - if ($target[0].id != $.datepicker._mainDivId && - $target.parents('#' + $.datepicker._mainDivId).length == 0 && - !$target.hasClass($.datepicker.markerClassName) && - !$target.hasClass($.datepicker._triggerClass) && - $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI)) - $.datepicker._hideDatepicker(); - }, + values: function( index, newValue ) { + var vals, + newValues, + i; - /* Adjust one of the date sub-fields. */ - _adjustDate: function(id, offset, period) { - var target = $(id); - var inst = this._getInst(target[0]); - if (this._isDisabledDatepicker(target[0])) { + if ( arguments.length > 1 ) { + this.options.values[ index ] = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, index ); return; } - this._adjustInstDate(inst, offset + - (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning - period); - this._updateDatepicker(inst); + + if ( arguments.length ) { + if ( $.isArray( arguments[ 0 ] ) ) { + vals = this.options.values; + newValues = arguments[ 0 ]; + for ( i = 0; i < vals.length; i += 1 ) { + vals[ i ] = this._trimAlignValue( newValues[ i ] ); + this._change( null, i ); + } + this._refreshValue(); + } else { + if ( this.options.values && this.options.values.length ) { + return this._values( index ); + } else { + return this.value(); + } + } + } else { + return this._values(); + } }, - /* Action for current link. */ - _gotoToday: function(id) { - var target = $(id); - var inst = this._getInst(target[0]); - if (this._get(inst, 'gotoCurrent') && inst.currentDay) { - inst.selectedDay = inst.currentDay; - inst.drawMonth = inst.selectedMonth = inst.currentMonth; - inst.drawYear = inst.selectedYear = inst.currentYear; + _setOption: function( key, value ) { + var i, + valsLength = 0; + + if ( $.isArray( this.options.values ) ) { + valsLength = this.options.values.length; } - else { - var date = new Date(); - inst.selectedDay = date.getDate(); - inst.drawMonth = inst.selectedMonth = date.getMonth(); - inst.drawYear = inst.selectedYear = date.getFullYear(); + + $.Widget.prototype._setOption.apply( this, arguments ); + + switch ( key ) { + case "disabled": + if ( value ) { + this.handles.filter( ".ui-state-focus" ).blur(); + this.handles.removeClass( "ui-state-hover" ); + this.handles.prop( "disabled", true ); + this.element.addClass( "ui-disabled" ); + } else { + this.handles.prop( "disabled", false ); + this.element.removeClass( "ui-disabled" ); + } + break; + case "orientation": + this._detectOrientation(); + this.element + .removeClass( "ui-slider-horizontal ui-slider-vertical" ) + .addClass( "ui-slider-" + this.orientation ); + this._refreshValue(); + break; + case "value": + this._animateOff = true; + this._refreshValue(); + this._change( null, 0 ); + this._animateOff = false; + break; + case "values": + this._animateOff = true; + this._refreshValue(); + for ( i = 0; i < valsLength; i += 1 ) { + this._change( null, i ); + } + this._animateOff = false; + break; + case "min": + case "max": + this._animateOff = true; + this._refreshValue(); + this._animateOff = false; + break; } - this._notifyChange(inst); - this._adjustDate(target); }, - /* Action for selecting a new month/year. */ - _selectMonthYear: function(id, select, period) { - var target = $(id); - var inst = this._getInst(target[0]); - inst['selected' + (period == 'M' ? 'Month' : 'Year')] = - inst['draw' + (period == 'M' ? 'Month' : 'Year')] = - parseInt(select.options[select.selectedIndex].value,10); - this._notifyChange(inst); - this._adjustDate(target); - }, + //internal value getter + // _value() returns value trimmed by min and max, aligned by step + _value: function() { + var val = this.options.value; + val = this._trimAlignValue( val ); - /* Action for selecting a day. */ - _selectDay: function(id, month, year, td) { - var target = $(id); - if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { - return; - } - var inst = this._getInst(target[0]); - inst.selectedDay = inst.currentDay = $('a', td).html(); - inst.selectedMonth = inst.currentMonth = month; - inst.selectedYear = inst.currentYear = year; - this._selectDate(id, this._formatDate(inst, - inst.currentDay, inst.currentMonth, inst.currentYear)); + return val; }, - /* Erase the input field and hide the date picker. */ - _clearDate: function(id) { - var target = $(id); - var inst = this._getInst(target[0]); - this._selectDate(target, ''); - }, + //internal values getter + // _values() returns array of values trimmed by min and max, aligned by step + // _values( index ) returns single value trimmed by min and max, aligned by step + _values: function( index ) { + var val, + vals, + i; + + if ( arguments.length ) { + val = this.options.values[ index ]; + val = this._trimAlignValue( val ); + + return val; + } else { + // .slice() creates a copy of the array + // this copy gets trimmed by min and max and then returned + vals = this.options.values.slice(); + for ( i = 0; i < vals.length; i+= 1) { + vals[ i ] = this._trimAlignValue( vals[ i ] ); + } - /* Update the input field with the selected date. */ - _selectDate: function(id, dateStr) { - var target = $(id); - var inst = this._getInst(target[0]); - dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); - if (inst.input) - inst.input.val(dateStr); - this._updateAlternate(inst); - var onSelect = this._get(inst, 'onSelect'); - if (onSelect) - onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback - else if (inst.input) - inst.input.trigger('change'); // fire the change event - if (inst.inline) - this._updateDatepicker(inst); - else { - this._hideDatepicker(); - this._lastInput = inst.input[0]; - if (typeof(inst.input[0]) != 'object') - inst.input.focus(); // restore focus - this._lastInput = null; + return vals; } }, - /* Update any alternate field to synchronise with the main field. */ - _updateAlternate: function(inst) { - var altField = this._get(inst, 'altField'); - if (altField) { // update alternate field too - var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); - var date = this._getDate(inst); - var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); - $(altField).each(function() { $(this).val(dateStr); }); + // returns the step-aligned value that val is closest to, between (inclusive) min and max + _trimAlignValue: function( val ) { + if ( val <= this._valueMin() ) { + return this._valueMin(); } + if ( val >= this._valueMax() ) { + return this._valueMax(); + } + var step = ( this.options.step > 0 ) ? this.options.step : 1, + valModStep = (val - this._valueMin()) % step, + alignValue = val - valModStep; + + if ( Math.abs(valModStep) * 2 >= step ) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); + } + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat( alignValue.toFixed(5) ); }, - /* Set as beforeShowDay function to prevent selection of weekends. - @param date Date - the date to customise - @return [boolean, string] - is this date selectable?, what is its CSS class? */ - noWeekends: function(date) { - var day = date.getDay(); - return [(day > 0 && day < 6), '']; + _valueMin: function() { + return this.options.min; }, - /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. - @param date Date - the date to get the week for - @return number - the number of the week within the year that contains this date */ - iso8601Week: function(date) { - var checkDate = new Date(date.getTime()); - // Find Thursday of this week starting on Monday - checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); - var time = checkDate.getTime(); - checkDate.setMonth(0); // Compare with Jan 1 - checkDate.setDate(1); - return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + _valueMax: function() { + return this.options.max; }, - /* Parse a string value into a date object. - See formatDate below for the possible formats. + _refreshValue: function() { + var lastValPercent, valPercent, value, valueMin, valueMax, + oRange = this.options.range, + o = this.options, + that = this, + animate = ( !this._animateOff ) ? o.animate : false, + _set = {}; - @param format string - the expected format of the date - @param value string - the date in the above format - @param settings Object - attributes include: - shortYearCutoff number - the cutoff year for determining the century (optional) - dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) - dayNames string[7] - names of the days from Sunday (optional) - monthNamesShort string[12] - abbreviated names of the months (optional) - monthNames string[12] - names of the months (optional) - @return Date - the extracted date value or null if value is blank */ - parseDate: function (format, value, settings) { - if (format == null || value == null) - throw 'Invalid arguments'; - value = (typeof value == 'object' ? value.toString() : value + ''); - if (value == '') - return null; - var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; - shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : - new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); - var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; - var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; - var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; - var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; - var year = -1; - var month = -1; - var day = -1; - var doy = -1; - var literal = false; - // Check whether a format character is doubled - var lookAhead = function(match) { - var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); - if (matches) - iFormat++; - return matches; - }; - // Extract a number from the string value - var getNumber = function(match) { - var isDoubled = lookAhead(match); - var size = (match == '@' ? 14 : (match == '!' ? 20 : - (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2)))); - var digits = new RegExp('^\\d{1,' + size + '}'); - var num = value.substring(iValue).match(digits); - if (!num) - throw 'Missing number at position ' + iValue; - iValue += num[0].length; - return parseInt(num[0], 10); - }; - // Extract a name from the string value and convert to an index - var getName = function(match, shortNames, longNames) { - var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { - return [ [k, v] ]; - }).sort(function (a, b) { - return -(a[1].length - b[1].length); - }); - var index = -1; - $.each(names, function (i, pair) { - var name = pair[1]; - if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) { - index = pair[0]; - iValue += name.length; - return false; + if ( this.options.values && this.options.values.length ) { + this.handles.each(function( i ) { + valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; + _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + if ( that.options.range === true ) { + if ( that.orientation === "horizontal" ) { + if ( i === 0 ) { + that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); + } + if ( i === 1 ) { + that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } else { + if ( i === 0 ) { + that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); + } + if ( i === 1 ) { + that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } } + lastValPercent = valPercent; }); - if (index != -1) - return index + 1; - else - throw 'Unknown name at position ' + iValue; - }; - // Confirm that a literal character matches the string value - var checkLiteral = function() { - if (value.charAt(iValue) != format.charAt(iFormat)) - throw 'Unexpected literal at position ' + iValue; - iValue++; - }; - var iValue = 0; - for (var iFormat = 0; iFormat < format.length; iFormat++) { - if (literal) - if (format.charAt(iFormat) == "'" && !lookAhead("'")) - literal = false; - else - checkLiteral(); - else - switch (format.charAt(iFormat)) { - case 'd': - day = getNumber('d'); - break; - case 'D': - getName('D', dayNamesShort, dayNames); - break; - case 'o': - doy = getNumber('o'); - break; - case 'm': - month = getNumber('m'); - break; - case 'M': - month = getName('M', monthNamesShort, monthNames); - break; - case 'y': - year = getNumber('y'); - break; - case '@': - var date = new Date(getNumber('@')); - year = date.getFullYear(); - month = date.getMonth() + 1; - day = date.getDate(); - break; - case '!': - var date = new Date((getNumber('!') - this._ticksTo1970) / 10000); - year = date.getFullYear(); - month = date.getMonth() + 1; - day = date.getDate(); - break; - case "'": - if (lookAhead("'")) - checkLiteral(); - else - literal = true; - break; - default: - checkLiteral(); - } - } - if (iValue < value.length){ - throw "Extra/unparsed characters found in date: " + value.substring(iValue); - } - if (year == -1) - year = new Date().getFullYear(); - else if (year < 100) - year += new Date().getFullYear() - new Date().getFullYear() % 100 + - (year <= shortYearCutoff ? 0 : -100); - if (doy > -1) { - month = 1; - day = doy; - do { - var dim = this._getDaysInMonth(year, month - 1); - if (day <= dim) - break; - month++; - day -= dim; - } while (true); + } else { + value = this.value(); + valueMin = this._valueMin(); + valueMax = this._valueMax(); + valPercent = ( valueMax !== valueMin ) ? + ( value - valueMin ) / ( valueMax - valueMin ) * 100 : + 0; + _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + + if ( oRange === "min" && this.orientation === "horizontal" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "horizontal" ) { + this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + if ( oRange === "min" && this.orientation === "vertical" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "vertical" ) { + this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } } - var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); - if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) - throw 'Invalid date'; // E.g. 31/02/00 - return date; + } + +}); + +}(jQuery)); +(function( $, undefined ) { + +$.widget("ui.sortable", $.ui.mouse, { + version: "1.9.2", + widgetEventPrefix: "sort", + ready: false, + options: { + appendTo: "parent", + axis: false, + connectWith: false, + containment: false, + cursor: 'auto', + cursorAt: false, + dropOnEmpty: true, + forcePlaceholderSize: false, + forceHelperSize: false, + grid: false, + handle: false, + helper: "original", + items: '> *', + opacity: false, + placeholder: false, + revert: false, + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + scope: "default", + tolerance: "intersect", + zIndex: 1000 }, + _create: function() { - /* Standard date formats. */ - ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) - COOKIE: 'D, dd M yy', - ISO_8601: 'yy-mm-dd', - RFC_822: 'D, d M y', - RFC_850: 'DD, dd-M-y', - RFC_1036: 'D, d M y', - RFC_1123: 'D, d M yy', - RFC_2822: 'D, d M yy', - RSS: 'D, d M y', // RFC 822 - TICKS: '!', - TIMESTAMP: '@', - W3C: 'yy-mm-dd', // ISO 8601 + var o = this.options; + this.containerCache = {}; + this.element.addClass("ui-sortable"); - _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + - Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), + //Get the items + this.refresh(); - /* Format a date object into a string value. - The format can be combinations of the following: - d - day of month (no leading zero) - dd - day of month (two digit) - o - day of year (no leading zeros) - oo - day of year (three digit) - D - day name short - DD - day name long - m - month of year (no leading zero) - mm - month of year (two digit) - M - month name short - MM - month name long - y - year (two digit) - yy - year (four digit) - @ - Unix timestamp (ms since 01/01/1970) - ! - Windows ticks (100ns since 01/01/0001) - '...' - literal text - '' - single quote + //Let's determine if the items are being displayed horizontally + this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false; - @param format string - the desired format of the date - @param date Date - the date value to format - @param settings Object - attributes include: - dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) - dayNames string[7] - names of the days from Sunday (optional) - monthNamesShort string[12] - abbreviated names of the months (optional) - monthNames string[12] - names of the months (optional) - @return string - the date in the above format */ - formatDate: function (format, date, settings) { - if (!date) - return ''; - var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; - var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; - var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; - var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; - // Check whether a format character is doubled - var lookAhead = function(match) { - var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); - if (matches) - iFormat++; - return matches; - }; - // Format a number, with leading zero if necessary - var formatNumber = function(match, value, len) { - var num = '' + value; - if (lookAhead(match)) - while (num.length < len) - num = '0' + num; - return num; - }; - // Format a name, short or long as requested - var formatName = function(match, value, shortNames, longNames) { - return (lookAhead(match) ? longNames[value] : shortNames[value]); - }; - var output = ''; - var literal = false; - if (date) - for (var iFormat = 0; iFormat < format.length; iFormat++) { - if (literal) - if (format.charAt(iFormat) == "'" && !lookAhead("'")) - literal = false; - else - output += format.charAt(iFormat); - else - switch (format.charAt(iFormat)) { - case 'd': - output += formatNumber('d', date.getDate(), 2); - break; - case 'D': - output += formatName('D', date.getDay(), dayNamesShort, dayNames); - break; - case 'o': - output += formatNumber('o', - Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); - break; - case 'm': - output += formatNumber('m', date.getMonth() + 1, 2); - break; - case 'M': - output += formatName('M', date.getMonth(), monthNamesShort, monthNames); - break; - case 'y': - output += (lookAhead('y') ? date.getFullYear() : - (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); - break; - case '@': - output += date.getTime(); - break; - case '!': - output += date.getTime() * 10000 + this._ticksTo1970; - break; - case "'": - if (lookAhead("'")) - output += "'"; - else - literal = true; - break; - default: - output += format.charAt(iFormat); - } + //Let's determine the parent's offset + this.offset = this.element.offset(); + + //Initialize mouse events for interaction + this._mouseInit(); + + //We're ready to go + this.ready = true + + }, + + _destroy: function() { + this.element + .removeClass("ui-sortable ui-sortable-disabled"); + this._mouseDestroy(); + + for ( var i = this.items.length - 1; i >= 0; i-- ) + this.items[i].item.removeData(this.widgetName + "-item"); + + return this; + }, + + _setOption: function(key, value){ + if ( key === "disabled" ) { + this.options[ key ] = value; + + this.widget().toggleClass( "ui-sortable-disabled", !!value ); + } else { + // Don't call widget base _setOption for disable as it adds ui-state-disabled class + $.Widget.prototype._setOption.apply(this, arguments); + } + }, + + _mouseCapture: function(event, overrideHandle) { + var that = this; + + if (this.reverting) { + return false; + } + + if(this.options.disabled || this.options.type == 'static') return false; + + //We have to refresh the items data once first + this._refreshItems(event); + + //Find out if the clicked node (or one of its parents) is a actual item in this.items + var currentItem = null, nodes = $(event.target).parents().each(function() { + if($.data(this, that.widgetName + '-item') == that) { + currentItem = $(this); + return false; } - return output; + }); + if($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target); + + if(!currentItem) return false; + if(this.options.handle && !overrideHandle) { + var validHandle = false; + + $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); + if(!validHandle) return false; + } + + this.currentItem = currentItem; + this._removeCurrentsFromItems(); + return true; + }, - /* Extract all possible characters from the date format. */ - _possibleChars: function (format) { - var chars = ''; - var literal = false; - // Check whether a format character is doubled - var lookAhead = function(match) { - var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); - if (matches) - iFormat++; - return matches; + _mouseStart: function(event, overrideHandle, noActivation) { + + var o = this.options; + this.currentContainer = this; + + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture + this.refreshPositions(); + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Get the next scrolling parent + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.currentItem.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left }; - for (var iFormat = 0; iFormat < format.length; iFormat++) - if (literal) - if (format.charAt(iFormat) == "'" && !lookAhead("'")) - literal = false; - else - chars += format.charAt(iFormat); - else - switch (format.charAt(iFormat)) { - case 'd': case 'm': case 'y': case '@': - chars += '0123456789'; - break; - case 'D': case 'M': - return null; // Accept anything - case "'": - if (lookAhead("'")) - chars += "'"; - else - literal = true; - break; - default: - chars += format.charAt(iFormat); - } - return chars; - }, - /* Get a setting value, defaulting if necessary. */ - _get: function(inst, name) { - return inst.settings[name] !== undefined ? - inst.settings[name] : this._defaults[name]; - }, + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); - /* Parse existing date and initialise date picker. */ - _setDateFromField: function(inst, noDefault) { - if (inst.input.val() == inst.lastVal) { - return; + // Only after we got the offset, we can change the helper's position to absolute + // TODO: Still need to figure out a way to make relative sorting possible + this.helper.css("position", "absolute"); + this.cssPosition = this.helper.css("position"); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Cache the former DOM position + this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; + + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way + if(this.helper[0] != this.currentItem[0]) { + this.currentItem.hide(); } - var dateFormat = this._get(inst, 'dateFormat'); - var dates = inst.lastVal = inst.input ? inst.input.val() : null; - var date, defaultDate; - date = defaultDate = this._getDefaultDate(inst); - var settings = this._getFormatConfig(inst); - try { - date = this.parseDate(dateFormat, dates, settings) || defaultDate; - } catch (event) { - this.log(event); - dates = (noDefault ? '' : dates); + + //Create the placeholder + this._createPlaceholder(); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + if(o.cursor) { // cursor option + if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); + $('body').css("cursor", o.cursor); } - inst.selectedDay = date.getDate(); - inst.drawMonth = inst.selectedMonth = date.getMonth(); - inst.drawYear = inst.selectedYear = date.getFullYear(); - inst.currentDay = (dates ? date.getDate() : 0); - inst.currentMonth = (dates ? date.getMonth() : 0); - inst.currentYear = (dates ? date.getFullYear() : 0); - this._adjustInstDate(inst); - }, - /* Retrieve the default date shown on opening. */ - _getDefaultDate: function(inst) { - return this._restrictMinMax(inst, - this._determineDate(inst, this._get(inst, 'defaultDate'), new Date())); - }, + if(o.opacity) { // opacity option + if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); + this.helper.css("opacity", o.opacity); + } - /* A date may be specified as an exact value or a relative one. */ - _determineDate: function(inst, date, defaultDate) { - var offsetNumeric = function(offset) { - var date = new Date(); - date.setDate(date.getDate() + offset); - return date; - }; - var offsetString = function(offset) { - try { - return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), - offset, $.datepicker._getFormatConfig(inst)); - } - catch (e) { - // Ignore - } - var date = (offset.toLowerCase().match(/^c/) ? - $.datepicker._getDate(inst) : null) || new Date(); - var year = date.getFullYear(); - var month = date.getMonth(); - var day = date.getDate(); - var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; - var matches = pattern.exec(offset); - while (matches) { - switch (matches[2] || 'd') { - case 'd' : case 'D' : - day += parseInt(matches[1],10); break; - case 'w' : case 'W' : - day += parseInt(matches[1],10) * 7; break; - case 'm' : case 'M' : - month += parseInt(matches[1],10); - day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); - break; - case 'y': case 'Y' : - year += parseInt(matches[1],10); - day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); - break; - } - matches = pattern.exec(offset); - } - return new Date(year, month, day); - }; - var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) : - (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); - newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate); - if (newDate) { - newDate.setHours(0); - newDate.setMinutes(0); - newDate.setSeconds(0); - newDate.setMilliseconds(0); + if(o.zIndex) { // zIndex option + if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); + this.helper.css("zIndex", o.zIndex); } - return this._daylightSavingAdjust(newDate); - }, - /* Handle switch to/from daylight saving. - Hours may be non-zero on daylight saving cut-over: - > 12 when midnight changeover, but then cannot generate - midnight datetime, so jump to 1AM, otherwise reset. - @param date (Date) the date to check - @return (Date) the corrected date */ - _daylightSavingAdjust: function(date) { - if (!date) return null; - date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); - return date; - }, + //Prepare scrolling + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') + this.overflowOffset = this.scrollParent.offset(); - /* Set the date(s) directly. */ - _setDate: function(inst, date, noChange) { - var clear = !date; - var origMonth = inst.selectedMonth; - var origYear = inst.selectedYear; - var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); - inst.selectedDay = inst.currentDay = newDate.getDate(); - inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); - inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); - if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange) - this._notifyChange(inst); - this._adjustInstDate(inst); - if (inst.input) { - inst.input.val(clear ? '' : this._formatDate(inst)); + //Call callbacks + this._trigger("start", event, this._uiHash()); + + //Recache the helper size + if(!this._preserveHelperProportions) + this._cacheHelperProportions(); + + + //Post 'activate' events to possible containers + if(!noActivation) { + for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); } } - }, - /* Retrieve the date(s) directly. */ - _getDate: function(inst) { - var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : - this._daylightSavingAdjust(new Date( - inst.currentYear, inst.currentMonth, inst.currentDay))); - return startDate; + //Prepare possible droppables + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.dragging = true; + + this.helper.addClass("ui-sortable-helper"); + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + }, - /* Generate the HTML for the current state of the date picker. */ - _generateHTML: function(inst) { - var today = new Date(); - today = this._daylightSavingAdjust( - new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time - var isRTL = this._get(inst, 'isRTL'); - var showButtonPanel = this._get(inst, 'showButtonPanel'); - var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); - var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); - var numMonths = this._getNumberOfMonths(inst); - var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); - var stepMonths = this._get(inst, 'stepMonths'); - var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); - var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : - new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); - var minDate = this._getMinMaxDate(inst, 'min'); - var maxDate = this._getMinMaxDate(inst, 'max'); - var drawMonth = inst.drawMonth - showCurrentAtPos; - var drawYear = inst.drawYear; - if (drawMonth < 0) { - drawMonth += 12; - drawYear--; + _mouseDrag: function(event) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; } - if (maxDate) { - var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), - maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); - maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); - while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { - drawMonth--; - if (drawMonth < 0) { - drawMonth = 11; - drawYear--; - } + + //Do scrolling + if(this.options.scroll) { + var o = this.options, scrolled = false; + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { + + if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + + if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + + } else { + + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); } - inst.drawMonth = drawMonth; - inst.drawYear = drawYear; - var prevText = this._get(inst, 'prevText'); - prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, - this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), - this._getFormatConfig(inst))); - var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? - '' + prevText + '' : - (hideIfNoPrevNext ? '' : '' + prevText + '')); - var nextText = this._get(inst, 'nextText'); - nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, - this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), - this._getFormatConfig(inst))); - var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? - '' + nextText + '' : - (hideIfNoPrevNext ? '' : '' + nextText + '')); - var currentText = this._get(inst, 'currentText'); - var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); - currentText = (!navigationAsDateFormat ? currentText : - this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); - var controls = (!inst.inline ? '' : ''); - var buttonPanel = (showButtonPanel) ? '
          ' + (isRTL ? controls : '') + - (this._isInRange(inst, gotoDate) ? '' : '') + (isRTL ? '' : controls) + '
          ' : ''; - var firstDay = parseInt(this._get(inst, 'firstDay'),10); - firstDay = (isNaN(firstDay) ? 0 : firstDay); - var showWeek = this._get(inst, 'showWeek'); - var dayNames = this._get(inst, 'dayNames'); - var dayNamesShort = this._get(inst, 'dayNamesShort'); - var dayNamesMin = this._get(inst, 'dayNamesMin'); - var monthNames = this._get(inst, 'monthNames'); - var monthNamesShort = this._get(inst, 'monthNamesShort'); - var beforeShowDay = this._get(inst, 'beforeShowDay'); - var showOtherMonths = this._get(inst, 'showOtherMonths'); - var selectOtherMonths = this._get(inst, 'selectOtherMonths'); - var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; - var defaultDate = this._getDefaultDate(inst); - var html = ''; - for (var row = 0; row < numMonths[0]; row++) { - var group = ''; - this.maxRows = 4; - for (var col = 0; col < numMonths[1]; col++) { - var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); - var cornerClass = ' ui-corner-all'; - var calender = ''; - if (isMultiMonth) { - calender += '
          '; - } - calender += '
          ' + - (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + - (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + - this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, - row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers - '
          ' + - ''; - var thead = (showWeek ? '' : ''); - for (var dow = 0; dow < 7; dow++) { // days of the week - var day = (dow + firstDay) % 7; - thead += '= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' + - '' + dayNamesMin[day] + ''; - } - calender += thead + ''; - var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); - if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) - inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); - var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; - var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate - var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) - this.maxRows = numRows; - var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); - for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows - calender += ''; - var tbody = (!showWeek ? '' : ''); - for (var dow = 0; dow < 7; dow++) { // create date picker days - var daySettings = (beforeShowDay ? - beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); - var otherMonth = (printDate.getMonth() != drawMonth); - var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || - (minDate && printDate < minDate) || (maxDate && printDate > maxDate); - tbody += ''; // display selectable date - printDate.setDate(printDate.getDate() + 1); - printDate = this._daylightSavingAdjust(printDate); - } - calender += tbody + ''; - } - drawMonth++; - if (drawMonth > 11) { - drawMonth = 0; - drawYear++; + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + //Set the helper position + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + + //Rearrange + for (var i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); + if (!intersection) continue; + + // Only put the placeholder inside the current Container, skip all + // items form other containers. This works because when moving + // an item from one container to another the + // currentContainer is switched before the placeholder is moved. + // + // Without this moving items in "sub-sortables" can cause the placeholder to jitter + // beetween the outer and inner container. + if (item.instance !== this.currentContainer) continue; + + if (itemElement != this.currentItem[0] //cannot intersect with itself + && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before + && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked + && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true) + //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container + ) { + + this.direction = intersection == 1 ? "down" : "up"; + + if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { + this._rearrange(event, item); + } else { + break; } - calender += '
          ' + this._get(inst, 'weekHeader') + '
          ' + - this._get(inst, 'calculateWeek')(printDate) + '' + // actions - (otherMonth && !showOtherMonths ? ' ' : // display for other months - (unselectable ? '' + printDate.getDate() + '' : '' + printDate.getDate() + '')) + '
          ' + (isMultiMonth ? '
          ' + - ((numMonths[0] > 0 && col == numMonths[1]-1) ? '
          ' : '') : ''); - group += calender; + + this._trigger("change", event, this._uiHash()); + break; } - html += group; } - html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ? - '' : ''); - inst._keyEvent = false; - return html; + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + //Call callbacks + this._trigger('sort', event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + }, - /* Generate the month and year header. */ - _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, - secondary, monthNames, monthNamesShort) { - var changeMonth = this._get(inst, 'changeMonth'); - var changeYear = this._get(inst, 'changeYear'); - var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); - var html = '
          '; - var monthHtml = ''; - // month selection - if (secondary || !changeMonth) - monthHtml += '' + monthNames[drawMonth] + ''; - else { - var inMinYear = (minDate && minDate.getFullYear() == drawYear); - var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); - monthHtml += ''; + _mouseStop: function(event, noPropagation) { + + if(!event) return; + + //If we are using droppables, inform the manager about the drop + if ($.ui.ddmanager && !this.options.dropBehaviour) + $.ui.ddmanager.drop(this, event); + + if(this.options.revert) { + var that = this; + var cur = this.placeholder.offset(); + + this.reverting = true; + + $(this.helper).animate({ + left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), + top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) + }, parseInt(this.options.revert, 10) || 500, function() { + that._clear(event); + }); + } else { + this._clear(event, noPropagation); } - if (!showMonthAfterYear) - html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); - // year selection - if ( !inst.yearshtml ) { - inst.yearshtml = ''; - if (secondary || !changeYear) - html += '' + drawYear + ''; - else { - // determine range of years to display - var years = this._get(inst, 'yearRange').split(':'); - var thisYear = new Date().getFullYear(); - var determineYear = function(value) { - var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : - (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : - parseInt(value, 10))); - return (isNaN(year) ? thisYear : year); - }; - var year = determineYear(years[0]); - var endYear = Math.max(year, determineYear(years[1] || '')); - year = (minDate ? Math.max(year, minDate.getFullYear()) : year); - endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); - inst.yearshtml += ''; - - html += inst.yearshtml; - inst.yearshtml = null; } + } - html += this._get(inst, 'yearSuffix'); - if (showMonthAfterYear) - html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; - html += '
          '; // Close datepicker_header - return html; - }, - /* Adjust one of the date sub-fields. */ - _adjustInstDate: function(inst, offset, period) { - var year = inst.drawYear + (period == 'Y' ? offset : 0); - var month = inst.drawMonth + (period == 'M' ? offset : 0); - var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + - (period == 'D' ? offset : 0); - var date = this._restrictMinMax(inst, - this._daylightSavingAdjust(new Date(year, month, day))); - inst.selectedDay = date.getDate(); - inst.drawMonth = inst.selectedMonth = date.getMonth(); - inst.drawYear = inst.selectedYear = date.getFullYear(); - if (period == 'M' || period == 'Y') - this._notifyChange(inst); + if (this.placeholder) { + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); + + $.extend(this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + }); + + if(this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } + } + + return this; + }, - /* Ensure a date is within any min/max bounds. */ - _restrictMinMax: function(inst, date) { - var minDate = this._getMinMaxDate(inst, 'min'); - var maxDate = this._getMinMaxDate(inst, 'max'); - var newDate = (minDate && date < minDate ? minDate : date); - newDate = (maxDate && newDate > maxDate ? maxDate : newDate); - return newDate; + serialize: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var str = []; o = o || {}; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); + if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); + }); + + if(!str.length && o.key) { + str.push(o.key + '='); + } + + return str.join('&'); + }, - /* Notify change of month/year. */ - _notifyChange: function(inst) { - var onChange = this._get(inst, 'onChangeMonthYear'); - if (onChange) - onChange.apply((inst.input ? inst.input[0] : null), - [inst.selectedYear, inst.selectedMonth + 1, inst]); + toArray: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var ret = []; o = o || {}; + + items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); + return ret; + }, - /* Determine the number of months to show. */ - _getNumberOfMonths: function(inst) { - var numMonths = this._get(inst, 'numberOfMonths'); - return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + /* Be careful with the following core functions */ + _intersectsWith: function(item) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height; + + var l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height; + + var dyClick = this.offset.click.top, + dxClick = this.offset.click.left; + + var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + + if( this.options.tolerance == "pointer" + || this.options.forcePointerForContainers + || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) + ) { + return isOverElement; + } else { + + return (l < x1 + (this.helperProportions.width / 2) // Right Half + && x2 - (this.helperProportions.width / 2) < r // Left Half + && t < y1 + (this.helperProportions.height / 2) // Bottom Half + && y2 - (this.helperProportions.height / 2) < b ); // Top Half + + } }, - /* Determine the current maximum date - ensure no time components are set. */ - _getMinMaxDate: function(inst, minMax) { - return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); + _intersectsWithPointer: function(item) { + + var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), + isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), + isOverElement = isOverElementHeight && isOverElementWidth, + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (!isOverElement) + return false; + + return this.floating ? + ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) + : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); + }, - /* Find the number of days in a given month. */ - _getDaysInMonth: function(year, month) { - return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); + _intersectsWithSides: function(item) { + + var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), + isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); + } else { + return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); + } + }, - /* Find the day of the week of the first of a month. */ - _getFirstDayOfMonth: function(year, month) { - return new Date(year, month, 1).getDay(); + _getDragVerticalDirection: function() { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta != 0 && (delta > 0 ? "down" : "up"); }, - /* Determines if we should allow a "next/prev" month display change. */ - _canAdjustMonth: function(inst, offset, curYear, curMonth) { - var numMonths = this._getNumberOfMonths(inst); - var date = this._daylightSavingAdjust(new Date(curYear, - curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); - if (offset < 0) - date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); - return this._isInRange(inst, date); + _getDragHorizontalDirection: function() { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta != 0 && (delta > 0 ? "right" : "left"); }, - /* Is the given date in the accepted range? */ - _isInRange: function(inst, date) { - var minDate = this._getMinMaxDate(inst, 'min'); - var maxDate = this._getMinMaxDate(inst, 'max'); - return ((!minDate || date.getTime() >= minDate.getTime()) && - (!maxDate || date.getTime() <= maxDate.getTime())); + refresh: function(event) { + this._refreshItems(event); + this.refreshPositions(); + return this; }, - /* Provide the configuration settings for formatting/parsing. */ - _getFormatConfig: function(inst) { - var shortYearCutoff = this._get(inst, 'shortYearCutoff'); - shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : - new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); - return {shortYearCutoff: shortYearCutoff, - dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), - monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + _connectWith: function() { + var options = this.options; + return options.connectWith.constructor == String + ? [options.connectWith] + : options.connectWith; }, - /* Format the given date for display. */ - _formatDate: function(inst, day, month, year) { - if (!day) { - inst.currentDay = inst.selectedDay; - inst.currentMonth = inst.selectedMonth; - inst.currentYear = inst.selectedYear; - } - var date = (day ? (typeof day == 'object' ? day : - this._daylightSavingAdjust(new Date(year, month, day))) : - this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); - return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); - } -}); + _getItemsAsjQuery: function(connected) { -/* - * Bind hover events for datepicker elements. - * Done via delegate so the binding only occurs once in the lifetime of the parent div. - * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. - */ -function bindHover(dpDiv) { - var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; - return dpDiv.bind('mouseout', function(event) { - var elem = $( event.target ).closest( selector ); - if ( !elem.length ) { - return; - } - elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" ); - }) - .bind('mouseover', function(event) { - var elem = $( event.target ).closest( selector ); - if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) || - !elem.length ) { - return; - } - elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); - elem.addClass('ui-state-hover'); - if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover'); - if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover'); - }); -} + var items = []; + var queries = []; + var connectWith = this._connectWith(); -/* jQuery extend now ignores nulls! */ -function extendRemove(target, props) { - $.extend(target, props); - for (var name in props) - if (props[name] == null || props[name] == undefined) - target[name] = props[name]; - return target; -}; + if(connectWith && connected) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], this.widgetName); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); + } + }; + }; + } -/* Determine whether an object is an array. */ -function isArray(a) { - return (a && (($.browser.safari && typeof a == 'object' && a.length) || - (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); -}; + queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); + + for (var i = queries.length - 1; i >= 0; i--){ + queries[i][0].each(function() { + items.push(this); + }); + }; -/* Invoke the datepicker functionality. - @param options string - a command, optionally followed by additional parameters or - Object - settings for attaching new datepicker functionality - @return jQuery object */ -$.fn.datepicker = function(options){ - - /* Verify an empty collection wasn't passed - Fixes #6976 */ - if ( !this.length ) { - return this; - } - - /* Initialise the date picker. */ - if (!$.datepicker.initialized) { - $(document).mousedown($.datepicker._checkExternalClick). - find('body').append($.datepicker.dpDiv); - $.datepicker.initialized = true; - } + return $(items); - var otherArgs = Array.prototype.slice.call(arguments, 1); - if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) - return $.datepicker['_' + options + 'Datepicker']. - apply($.datepicker, [this[0]].concat(otherArgs)); - if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') - return $.datepicker['_' + options + 'Datepicker']. - apply($.datepicker, [this[0]].concat(otherArgs)); - return this.each(function() { - typeof options == 'string' ? - $.datepicker['_' + options + 'Datepicker']. - apply($.datepicker, [this].concat(otherArgs)) : - $.datepicker._attachDatepicker(this, options); - }); -}; + }, -$.datepicker = new Datepicker(); // singleton instance -$.datepicker.initialized = false; -$.datepicker.uuid = new Date().getTime(); -$.datepicker.version = "1.8.16"; + _removeCurrentsFromItems: function() { -// Workaround for #4055 -// Add another global to avoid noConflict issues with inline event handlers -window['DP_jQuery_' + dpuuid] = $; + var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); -})(jQuery); -/* - * jQuery UI Dialog 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Dialog - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.button.js - * jquery.ui.draggable.js - * jquery.ui.mouse.js - * jquery.ui.position.js - * jquery.ui.resizable.js - */ -(function( $, undefined ) { + this.items = $.grep(this.items, function (item) { + for (var j=0; j < list.length; j++) { + if(list[j] == item.item[0]) + return false; + }; + return true; + }); -var uiDialogClasses = - 'ui-dialog ' + - 'ui-widget ' + - 'ui-widget-content ' + - 'ui-corner-all ', - sizeRelatedOptions = { - buttons: true, - height: true, - maxHeight: true, - maxWidth: true, - minHeight: true, - minWidth: true, - width: true - }, - resizableRelatedOptions = { - maxHeight: true, - maxWidth: true, - minHeight: true, - minWidth: true }, - // support for jQuery 1.3.2 - handle common attrFn methods for dialog - attrFn = $.attrFn || { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true, - click: true - }; -$.widget("ui.dialog", { - options: { - autoOpen: true, - buttons: {}, - closeOnEscape: true, - closeText: 'close', - dialogClass: '', - draggable: true, - hide: null, - height: 'auto', - maxHeight: false, - maxWidth: false, - minHeight: 150, - minWidth: 150, - modal: false, - position: { - my: 'center', - at: 'center', - collision: 'fit', - // ensure that the titlebar is never outside the document - using: function(pos) { - var topOffset = $(this).css(pos).offset().top; - if (topOffset < 0) { - $(this).css('top', pos.top - topOffset); - } - } - }, - resizable: true, - show: null, - stack: true, - title: '', - width: 300, - zIndex: 1000 - }, + _refreshItems: function(event) { - _create: function() { - this.originalTitle = this.element.attr('title'); - // #5742 - .attr() might return a DOMElement - if ( typeof this.originalTitle !== "string" ) { - this.originalTitle = ""; + this.items = []; + this.containers = [this]; + var items = this.items; + var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; + var connectWith = this._connectWith(); + + if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], this.widgetName); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); + this.containers.push(inst); + } + }; + }; } - this.options.title = this.options.title || this.originalTitle; - var self = this, - options = self.options, + for (var i = queries.length - 1; i >= 0; i--) { + var targetData = queries[i][1]; + var _queries = queries[i][0]; - title = options.title || ' ', - titleId = $.ui.dialog.getTitleId(self.element), + for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { + var item = $(_queries[j]); - uiDialog = (self.uiDialog = $('
          ')) - .appendTo(document.body) - .hide() - .addClass(uiDialogClasses + options.dialogClass) - .css({ - zIndex: options.zIndex - }) - // setting tabIndex makes the div focusable - // setting outline to 0 prevents a border on focus in Mozilla - .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { - if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && - event.keyCode === $.ui.keyCode.ESCAPE) { - - self.close(event); - event.preventDefault(); - } - }) - .attr({ - role: 'dialog', - 'aria-labelledby': titleId - }) - .mousedown(function(event) { - self.moveToTop(false, event); - }), + item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager) - uiDialogContent = self.element - .show() - .removeAttr('title') - .addClass( - 'ui-dialog-content ' + - 'ui-widget-content') - .appendTo(uiDialog), - - uiDialogTitlebar = (self.uiDialogTitlebar = $('
          ')) - .addClass( - 'ui-dialog-titlebar ' + - 'ui-widget-header ' + - 'ui-corner-all ' + - 'ui-helper-clearfix' - ) - .prependTo(uiDialog), - - uiDialogTitlebarClose = $('') - .addClass( - 'ui-dialog-titlebar-close ' + - 'ui-corner-all' - ) - .attr('role', 'button') - .hover( - function() { - uiDialogTitlebarClose.addClass('ui-state-hover'); - }, - function() { - uiDialogTitlebarClose.removeClass('ui-state-hover'); - } - ) - .focus(function() { - uiDialogTitlebarClose.addClass('ui-state-focus'); - }) - .blur(function() { - uiDialogTitlebarClose.removeClass('ui-state-focus'); - }) - .click(function(event) { - self.close(event); - return false; - }) - .appendTo(uiDialogTitlebar), + items.push({ + item: item, + instance: targetData, + width: 0, height: 0, + left: 0, top: 0 + }); + }; + }; - uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('')) - .addClass( - 'ui-icon ' + - 'ui-icon-closethick' - ) - .text(options.closeText) - .appendTo(uiDialogTitlebarClose), + }, - uiDialogTitle = $('') - .addClass('ui-dialog-title') - .attr('id', titleId) - .html(title) - .prependTo(uiDialogTitlebar); + refreshPositions: function(fast) { - //handling of deprecated beforeclose (vs beforeClose) option - //Ticket #4669 http://dev.jqueryui.com/ticket/4669 - //TODO: remove in 1.9pre - if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) { - options.beforeClose = options.beforeclose; + //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change + if(this.offsetParent && this.helper) { + this.offset.parent = this._getParentOffset(); } - uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); + for (var i = this.items.length - 1; i >= 0; i--){ + var item = this.items[i]; - if (options.draggable && $.fn.draggable) { - self._makeDraggable(); - } - if (options.resizable && $.fn.resizable) { - self._makeResizable(); - } + //We ignore calculating positions of all connected containers when we're not over them + if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) + continue; - self._createButtons(options.buttons); - self._isOpen = false; + var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; - if ($.fn.bgiframe) { - uiDialog.bgiframe(); - } - }, + if (!fast) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } - _init: function() { - if ( this.options.autoOpen ) { - this.open(); + var p = t.offset(); + item.left = p.left; + item.top = p.top; + }; + + if(this.options.custom && this.options.custom.refreshContainers) { + this.options.custom.refreshContainers.call(this); + } else { + for (var i = this.containers.length - 1; i >= 0; i--){ + var p = this.containers[i].element.offset(); + this.containers[i].containerCache.left = p.left; + this.containers[i].containerCache.top = p.top; + this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); + this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); + }; } + + return this; }, - destroy: function() { - var self = this; - - if (self.overlay) { - self.overlay.destroy(); - } - self.uiDialog.hide(); - self.element - .unbind('.dialog') - .removeData('dialog') - .removeClass('ui-dialog-content ui-widget-content') - .hide().appendTo('body'); - self.uiDialog.remove(); + _createPlaceholder: function(that) { + that = that || this; + var o = that.options; + + if(!o.placeholder || o.placeholder.constructor == String) { + var className = o.placeholder; + o.placeholder = { + element: function() { + + var el = $(document.createElement(that.currentItem[0].nodeName)) + .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") + .removeClass("ui-sortable-helper")[0]; + + if(!className) + el.style.visibility = "hidden"; + + return el; + }, + update: function(container, p) { - if (self.originalTitle) { - self.element.attr('title', self.originalTitle); + // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified + if(className && !o.forcePlaceholderSize) return; + + //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item + if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); }; + if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); }; + } + }; } - return self; - }, + //Create the placeholder + that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); + + //Append it after the actual current item + that.currentItem.after(that.placeholder); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update(that, that.placeholder); - widget: function() { - return this.uiDialog; }, - close: function(event) { - var self = this, - maxZ, thisZ; - - if (false === self._trigger('beforeClose', event)) { - return; - } + _contactContainers: function(event) { - if (self.overlay) { - self.overlay.destroy(); - } - self.uiDialog.unbind('keypress.ui-dialog'); + // get innermost container that intersects with item + var innermostContainer = null, innermostIndex = null; - self._isOpen = false; - if (self.options.hide) { - self.uiDialog.hide(self.options.hide, function() { - self._trigger('close', event); - }); - } else { - self.uiDialog.hide(); - self._trigger('close', event); - } + for (var i = this.containers.length - 1; i >= 0; i--){ - $.ui.dialog.overlay.resize(); + // never consider a container that's located within the item itself + if($.contains(this.currentItem[0], this.containers[i].element[0])) + continue; - // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) - if (self.options.modal) { - maxZ = 0; - $('.ui-dialog').each(function() { - if (this !== self.uiDialog[0]) { - thisZ = $(this).css('z-index'); - if(!isNaN(thisZ)) { - maxZ = Math.max(maxZ, thisZ); - } + if(this._intersectsWith(this.containers[i].containerCache)) { + + // if we've already found a container and it's more "inner" than this, then continue + if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) + continue; + + innermostContainer = this.containers[i]; + innermostIndex = i; + + } else { + // container doesn't intersect. trigger "out" event if necessary + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", event, this._uiHash(this)); + this.containers[i].containerCache.over = 0; } - }); - $.ui.dialog.maxZ = maxZ; + } + } - return self; - }, + // if no intersecting containers found, return + if(!innermostContainer) return; - isOpen: function() { - return this._isOpen; - }, + // move the item into the container if it's not there already + if(this.containers.length === 1) { + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } else { + + //When entering a new container, we will find the item with the least distance and append our item near it + var dist = 10000; var itemWithLeastDistance = null; + var posProperty = this.containers[innermostIndex].floating ? 'left' : 'top'; + var sizeProperty = this.containers[innermostIndex].floating ? 'width' : 'height'; + var base = this.positionAbs[posProperty] + this.offset.click[posProperty]; + for (var j = this.items.length - 1; j >= 0; j--) { + if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; + if(this.items[j].item[0] == this.currentItem[0]) continue; + var cur = this.items[j].item.offset()[posProperty]; + var nearBottom = false; + if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ + nearBottom = true; + cur += this.items[j][sizeProperty]; + } + + if(Math.abs(cur - base) < dist) { + dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; + this.direction = nearBottom ? "up": "down"; + } + } - // the force parameter allows us to move modal dialogs to their correct - // position on open - moveToTop: function(force, event) { - var self = this, - options = self.options, - saveScroll; + if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled + return; - if ((options.modal && !force) || - (!options.stack && !options.modal)) { - return self._trigger('focus', event); - } + this.currentContainer = this.containers[innermostIndex]; + itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); + this._trigger("change", event, this._uiHash()); + this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); - if (options.zIndex > $.ui.dialog.maxZ) { - $.ui.dialog.maxZ = options.zIndex; - } - if (self.overlay) { - $.ui.dialog.maxZ += 1; - self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ); + //Update the placeholder + this.options.placeholder.update(this.currentContainer, this.placeholder); + + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; } - //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. - // http://ui.jquery.com/bugs/ticket/3193 - saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() }; - $.ui.dialog.maxZ += 1; - self.uiDialog.css('z-index', $.ui.dialog.maxZ); - self.element.attr(saveScroll); - self._trigger('focus', event); - return self; }, - open: function() { - if (this._isOpen) { return; } - - var self = this, - options = self.options, - uiDialog = self.uiDialog; + _createHelper: function(event) { - self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null; - self._size(); - self._position(options.position); - uiDialog.show(options.show); - self.moveToTop(true); + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); - // prevent tabbing out of modal dialogs - if (options.modal) { - uiDialog.bind('keypress.ui-dialog', function(event) { - if (event.keyCode !== $.ui.keyCode.TAB) { - return; - } + if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already + $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); - var tabbables = $(':tabbable', this), - first = tabbables.filter(':first'), - last = tabbables.filter(':last'); + if(helper[0] == this.currentItem[0]) + this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; - if (event.target === last[0] && !event.shiftKey) { - first.focus(1); - return false; - } else if (event.target === first[0] && event.shiftKey) { - last.focus(1); - return false; - } - }); - } + if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); + if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); - // set focus to the first tabbable element in the content area or the first button - // if there are no tabbable elements, set focus on the dialog itself - $(self.element.find(':tabbable').get().concat( - uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat( - uiDialog.get()))).eq(0).focus(); - - self._isOpen = true; - self._trigger('open'); - - return self; - }, - - _createButtons: function(buttons) { - var self = this, - hasButtons = false, - uiDialogButtonPane = $('
          ') - .addClass( - 'ui-dialog-buttonpane ' + - 'ui-widget-content ' + - 'ui-helper-clearfix' - ), - uiButtonSet = $( "
          " ) - .addClass( "ui-dialog-buttonset" ) - .appendTo( uiDialogButtonPane ); + return helper; - // if we already have a button pane, remove it - self.uiDialog.find('.ui-dialog-buttonpane').remove(); + }, - if (typeof buttons === 'object' && buttons !== null) { - $.each(buttons, function() { - return !(hasButtons = true); - }); + _adjustOffsetFromHelper: function(obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); } - if (hasButtons) { - $.each(buttons, function(name, props) { - props = $.isFunction( props ) ? - { click: props, text: name } : - props; - var button = $('') - .click(function() { - props.click.apply(self.element[0], arguments); - }) - .appendTo(uiButtonSet); - // can't use .attr( props, true ) with jQuery 1.3.2. - $.each( props, function( key, value ) { - if ( key === "click" ) { - return; - } - if ( key in attrFn ) { - button[ key ]( value ); - } else { - button.attr( key, value ); - } - }); - if ($.fn.button) { - button.button(); - } - }); - uiDialogButtonPane.appendTo(self.uiDialog); + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; } }, - _makeDraggable: function() { - var self = this, - options = self.options, - doc = $(document), - heightBeforeDrag; + _getParentOffset: function() { - function filteredUi(ui) { - return { - position: ui.position, - offset: ui.offset - }; + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); } - self.uiDialog.draggable({ - cancel: '.ui-dialog-content, .ui-dialog-titlebar-close', - handle: '.ui-dialog-titlebar', - containment: 'document', - start: function(event, ui) { - heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height(); - $(this).height($(this).height()).addClass("ui-dialog-dragging"); - self._trigger('dragStart', event, filteredUi(ui)); - }, - drag: function(event, ui) { - self._trigger('drag', event, filteredUi(ui)); - }, - stop: function(event, ui) { - options.position = [ui.position.left - doc.scrollLeft(), - ui.position.top - doc.scrollTop()]; - $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); - self._trigger('dragStop', event, filteredUi(ui)); - $.ui.dialog.overlay.resize(); - } - }); + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + }, - _makeResizable: function(handles) { - handles = (handles === undefined ? this.options.resizable : handles); - var self = this, - options = self.options, - // .ui-resizable has position: relative defined in the stylesheet - // but dialogs have to use absolute or fixed positioning - position = self.uiDialog.css('position'), - resizeHandles = (typeof handles === 'string' ? - handles : - 'n,e,s,w,se,sw,ne,nw' - ); + _getRelativeOffset: function() { - function filteredUi(ui) { + if(this.cssPosition == "relative") { + var p = this.currentItem.position(); return { - originalPosition: ui.originalPosition, - originalSize: ui.originalSize, - position: ui.position, - size: ui.size + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() }; + } else { + return { top: 0, left: 0 }; } - self.uiDialog.resizable({ - cancel: '.ui-dialog-content', - containment: 'document', - alsoResize: self.element, - maxWidth: options.maxWidth, - maxHeight: options.maxHeight, - minWidth: options.minWidth, - minHeight: self._minHeight(), - handles: resizeHandles, - start: function(event, ui) { - $(this).addClass("ui-dialog-resizing"); - self._trigger('resizeStart', event, filteredUi(ui)); - }, - resize: function(event, ui) { - self._trigger('resize', event, filteredUi(ui)); - }, - stop: function(event, ui) { - $(this).removeClass("ui-dialog-resizing"); - options.height = $(this).height(); - options.width = $(this).width(); - self._trigger('resizeStop', event, filteredUi(ui)); - $.ui.dialog.overlay.resize(); - } - }) - .css('position', position) - .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); }, - _minHeight: function() { - var options = this.options; + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), + top: (parseInt(this.currentItem.css("marginTop"),10) || 0) + }; + }, - if (options.height === 'auto') { - return options.minHeight; - } else { - return Math.min(options.minHeight, options.height); - } + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; }, - _position: function(position) { - var myAt = [], - offset = [0, 0], - isVisible; + _setContainment: function() { - if (position) { - // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( - // if (typeof position == 'string' || $.isArray(position)) { - // myAt = $.isArray(position) ? position : position.split(' '); + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; - if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) { - myAt = position.split ? position.split(' ') : [position[0], position[1]]; - if (myAt.length === 1) { - myAt[1] = myAt[0]; - } + if(!(/^(document|window|parent)$/).test(o.containment)) { + var ce = $(o.containment)[0]; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); - $.each(['left', 'top'], function(i, offsetPosition) { - if (+myAt[i] === myAt[i]) { - offset[i] = myAt[i]; - myAt[i] = offsetPosition; - } - }); + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, + co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, + co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top + ]; + } - position = { - my: myAt.join(" "), - at: myAt.join(" "), - offset: offset.join(" ") - }; - } + }, - position = $.extend({}, $.ui.dialog.prototype.options.position, position); - } else { - position = $.ui.dialog.prototype.options.position; - } + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; - // need to show the dialog to get the actual offset in the position plugin - isVisible = this.uiDialog.is(':visible'); - if (!isVisible) { - this.uiDialog.show(); - } - this.uiDialog - // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 - .css({ top: 0, left: 0 }) - .position($.extend({ of: window }, position)); - if (!isVisible) { - this.uiDialog.hide(); - } }, - _setOptions: function( options ) { - var self = this, - resizableOptions = {}, - resize = false; + _generatePosition: function(event) { - $.each( options, function( key, value ) { - self._setOption( key, value ); - - if ( key in sizeRelatedOptions ) { - resize = true; - } - if ( key in resizableRelatedOptions ) { - resizableOptions[ key ] = value; - } - }); + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - if ( resize ) { - this._size(); - } - if ( this.uiDialog.is( ":data(resizable)" ) ) { - this.uiDialog.resizable( "option", resizableOptions ); + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); } - }, - _setOption: function(key, value){ - var self = this, - uiDialog = self.uiDialog; - - switch (key) { - //handling of deprecated beforeclose (vs beforeClose) option - //Ticket #4669 http://dev.jqueryui.com/ticket/4669 - //TODO: remove in 1.9pre - case "beforeclose": - key = "beforeClose"; - break; - case "buttons": - self._createButtons(value); - break; - case "closeText": - // ensure that we always pass a string - self.uiDialogTitlebarCloseText.text("" + value); - break; - case "dialogClass": - uiDialog - .removeClass(self.options.dialogClass) - .addClass(uiDialogClasses + value); - break; - case "disabled": - if (value) { - uiDialog.addClass('ui-dialog-disabled'); - } else { - uiDialog.removeClass('ui-dialog-disabled'); - } - break; - case "draggable": - var isDraggable = uiDialog.is( ":data(draggable)" ); - if ( isDraggable && !value ) { - uiDialog.draggable( "destroy" ); - } - - if ( !isDraggable && value ) { - self._makeDraggable(); - } - break; - case "position": - self._position(value); - break; - case "resizable": - // currently resizable, becoming non-resizable - var isResizable = uiDialog.is( ":data(resizable)" ); - if (isResizable && !value) { - uiDialog.resizable('destroy'); - } + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options - // currently resizable, changing handles - if (isResizable && typeof value === 'string') { - uiDialog.resizable('option', 'handles', value); - } + if(this.containment) { + if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if(o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } - // currently non-resizable, becoming resizable - if (!isResizable && value !== false) { - self._makeResizable(value); - } - break; - case "title": - // convert whatever was passed in o a string, for html() to not throw up - $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' ')); - break; } - $.Widget.prototype._setOption.apply(self, arguments); + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + }, - _size: function() { - /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content - * divs will both have width and height set, so we need to reset them - */ - var options = this.options, - nonContentHeight, - minContentHeight, - isVisible = this.uiDialog.is( ":visible" ); + _rearrange: function(event, i, a, hardRefresh) { - // reset content sizing - this.element.show().css({ - width: 'auto', - minHeight: 0, - height: 0 + a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var counter = this.counter; + + this._delay(function() { + if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove }); - if (options.minWidth > options.width) { - options.width = options.minWidth; - } + }, - // reset wrapper sizing - // determine the height of all the non-content elements - nonContentHeight = this.uiDialog.css({ - height: 'auto', - width: options.width - }) - .height(); - minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); - - if ( options.height === "auto" ) { - // only needed for IE6 support - if ( $.support.minHeight ) { - this.element.css({ - minHeight: minContentHeight, - height: "auto" - }); - } else { - this.uiDialog.show(); - var autoHeight = this.element.css( "height", "auto" ).height(); - if ( !isVisible ) { - this.uiDialog.hide(); - } - this.element.height( Math.max( autoHeight, minContentHeight ) ); + _clear: function(event, noPropagation) { + + this.reverting = false; + // We delay all events that have to be triggered to after the point where the placeholder has been removed and + // everything else normalized again + var delayedTriggers = []; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) + if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); + this._noFinalSort = null; + + if(this.helper[0] == this.currentItem[0]) { + for(var i in this._storedCSS) { + if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; } + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); } else { - this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); + this.currentItem.show(); } - if (this.uiDialog.is(':data(resizable)')) { - this.uiDialog.resizable('option', 'minHeight', this._minHeight()); - } - } -}); + if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); + if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed -$.extend($.ui.dialog, { - version: "1.8.16", + // Check if the items Container has Changed and trigger appropriate + // events. + if (this !== this.currentContainer) { + if(!noPropagation) { + delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); + delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); + delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); + } + } - uuid: 0, - maxZ: 0, - getTitleId: function($el) { - var id = $el.attr('id'); - if (!id) { - this.uuid += 1; - id = this.uuid; + //Post events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + if(this.containers[i].containerCache.over) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + this.containers[i].containerCache.over = 0; + } } - return 'ui-dialog-title-' + id; - }, - - overlay: function(dialog) { - this.$el = $.ui.dialog.overlay.create(dialog); - } -}); -$.extend($.ui.dialog.overlay, { - instances: [], - // reuse old instances due to IE memory leak with alpha transparency (see #5185) - oldInstances: [], - maxZ: 0, - events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), - function(event) { return event + '.dialog-overlay'; }).join(' '), - create: function(dialog) { - if (this.instances.length === 0) { - // prevent use of anchors and inputs - // we use a setTimeout in case the overlay is created from an - // event that we're going to be cancelling (see #2804) - setTimeout(function() { - // handle $(el).dialog().dialog('close') (see #4065) - if ($.ui.dialog.overlay.instances.length) { - $(document).bind($.ui.dialog.overlay.events, function(event) { - // stop events if the z-index of the target is < the z-index of the overlay - // we cannot return true when we don't want to cancel the event (#3523) - if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) { - return false; - } - }); - } - }, 1); + //Do what was originally in plugins + if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor + if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity + if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index - // allow closing by pressing the escape key - $(document).bind('keydown.dialog-overlay', function(event) { - if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && - event.keyCode === $.ui.keyCode.ESCAPE) { - - dialog.close(event); - event.preventDefault(); - } - }); + this.dragging = false; + if(this.cancelHelperRemoval) { + if(!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } - // handle window resize - $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); + this.fromOutside = false; + return false; } - var $el = (this.oldInstances.pop() || $('
          ').addClass('ui-widget-overlay')) - .appendTo(document.body) - .css({ - width: this.width(), - height: this.height() - }); + if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); - if ($.fn.bgiframe) { - $el.bgiframe(); + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + + if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; + + if(!noPropagation) { + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); } - this.instances.push($el); - return $el; + this.fromOutside = false; + return true; + }, - destroy: function($el) { - var indexOf = $.inArray($el, this.instances); - if (indexOf != -1){ - this.oldInstances.push(this.instances.splice(indexOf, 1)[0]); + _trigger: function() { + if ($.Widget.prototype._trigger.apply(this, arguments) === false) { + this.cancel(); } + }, + + _uiHash: function(_inst) { + var inst = _inst || this; + return { + helper: inst.helper, + placeholder: inst.placeholder || $([]), + position: inst.position, + originalPosition: inst.originalPosition, + offset: inst.positionAbs, + item: inst.currentItem, + sender: _inst ? _inst.element : null + }; + } - if (this.instances.length === 0) { - $([document, window]).unbind('.dialog-overlay'); +}); + +})(jQuery); +(function( $ ) { + +function modifier( fn ) { + return function() { + var previous = this.element.val(); + fn.apply( this, arguments ); + this._refresh(); + if ( previous !== this.element.val() ) { + this._trigger( "change" ); } + }; +} - $el.remove(); - - // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) - var maxZ = 0; - $.each(this.instances, function() { - maxZ = Math.max(maxZ, this.css('z-index')); - }); - this.maxZ = maxZ; +$.widget( "ui.spinner", { + version: "1.9.2", + defaultElement: "", + widgetEventPrefix: "spin", + options: { + culture: null, + icons: { + down: "ui-icon-triangle-1-s", + up: "ui-icon-triangle-1-n" + }, + incremental: true, + max: null, + min: null, + numberFormat: null, + page: 10, + step: 1, + + change: null, + spin: null, + start: null, + stop: null }, - height: function() { - var scrollHeight, - offsetHeight; - // handle IE 6 - if ($.browser.msie && $.browser.version < 7) { - scrollHeight = Math.max( - document.documentElement.scrollHeight, - document.body.scrollHeight - ); - offsetHeight = Math.max( - document.documentElement.offsetHeight, - document.body.offsetHeight - ); + _create: function() { + // handle string values that need to be parsed + this._setOption( "max", this.options.max ); + this._setOption( "min", this.options.min ); + this._setOption( "step", this.options.step ); - if (scrollHeight < offsetHeight) { - return $(window).height() + 'px'; - } else { - return scrollHeight + 'px'; + // format the value, but don't constrain + this._value( this.element.val(), true ); + + this._draw(); + this._on( this._events ); + this._refresh(); + + // turning off autocomplete prevents the browser from remembering the + // value when navigating through history, so we re-enable autocomplete + // if the page is unloaded before the widget is destroyed. #7790 + this._on( this.window, { + beforeunload: function() { + this.element.removeAttr( "autocomplete" ); } - // handle "good" browsers - } else { - return $(document).height() + 'px'; - } + }); }, - width: function() { - var scrollWidth, - offsetWidth; - // handle IE - if ( $.browser.msie ) { - scrollWidth = Math.max( - document.documentElement.scrollWidth, - document.body.scrollWidth - ); - offsetWidth = Math.max( - document.documentElement.offsetWidth, - document.body.offsetWidth - ); + _getCreateOptions: function() { + var options = {}, + element = this.element; - if (scrollWidth < offsetWidth) { - return $(window).width() + 'px'; - } else { - return scrollWidth + 'px'; + $.each( [ "min", "max", "step" ], function( i, option ) { + var value = element.attr( option ); + if ( value !== undefined && value.length ) { + options[ option ] = value; } - // handle "good" browsers - } else { - return $(document).width() + 'px'; - } + }); + + return options; }, - resize: function() { - /* If the dialog is draggable and the user drags it past the - * right edge of the window, the document becomes wider so we - * need to stretch the overlay. If the user then drags the - * dialog back to the left, the document will become narrower, - * so we need to shrink the overlay to the appropriate size. - * This is handled by shrinking the overlay before setting it - * to the full document size. - */ - var $overlays = $([]); - $.each($.ui.dialog.overlay.instances, function() { - $overlays = $overlays.add(this); - }); + _events: { + keydown: function( event ) { + if ( this._start( event ) && this._keydown( event ) ) { + event.preventDefault(); + } + }, + keyup: "_stop", + focus: function() { + this.previous = this.element.val(); + }, + blur: function( event ) { + if ( this.cancelBlur ) { + delete this.cancelBlur; + return; + } - $overlays.css({ - width: 0, - height: 0 - }).css({ - width: $.ui.dialog.overlay.width(), - height: $.ui.dialog.overlay.height() - }); - } -}); + this._refresh(); + if ( this.previous !== this.element.val() ) { + this._trigger( "change", event ); + } + }, + mousewheel: function( event, delta ) { + if ( !delta ) { + return; + } + if ( !this.spinning && !this._start( event ) ) { + return false; + } -$.extend($.ui.dialog.overlay.prototype, { - destroy: function() { - $.ui.dialog.overlay.destroy(this.$el); - } -}); + this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); + clearTimeout( this.mousewheelTimer ); + this.mousewheelTimer = this._delay(function() { + if ( this.spinning ) { + this._stop( event ); + } + }, 100 ); + event.preventDefault(); + }, + "mousedown .ui-spinner-button": function( event ) { + var previous; + + // We never want the buttons to have focus; whenever the user is + // interacting with the spinner, the focus should be on the input. + // If the input is focused then this.previous is properly set from + // when the input first received focus. If the input is not focused + // then we need to set this.previous based on the value before spinning. + previous = this.element[0] === this.document[0].activeElement ? + this.previous : this.element.val(); + function checkFocus() { + var isActive = this.element[0] === this.document[0].activeElement; + if ( !isActive ) { + this.element.focus(); + this.previous = previous; + // support: IE + // IE sets focus asynchronously, so we need to check if focus + // moved off of the input because the user clicked on the button. + this._delay(function() { + this.previous = previous; + }); + } + } -}(jQuery)); -/* - * jQuery UI Position 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Position - */ -(function( $, undefined ) { + // ensure focus is on (or stays on) the text field + event.preventDefault(); + checkFocus.call( this ); + + // support: IE + // IE doesn't prevent moving focus even with event.preventDefault() + // so we set a flag to know when we should ignore the blur event + // and check (again) if focus moved off of the input. + this.cancelBlur = true; + this._delay(function() { + delete this.cancelBlur; + checkFocus.call( this ); + }); -$.ui = $.ui || {}; + if ( this._start( event ) === false ) { + return; + } -var horizontalPositions = /left|center|right/, - verticalPositions = /top|center|bottom/, - center = "center", - _position = $.fn.position, - _offset = $.fn.offset; + this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); + }, + "mouseup .ui-spinner-button": "_stop", + "mouseenter .ui-spinner-button": function( event ) { + // button will add ui-state-active if mouse was down while mouseleave and kept down + if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { + return; + } -$.fn.position = function( options ) { - if ( !options || !options.of ) { - return _position.apply( this, arguments ); - } + if ( this._start( event ) === false ) { + return false; + } + this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); + }, + // TODO: do we really want to consider this a stop? + // shouldn't we just stop the repeater and wait until mouseup before + // we trigger the stop event? + "mouseleave .ui-spinner-button": "_stop" + }, - // make a copy, we don't want to modify arguments - options = $.extend( {}, options ); + _draw: function() { + var uiSpinner = this.uiSpinner = this.element + .addClass( "ui-spinner-input" ) + .attr( "autocomplete", "off" ) + .wrap( this._uiSpinnerHtml() ) + .parent() + // add buttons + .append( this._buttonHtml() ); - var target = $( options.of ), - targetElem = target[0], - collision = ( options.collision || "flip" ).split( " " ), - offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], - targetWidth, - targetHeight, - basePosition; + this.element.attr( "role", "spinbutton" ); - if ( targetElem.nodeType === 9 ) { - targetWidth = target.width(); - targetHeight = target.height(); - basePosition = { top: 0, left: 0 }; - // TODO: use $.isWindow() in 1.9 - } else if ( targetElem.setTimeout ) { - targetWidth = target.width(); - targetHeight = target.height(); - basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; - } else if ( targetElem.preventDefault ) { - // force left top to allow flipping - options.at = "left top"; - targetWidth = targetHeight = 0; - basePosition = { top: options.of.pageY, left: options.of.pageX }; - } else { - targetWidth = target.outerWidth(); - targetHeight = target.outerHeight(); - basePosition = target.offset(); - } + // button bindings + this.buttons = uiSpinner.find( ".ui-spinner-button" ) + .attr( "tabIndex", -1 ) + .button() + .removeClass( "ui-corner-all" ); - // force my and at to have valid horizontal and veritcal positions - // if a value is missing or invalid, it will be converted to center - $.each( [ "my", "at" ], function() { - var pos = ( options[this] || "" ).split( " " ); - if ( pos.length === 1) { - pos = horizontalPositions.test( pos[0] ) ? - pos.concat( [center] ) : - verticalPositions.test( pos[0] ) ? - [ center ].concat( pos ) : - [ center, center ]; - } - pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; - pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; - options[ this ] = pos; - }); + // IE 6 doesn't understand height: 50% for the buttons + // unless the wrapper has an explicit height + if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && + uiSpinner.height() > 0 ) { + uiSpinner.height( uiSpinner.height() ); + } - // normalize collision option - if ( collision.length === 1 ) { - collision[ 1 ] = collision[ 0 ]; - } + // disable spinner if element was already disabled + if ( this.options.disabled ) { + this.disable(); + } + }, - // normalize offset option - offset[ 0 ] = parseInt( offset[0], 10 ) || 0; - if ( offset.length === 1 ) { - offset[ 1 ] = offset[ 0 ]; - } - offset[ 1 ] = parseInt( offset[1], 10 ) || 0; + _keydown: function( event ) { + var options = this.options, + keyCode = $.ui.keyCode; - if ( options.at[0] === "right" ) { - basePosition.left += targetWidth; - } else if ( options.at[0] === center ) { - basePosition.left += targetWidth / 2; - } + switch ( event.keyCode ) { + case keyCode.UP: + this._repeat( null, 1, event ); + return true; + case keyCode.DOWN: + this._repeat( null, -1, event ); + return true; + case keyCode.PAGE_UP: + this._repeat( null, options.page, event ); + return true; + case keyCode.PAGE_DOWN: + this._repeat( null, -options.page, event ); + return true; + } - if ( options.at[1] === "bottom" ) { - basePosition.top += targetHeight; - } else if ( options.at[1] === center ) { - basePosition.top += targetHeight / 2; - } + return false; + }, - basePosition.left += offset[ 0 ]; - basePosition.top += offset[ 1 ]; + _uiSpinnerHtml: function() { + return ""; + }, - return this.each(function() { - var elem = $( this ), - elemWidth = elem.outerWidth(), - elemHeight = elem.outerHeight(), - marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, - marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, - collisionWidth = elemWidth + marginLeft + - ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), - collisionHeight = elemHeight + marginTop + - ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), - position = $.extend( {}, basePosition ), - collisionPosition; + _buttonHtml: function() { + return "" + + "" + + "" + + "" + + "" + + "" + + ""; + }, - if ( options.my[0] === "right" ) { - position.left -= elemWidth; - } else if ( options.my[0] === center ) { - position.left -= elemWidth / 2; + _start: function( event ) { + if ( !this.spinning && this._trigger( "start", event ) === false ) { + return false; } - if ( options.my[1] === "bottom" ) { - position.top -= elemHeight; - } else if ( options.my[1] === center ) { - position.top -= elemHeight / 2; + if ( !this.counter ) { + this.counter = 1; } + this.spinning = true; + return true; + }, - // prevent fractions (see #5280) - position.left = Math.round( position.left ); - position.top = Math.round( position.top ); + _repeat: function( i, steps, event ) { + i = i || 500; - collisionPosition = { - left: position.left - marginLeft, - top: position.top - marginTop - }; + clearTimeout( this.timer ); + this.timer = this._delay(function() { + this._repeat( 40, steps, event ); + }, i ); - $.each( [ "left", "top" ], function( i, dir ) { - if ( $.ui.position[ collision[i] ] ) { - $.ui.position[ collision[i] ][ dir ]( position, { - targetWidth: targetWidth, - targetHeight: targetHeight, - elemWidth: elemWidth, - elemHeight: elemHeight, - collisionPosition: collisionPosition, - collisionWidth: collisionWidth, - collisionHeight: collisionHeight, - offset: offset, - my: options.my, - at: options.at - }); - } - }); + this._spin( steps * this.options.step, event ); + }, - if ( $.fn.bgiframe ) { - elem.bgiframe(); + _spin: function( step, event ) { + var value = this.value() || 0; + + if ( !this.counter ) { + this.counter = 1; } - elem.offset( $.extend( position, { using: options.using } ) ); - }); -}; -$.ui.position = { - fit: { - left: function( position, data ) { - var win = $( window ), - over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); - position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); - }, - top: function( position, data ) { - var win = $( window ), - over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); - position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); + value = this._adjustValue( value + step * this._increment( this.counter ) ); + + if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { + this._value( value ); + this.counter++; } }, - flip: { - left: function( position, data ) { - if ( data.at[0] === center ) { - return; - } - var win = $( window ), - over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), - myOffset = data.my[ 0 ] === "left" ? - -data.elemWidth : - data.my[ 0 ] === "right" ? - data.elemWidth : - 0, - atOffset = data.at[ 0 ] === "left" ? - data.targetWidth : - -data.targetWidth, - offset = -2 * data.offset[ 0 ]; - position.left += data.collisionPosition.left < 0 ? - myOffset + atOffset + offset : - over > 0 ? - myOffset + atOffset + offset : - 0; - }, - top: function( position, data ) { - if ( data.at[1] === center ) { - return; - } - var win = $( window ), - over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), - myOffset = data.my[ 1 ] === "top" ? - -data.elemHeight : - data.my[ 1 ] === "bottom" ? - data.elemHeight : - 0, - atOffset = data.at[ 1 ] === "top" ? - data.targetHeight : - -data.targetHeight, - offset = -2 * data.offset[ 1 ]; - position.top += data.collisionPosition.top < 0 ? - myOffset + atOffset + offset : - over > 0 ? - myOffset + atOffset + offset : - 0; + _increment: function( i ) { + var incremental = this.options.incremental; + + if ( incremental ) { + return $.isFunction( incremental ) ? + incremental( i ) : + Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); } - } -}; -// offset setter from jQuery 1.4 -if ( !$.offset.setOffset ) { - $.offset.setOffset = function( elem, options ) { - // set position first, in-case top/left are set even on static elem - if ( /static/.test( $.curCSS( elem, "position" ) ) ) { - elem.style.position = "relative"; - } - var curElem = $( elem ), - curOffset = curElem.offset(), - curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, - curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, - props = { - top: (options.top - curOffset.top) + curTop, - left: (options.left - curOffset.left) + curLeft - }; - - if ( 'using' in options ) { - options.using.call( elem, props ); - } else { - curElem.css( props ); + return 1; + }, + + _precision: function() { + var precision = this._precisionOf( this.options.step ); + if ( this.options.min !== null ) { + precision = Math.max( precision, this._precisionOf( this.options.min ) ); } - }; + return precision; + }, - $.fn.offset = function( options ) { - var elem = this[ 0 ]; - if ( !elem || !elem.ownerDocument ) { return null; } - if ( options ) { - return this.each(function() { - $.offset.setOffset( this, options ); - }); + _precisionOf: function( num ) { + var str = num.toString(), + decimal = str.indexOf( "." ); + return decimal === -1 ? 0 : str.length - decimal - 1; + }, + + _adjustValue: function( value ) { + var base, aboveMin, + options = this.options; + + // make sure we're at a valid step + // - find out where we are relative to the base (min or 0) + base = options.min !== null ? options.min : 0; + aboveMin = value - base; + // - round to the nearest step + aboveMin = Math.round(aboveMin / options.step) * options.step; + // - rounding is based on 0, so adjust back to our base + value = base + aboveMin; + + // fix precision from bad JS floating point math + value = parseFloat( value.toFixed( this._precision() ) ); + + // clamp the value + if ( options.max !== null && value > options.max) { + return options.max; + } + if ( options.min !== null && value < options.min ) { + return options.min; } - return _offset.call( this ); - }; -} -}( jQuery )); -/* - * jQuery UI Progressbar 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Progressbar - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function( $, undefined ) { + return value; + }, -$.widget( "ui.progressbar", { - options: { - value: 0, - max: 100 + _stop: function( event ) { + if ( !this.spinning ) { + return; + } + + clearTimeout( this.timer ); + clearTimeout( this.mousewheelTimer ); + this.counter = 0; + this.spinning = false; + this._trigger( "stop", event ); }, - min: 0, + _setOption: function( key, value ) { + if ( key === "culture" || key === "numberFormat" ) { + var prevValue = this._parse( this.element.val() ); + this.options[ key ] = value; + this.element.val( this._format( prevValue ) ); + return; + } - _create: function() { - this.element - .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) - .attr({ - role: "progressbar", - "aria-valuemin": this.min, - "aria-valuemax": this.options.max, - "aria-valuenow": this._value() - }); + if ( key === "max" || key === "min" || key === "step" ) { + if ( typeof value === "string" ) { + value = this._parse( value ); + } + } - this.valueDiv = $( "
          " ) - .appendTo( this.element ); + this._super( key, value ); - this.oldValue = this._value(); - this._refreshValue(); + if ( key === "disabled" ) { + if ( value ) { + this.element.prop( "disabled", true ); + this.buttons.button( "disable" ); + } else { + this.element.prop( "disabled", false ); + this.buttons.button( "enable" ); + } + } }, - destroy: function() { - this.element - .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) - .removeAttr( "role" ) - .removeAttr( "aria-valuemin" ) - .removeAttr( "aria-valuemax" ) - .removeAttr( "aria-valuenow" ); - - this.valueDiv.remove(); + _setOptions: modifier(function( options ) { + this._super( options ); + this._value( this.element.val() ); + }), - $.Widget.prototype.destroy.apply( this, arguments ); + _parse: function( val ) { + if ( typeof val === "string" && val !== "" ) { + val = window.Globalize && this.options.numberFormat ? + Globalize.parseFloat( val, 10, this.options.culture ) : +val; + } + return val === "" || isNaN( val ) ? null : val; }, - value: function( newValue ) { - if ( newValue === undefined ) { - return this._value(); + _format: function( value ) { + if ( value === "" ) { + return ""; } + return window.Globalize && this.options.numberFormat ? + Globalize.format( value, this.options.numberFormat, this.options.culture ) : + value; + }, - this._setOption( "value", newValue ); - return this; + _refresh: function() { + this.element.attr({ + "aria-valuemin": this.options.min, + "aria-valuemax": this.options.max, + // TODO: what should we do with values that can't be parsed? + "aria-valuenow": this._parse( this.element.val() ) + }); }, - _setOption: function( key, value ) { - if ( key === "value" ) { - this.options.value = value; - this._refreshValue(); - if ( this._value() === this.options.max ) { - this._trigger( "complete" ); + // update the value without triggering change + _value: function( value, allowAny ) { + var parsed; + if ( value !== "" ) { + parsed = this._parse( value ); + if ( parsed !== null ) { + if ( !allowAny ) { + parsed = this._adjustValue( parsed ); + } + value = this._format( parsed ); } } + this.element.val( value ); + this._refresh(); + }, - $.Widget.prototype._setOption.apply( this, arguments ); + _destroy: function() { + this.element + .removeClass( "ui-spinner-input" ) + .prop( "disabled", false ) + .removeAttr( "autocomplete" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); + this.uiSpinner.replaceWith( this.element ); }, - _value: function() { - var val = this.options.value; - // normalize invalid value - if ( typeof val !== "number" ) { - val = 0; - } - return Math.min( this.options.max, Math.max( this.min, val ) ); + stepUp: modifier(function( steps ) { + this._stepUp( steps ); + }), + _stepUp: function( steps ) { + this._spin( (steps || 1) * this.options.step ); }, - _percentage: function() { - return 100 * this._value() / this.options.max; + stepDown: modifier(function( steps ) { + this._stepDown( steps ); + }), + _stepDown: function( steps ) { + this._spin( (steps || 1) * -this.options.step ); }, - _refreshValue: function() { - var value = this.value(); - var percentage = this._percentage(); + pageUp: modifier(function( pages ) { + this._stepUp( (pages || 1) * this.options.page ); + }), - if ( this.oldValue !== value ) { - this.oldValue = value; - this._trigger( "change" ); - } + pageDown: modifier(function( pages ) { + this._stepDown( (pages || 1) * this.options.page ); + }), - this.valueDiv - .toggle( value > this.min ) - .toggleClass( "ui-corner-right", value === this.options.max ) - .width( percentage.toFixed(0) + "%" ); - this.element.attr( "aria-valuenow", value ); - } -}); + value: function( newVal ) { + if ( !arguments.length ) { + return this._parse( this.element.val() ); + } + modifier( this._value ).call( this, newVal ); + }, -$.extend( $.ui.progressbar, { - version: "1.8.16" + widget: function() { + return this.uiSpinner; + } }); -})( jQuery ); -/* - * jQuery UI Slider 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Slider - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ +}( jQuery ) ); (function( $, undefined ) { -// number of pages in a slider -// (how many times can you page up/down to go through the whole range) -var numPages = 5; +var tabId = 0, + rhash = /#.*$/; -$.widget( "ui.slider", $.ui.mouse, { +function getNextTabId() { + return ++tabId; +} - widgetEventPrefix: "slide", +function isLocal( anchor ) { + return anchor.hash.length > 1 && + anchor.href.replace( rhash, "" ) === + location.href.replace( rhash, "" ) + // support: Safari 5.1 + // Safari 5.1 doesn't encode spaces in window.location + // but it does encode spaces from anchors (#8777) + .replace( /\s/g, "%20" ); +} +$.widget( "ui.tabs", { + version: "1.9.2", + delay: 300, options: { - animate: false, - distance: 0, - max: 100, - min: 0, - orientation: "horizontal", - range: false, - step: 1, - value: 0, - values: null + active: null, + collapsible: false, + event: "click", + heightStyle: "content", + hide: null, + show: null, + + // callbacks + activate: null, + beforeActivate: null, + beforeLoad: null, + load: null }, _create: function() { - var self = this, - o = this.options, - existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), - handle = "", - handleCount = ( o.values && o.values.length ) || 1, - handles = []; + var that = this, + options = this.options, + active = options.active, + locationHash = location.hash.substring( 1 ); - this._keySliding = false; - this._mouseSliding = false; - this._animateOff = true; - this._handleIndex = null; - this._detectOrientation(); - this._mouseInit(); + this.running = false; this.element - .addClass( "ui-slider" + - " ui-slider-" + this.orientation + - " ui-widget" + - " ui-widget-content" + - " ui-corner-all" + - ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); - - this.range = $([]); - - if ( o.range ) { - if ( o.range === true ) { - if ( !o.values ) { - o.values = [ this._valueMin(), this._valueMin() ]; + .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) + .toggleClass( "ui-tabs-collapsible", options.collapsible ) + // Prevent users from focusing disabled tabs via click + .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { + if ( $( this ).is( ".ui-state-disabled" ) ) { + event.preventDefault(); } - if ( o.values.length && o.values.length !== 2 ) { - o.values = [ o.values[0], o.values[0] ]; + }) + // support: IE <9 + // Preventing the default action in mousedown doesn't prevent IE + // from focusing the element, so if the anchor gets focused, blur. + // We don't have to worry about focusing the previously focused + // element since clicking on a non-focusable element should focus + // the body anyway. + .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { + if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { + this.blur(); } + }); + + this._processTabs(); + + if ( active === null ) { + // check the fragment identifier in the URL + if ( locationHash ) { + this.tabs.each(function( i, tab ) { + if ( $( tab ).attr( "aria-controls" ) === locationHash ) { + active = i; + return false; + } + }); } - this.range = $( "
          " ) - .appendTo( this.element ) - .addClass( "ui-slider-range" + - // note: this isn't the most fittingly semantic framework class for this element, - // but worked best visually with a variety of themes - " ui-widget-header" + - ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); - } + // check for a tab marked active via a class + if ( active === null ) { + active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); + } - for ( var i = existingHandles.length; i < handleCount; i += 1 ) { - handles.push( handle ); + // no active tab, set to false + if ( active === null || active === -1 ) { + active = this.tabs.length ? 0 : false; + } } - this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) ); + // handle numbers: negative, out of range + if ( active !== false ) { + active = this.tabs.index( this.tabs.eq( active ) ); + if ( active === -1 ) { + active = options.collapsible ? false : 0; + } + } + options.active = active; - this.handle = this.handles.eq( 0 ); + // don't allow collapsible: false and active: false + if ( !options.collapsible && options.active === false && this.anchors.length ) { + options.active = 0; + } - this.handles.add( this.range ).filter( "a" ) - .click(function( event ) { - event.preventDefault(); - }) - .hover(function() { - if ( !o.disabled ) { - $( this ).addClass( "ui-state-hover" ); - } - }, function() { - $( this ).removeClass( "ui-state-hover" ); - }) - .focus(function() { - if ( !o.disabled ) { - $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); - $( this ).addClass( "ui-state-focus" ); - } else { - $( this ).blur(); - } - }) - .blur(function() { - $( this ).removeClass( "ui-state-focus" ); - }); + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + if ( $.isArray( options.disabled ) ) { + options.disabled = $.unique( options.disabled.concat( + $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { + return that.tabs.index( li ); + }) + ) ).sort(); + } - this.handles.each(function( i ) { - $( this ).data( "index.ui-slider-handle", i ); - }); + // check for length avoids error when initializing empty list + if ( this.options.active !== false && this.anchors.length ) { + this.active = this._findActive( this.options.active ); + } else { + this.active = $(); + } - this.handles - .keydown(function( event ) { - var ret = true, - index = $( this ).data( "index.ui-slider-handle" ), - allowed, - curVal, - newVal, - step; - - if ( self.options.disabled ) { - return; - } - - switch ( event.keyCode ) { - case $.ui.keyCode.HOME: - case $.ui.keyCode.END: - case $.ui.keyCode.PAGE_UP: - case $.ui.keyCode.PAGE_DOWN: - case $.ui.keyCode.UP: - case $.ui.keyCode.RIGHT: - case $.ui.keyCode.DOWN: - case $.ui.keyCode.LEFT: - ret = false; - if ( !self._keySliding ) { - self._keySliding = true; - $( this ).addClass( "ui-state-active" ); - allowed = self._start( event, index ); - if ( allowed === false ) { - return; - } - } - break; - } - - step = self.options.step; - if ( self.options.values && self.options.values.length ) { - curVal = newVal = self.values( index ); - } else { - curVal = newVal = self.value(); - } - - switch ( event.keyCode ) { - case $.ui.keyCode.HOME: - newVal = self._valueMin(); - break; - case $.ui.keyCode.END: - newVal = self._valueMax(); - break; - case $.ui.keyCode.PAGE_UP: - newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) ); - break; - case $.ui.keyCode.PAGE_DOWN: - newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) ); - break; - case $.ui.keyCode.UP: - case $.ui.keyCode.RIGHT: - if ( curVal === self._valueMax() ) { - return; - } - newVal = self._trimAlignValue( curVal + step ); - break; - case $.ui.keyCode.DOWN: - case $.ui.keyCode.LEFT: - if ( curVal === self._valueMin() ) { - return; - } - newVal = self._trimAlignValue( curVal - step ); - break; - } - - self._slide( event, index, newVal ); - - return ret; - - }) - .keyup(function( event ) { - var index = $( this ).data( "index.ui-slider-handle" ); - - if ( self._keySliding ) { - self._keySliding = false; - self._stop( event, index ); - self._change( event, index ); - $( this ).removeClass( "ui-state-active" ); - } - - }); + this._refresh(); - this._refreshValue(); + if ( this.active.length ) { + this.load( options.active ); + } + }, - this._animateOff = false; + _getCreateEventData: function() { + return { + tab: this.active, + panel: !this.active.length ? $() : this._getPanelForTab( this.active ) + }; }, - destroy: function() { - this.handles.remove(); - this.range.remove(); + _tabKeydown: function( event ) { + var focusedTab = $( this.document[0].activeElement ).closest( "li" ), + selectedIndex = this.tabs.index( focusedTab ), + goingForward = true; - this.element - .removeClass( "ui-slider" + - " ui-slider-horizontal" + - " ui-slider-vertical" + - " ui-slider-disabled" + - " ui-widget" + - " ui-widget-content" + - " ui-corner-all" ) - .removeData( "slider" ) - .unbind( ".slider" ); + if ( this._handlePageNav( event ) ) { + return; + } - this._mouseDestroy(); + switch ( event.keyCode ) { + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + selectedIndex++; + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.LEFT: + goingForward = false; + selectedIndex--; + break; + case $.ui.keyCode.END: + selectedIndex = this.anchors.length - 1; + break; + case $.ui.keyCode.HOME: + selectedIndex = 0; + break; + case $.ui.keyCode.SPACE: + // Activate only, no collapsing + event.preventDefault(); + clearTimeout( this.activating ); + this._activate( selectedIndex ); + return; + case $.ui.keyCode.ENTER: + // Toggle (cancel delayed activation, allow collapsing) + event.preventDefault(); + clearTimeout( this.activating ); + // Determine if we should collapse or activate + this._activate( selectedIndex === this.options.active ? false : selectedIndex ); + return; + default: + return; + } - return this; + // Focus the appropriate tab, based on which key was pressed + event.preventDefault(); + clearTimeout( this.activating ); + selectedIndex = this._focusNextTab( selectedIndex, goingForward ); + + // Navigating with control key will prevent automatic activation + if ( !event.ctrlKey ) { + // Update aria-selected immediately so that AT think the tab is already selected. + // Otherwise AT may confuse the user by stating that they need to activate the tab, + // but the tab will already be activated by the time the announcement finishes. + focusedTab.attr( "aria-selected", "false" ); + this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); + + this.activating = this._delay(function() { + this.option( "active", selectedIndex ); + }, this.delay ); + } }, - _mouseCapture: function( event ) { - var o = this.options, - position, - normValue, - distance, - closestHandle, - self, - index, - allowed, - offset, - mouseOverHandle; + _panelKeydown: function( event ) { + if ( this._handlePageNav( event ) ) { + return; + } - if ( o.disabled ) { - return false; + // Ctrl+up moves focus to the current tab + if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { + event.preventDefault(); + this.active.focus(); } + }, - this.elementSize = { - width: this.element.outerWidth(), - height: this.element.outerHeight() - }; - this.elementOffset = this.element.offset(); + // Alt+page up/down moves focus to the previous/next tab (and activates) + _handlePageNav: function( event ) { + if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { + this._activate( this._focusNextTab( this.options.active - 1, false ) ); + return true; + } + if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { + this._activate( this._focusNextTab( this.options.active + 1, true ) ); + return true; + } + }, - position = { x: event.pageX, y: event.pageY }; - normValue = this._normValueFromMouse( position ); - distance = this._valueMax() - this._valueMin() + 1; - self = this; - this.handles.each(function( i ) { - var thisDistance = Math.abs( normValue - self.values(i) ); - if ( distance > thisDistance ) { - distance = thisDistance; - closestHandle = $( this ); - index = i; + _findNextTab: function( index, goingForward ) { + var lastTabIndex = this.tabs.length - 1; + + function constrain() { + if ( index > lastTabIndex ) { + index = 0; } - }); + if ( index < 0 ) { + index = lastTabIndex; + } + return index; + } - // workaround for bug #3736 (if both handles of a range are at 0, - // the first is always used as the one with least distance, - // and moving it is obviously prevented by preventing negative ranges) - if( o.range === true && this.values(1) === o.min ) { - index += 1; - closestHandle = $( this.handles[index] ); + while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { + index = goingForward ? index + 1 : index - 1; } - allowed = this._start( event, index ); - if ( allowed === false ) { - return false; + return index; + }, + + _focusNextTab: function( index, goingForward ) { + index = this._findNextTab( index, goingForward ); + this.tabs.eq( index ).focus(); + return index; + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + if ( key === "disabled" ) { + // don't use the widget factory's disabled handling + this._setupDisabled( value ); + return; } - this._mouseSliding = true; - self._handleIndex = index; + this._super( key, value); - closestHandle - .addClass( "ui-state-active" ) - .focus(); - - offset = closestHandle.offset(); - mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); - this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { - left: event.pageX - offset.left - ( closestHandle.width() / 2 ), - top: event.pageY - offset.top - - ( closestHandle.height() / 2 ) - - ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - - ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + - ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) - }; + if ( key === "collapsible" ) { + this.element.toggleClass( "ui-tabs-collapsible", value ); + // Setting collapsible: false while collapsed; open first panel + if ( !value && this.options.active === false ) { + this._activate( 0 ); + } + } - if ( !this.handles.hasClass( "ui-state-hover" ) ) { - this._slide( event, index, normValue ); + if ( key === "event" ) { + this._setupEvents( value ); } - this._animateOff = true; - return true; - }, - _mouseStart: function( event ) { - return true; + if ( key === "heightStyle" ) { + this._setupHeightStyle( value ); + } }, - _mouseDrag: function( event ) { - var position = { x: event.pageX, y: event.pageY }, - normValue = this._normValueFromMouse( position ); - - this._slide( event, this._handleIndex, normValue ); + _tabId: function( tab ) { + return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); + }, - return false; + _sanitizeSelector: function( hash ) { + return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; }, - _mouseStop: function( event ) { - this.handles.removeClass( "ui-state-active" ); - this._mouseSliding = false; + refresh: function() { + var options = this.options, + lis = this.tablist.children( ":has(a[href])" ); - this._stop( event, this._handleIndex ); - this._change( event, this._handleIndex ); + // get disabled tabs from class attribute from HTML + // this will get converted to a boolean if needed in _refresh() + options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { + return lis.index( tab ); + }); - this._handleIndex = null; - this._clickOffset = null; - this._animateOff = false; + this._processTabs(); + + // was collapsed or no tabs + if ( options.active === false || !this.anchors.length ) { + options.active = false; + this.active = $(); + // was active, but active tab is gone + } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { + // all remaining tabs are disabled + if ( this.tabs.length === options.disabled.length ) { + options.active = false; + this.active = $(); + // activate previous tab + } else { + this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); + } + // was active, active tab still exists + } else { + // make sure active index is correct + options.active = this.tabs.index( this.active ); + } - return false; - }, - - _detectOrientation: function() { - this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; + this._refresh(); }, - _normValueFromMouse: function( position ) { - var pixelTotal, - pixelMouse, - percentMouse, - valueTotal, - valueMouse; + _refresh: function() { + this._setupDisabled( this.options.disabled ); + this._setupEvents( this.options.event ); + this._setupHeightStyle( this.options.heightStyle ); - if ( this.orientation === "horizontal" ) { - pixelTotal = this.elementSize.width; - pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); + this.tabs.not( this.active ).attr({ + "aria-selected": "false", + tabIndex: -1 + }); + this.panels.not( this._getPanelForTab( this.active ) ) + .hide() + .attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + + // Make sure one tab is in the tab order + if ( !this.active.length ) { + this.tabs.eq( 0 ).attr( "tabIndex", 0 ); } else { - pixelTotal = this.elementSize.height; - pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); + this.active + .addClass( "ui-tabs-active ui-state-active" ) + .attr({ + "aria-selected": "true", + tabIndex: 0 + }); + this._getPanelForTab( this.active ) + .show() + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); } + }, - percentMouse = ( pixelMouse / pixelTotal ); - if ( percentMouse > 1 ) { - percentMouse = 1; - } - if ( percentMouse < 0 ) { - percentMouse = 0; - } - if ( this.orientation === "vertical" ) { - percentMouse = 1 - percentMouse; - } + _processTabs: function() { + var that = this; - valueTotal = this._valueMax() - this._valueMin(); - valueMouse = this._valueMin() + percentMouse * valueTotal; + this.tablist = this._getList() + .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) + .attr( "role", "tablist" ); - return this._trimAlignValue( valueMouse ); - }, + this.tabs = this.tablist.find( "> li:has(a[href])" ) + .addClass( "ui-state-default ui-corner-top" ) + .attr({ + role: "tab", + tabIndex: -1 + }); - _start: function( event, index ) { - var uiHash = { - handle: this.handles[ index ], - value: this.value() - }; - if ( this.options.values && this.options.values.length ) { - uiHash.value = this.values( index ); - uiHash.values = this.values(); - } - return this._trigger( "start", event, uiHash ); - }, + this.anchors = this.tabs.map(function() { + return $( "a", this )[ 0 ]; + }) + .addClass( "ui-tabs-anchor" ) + .attr({ + role: "presentation", + tabIndex: -1 + }); - _slide: function( event, index, newVal ) { - var otherVal, - newValues, - allowed; + this.panels = $(); - if ( this.options.values && this.options.values.length ) { - otherVal = this.values( index ? 0 : 1 ); + this.anchors.each(function( i, anchor ) { + var selector, panel, panelId, + anchorId = $( anchor ).uniqueId().attr( "id" ), + tab = $( anchor ).closest( "li" ), + originalAriaControls = tab.attr( "aria-controls" ); - if ( ( this.options.values.length === 2 && this.options.range === true ) && - ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) - ) { - newVal = otherVal; + // inline tab + if ( isLocal( anchor ) ) { + selector = anchor.hash; + panel = that.element.find( that._sanitizeSelector( selector ) ); + // remote tab + } else { + panelId = that._tabId( tab ); + selector = "#" + panelId; + panel = that.element.find( selector ); + if ( !panel.length ) { + panel = that._createPanel( panelId ); + panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); + } + panel.attr( "aria-live", "polite" ); } - if ( newVal !== this.values( index ) ) { - newValues = this.values(); - newValues[ index ] = newVal; - // A slide can be canceled by returning false from the slide callback - allowed = this._trigger( "slide", event, { - handle: this.handles[ index ], - value: newVal, - values: newValues - } ); - otherVal = this.values( index ? 0 : 1 ); - if ( allowed !== false ) { - this.values( index, newVal, true ); - } + if ( panel.length) { + that.panels = that.panels.add( panel ); } - } else { - if ( newVal !== this.value() ) { - // A slide can be canceled by returning false from the slide callback - allowed = this._trigger( "slide", event, { - handle: this.handles[ index ], - value: newVal - } ); - if ( allowed !== false ) { - this.value( newVal ); - } + if ( originalAriaControls ) { + tab.data( "ui-tabs-aria-controls", originalAriaControls ); } - } + tab.attr({ + "aria-controls": selector.substring( 1 ), + "aria-labelledby": anchorId + }); + panel.attr( "aria-labelledby", anchorId ); + }); + + this.panels + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .attr( "role", "tabpanel" ); }, - _stop: function( event, index ) { - var uiHash = { - handle: this.handles[ index ], - value: this.value() - }; - if ( this.options.values && this.options.values.length ) { - uiHash.value = this.values( index ); - uiHash.values = this.values(); - } + // allow overriding how to find the list for rare usage scenarios (#7715) + _getList: function() { + return this.element.find( "ol,ul" ).eq( 0 ); + }, - this._trigger( "stop", event, uiHash ); + _createPanel: function( id ) { + return $( "
          " ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "ui-tabs-destroy", true ); }, - _change: function( event, index ) { - if ( !this._keySliding && !this._mouseSliding ) { - var uiHash = { - handle: this.handles[ index ], - value: this.value() - }; - if ( this.options.values && this.options.values.length ) { - uiHash.value = this.values( index ); - uiHash.values = this.values(); + _setupDisabled: function( disabled ) { + if ( $.isArray( disabled ) ) { + if ( !disabled.length ) { + disabled = false; + } else if ( disabled.length === this.anchors.length ) { + disabled = true; } + } - this._trigger( "change", event, uiHash ); + // disable tabs + for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { + if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { + $( li ) + .addClass( "ui-state-disabled" ) + .attr( "aria-disabled", "true" ); + } else { + $( li ) + .removeClass( "ui-state-disabled" ) + .removeAttr( "aria-disabled" ); + } } + + this.options.disabled = disabled; }, - value: function( newValue ) { - if ( arguments.length ) { - this.options.value = this._trimAlignValue( newValue ); - this._refreshValue(); - this._change( null, 0 ); - return; + _setupEvents: function( event ) { + var events = { + click: function( event ) { + event.preventDefault(); + } + }; + if ( event ) { + $.each( event.split(" "), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + }); } - return this._value(); + this._off( this.anchors.add( this.tabs ).add( this.panels ) ); + this._on( this.anchors, events ); + this._on( this.tabs, { keydown: "_tabKeydown" } ); + this._on( this.panels, { keydown: "_panelKeydown" } ); + + this._focusable( this.tabs ); + this._hoverable( this.tabs ); }, - values: function( index, newValue ) { - var vals, - newValues, - i; + _setupHeightStyle: function( heightStyle ) { + var maxHeight, overflow, + parent = this.element.parent(); - if ( arguments.length > 1 ) { - this.options.values[ index ] = this._trimAlignValue( newValue ); - this._refreshValue(); - this._change( null, index ); - return; - } + if ( heightStyle === "fill" ) { + // IE 6 treats height like minHeight, so we need to turn off overflow + // in order to get a reliable height + // we use the minHeight support test because we assume that only + // browsers that don't support minHeight will treat height as minHeight + if ( !$.support.minHeight ) { + overflow = parent.css( "overflow" ); + parent.css( "overflow", "hidden"); + } + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each(function() { + var elem = $( this ), + position = elem.css( "position" ); - if ( arguments.length ) { - if ( $.isArray( arguments[ 0 ] ) ) { - vals = this.options.values; - newValues = arguments[ 0 ]; - for ( i = 0; i < vals.length; i += 1 ) { - vals[ i ] = this._trimAlignValue( newValues[ i ] ); - this._change( null, i ); - } - this._refreshValue(); - } else { - if ( this.options.values && this.options.values.length ) { - return this._values( index ); - } else { - return this.value(); + if ( position === "absolute" || position === "fixed" ) { + return; } + maxHeight -= elem.outerHeight( true ); + }); + if ( overflow ) { + parent.css( "overflow", overflow ); } - } else { - return this._values(); + + this.element.children().not( this.panels ).each(function() { + maxHeight -= $( this ).outerHeight( true ); + }); + + this.panels.each(function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + }) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.panels.each(function() { + maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); + }).height( maxHeight ); } }, - _setOption: function( key, value ) { - var i, - valsLength = 0; + _eventHandler: function( event ) { + var options = this.options, + active = this.active, + anchor = $( event.currentTarget ), + tab = anchor.closest( "li" ), + clickedIsActive = tab[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : this._getPanelForTab( tab ), + toHide = !active.length ? $() : this._getPanelForTab( active ), + eventData = { + oldTab: active, + oldPanel: toHide, + newTab: collapsing ? $() : tab, + newPanel: toShow + }; - if ( $.isArray( this.options.values ) ) { - valsLength = this.options.values.length; + event.preventDefault(); + + if ( tab.hasClass( "ui-state-disabled" ) || + // tab is already loading + tab.hasClass( "ui-tabs-loading" ) || + // can't switch durning an animation + this.running || + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; } - $.Widget.prototype._setOption.apply( this, arguments ); + options.active = collapsing ? false : this.tabs.index( tab ); - switch ( key ) { - case "disabled": - if ( value ) { - this.handles.filter( ".ui-state-focus" ).blur(); - this.handles.removeClass( "ui-state-hover" ); - this.handles.propAttr( "disabled", true ); - this.element.addClass( "ui-disabled" ); - } else { - this.handles.propAttr( "disabled", false ); - this.element.removeClass( "ui-disabled" ); - } - break; - case "orientation": - this._detectOrientation(); - this.element - .removeClass( "ui-slider-horizontal ui-slider-vertical" ) - .addClass( "ui-slider-" + this.orientation ); - this._refreshValue(); - break; - case "value": - this._animateOff = true; - this._refreshValue(); - this._change( null, 0 ); - this._animateOff = false; - break; - case "values": - this._animateOff = true; - this._refreshValue(); - for ( i = 0; i < valsLength; i += 1 ) { - this._change( null, i ); - } - this._animateOff = false; - break; + this.active = clickedIsActive ? $() : tab; + if ( this.xhr ) { + this.xhr.abort(); } - }, - //internal value getter - // _value() returns value trimmed by min and max, aligned by step - _value: function() { - var val = this.options.value; - val = this._trimAlignValue( val ); + if ( !toHide.length && !toShow.length ) { + $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); + } - return val; + if ( toShow.length ) { + this.load( this.tabs.index( tab ), event ); + } + this._toggle( event, eventData ); }, - //internal values getter - // _values() returns array of values trimmed by min and max, aligned by step - // _values( index ) returns single value trimmed by min and max, aligned by step - _values: function( index ) { - var val, - vals, - i; + // handles show/hide for selecting tabs + _toggle: function( event, eventData ) { + var that = this, + toShow = eventData.newPanel, + toHide = eventData.oldPanel; - if ( arguments.length ) { - val = this.options.values[ index ]; - val = this._trimAlignValue( val ); + this.running = true; - return val; - } else { - // .slice() creates a copy of the array - // this copy gets trimmed by min and max and then returned - vals = this.options.values.slice(); - for ( i = 0; i < vals.length; i+= 1) { - vals[ i ] = this._trimAlignValue( vals[ i ] ); + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } + + function show() { + eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + + if ( toShow.length && that.options.show ) { + that._show( toShow, that.options.show, complete ); + } else { + toShow.show(); + complete(); } + } - return vals; + // start out by hiding, then showing, then completing + if ( toHide.length && this.options.hide ) { + this._hide( toHide, this.options.hide, function() { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + show(); + }); + } else { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + toHide.hide(); + show(); } - }, - - // returns the step-aligned value that val is closest to, between (inclusive) min and max - _trimAlignValue: function( val ) { - if ( val <= this._valueMin() ) { - return this._valueMin(); + + toHide.attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + eventData.oldTab.attr( "aria-selected", "false" ); + // If we're switching tabs, remove the old tab from the tab order. + // If we're opening from collapsed state, remove the previous tab from the tab order. + // If we're collapsing, then keep the collapsing tab in the tab order. + if ( toShow.length && toHide.length ) { + eventData.oldTab.attr( "tabIndex", -1 ); + } else if ( toShow.length ) { + this.tabs.filter(function() { + return $( this ).attr( "tabIndex" ) === 0; + }) + .attr( "tabIndex", -1 ); } - if ( val >= this._valueMax() ) { - return this._valueMax(); + + toShow.attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); + eventData.newTab.attr({ + "aria-selected": "true", + tabIndex: 0 + }); + }, + + _activate: function( index ) { + var anchor, + active = this._findActive( index ); + + // trying to activate the already active panel + if ( active[ 0 ] === this.active[ 0 ] ) { + return; } - var step = ( this.options.step > 0 ) ? this.options.step : 1, - valModStep = (val - this._valueMin()) % step, - alignValue = val - valModStep; - if ( Math.abs(valModStep) * 2 >= step ) { - alignValue += ( valModStep > 0 ) ? step : ( -step ); + // trying to collapse, simulate a click on the current active header + if ( !active.length ) { + active = this.active; } - // Since JavaScript has problems with large floats, round - // the final value to 5 digits after the decimal point (see #4124) - return parseFloat( alignValue.toFixed(5) ); + anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; + this._eventHandler({ + target: anchor, + currentTarget: anchor, + preventDefault: $.noop + }); }, - _valueMin: function() { - return this.options.min; + _findActive: function( index ) { + return index === false ? $() : this.tabs.eq( index ); }, - _valueMax: function() { - return this.options.max; - }, - - _refreshValue: function() { - var oRange = this.options.range, - o = this.options, - self = this, - animate = ( !this._animateOff ) ? o.animate : false, - valPercent, - _set = {}, - lastValPercent, - value, - valueMin, - valueMax; + _getIndex: function( index ) { + // meta-function to give users option to provide a href string instead of a numerical index. + if ( typeof index === "string" ) { + index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); + } - if ( this.options.values && this.options.values.length ) { - this.handles.each(function( i, j ) { - valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; - _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; - $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); - if ( self.options.range === true ) { - if ( self.orientation === "horizontal" ) { - if ( i === 0 ) { - self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); - } - if ( i === 1 ) { - self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); - } - } else { - if ( i === 0 ) { - self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); - } - if ( i === 1 ) { - self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); - } - } - } - lastValPercent = valPercent; - }); - } else { - value = this.value(); - valueMin = this._valueMin(); - valueMax = this._valueMax(); - valPercent = ( valueMax !== valueMin ) ? - ( value - valueMin ) / ( valueMax - valueMin ) * 100 : - 0; - _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; - this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + return index; + }, - if ( oRange === "min" && this.orientation === "horizontal" ) { - this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); - } - if ( oRange === "max" && this.orientation === "horizontal" ) { - this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); - } - if ( oRange === "min" && this.orientation === "vertical" ) { - this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); - } - if ( oRange === "max" && this.orientation === "vertical" ) { - this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); - } + _destroy: function() { + if ( this.xhr ) { + this.xhr.abort(); } - } -}); + this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); -$.extend( $.ui.slider, { - version: "1.8.16" -}); + this.tablist + .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) + .removeAttr( "role" ); -}(jQuery)); -/* - * jQuery UI Tabs 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Tabs - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function( $, undefined ) { + this.anchors + .removeClass( "ui-tabs-anchor" ) + .removeAttr( "role" ) + .removeAttr( "tabIndex" ) + .removeData( "href.tabs" ) + .removeData( "load.tabs" ) + .removeUniqueId(); -var tabId = 0, - listId = 0; + this.tabs.add( this.panels ).each(function() { + if ( $.data( this, "ui-tabs-destroy" ) ) { + $( this ).remove(); + } else { + $( this ) + .removeClass( "ui-state-default ui-state-active ui-state-disabled " + + "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) + .removeAttr( "tabIndex" ) + .removeAttr( "aria-live" ) + .removeAttr( "aria-busy" ) + .removeAttr( "aria-selected" ) + .removeAttr( "aria-labelledby" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "role" ); + } + }); -function getNextTabId() { - return ++tabId; -} + this.tabs.each(function() { + var li = $( this ), + prev = li.data( "ui-tabs-aria-controls" ); + if ( prev ) { + li.attr( "aria-controls", prev ); + } else { + li.removeAttr( "aria-controls" ); + } + }); -function getNextListId() { - return ++listId; -} + this.panels.show(); -$.widget( "ui.tabs", { - options: { - add: null, - ajaxOptions: null, - cache: false, - cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } - collapsible: false, - disable: null, - disabled: [], - enable: null, - event: "click", - fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } - idPrefix: "ui-tabs-", - load: null, - panelTemplate: "
          ", - remove: null, - select: null, - show: null, - spinner: "Loading…", - tabTemplate: "
        • #{label}
        • " + if ( this.options.heightStyle !== "content" ) { + this.panels.css( "height", "" ); + } }, - _create: function() { - this._tabify( true ); + enable: function( index ) { + var disabled = this.options.disabled; + if ( disabled === false ) { + return; + } + + if ( index === undefined ) { + disabled = false; + } else { + index = this._getIndex( index ); + if ( $.isArray( disabled ) ) { + disabled = $.map( disabled, function( num ) { + return num !== index ? num : null; + }); + } else { + disabled = $.map( this.tabs, function( li, num ) { + return num !== index ? num : null; + }); + } + } + this._setupDisabled( disabled ); }, - _setOption: function( key, value ) { - if ( key == "selected" ) { - if (this.options.collapsible && value == this.options.selected ) { + disable: function( index ) { + var disabled = this.options.disabled; + if ( disabled === true ) { + return; + } + + if ( index === undefined ) { + disabled = true; + } else { + index = this._getIndex( index ); + if ( $.inArray( index, disabled ) !== -1 ) { return; } - this.select( value ); - } else { - this.options[ key ] = value; - this._tabify(); + if ( $.isArray( disabled ) ) { + disabled = $.merge( [ index ], disabled ).sort(); + } else { + disabled = [ index ]; + } } + this._setupDisabled( disabled ); }, - _tabId: function( a ) { - return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || - this.options.idPrefix + getNextTabId(); - }, + load: function( index, event ) { + index = this._getIndex( index ); + var that = this, + tab = this.tabs.eq( index ), + anchor = tab.find( ".ui-tabs-anchor" ), + panel = this._getPanelForTab( tab ), + eventData = { + tab: tab, + panel: panel + }; - _sanitizeSelector: function( hash ) { - // we need this because an id may contain a ":" - return hash.replace( /:/g, "\\:" ); + // not remote + if ( isLocal( anchor[ 0 ] ) ) { + return; + } + + this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); + + // support: jQuery <1.8 + // jQuery <1.8 returns false if the request is canceled in beforeSend, + // but as of 1.8, $.ajax() always returns a jqXHR object. + if ( this.xhr && this.xhr.statusText !== "canceled" ) { + tab.addClass( "ui-tabs-loading" ); + panel.attr( "aria-busy", "true" ); + + this.xhr + .success(function( response ) { + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 + setTimeout(function() { + panel.html( response ); + that._trigger( "load", event, eventData ); + }, 1 ); + }) + .complete(function( jqXHR, status ) { + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 + setTimeout(function() { + if ( status === "abort" ) { + that.panels.stop( false, true ); + } + + tab.removeClass( "ui-tabs-loading" ); + panel.removeAttr( "aria-busy" ); + + if ( jqXHR === that.xhr ) { + delete that.xhr; + } + }, 1 ); + }); + } }, - _cookie: function() { - var cookie = this.cookie || - ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ); - return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) ); + // TODO: Remove this function in 1.10 when ajaxOptions is removed + _ajaxSettings: function( anchor, event, eventData ) { + var that = this; + return { + url: anchor.attr( "href" ), + beforeSend: function( jqXHR, settings ) { + return that._trigger( "beforeLoad", event, + $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); + } + }; }, - _ui: function( tab, panel ) { + _getPanelForTab: function( tab ) { + var id = $( tab ).attr( "aria-controls" ); + return this.element.find( this._sanitizeSelector( "#" + id ) ); + } +}); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + + // helper method for a lot of the back compat extensions + $.ui.tabs.prototype._ui = function( tab, panel ) { return { tab: tab, panel: panel, index: this.anchors.index( tab ) }; - }, + }; - _cleanup: function() { - // restore all former loading tabs labels - this.lis.filter( ".ui-state-processing" ) - .removeClass( "ui-state-processing" ) - .find( "span:data(label.tabs)" ) - .each(function() { - var el = $( this ); - el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" ); + // url method + $.widget( "ui.tabs", $.ui.tabs, { + url: function( index, url ) { + this.anchors.eq( index ).attr( "href", url ); + } + }); + + // TODO: Remove _ajaxSettings() method when removing this extension + // ajaxOptions and cache options + $.widget( "ui.tabs", $.ui.tabs, { + options: { + ajaxOptions: null, + cache: false + }, + + _create: function() { + this._super(); + + var that = this; + + this._on({ tabsbeforeload: function( event, ui ) { + // tab is already cached + if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) { + event.preventDefault(); + return; + } + + ui.jqXHR.success(function() { + if ( that.options.cache ) { + $.data( ui.tab[ 0 ], "cache.tabs", true ); + } }); - }, + }}); + }, - _tabify: function( init ) { - var self = this, - o = this.options, - fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash + _ajaxSettings: function( anchor, event, ui ) { + var ajaxOptions = this.options.ajaxOptions; + return $.extend( {}, ajaxOptions, { + error: function( xhr, status ) { + try { + // Passing index avoid a race condition when this method is + // called after the user has selected another tab. + // Pass the anchor that initiated this request allows + // loadError to manipulate the tab content panel via $(a.hash) + ajaxOptions.error( + xhr, status, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] ); + } + catch ( error ) {} + } + }, this._superApply( arguments ) ); + }, - this.list = this.element.find( "ol,ul" ).eq( 0 ); - this.lis = $( " > li:has(a[href])", this.list ); - this.anchors = this.lis.map(function() { - return $( "a", this )[ 0 ]; - }); - this.panels = $( [] ); - - this.anchors.each(function( i, a ) { - var href = $( a ).attr( "href" ); - // For dynamically created HTML that contains a hash as href IE < 8 expands - // such href to the full page url with hash and then misinterprets tab as ajax. - // Same consideration applies for an added tab with a fragment identifier - // since a[href=#fragment-identifier] does unexpectedly not match. - // Thus normalize href attribute... - var hrefBase = href.split( "#" )[ 0 ], - baseEl; - if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] || - ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) { - href = a.hash; - a.href = href; + _setOption: function( key, value ) { + // reset cache if switching from cached to not cached + if ( key === "cache" && value === false ) { + this.anchors.removeData( "cache.tabs" ); } + this._super( key, value ); + }, - // inline tab - if ( fragmentId.test( href ) ) { - self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) ); - // remote tab - // prevent loading the page itself if href is just "#" - } else if ( href && href !== "#" ) { - // required for restore on destroy - $.data( a, "href.tabs", href ); - - // TODO until #3808 is fixed strip fragment identifier from url - // (IE fails to load from such url) - $.data( a, "load.tabs", href.replace( /#.*$/, "" ) ); - - var id = self._tabId( a ); - a.href = "#" + id; - var $panel = self.element.find( "#" + id ); - if ( !$panel.length ) { - $panel = $( o.panelTemplate ) - .attr( "id", id ) - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) - .insertAfter( self.panels[ i - 1 ] || self.list ); - $panel.data( "destroy.tabs", true ); - } - self.panels = self.panels.add( $panel ); - // invalid tab href - } else { - o.disabled.push( i ); + _destroy: function() { + this.anchors.removeData( "cache.tabs" ); + this._super(); + }, + + url: function( index ){ + this.anchors.eq( index ).removeData( "cache.tabs" ); + this._superApply( arguments ); + } + }); + + // abort method + $.widget( "ui.tabs", $.ui.tabs, { + abort: function() { + if ( this.xhr ) { + this.xhr.abort(); } - }); + } + }); - // initialization from scratch - if ( init ) { - // attach necessary classes for styling - this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); - this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); - this.lis.addClass( "ui-state-default ui-corner-top" ); - this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); - - // Selected tab - // use "selected" option or try to retrieve: - // 1. from fragment identifier in url - // 2. from cookie - // 3. from selected class attribute on
        • - if ( o.selected === undefined ) { - if ( location.hash ) { - this.anchors.each(function( i, a ) { - if ( a.hash == location.hash ) { - o.selected = i; - return false; - } + // spinner + $.widget( "ui.tabs", $.ui.tabs, { + options: { + spinner: "Loading…" + }, + _create: function() { + this._super(); + this._on({ + tabsbeforeload: function( event, ui ) { + // Don't react to nested tabs or tabs that don't use a spinner + if ( event.target !== this.element[ 0 ] || + !this.options.spinner ) { + return; + } + + var span = ui.tab.find( "span" ), + html = span.html(); + span.html( this.options.spinner ); + ui.jqXHR.complete(function() { + span.html( html ); }); } - if ( typeof o.selected !== "number" && o.cookie ) { - o.selected = parseInt( self._cookie(), 10 ); - } - if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { - o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); + }); + } + }); + + // enable/disable events + $.widget( "ui.tabs", $.ui.tabs, { + options: { + enable: null, + disable: null + }, + + enable: function( index ) { + var options = this.options, + trigger; + + if ( index && options.disabled === true || + ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) { + trigger = true; + } + + this._superApply( arguments ); + + if ( trigger ) { + this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + }, + + disable: function( index ) { + var options = this.options, + trigger; + + if ( index && options.disabled === false || + ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) { + trigger = true; + } + + this._superApply( arguments ); + + if ( trigger ) { + this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + } + }); + + // add/remove methods and events + $.widget( "ui.tabs", $.ui.tabs, { + options: { + add: null, + remove: null, + tabTemplate: "
        • #{label}
        • " + }, + + add: function( url, label, index ) { + if ( index === undefined ) { + index = this.anchors.length; + } + + var doInsertAfter, panel, + options = this.options, + li = $( options.tabTemplate + .replace( /#\{href\}/g, url ) + .replace( /#\{label\}/g, label ) ), + id = !url.indexOf( "#" ) ? + url.replace( "#", "" ) : + this._tabId( li ); + + li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true ); + li.attr( "aria-controls", id ); + + doInsertAfter = index >= this.tabs.length; + + // try to find an existing element before creating a new one + panel = this.element.find( "#" + id ); + if ( !panel.length ) { + panel = this._createPanel( id ); + if ( doInsertAfter ) { + if ( index > 0 ) { + panel.insertAfter( this.panels.eq( -1 ) ); + } else { + panel.appendTo( this.element ); + } + } else { + panel.insertBefore( this.panels[ index ] ); } - o.selected = o.selected || ( this.lis.length ? 0 : -1 ); - } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release - o.selected = -1; } + panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide(); - // sanity check - default to first tab... - o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) - ? o.selected - : 0; + if ( doInsertAfter ) { + li.appendTo( this.tablist ); + } else { + li.insertBefore( this.tabs[ index ] ); + } - // Take disabling tabs via class attribute from HTML - // into account and update option properly. - // A selected tab cannot become disabled. - o.disabled = $.unique( o.disabled.concat( - $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) { - return self.lis.index( n ); - }) - ) ).sort(); + options.disabled = $.map( options.disabled, function( n ) { + return n >= index ? ++n : n; + }); - if ( $.inArray( o.selected, o.disabled ) != -1 ) { - o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 ); + this.refresh(); + if ( this.tabs.length === 1 && options.active === false ) { + this.option( "active", 0 ); } - // highlight selected tab - this.panels.addClass( "ui-tabs-hide" ); - this.lis.removeClass( "ui-tabs-selected ui-state-active" ); - // check for length avoids error when initializing empty list - if ( o.selected >= 0 && this.anchors.length ) { - self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" ); - this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); + this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + return this; + }, - // seems to be expected behavior that the show callback is fired - self.element.queue( "tabs", function() { - self._trigger( "show", null, - self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); - }); + remove: function( index ) { + index = this._getIndex( index ); + var options = this.options, + tab = this.tabs.eq( index ).remove(), + panel = this._getPanelForTab( tab ).remove(); - this.load( o.selected ); + // If selected tab was removed focus tab to the right or + // in case the last tab was removed the tab to the left. + // We check for more than 2 tabs, because if there are only 2, + // then when we remove this tab, there will only be one tab left + // so we don't need to detect which tab to activate. + if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) { + this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); } - // clean up to avoid memory leaks in certain versions of IE 6 - // TODO: namespace this event - $( window ).bind( "unload", function() { - self.lis.add( self.anchors ).unbind( ".tabs" ); - self.lis = self.anchors = self.panels = null; - }); - // update selected after add/remove - } else { - o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); - } + options.disabled = $.map( + $.grep( options.disabled, function( n ) { + return n !== index; + }), + function( n ) { + return n >= index ? --n : n; + }); - // update collapsible - // TODO: use .toggleClass() - this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" ); + this.refresh(); - // set or update cookie after init and add/remove respectively - if ( o.cookie ) { - this._cookie( o.selected, o.cookie ); + this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) ); + return this; } + }); - // disable tabs - for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { - $( li )[ $.inArray( i, o.disabled ) != -1 && - // TODO: use .toggleClass() - !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" ); + // length method + $.widget( "ui.tabs", $.ui.tabs, { + length: function() { + return this.anchors.length; } + }); - // reset cache if switching from cached to not cached - if ( o.cache === false ) { - this.anchors.removeData( "cache.tabs" ); + // panel ids (idPrefix option + title attribute) + $.widget( "ui.tabs", $.ui.tabs, { + options: { + idPrefix: "ui-tabs-" + }, + + _tabId: function( tab ) { + var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab; + a = a[0]; + return $( a ).closest( "li" ).attr( "aria-controls" ) || + a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) || + this.options.idPrefix + getNextTabId(); } + }); - // remove all handlers before, tabify may run on existing tabs after add or option change - this.lis.add( this.anchors ).unbind( ".tabs" ); + // _createPanel method + $.widget( "ui.tabs", $.ui.tabs, { + options: { + panelTemplate: "
          " + }, - if ( o.event !== "mouseover" ) { - var addState = function( state, el ) { - if ( el.is( ":not(.ui-state-disabled)" ) ) { - el.addClass( "ui-state-" + state ); - } - }; - var removeState = function( state, el ) { - el.removeClass( "ui-state-" + state ); - }; - this.lis.bind( "mouseover.tabs" , function() { - addState( "hover", $( this ) ); - }); - this.lis.bind( "mouseout.tabs", function() { - removeState( "hover", $( this ) ); - }); - this.anchors.bind( "focus.tabs", function() { - addState( "focus", $( this ).closest( "li" ) ); - }); - this.anchors.bind( "blur.tabs", function() { - removeState( "focus", $( this ).closest( "li" ) ); - }); + _createPanel: function( id ) { + return $( this.options.panelTemplate ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "ui-tabs-destroy", true ); } + }); - // set up animations - var hideFx, showFx; - if ( o.fx ) { - if ( $.isArray( o.fx ) ) { - hideFx = o.fx[ 0 ]; - showFx = o.fx[ 1 ]; - } else { - hideFx = showFx = o.fx; + // selected option + $.widget( "ui.tabs", $.ui.tabs, { + _create: function() { + var options = this.options; + if ( options.active === null && options.selected !== undefined ) { + options.active = options.selected === -1 ? false : options.selected; } - } - - // Reset certain styles left over from animation - // and prevent IE's ClearType bug... - function resetStyle( $el, fx ) { - $el.css( "display", "" ); - if ( !$.support.opacity && fx.opacity ) { - $el[ 0 ].style.removeAttribute( "filter" ); + this._super(); + options.selected = options.active; + if ( options.selected === false ) { + options.selected = -1; } - } + }, - // Show a tab... - var showTab = showFx - ? function( clicked, $show ) { - $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); - $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way - .animate( showFx, showFx.duration || "normal", function() { - resetStyle( $show, showFx ); - self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); - }); + _setOption: function( key, value ) { + if ( key !== "selected" ) { + return this._super( key, value ); } - : function( clicked, $show ) { - $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); - $show.removeClass( "ui-tabs-hide" ); - self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); - }; - // Hide a tab, $show is optional... - var hideTab = hideFx - ? function( clicked, $hide ) { - $hide.animate( hideFx, hideFx.duration || "normal", function() { - self.lis.removeClass( "ui-tabs-selected ui-state-active" ); - $hide.addClass( "ui-tabs-hide" ); - resetStyle( $hide, hideFx ); - self.element.dequeue( "tabs" ); - }); + var options = this.options; + this._super( "active", value === -1 ? false : value ); + options.selected = options.active; + if ( options.selected === false ) { + options.selected = -1; } - : function( clicked, $hide, $show ) { - self.lis.removeClass( "ui-tabs-selected ui-state-active" ); - $hide.addClass( "ui-tabs-hide" ); - self.element.dequeue( "tabs" ); - }; + }, - // attach tab event handler, unbind to avoid duplicates from former tabifying... - this.anchors.bind( o.event + ".tabs", function() { - var el = this, - $li = $(el).closest( "li" ), - $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), - $show = self.element.find( self._sanitizeSelector( el.hash ) ); - - // If tab is already selected and not collapsible or tab disabled or - // or is already loading or click callback returns false stop here. - // Check if click handler returns false last so that it is not executed - // for a disabled or loading tab! - if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || - $li.hasClass( "ui-state-disabled" ) || - $li.hasClass( "ui-state-processing" ) || - self.panels.filter( ":animated" ).length || - self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) { - this.blur(); - return false; + _eventHandler: function() { + this._superApply( arguments ); + this.options.selected = this.options.active; + if ( this.options.selected === false ) { + this.options.selected = -1; } + } + }); - o.selected = self.anchors.index( this ); - - self.abort(); - - // if tab may be closed - if ( o.collapsible ) { - if ( $li.hasClass( "ui-tabs-selected" ) ) { - o.selected = -1; + // show and select event + $.widget( "ui.tabs", $.ui.tabs, { + options: { + show: null, + select: null + }, + _create: function() { + this._super(); + if ( this.options.active !== false ) { + this._trigger( "show", null, this._ui( + this.active.find( ".ui-tabs-anchor" )[ 0 ], + this._getPanelForTab( this.active )[ 0 ] ) ); + } + }, + _trigger: function( type, event, data ) { + var tab, panel, + ret = this._superApply( arguments ); - if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); - } + if ( !ret ) { + return false; + } - self.element.queue( "tabs", function() { - hideTab( el, $hide ); - }).dequeue( "tabs" ); + if ( type === "beforeActivate" ) { + tab = data.newTab.length ? data.newTab : data.oldTab; + panel = data.newPanel.length ? data.newPanel : data.oldPanel; + ret = this._super( "select", event, { + tab: tab.find( ".ui-tabs-anchor" )[ 0], + panel: panel[ 0 ], + index: tab.closest( "li" ).index() + }); + } else if ( type === "activate" && data.newTab.length ) { + ret = this._super( "show", event, { + tab: data.newTab.find( ".ui-tabs-anchor" )[ 0 ], + panel: data.newPanel[ 0 ], + index: data.newTab.closest( "li" ).index() + }); + } + return ret; + } + }); - this.blur(); - return false; - } else if ( !$hide.length ) { - if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); - } + // select method + $.widget( "ui.tabs", $.ui.tabs, { + select: function( index ) { + index = this._getIndex( index ); + if ( index === -1 ) { + if ( this.options.collapsible && this.options.selected !== -1 ) { + index = this.options.selected; + } else { + return; + } + } + this.anchors.eq( index ).trigger( this.options.event + this.eventNamespace ); + } + }); - self.element.queue( "tabs", function() { - showTab( el, $show ); - }); + // cookie option + (function() { - // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 - self.load( self.anchors.index( this ) ); + var listId = 0; - this.blur(); - return false; + $.widget( "ui.tabs", $.ui.tabs, { + options: { + cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } + }, + _create: function() { + var options = this.options, + active; + if ( options.active == null && options.cookie ) { + active = parseInt( this._cookie(), 10 ); + if ( active === -1 ) { + active = false; } + options.active = active; } - - if ( o.cookie ) { - self._cookie( o.selected, o.cookie ); + this._super(); + }, + _cookie: function( active ) { + var cookie = [ this.cookie || + ( this.cookie = this.options.cookie.name || "ui-tabs-" + (++listId) ) ]; + if ( arguments.length ) { + cookie.push( active === false ? -1 : active ); + cookie.push( this.options.cookie ); + } + return $.cookie.apply( null, cookie ); + }, + _refresh: function() { + this._super(); + if ( this.options.cookie ) { + this._cookie( this.options.active, this.options.cookie ); + } + }, + _eventHandler: function() { + this._superApply( arguments ); + if ( this.options.cookie ) { + this._cookie( this.options.active, this.options.cookie ); + } + }, + _destroy: function() { + this._super(); + if ( this.options.cookie ) { + this._cookie( null, this.options.cookie ); } + } + }); - // show new tab - if ( $show.length ) { - if ( $hide.length ) { - self.element.queue( "tabs", function() { - hideTab( el, $hide ); - }); - } - self.element.queue( "tabs", function() { - showTab( el, $show ); - }); + })(); - self.load( self.anchors.index( this ) ); - } else { - throw "jQuery UI Tabs: Mismatching fragment identifier."; + // load event + $.widget( "ui.tabs", $.ui.tabs, { + _trigger: function( type, event, data ) { + var _data = $.extend( {}, data ); + if ( type === "load" ) { + _data.panel = _data.panel[ 0 ]; + _data.tab = _data.tab.find( ".ui-tabs-anchor" )[ 0 ]; } + return this._super( type, event, _data ); + } + }); - // Prevent IE from keeping other link focussed when using the back button - // and remove dotted border from clicked link. This is controlled via CSS - // in modern browsers; blur() removes focus from address bar in Firefox - // which can become a usability and annoying problem with tabs('rotate'). - if ( $.browser.msie ) { - this.blur(); - } - }); + // fx option + // The new animation options (show, hide) conflict with the old show callback. + // The old fx option wins over show/hide anyway (always favor back-compat). + // If a user wants to use the new animation API, they must give up the old API. + $.widget( "ui.tabs", $.ui.tabs, { + options: { + fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 } + }, - // disable click in any case - this.anchors.bind( "click.tabs", function(){ - return false; - }); - }, + _getFx: function() { + var hide, show, + fx = this.options.fx; - _getIndex: function( index ) { - // meta-function to give users option to provide a href string instead of a numerical index. - // also sanitizes numerical indexes to valid values. - if ( typeof index == "string" ) { - index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) ); - } + if ( fx ) { + if ( $.isArray( fx ) ) { + hide = fx[ 0 ]; + show = fx[ 1 ]; + } else { + hide = show = fx; + } + } - return index; - }, + return fx ? { show: show, hide: hide } : null; + }, - destroy: function() { - var o = this.options; + _toggle: function( event, eventData ) { + var that = this, + toShow = eventData.newPanel, + toHide = eventData.oldPanel, + fx = this._getFx(); + + if ( !fx ) { + return this._super( event, eventData ); + } - this.abort(); + that.running = true; - this.element - .unbind( ".tabs" ) - .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ) - .removeData( "tabs" ); + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } - this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); + function show() { + eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); - this.anchors.each(function() { - var href = $.data( this, "href.tabs" ); - if ( href ) { - this.href = href; + if ( toShow.length && fx.show ) { + toShow + .animate( fx.show, fx.show.duration, function() { + complete(); + }); + } else { + toShow.show(); + complete(); + } } - var $this = $( this ).unbind( ".tabs" ); - $.each( [ "href", "load", "cache" ], function( i, prefix ) { - $this.removeData( prefix + ".tabs" ); - }); - }); - this.lis.unbind( ".tabs" ).add( this.panels ).each(function() { - if ( $.data( this, "destroy.tabs" ) ) { - $( this ).remove(); + // start out by hiding, then showing, then completing + if ( toHide.length && fx.hide ) { + toHide.animate( fx.hide, fx.hide.duration, function() { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + show(); + }); } else { - $( this ).removeClass([ - "ui-state-default", - "ui-corner-top", - "ui-tabs-selected", - "ui-state-active", - "ui-state-hover", - "ui-state-focus", - "ui-state-disabled", - "ui-tabs-panel", - "ui-widget-content", - "ui-corner-bottom", - "ui-tabs-hide" - ].join( " " ) ); + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + toHide.hide(); + show(); } - }); - - if ( o.cookie ) { - this._cookie( null, o.cookie ); } + }); +} - return this; - }, +})( jQuery ); +(function( $ ) { - add: function( url, label, index ) { - if ( index === undefined ) { - index = this.anchors.length; - } +var increments = 0; - var self = this, - o = this.options, - $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), - id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); +function addDescribedBy( elem, id ) { + var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); + describedby.push( id ); + elem + .data( "ui-tooltip-id", id ) + .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); +} - $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); +function removeDescribedBy( elem ) { + var id = elem.data( "ui-tooltip-id" ), + describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), + index = $.inArray( id, describedby ); + if ( index !== -1 ) { + describedby.splice( index, 1 ); + } - // try to find an existing element before creating a new one - var $panel = self.element.find( "#" + id ); - if ( !$panel.length ) { - $panel = $( o.panelTemplate ) - .attr( "id", id ) - .data( "destroy.tabs", true ); - } - $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); + elem.removeData( "ui-tooltip-id" ); + describedby = $.trim( describedby.join( " " ) ); + if ( describedby ) { + elem.attr( "aria-describedby", describedby ); + } else { + elem.removeAttr( "aria-describedby" ); + } +} - if ( index >= this.lis.length ) { - $li.appendTo( this.list ); - $panel.appendTo( this.list[ 0 ].parentNode ); - } else { - $li.insertBefore( this.lis[ index ] ); - $panel.insertBefore( this.panels[ index ] ); - } +$.widget( "ui.tooltip", { + version: "1.9.2", + options: { + content: function() { + return $( this ).attr( "title" ); + }, + hide: true, + // Disabled elements have inconsistent behavior across browsers (#8661) + items: "[title]:not([disabled])", + position: { + my: "left top+15", + at: "left bottom", + collision: "flipfit flip" + }, + show: true, + tooltipClass: null, + track: false, - o.disabled = $.map( o.disabled, function( n, i ) { - return n >= index ? ++n : n; - }); + // callbacks + close: null, + open: null + }, - this._tabify(); + _create: function() { + this._on({ + mouseover: "open", + focusin: "open" + }); - if ( this.anchors.length == 1 ) { - o.selected = 0; - $li.addClass( "ui-tabs-selected ui-state-active" ); - $panel.removeClass( "ui-tabs-hide" ); - this.element.queue( "tabs", function() { - self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); - }); + // IDs of generated tooltips, needed for destroy + this.tooltips = {}; + // IDs of parent tooltips where we removed the title attribute + this.parents = {}; - this.load( 0 ); + if ( this.options.disabled ) { + this._disable(); } - - this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); - return this; }, - remove: function( index ) { - index = this._getIndex( index ); - var o = this.options, - $li = this.lis.eq( index ).remove(), - $panel = this.panels.eq( index ).remove(); - - // If selected tab was removed focus tab to the right or - // in case the last tab was removed the tab to the left. - if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) { - this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); - } - - o.disabled = $.map( - $.grep( o.disabled, function(n, i) { - return n != index; - }), - function( n, i ) { - return n >= index ? --n : n; - }); + _setOption: function( key, value ) { + var that = this; - this._tabify(); + if ( key === "disabled" ) { + this[ value ? "_disable" : "_enable" ](); + this.options[ key ] = value; + // disable element style changes + return; + } - this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); - return this; - }, + this._super( key, value ); - enable: function( index ) { - index = this._getIndex( index ); - var o = this.options; - if ( $.inArray( index, o.disabled ) == -1 ) { - return; + if ( key === "content" ) { + $.each( this.tooltips, function( id, element ) { + that._updateContent( element ); + }); } + }, + + _disable: function() { + var that = this; - this.lis.eq( index ).removeClass( "ui-state-disabled" ); - o.disabled = $.grep( o.disabled, function( n, i ) { - return n != index; + // close open tooltips + $.each( this.tooltips, function( id, element ) { + var event = $.Event( "blur" ); + event.target = event.currentTarget = element[0]; + that.close( event, true ); }); - this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); - return this; + // remove title attributes to prevent native tooltips + this.element.find( this.options.items ).andSelf().each(function() { + var element = $( this ); + if ( element.is( "[title]" ) ) { + element + .data( "ui-tooltip-title", element.attr( "title" ) ) + .attr( "title", "" ); + } + }); }, - disable: function( index ) { - index = this._getIndex( index ); - var self = this, o = this.options; - // cannot disable already selected tab - if ( index != o.selected ) { - this.lis.eq( index ).addClass( "ui-state-disabled" ); + _enable: function() { + // restore title attributes + this.element.find( this.options.items ).andSelf().each(function() { + var element = $( this ); + if ( element.data( "ui-tooltip-title" ) ) { + element.attr( "title", element.data( "ui-tooltip-title" ) ); + } + }); + }, - o.disabled.push( index ); - o.disabled.sort(); + open: function( event ) { + var that = this, + target = $( event ? event.target : this.element ) + // we need closest here due to mouseover bubbling, + // but always pointing at the same event target + .closest( this.options.items ); - this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + // No element to show a tooltip for or the tooltip is already open + if ( !target.length || target.data( "ui-tooltip-id" ) ) { + return; } - return this; + if ( target.attr( "title" ) ) { + target.data( "ui-tooltip-title", target.attr( "title" ) ); + } + + target.data( "ui-tooltip-open", true ); + + // kill parent tooltips, custom or native, for hover + if ( event && event.type === "mouseover" ) { + target.parents().each(function() { + var parent = $( this ), + blurEvent; + if ( parent.data( "ui-tooltip-open" ) ) { + blurEvent = $.Event( "blur" ); + blurEvent.target = blurEvent.currentTarget = this; + that.close( blurEvent, true ); + } + if ( parent.attr( "title" ) ) { + parent.uniqueId(); + that.parents[ this.id ] = { + element: this, + title: parent.attr( "title" ) + }; + parent.attr( "title", "" ); + } + }); + } + + this._updateContent( target, event ); }, - select: function( index ) { - index = this._getIndex( index ); - if ( index == -1 ) { - if ( this.options.collapsible && this.options.selected != -1 ) { - index = this.options.selected; - } else { - return this; + _updateContent: function( target, event ) { + var content, + contentOption = this.options.content, + that = this, + eventType = event ? event.type : null; + + if ( typeof contentOption === "string" ) { + return this._open( event, target, contentOption ); + } + + content = contentOption.call( target[0], function( response ) { + // ignore async response if tooltip was closed already + if ( !target.data( "ui-tooltip-open" ) ) { + return; } + // IE may instantly serve a cached response for ajax requests + // delay this call to _open so the other call to _open runs first + that._delay(function() { + // jQuery creates a special event for focusin when it doesn't + // exist natively. To improve performance, the native event + // object is reused and the type is changed. Therefore, we can't + // rely on the type being correct after the event finished + // bubbling, so we set it back to the previous value. (#8740) + if ( event ) { + event.type = eventType; + } + this._open( event, target, response ); + }); + }); + if ( content ) { + this._open( event, target, content ); } - this.anchors.eq( index ).trigger( this.options.event + ".tabs" ); - return this; }, - load: function( index ) { - index = this._getIndex( index ); - var self = this, - o = this.options, - a = this.anchors.eq( index )[ 0 ], - url = $.data( a, "load.tabs" ); + _open: function( event, target, content ) { + var tooltip, events, delayedShow, + positionOption = $.extend( {}, this.options.position ); - this.abort(); - - // not remote or from cache - if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) { - this.element.dequeue( "tabs" ); + if ( !content ) { return; } - // load remote from here on - this.lis.eq( index ).addClass( "ui-state-processing" ); - - if ( o.spinner ) { - var span = $( "span", a ); - span.data( "label.tabs", span.html() ).html( o.spinner ); + // Content can be updated multiple times. If the tooltip already + // exists, then just update the content and bail. + tooltip = this._find( target ); + if ( tooltip.length ) { + tooltip.find( ".ui-tooltip-content" ).html( content ); + return; } - this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, { - url: url, - success: function( r, s ) { - self.element.find( self._sanitizeSelector( a.hash ) ).html( r ); + // if we have a title, clear it to prevent the native tooltip + // we have to check first to avoid defining a title if none exists + // (we don't want to cause an element to start matching [title]) + // + // We use removeAttr only for key events, to allow IE to export the correct + // accessible attributes. For mouse events, set to empty string to avoid + // native tooltip showing up (happens only when removing inside mouseover). + if ( target.is( "[title]" ) ) { + if ( event && event.type === "mouseover" ) { + target.attr( "title", "" ); + } else { + target.removeAttr( "title" ); + } + } - // take care of tab labels - self._cleanup(); + tooltip = this._tooltip( target ); + addDescribedBy( target, tooltip.attr( "id" ) ); + tooltip.find( ".ui-tooltip-content" ).html( content ); - if ( o.cache ) { - $.data( a, "cache.tabs", true ); + function position( event ) { + positionOption.of = event; + if ( tooltip.is( ":hidden" ) ) { + return; + } + tooltip.position( positionOption ); + } + if ( this.options.track && event && /^mouse/.test( event.type ) ) { + this._on( this.document, { + mousemove: position + }); + // trigger once to override element-relative positioning + position( event ); + } else { + tooltip.position( $.extend({ + of: target + }, this.options.position ) ); + } + + tooltip.hide(); + + this._show( tooltip, this.options.show ); + // Handle tracking tooltips that are shown with a delay (#8644). As soon + // as the tooltip is visible, position the tooltip using the most recent + // event. + if ( this.options.show && this.options.show.delay ) { + delayedShow = setInterval(function() { + if ( tooltip.is( ":visible" ) ) { + position( positionOption.of ); + clearInterval( delayedShow ); } + }, $.fx.interval ); + } - self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); - try { - o.ajaxOptions.success( r, s ); - } - catch ( e ) {} - }, - error: function( xhr, s, e ) { - // take care of tab labels - self._cleanup(); + this._trigger( "open", event, { tooltip: tooltip } ); - self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); - try { - // Passing index avoid a race condition when this method is - // called after the user has selected another tab. - // Pass the anchor that initiated this request allows - // loadError to manipulate the tab content panel via $(a.hash) - o.ajaxOptions.error( xhr, s, index, a ); + events = { + keyup: function( event ) { + if ( event.keyCode === $.ui.keyCode.ESCAPE ) { + var fakeEvent = $.Event(event); + fakeEvent.currentTarget = target[0]; + this.close( fakeEvent, true ); } - catch ( e ) {} + }, + remove: function() { + this._removeTooltip( tooltip ); } - } ) ); + }; + if ( !event || event.type === "mouseover" ) { + events.mouseleave = "close"; + } + if ( !event || event.type === "focusin" ) { + events.focusout = "close"; + } + this._on( true, target, events ); + }, - // last, so that load event is fired before show... - self.element.dequeue( "tabs" ); + close: function( event ) { + var that = this, + target = $( event ? event.currentTarget : this.element ), + tooltip = this._find( target ); - return this; - }, + // disabling closes the tooltip, so we need to track when we're closing + // to avoid an infinite loop in case the tooltip becomes disabled on close + if ( this.closing ) { + return; + } - abort: function() { - // stop possibly running animations - this.element.queue( [] ); - this.panels.stop( false, true ); + // only set title if we had one before (see comment in _open()) + if ( target.data( "ui-tooltip-title" ) ) { + target.attr( "title", target.data( "ui-tooltip-title" ) ); + } - // "tabs" queue must not contain more than two elements, - // which are the callbacks for the latest clicked tab... - this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) ); + removeDescribedBy( target ); - // terminate pending requests from other tabs - if ( this.xhr ) { - this.xhr.abort(); - delete this.xhr; + tooltip.stop( true ); + this._hide( tooltip, this.options.hide, function() { + that._removeTooltip( $( this ) ); + }); + + target.removeData( "ui-tooltip-open" ); + this._off( target, "mouseleave focusout keyup" ); + // Remove 'remove' binding only on delegated targets + if ( target[0] !== this.element[0] ) { + this._off( target, "remove" ); } + this._off( this.document, "mousemove" ); - // take care of tab labels - this._cleanup(); - return this; + if ( event && event.type === "mouseleave" ) { + $.each( this.parents, function( id, parent ) { + $( parent.element ).attr( "title", parent.title ); + delete that.parents[ id ]; + }); + } + + this.closing = true; + this._trigger( "close", event, { tooltip: tooltip } ); + this.closing = false; }, - url: function( index, url ) { - this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url ); - return this; + _tooltip: function( element ) { + var id = "ui-tooltip-" + increments++, + tooltip = $( "
          " ) + .attr({ + id: id, + role: "tooltip" + }) + .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + + ( this.options.tooltipClass || "" ) ); + $( "
          " ) + .addClass( "ui-tooltip-content" ) + .appendTo( tooltip ); + tooltip.appendTo( this.document[0].body ); + if ( $.fn.bgiframe ) { + tooltip.bgiframe(); + } + this.tooltips[ id ] = element; + return tooltip; }, - length: function() { - return this.anchors.length; - } -}); + _find: function( target ) { + var id = target.data( "ui-tooltip-id" ); + return id ? $( "#" + id ) : $(); + }, -$.extend( $.ui.tabs, { - version: "1.8.16" -}); + _removeTooltip: function( tooltip ) { + tooltip.remove(); + delete this.tooltips[ tooltip.attr( "id" ) ]; + }, -/* - * Tabs Extensions - */ + _destroy: function() { + var that = this; -/* - * Rotate - */ -$.extend( $.ui.tabs.prototype, { - rotation: null, - rotate: function( ms, continuing ) { - var self = this, - o = this.options; + // close open tooltips + $.each( this.tooltips, function( id, element ) { + // Delegate to close method to handle common cleanup + var event = $.Event( "blur" ); + event.target = event.currentTarget = element[0]; + that.close( event, true ); - var rotate = self._rotate || ( self._rotate = function( e ) { - clearTimeout( self.rotation ); - self.rotation = setTimeout(function() { - var t = o.selected; - self.select( ++t < self.anchors.length ? t : 0 ); - }, ms ); - - if ( e ) { - e.stopPropagation(); - } - }); + // Remove immediately; destroying an open tooltip doesn't use the + // hide animation + $( "#" + id ).remove(); - var stop = self._unrotate || ( self._unrotate = !continuing - ? function(e) { - if (e.clientX) { // in case of a true click - self.rotate(null); - } + // Restore the title + if ( element.data( "ui-tooltip-title" ) ) { + element.attr( "title", element.data( "ui-tooltip-title" ) ); + element.removeData( "ui-tooltip-title" ); } - : function( e ) { - t = o.selected; - rotate(); - }); - - // start rotation - if ( ms ) { - this.element.bind( "tabsshow", rotate ); - this.anchors.bind( o.event + ".tabs", stop ); - rotate(); - // stop rotation - } else { - clearTimeout( self.rotation ); - this.element.unbind( "tabsshow", rotate ); - this.anchors.unbind( o.event + ".tabs", stop ); - delete this._rotate; - delete this._unrotate; - } - - return this; + }); } }); -})( jQuery ); +}( jQuery ) ); diff --git a/lib/scripts/jquery/jquery-ui.min.js b/lib/scripts/jquery/jquery-ui.min.js old mode 100644 new mode 100755 index 0202506b5..9b3b84deb --- a/lib/scripts/jquery/jquery-ui.min.js +++ b/lib/scripts/jquery/jquery-ui.min.js @@ -1,414 +1,6 @@ -/*! - * jQuery UI 1.8.16 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI - */ -(function(a,d){function c(h,g){var i=h.nodeName.toLowerCase();if("area"===i){g=h.parentNode;i=g.name;if(!h.href||!i||g.nodeName.toLowerCase()!=="map")return false;h=a("img[usemap=#"+i+"]")[0];return!!h&&e(h)}return(/input|select|textarea|button|object/.test(i)?!h.disabled:"a"==i?h.href||g:g)&&e(h)}function e(h){return!a(h).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(!a.ui.version){a.extend(a.ui,{version:"1.8.16", -keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(h,g){return typeof h==="number"?this.each(function(){var i= -this;setTimeout(function(){a(i).focus();g&&g.call(i)},h)}):this._focus.apply(this,arguments)},scrollParent:function(){var h;h=a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this, -"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!h.length?a(document):h},zIndex:function(h){if(h!==d)return this.css("zIndex",h);if(this.length){h=a(this[0]);for(var g;h.length&&h[0]!==document;){g=h.css("position");if(g==="absolute"||g==="relative"||g==="fixed"){g=parseInt(h.css("zIndex"),10);if(!isNaN(g)&&g!==0)return g}h=h.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart": -"mousedown")+".ui-disableSelection",function(h){h.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(h,g){function i(l,o,n,k){a.each(b,function(){o-=parseFloat(a.curCSS(l,"padding"+this,true))||0;if(n)o-=parseFloat(a.curCSS(l,"border"+this+"Width",true))||0;if(k)o-=parseFloat(a.curCSS(l,"margin"+this,true))||0});return o}var b=g==="Width"?["Left","Right"]:["Top","Bottom"],f=g.toLowerCase(),j={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight, -outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+g]=function(l){if(l===d)return j["inner"+g].call(this);return this.each(function(){a(this).css(f,i(this,l)+"px")})};a.fn["outer"+g]=function(l,o){if(typeof l!=="number")return j["outer"+g].call(this,l);return this.each(function(){a(this).css(f,i(this,l,true,o)+"px")})}});a.extend(a.expr[":"],{data:function(h,g,i){return!!a.data(h,i[3])},focusable:function(h){return c(h,!isNaN(a.attr(h,"tabindex")))},tabbable:function(h){var g=a.attr(h, -"tabindex"),i=isNaN(g);return(i||g>=0)&&c(h,!i)}});a(function(){var h=document.body,g=h.appendChild(g=document.createElement("div"));a.extend(g.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=g.offsetHeight===100;a.support.selectstart="onselectstart"in g;h.removeChild(g).style.display="none"});a.extend(a.ui,{plugin:{add:function(h,g,i){h=a.ui[h].prototype;for(var b in i){h.plugins[b]=h.plugins[b]||[];h.plugins[b].push([g,i[b]])}},call:function(h,g,i){if((g=h.plugins[g])&& -h.element[0].parentNode)for(var b=0;b0)return true;h[g]=1;i=h[g]>0;h[g]=0;return i},isOverAxis:function(h,g,i){return h>g&&h=9)&&!c.button)return this._mouseUp(c);if(this._mouseStarted){this._mouseDrag(c);return c.preventDefault()}if(this._mouseDistanceMet(c)&&this._mouseDelayMet(c))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,c)!==false)?this._mouseDrag(c):this._mouseUp(c);return!this._mouseStarted},_mouseUp:function(c){a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted= -false;c.target==this._mouseDownEvent.target&&a.data(c.target,this.widgetName+".preventClickEvent",true);this._mouseStop(c)}return false},_mouseDistanceMet:function(c){return Math.max(Math.abs(this._mouseDownEvent.pageX-c.pageX),Math.abs(this._mouseDownEvent.pageY-c.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); -(function(a){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== -"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(d){var c= -this.options;if(this.helper||c.disabled||a(d.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(d);if(!this.handle)return false;if(c.iframeFix)a(c.iframeFix===true?"iframe":c.iframeFix).each(function(){a('
          ').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(a(this).offset()).appendTo("body")});return true},_mouseStart:function(d){var c=this.options; -this.helper=this._createHelper(d);this._cacheHelperProportions();if(a.ui.ddmanager)a.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};a.extend(this.offset,{click:{left:d.pageX-this.offset.left,top:d.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}); -this.originalPosition=this.position=this._generatePosition(d);this.originalPageX=d.pageX;this.originalPageY=d.pageY;c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt);c.containment&&this._setContainment();if(this._trigger("start",d)===false){this._clear();return false}this._cacheHelperProportions();a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,d);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(d,true);a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,d);return true}, -_mouseDrag:function(d,c){this.position=this._generatePosition(d);this.positionAbs=this._convertPositionTo("absolute");if(!c){c=this._uiHash();if(this._trigger("drag",d,c)===false){this._mouseUp({});return false}this.position=c.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";a.ui.ddmanager&&a.ui.ddmanager.drag(this,d);return false},_mouseStop:function(d){var c= -false;if(a.ui.ddmanager&&!this.options.dropBehaviour)c=a.ui.ddmanager.drop(this,d);if(this.dropped){c=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return false;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===true||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var e=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration, -10),function(){e._trigger("stop",d)!==false&&e._clear()})}else this._trigger("stop",d)!==false&&this._clear();return false},_mouseUp:function(d){this.options.iframeFix===true&&a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,d);return a.ui.mouse.prototype._mouseUp.call(this,d)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(d){var c=!this.options.handle|| -!a(this.options.handle,this.element).length?true:false;a(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==d.target)c=true});return c},_createHelper:function(d){var c=this.options;d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[d])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo);d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&& -d.css("position","absolute");return d},_adjustOffsetFromHelper:function(d){if(typeof d=="string")d=d.split(" ");if(a.isArray(d))d={left:+d[0],top:+d[1]||0};if("left"in d)this.offset.click.left=d.left+this.margins.left;if("right"in d)this.offset.click.left=this.helperProportions.width-d.right+this.margins.left;if("top"in d)this.offset.click.top=d.top+this.margins.top;if("bottom"in d)this.offset.click.top=this.helperProportions.height-d.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent= -this.helper.offsetParent();var d=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){d.left+=this.scrollParent.scrollLeft();d.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)d={top:0,left:0};return{top:d.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:d.left+(parseInt(this.offsetParent.css("borderLeftWidth"), -10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var d=this.element.position();return{top:d.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:d.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"), -10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var d=this.options;if(d.containment=="parent")d.containment=this.helper[0].parentNode;if(d.containment=="document"||d.containment=="window")this.containment=[d.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,d.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top, -(d.containment=="document"?0:a(window).scrollLeft())+a(d.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d.containment=="document"?0:a(window).scrollTop())+(a(d.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(d.containment)&&d.containment.constructor!=Array){d=a(d.containment);var c=d[0];if(c){d.offset();var e=a(c).css("overflow")!= -"hidden";this.containment=[(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0),(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0),(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"), -10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=d}}else if(d.containment.constructor==Array)this.containment=d.containment},_convertPositionTo:function(d,c){if(!c)c=this.position;d=d=="absolute"?1:-1;var e=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,h=/(html|body)/i.test(e[0].tagName);return{top:c.top+ -this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():h?0:e.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():h?0:e.scrollLeft())*d)}},_generatePosition:function(d){var c=this.options,e=this.cssPosition=="absolute"&& -!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,h=/(html|body)/i.test(e[0].tagName),g=d.pageX,i=d.pageY;if(this.originalPosition){var b;if(this.containment){if(this.relative_container){b=this.relative_container.offset();b=[this.containment[0]+b.left,this.containment[1]+b.top,this.containment[2]+b.left,this.containment[3]+b.top]}else b=this.containment;if(d.pageX-this.offset.click.leftb[2])g=b[2]+this.offset.click.left;if(d.pageY-this.offset.click.top>b[3])i=b[3]+this.offset.click.top}if(c.grid){i=c.grid[1]?this.originalPageY+Math.round((i-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;i=b?!(i-this.offset.click.topb[3])?i:!(i-this.offset.click.topb[2])?g:!(g-this.offset.click.left=0;l--){var o=e.snapElements[l].left,n=o+e.snapElements[l].width,k=e.snapElements[l].top,m=k+e.snapElements[l].height;if(o-g=l&&i<=o||b>=l&&b<=o||io)&&(h>= -f&&h<=j||g>=f&&g<=j||hj);default:return false}};a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(d,c){var e=a.ui.ddmanager.droppables[d.options.scope]||[],h=c?c.type:null,g=(d.currentItem||d.element).find(":data(droppable)").andSelf(),i=0;a:for(;i
          ').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), -top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= -this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=h.handles||(!a(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", -nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var g=this.handles.split(",");this.handles={};for(var i=0;i
          ');/sw|se|ne|nw/.test(b)&&f.css({zIndex:++h.zIndex});"se"==b&&f.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[b]=".ui-resizable-"+b;this.element.append(f)}}this._renderAxis=function(j){j=j||this.element;for(var l in this.handles){if(this.handles[l].constructor== -String)this.handles[l]=a(this.handles[l],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=a(this.handles[l],this.element),n=0;n=/sw|ne|nw|se|n|s/.test(l)?o.outerHeight():o.outerWidth();o=["padding",/ne|nw|n/.test(l)?"Top":/se|sw|s/.test(l)?"Bottom":/^e$/.test(l)?"Right":"Left"].join("");j.css(o,n);this._proportionallyResize()}a(this.handles[l])}};this._renderAxis(this.element);this._handles=a(".ui-resizable-handle",this.element).disableSelection(); -this._handles.mouseover(function(){if(!e.resizing){if(this.className)var j=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);e.axis=j&&j[1]?j[1]:"se"}});if(h.autoHide){this._handles.hide();a(this.element).addClass("ui-resizable-autohide").hover(function(){if(!h.disabled){a(this).removeClass("ui-resizable-autohide");e._handles.show()}},function(){if(!h.disabled)if(!e.resizing){a(this).addClass("ui-resizable-autohide");e._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy(); -var e=function(g){a(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var h=this.element;h.after(this.originalElement.css({position:h.css("position"),width:h.outerWidth(),height:h.outerHeight(),top:h.css("top"),left:h.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(e){var h= -false;for(var g in this.handles)if(a(this.handles[g])[0]==e.target)h=true;return!this.options.disabled&&h},_mouseStart:function(e){var h=this.options,g=this.element.position(),i=this.element;this.resizing=true;this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()};if(i.is(".ui-draggable")||/absolute/.test(i.css("position")))i.css({position:"absolute",top:g.top,left:g.left});a.browser.opera&&/relative/.test(i.css("position"))&&i.css({position:"relative",top:"auto",left:"auto"}); -this._renderProxy();g=d(this.helper.css("left"));var b=d(this.helper.css("top"));if(h.containment){g+=a(h.containment).scrollLeft()||0;b+=a(h.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:g,top:b};this.size=this._helper?{width:i.outerWidth(),height:i.outerHeight()}:{width:i.width(),height:i.height()};this.originalSize=this._helper?{width:i.outerWidth(),height:i.outerHeight()}:{width:i.width(),height:i.height()};this.originalPosition={left:g,top:b};this.sizeDiff= -{width:i.outerWidth()-i.width(),height:i.outerHeight()-i.height()};this.originalMousePosition={left:e.pageX,top:e.pageY};this.aspectRatio=typeof h.aspectRatio=="number"?h.aspectRatio:this.originalSize.width/this.originalSize.height||1;h=a(".ui-resizable-"+this.axis).css("cursor");a("body").css("cursor",h=="auto"?this.axis+"-resize":h);i.addClass("ui-resizable-resizing");this._propagate("start",e);return true},_mouseDrag:function(e){var h=this.helper,g=this.originalMousePosition,i=this._change[this.axis]; -if(!i)return false;g=i.apply(this,[e,e.pageX-g.left||0,e.pageY-g.top||0]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)g=this._updateRatio(g,e);g=this._respectSize(g,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(g);this._trigger("resize",e,this.ui());return false}, -_mouseStop:function(e){this.resizing=false;var h=this.options,g=this;if(this._helper){var i=this._proportionallyResizeElements,b=i.length&&/textarea/i.test(i[0].nodeName);i=b&&a.ui.hasScroll(i[0],"left")?0:g.sizeDiff.height;b=b?0:g.sizeDiff.width;b={width:g.helper.width()-b,height:g.helper.height()-i};i=parseInt(g.element.css("left"),10)+(g.position.left-g.originalPosition.left)||null;var f=parseInt(g.element.css("top"),10)+(g.position.top-g.originalPosition.top)||null;h.animate||this.element.css(a.extend(b, -{top:f,left:i}));g.helper.height(g.size.height);g.helper.width(g.size.width);this._helper&&!h.animate&&this._proportionallyResize()}a("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",e);this._helper&&this.helper.remove();return false},_updateVirtualBoundaries:function(e){var h=this.options,g,i,b;h={minWidth:c(h.minWidth)?h.minWidth:0,maxWidth:c(h.maxWidth)?h.maxWidth:Infinity,minHeight:c(h.minHeight)?h.minHeight:0,maxHeight:c(h.maxHeight)?h.maxHeight: -Infinity};if(this._aspectRatio||e){e=h.minHeight*this.aspectRatio;i=h.minWidth/this.aspectRatio;g=h.maxHeight*this.aspectRatio;b=h.maxWidth/this.aspectRatio;if(e>h.minWidth)h.minWidth=e;if(i>h.minHeight)h.minHeight=i;if(ge.width,j=c(e.height)&&h.minHeight&&h.minHeight>e.height;if(f)e.width=h.minWidth;if(j)e.height=h.minHeight;if(i)e.width=h.maxWidth;if(b)e.height=h.maxHeight;var l=this.originalPosition.left+this.originalSize.width,o=this.position.top+this.size.height,n=/sw|nw|w/.test(g);g=/nw|ne|n/.test(g);if(f&&n)e.left=l-h.minWidth;if(i&&n)e.left=l-h.maxWidth;if(j&&g)e.top=o-h.minHeight;if(b&&g)e.top=o-h.maxHeight;if((h=!e.width&&!e.height)&&!e.left&&e.top)e.top=null;else if(h&&!e.top&&e.left)e.left= -null;return e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var e=this.helper||this.element,h=0;h
          ');var h=a.browser.msie&&a.browser.version<7,g=h?1:0;h=h?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+ -h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++e.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,h){return{width:this.originalSize.width+h}},w:function(e,h){return{left:this.originalPosition.left+h,width:this.originalSize.width-h}},n:function(e,h,g){return{top:this.originalPosition.top+g,height:this.originalSize.height-g}},s:function(e,h,g){return{height:this.originalSize.height+ -g}},se:function(e,h,g){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,h,g]))},sw:function(e,h,g){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,h,g]))},ne:function(e,h,g){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,h,g]))},nw:function(e,h,g){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,h,g]))}},_propagate:function(e,h){a.ui.plugin.call(this,e,[h,this.ui()]); -e!="resize"&&this._trigger(e,h,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});a.extend(a.ui.resizable,{version:"1.8.16"});a.ui.plugin.add("resizable","alsoResize",{start:function(){var e=a(this).data("resizable").options,h=function(g){a(g).each(function(){var i=a(this);i.data("resizable-alsoresize",{width:parseInt(i.width(), -10),height:parseInt(i.height(),10),left:parseInt(i.css("left"),10),top:parseInt(i.css("top"),10),position:i.css("position")})})};if(typeof e.alsoResize=="object"&&!e.alsoResize.parentNode)if(e.alsoResize.length){e.alsoResize=e.alsoResize[0];h(e.alsoResize)}else a.each(e.alsoResize,function(g){h(g)});else h(e.alsoResize)},resize:function(e,h){var g=a(this).data("resizable");e=g.options;var i=g.originalSize,b=g.originalPosition,f={height:g.size.height-i.height||0,width:g.size.width-i.width||0,top:g.position.top- -b.top||0,left:g.position.left-b.left||0},j=function(l,o){a(l).each(function(){var n=a(this),k=a(this).data("resizable-alsoresize"),m={},p=o&&o.length?o:n.parents(h.originalElement[0]).length?["width","height"]:["width","height","top","left"];a.each(p,function(q,s){if((q=(k[s]||0)+(f[s]||0))&&q>=0)m[s]=q||null});if(a.browser.opera&&/relative/.test(n.css("position"))){g._revertToRelativePosition=true;n.css({position:"absolute",top:"auto",left:"auto"})}n.css(m)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType? -a.each(e.alsoResize,function(l,o){j(l,o)}):j(e.alsoResize)},stop:function(){var e=a(this).data("resizable"),h=e.options,g=function(i){a(i).each(function(){var b=a(this);b.css({position:b.data("resizable-alsoresize").position})})};if(e._revertToRelativePosition){e._revertToRelativePosition=false;typeof h.alsoResize=="object"&&!h.alsoResize.nodeType?a.each(h.alsoResize,function(i){g(i)}):g(h.alsoResize)}a(this).removeData("resizable-alsoresize")}});a.ui.plugin.add("resizable","animate",{stop:function(e){var h= -a(this).data("resizable"),g=h.options,i=h._proportionallyResizeElements,b=i.length&&/textarea/i.test(i[0].nodeName),f=b&&a.ui.hasScroll(i[0],"left")?0:h.sizeDiff.height;b={width:h.size.width-(b?0:h.sizeDiff.width),height:h.size.height-f};f=parseInt(h.element.css("left"),10)+(h.position.left-h.originalPosition.left)||null;var j=parseInt(h.element.css("top"),10)+(h.position.top-h.originalPosition.top)||null;h.element.animate(a.extend(b,j&&f?{top:j,left:f}:{}),{duration:g.animateDuration,easing:g.animateEasing, -step:function(){var l={width:parseInt(h.element.css("width"),10),height:parseInt(h.element.css("height"),10),top:parseInt(h.element.css("top"),10),left:parseInt(h.element.css("left"),10)};i&&i.length&&a(i[0]).css({width:l.width,height:l.height});h._updateCache(l);h._propagate("resize",e)}})}});a.ui.plugin.add("resizable","containment",{start:function(){var e=a(this).data("resizable"),h=e.element,g=e.options.containment;if(h=g instanceof a?g.get(0):/parent/.test(g)?h.parent().get(0):g){e.containerElement= -a(h);if(/document/.test(g)||g==document){e.containerOffset={left:0,top:0};e.containerPosition={left:0,top:0};e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight}}else{var i=a(h),b=[];a(["Top","Right","Left","Bottom"]).each(function(l,o){b[l]=d(i.css("padding"+o))});e.containerOffset=i.offset();e.containerPosition=i.position();e.containerSize={height:i.innerHeight()-b[3],width:i.innerWidth()-b[1]};g=e.containerOffset; -var f=e.containerSize.height,j=e.containerSize.width;j=a.ui.hasScroll(h,"left")?h.scrollWidth:j;f=a.ui.hasScroll(h)?h.scrollHeight:f;e.parentData={element:h,left:g.left,top:g.top,width:j,height:f}}}},resize:function(e){var h=a(this).data("resizable"),g=h.options,i=h.containerOffset,b=h.position;e=h._aspectRatio||e.shiftKey;var f={top:0,left:0},j=h.containerElement;if(j[0]!=document&&/static/.test(j.css("position")))f=i;if(b.left<(h._helper?i.left:0)){h.size.width+=h._helper?h.position.left-i.left: -h.position.left-f.left;if(e)h.size.height=h.size.width/g.aspectRatio;h.position.left=g.helper?i.left:0}if(b.top<(h._helper?i.top:0)){h.size.height+=h._helper?h.position.top-i.top:h.position.top;if(e)h.size.width=h.size.height*g.aspectRatio;h.position.top=h._helper?i.top:0}h.offset.left=h.parentData.left+h.position.left;h.offset.top=h.parentData.top+h.position.top;g=Math.abs((h._helper?h.offset.left-f.left:h.offset.left-f.left)+h.sizeDiff.width);i=Math.abs((h._helper?h.offset.top-f.top:h.offset.top- -i.top)+h.sizeDiff.height);b=h.containerElement.get(0)==h.element.parent().get(0);f=/relative|absolute/.test(h.containerElement.css("position"));if(b&&f)g-=h.parentData.left;if(g+h.size.width>=h.parentData.width){h.size.width=h.parentData.width-g;if(e)h.size.height=h.size.width/h.aspectRatio}if(i+h.size.height>=h.parentData.height){h.size.height=h.parentData.height-i;if(e)h.size.width=h.size.height*h.aspectRatio}},stop:function(){var e=a(this).data("resizable"),h=e.options,g=e.containerOffset,i=e.containerPosition, -b=e.containerElement,f=a(e.helper),j=f.offset(),l=f.outerWidth()-e.sizeDiff.width;f=f.outerHeight()-e.sizeDiff.height;e._helper&&!h.animate&&/relative/.test(b.css("position"))&&a(this).css({left:j.left-i.left-g.left,width:l,height:f});e._helper&&!h.animate&&/static/.test(b.css("position"))&&a(this).css({left:j.left-i.left-g.left,width:l,height:f})}});a.ui.plugin.add("resizable","ghost",{start:function(){var e=a(this).data("resizable"),h=e.options,g=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25, -display:"block",position:"relative",height:g.height,width:g.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof h.ghost=="string"?h.ghost:"");e.ghost.appendTo(e.helper)},resize:function(){var e=a(this).data("resizable");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=a(this).data("resizable");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}});a.ui.plugin.add("resizable","grid",{resize:function(){var e= -a(this).data("resizable"),h=e.options,g=e.size,i=e.originalSize,b=e.originalPosition,f=e.axis;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var j=Math.round((g.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1);h=Math.round((g.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(f)){e.size.width=i.width+j;e.size.height=i.height+h}else if(/^(ne)$/.test(f)){e.size.width=i.width+j;e.size.height=i.height+h;e.position.top=b.top-h}else{if(/^(sw)$/.test(f)){e.size.width=i.width+j;e.size.height= -i.height+h}else{e.size.width=i.width+j;e.size.height=i.height+h;e.position.top=b.top-h}e.position.left=b.left-j}}});var d=function(e){return parseInt(e,10)||0},c=function(e){return!isNaN(parseInt(e,10))}})(jQuery); -(function(a){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var d=this;this.element.addClass("ui-selectable");this.dragged=false;var c;this.refresh=function(){c=a(d.options.filter,d.element[0]);c.each(function(){var e=a(this),h=e.offset();a.data(this,"selectable-item",{element:this,$element:e,left:h.left,top:h.top,right:h.left+e.outerWidth(),bottom:h.top+e.outerHeight(),startselected:false,selected:e.hasClass("ui-selected"), -selecting:e.hasClass("ui-selecting"),unselecting:e.hasClass("ui-unselecting")})})};this.refresh();this.selectees=c.addClass("ui-selectee");this._mouseInit();this.helper=a("
          ")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(d){var c=this;this.opos=[d.pageX, -d.pageY];if(!this.options.disabled){var e=this.options;this.selectees=a(e.filter,this.element[0]);this._trigger("start",d);a(e.appendTo).append(this.helper);this.helper.css({left:d.clientX,top:d.clientY,width:0,height:0});e.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var h=a.data(this,"selectable-item");h.startselected=true;if(!d.metaKey){h.$element.removeClass("ui-selected");h.selected=false;h.$element.addClass("ui-unselecting");h.unselecting=true;c._trigger("unselecting", -d,{unselecting:h.element})}});a(d.target).parents().andSelf().each(function(){var h=a.data(this,"selectable-item");if(h){var g=!d.metaKey||!h.$element.hasClass("ui-selected");h.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");h.unselecting=!g;h.selecting=g;(h.selected=g)?c._trigger("selecting",d,{selecting:h.element}):c._trigger("unselecting",d,{unselecting:h.element});return false}})}},_mouseDrag:function(d){var c=this;this.dragged=true;if(!this.options.disabled){var e= -this.options,h=this.opos[0],g=this.opos[1],i=d.pageX,b=d.pageY;if(h>i){var f=i;i=h;h=f}if(g>b){f=b;b=g;g=f}this.helper.css({left:h,top:g,width:i-h,height:b-g});this.selectees.each(function(){var j=a.data(this,"selectable-item");if(!(!j||j.element==c.element[0])){var l=false;if(e.tolerance=="touch")l=!(j.left>i||j.rightb||j.bottomh&&j.rightg&&j.bottom *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){var d=this.options;this.containerCache={};this.element.addClass("ui-sortable"); -this.refresh();this.floating=this.items.length?d.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var d=this.items.length-1;d>=0;d--)this.items[d].item.removeData("sortable-item");return this},_setOption:function(d,c){if(d=== -"disabled"){this.options[d]=c;this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")}else a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(d,c){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(d);var e=null,h=this;a(d.target).parents().each(function(){if(a.data(this,"sortable-item")==h){e=a(this);return false}});if(a.data(d.target,"sortable-item")==h)e=a(d.target);if(!e)return false;if(this.options.handle&& -!c){var g=false;a(this.options.handle,e).find("*").andSelf().each(function(){if(this==d.target)g=true});if(!g)return false}this.currentItem=e;this._removeCurrentsFromItems();return true},_mouseStart:function(d,c,e){c=this.options;var h=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(d);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top, -left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");a.extend(this.offset,{click:{left:d.pageX-this.offset.left,top:d.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(d);this.originalPageX=d.pageX;this.originalPageY=d.pageY;c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]}; -this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();c.containment&&this._setContainment();if(c.cursor){if(a("body").css("cursor"))this._storedCursor=a("body").css("cursor");a("body").css("cursor",c.cursor)}if(c.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",c.opacity)}if(c.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",c.zIndex)}if(this.scrollParent[0]!= -document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",d,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!e)for(e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("activate",d,h._uiHash(this));if(a.ui.ddmanager)a.ui.ddmanager.current=this;a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,d);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(d); -return true},_mouseDrag:function(d){this.position=this._generatePosition(d);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var c=this.options,e=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-d.pageY=0;c--){e=this.items[c];var h=e.item[0],g=this._intersectsWithPointer(e);if(g)if(h!=this.currentItem[0]&&this.placeholder[g==1?"next":"prev"]()[0]!=h&&!a.ui.contains(this.placeholder[0],h)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0], -h):true)){this.direction=g==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(e))this._rearrange(d,e);else break;this._trigger("change",d,this._uiHash());break}}this._contactContainers(d);a.ui.ddmanager&&a.ui.ddmanager.drag(this,d);this._trigger("sort",d,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(d,c){if(d){a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,d);if(this.options.revert){var e=this;c=e.placeholder.offset(); -e.reverting=true;a(this.helper).animate({left:c.left-this.offset.parent.left-e.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:c.top-this.offset.parent.top-e.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){e._clear(d)})}else this._clear(d,c);return false}},cancel:function(){var d=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"): -this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--){this.containers[c]._trigger("deactivate",null,d._uiHash(this));if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",null,d._uiHash(this));this.containers[c].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();a.extend(this,{helper:null, -dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(d){var c=this._getItemsAsjQuery(d&&d.connected),e=[];d=d||{};a(c).each(function(){var h=(a(d.item||this).attr(d.attribute||"id")||"").match(d.expression||/(.+)[-=_](.+)/);if(h)e.push((d.key||h[1]+"[]")+"="+(d.key&&d.expression?h[1]:h[2]))});!e.length&&d.key&&e.push(d.key+"=");return e.join("&")}, -toArray:function(d){var c=this._getItemsAsjQuery(d&&d.connected),e=[];d=d||{};c.each(function(){e.push(a(d.item||this).attr(d.attribute||"id")||"")});return e},_intersectsWith:function(d){var c=this.positionAbs.left,e=c+this.helperProportions.width,h=this.positionAbs.top,g=h+this.helperProportions.height,i=d.left,b=i+d.width,f=d.top,j=f+d.height,l=this.offset.click.top,o=this.offset.click.left;l=h+l>f&&h+li&&c+od[this.floating?"width":"height"]?l:i0?"down":"up")},_getDragHorizontalDirection:function(){var d=this.positionAbs.left-this.lastPositionAbs.left;return d!=0&&(d>0?"right":"left")},refresh:function(d){this._refreshItems(d);this.refreshPositions();return this},_connectWith:function(){var d=this.options;return d.connectWith.constructor==String?[d.connectWith]:d.connectWith},_getItemsAsjQuery:function(d){var c=[],e=[],h=this._connectWith(); -if(h&&d)for(d=h.length-1;d>=0;d--)for(var g=a(h[d]),i=g.length-1;i>=0;i--){var b=a.data(g[i],"sortable");if(b&&b!=this&&!b.options.disabled)e.push([a.isFunction(b.options.items)?b.options.items.call(b.element):a(b.options.items,b.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),b])}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), -this]);for(d=e.length-1;d>=0;d--)e[d][0].each(function(){c.push(this)});return a(c)},_removeCurrentsFromItems:function(){for(var d=this.currentItem.find(":data(sortable-item)"),c=0;c=0;g--)for(var i=a(h[g]),b=i.length-1;b>=0;b--){var f=a.data(i[b],"sortable");if(f&&f!=this&&!f.options.disabled){e.push([a.isFunction(f.options.items)?f.options.items.call(f.element[0],d,{item:this.currentItem}):a(f.options.items,f.element),f]);this.containers.push(f)}}for(g=e.length-1;g>=0;g--){d=e[g][1];h=e[g][0];b=0;for(i=h.length;b=0;c--){var e=this.items[c];if(!(e.instance!=this.currentContainer&&this.currentContainer&&e.item[0]!=this.currentItem[0])){var h=this.options.toleranceElement?a(this.options.toleranceElement,e.item):e.item;if(!d){e.width=h.outerWidth();e.height=h.outerHeight()}h=h.offset();e.left=h.left;e.top=h.top}}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(c= -this.containers.length-1;c>=0;c--){h=this.containers[c].element.offset();this.containers[c].containerCache.left=h.left;this.containers[c].containerCache.top=h.top;this.containers[c].containerCache.width=this.containers[c].element.outerWidth();this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(d){var c=d||this,e=c.options;if(!e.placeholder||e.placeholder.constructor==String){var h=e.placeholder;e.placeholder={element:function(){var g= -a(document.createElement(c.currentItem[0].nodeName)).addClass(h||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!h)g.style.visibility="hidden";return g},update:function(g,i){if(!(h&&!e.forcePlaceholderSize)){i.height()||i.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10));i.width()||i.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft")||0,10)-parseInt(c.currentItem.css("paddingRight")|| -0,10))}}}}c.placeholder=a(e.placeholder.element.call(c.element,c.currentItem));c.currentItem.after(c.placeholder);e.placeholder.update(c,c.placeholder)},_contactContainers:function(d){for(var c=null,e=null,h=this.containers.length-1;h>=0;h--)if(!a.ui.contains(this.currentItem[0],this.containers[h].element[0]))if(this._intersectsWith(this.containers[h].containerCache)){if(!(c&&a.ui.contains(this.containers[h].element[0],c.element[0]))){c=this.containers[h];e=h}}else if(this.containers[h].containerCache.over){this.containers[h]._trigger("out", -d,this._uiHash(this));this.containers[h].containerCache.over=0}if(c)if(this.containers.length===1){this.containers[e]._trigger("over",d,this._uiHash(this));this.containers[e].containerCache.over=1}else if(this.currentContainer!=this.containers[e]){c=1E4;h=null;for(var g=this.positionAbs[this.containers[e].floating?"left":"top"],i=this.items.length-1;i>=0;i--)if(a.ui.contains(this.containers[e].element[0],this.items[i].item[0])){var b=this.items[i][this.containers[e].floating?"left":"top"];if(Math.abs(b- -g)this.containment[2])g=this.containment[2]+this.offset.click.left;if(d.pageY-this.offset.click.top>this.containment[3])i=this.containment[3]+this.offset.click.top}if(c.grid){i=this.originalPageY+Math.round((i- -this.originalPageY)/c.grid[1])*c.grid[1];i=this.containment?!(i-this.offset.click.topthis.containment[3])?i:!(i-this.offset.click.topthis.containment[2])?g:!(g-this.offset.click.left=0;h--)if(a.ui.contains(this.containers[h].element[0],this.currentItem[0])&&!c){e.push(function(g){return function(i){g._trigger("receive",i,this._uiHash(this))}}.call(this,this.containers[h]));e.push(function(g){return function(i){g._trigger("update",i,this._uiHash(this))}}.call(this,this.containers[h]))}}for(h=this.containers.length-1;h>=0;h--){c||e.push(function(g){return function(i){g._trigger("deactivate",i,this._uiHash(this))}}.call(this, -this.containers[h]));if(this.containers[h].containerCache.over){e.push(function(g){return function(i){g._trigger("out",i,this._uiHash(this))}}.call(this,this.containers[h]));this.containers[h].containerCache.over=0}}this._storedCursor&&a("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!c){this._trigger("beforeStop", -d,this._uiHash());for(h=0;h
        ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}), -p=document.activeElement;n.wrap(m);if(n[0]===p||a.contains(n[0],p))a(p).focus();m=n.parent();if(n.css("position")=="static"){m.css({position:"relative"});n.css({position:"relative"})}else{a.extend(k,{position:n.css("position"),zIndex:n.css("z-index")});a.each(["top","left","bottom","right"],function(q,s){k[s]=n.css(s);if(isNaN(parseInt(k[s],10)))k[s]="auto"});n.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return m.css(k).show()},removeWrapper:function(n){var k,m=document.activeElement; -if(n.parent().is(".ui-effects-wrapper")){k=n.parent().replaceWith(n);if(n[0]===m||a.contains(n[0],m))a(m).focus();return k}return n},setTransition:function(n,k,m,p){p=p||{};a.each(k,function(q,s){unit=n.cssUnit(s);if(unit[0]>0)p[s]=unit[0]*m+unit[1]});return p}});a.fn.extend({effect:function(n){var k=b.apply(this,arguments),m={options:k[1],duration:k[2],callback:k[3]};k=m.options.mode;var p=a.effects[n];if(a.fx.off||!p)return k?this[k](m.duration,m.callback):this.each(function(){m.callback&&m.callback.call(this)}); -return p.call(this,m)},_show:a.fn.show,show:function(n){if(f(n))return this._show.apply(this,arguments);else{var k=b.apply(this,arguments);k[1].mode="show";return this.effect.apply(this,k)}},_hide:a.fn.hide,hide:function(n){if(f(n))return this._hide.apply(this,arguments);else{var k=b.apply(this,arguments);k[1].mode="hide";return this.effect.apply(this,k)}},__toggle:a.fn.toggle,toggle:function(n){if(f(n)||typeof n==="boolean"||a.isFunction(n))return this.__toggle.apply(this,arguments);else{var k=b.apply(this, -arguments);k[1].mode="toggle";return this.effect.apply(this,k)}},cssUnit:function(n){var k=this.css(n),m=[];a.each(["em","px","%","pt"],function(p,q){if(k.indexOf(q)>0)m=[parseFloat(k),q]});return m}});a.easing.jswing=a.easing.swing;a.extend(a.easing,{def:"easeOutQuad",swing:function(n,k,m,p,q){return a.easing[a.easing.def](n,k,m,p,q)},easeInQuad:function(n,k,m,p,q){return p*(k/=q)*k+m},easeOutQuad:function(n,k,m,p,q){return-p*(k/=q)*(k-2)+m},easeInOutQuad:function(n,k,m,p,q){if((k/=q/2)<1)return p/ -2*k*k+m;return-p/2*(--k*(k-2)-1)+m},easeInCubic:function(n,k,m,p,q){return p*(k/=q)*k*k+m},easeOutCubic:function(n,k,m,p,q){return p*((k=k/q-1)*k*k+1)+m},easeInOutCubic:function(n,k,m,p,q){if((k/=q/2)<1)return p/2*k*k*k+m;return p/2*((k-=2)*k*k+2)+m},easeInQuart:function(n,k,m,p,q){return p*(k/=q)*k*k*k+m},easeOutQuart:function(n,k,m,p,q){return-p*((k=k/q-1)*k*k*k-1)+m},easeInOutQuart:function(n,k,m,p,q){if((k/=q/2)<1)return p/2*k*k*k*k+m;return-p/2*((k-=2)*k*k*k-2)+m},easeInQuint:function(n,k,m, -p,q){return p*(k/=q)*k*k*k*k+m},easeOutQuint:function(n,k,m,p,q){return p*((k=k/q-1)*k*k*k*k+1)+m},easeInOutQuint:function(n,k,m,p,q){if((k/=q/2)<1)return p/2*k*k*k*k*k+m;return p/2*((k-=2)*k*k*k*k+2)+m},easeInSine:function(n,k,m,p,q){return-p*Math.cos(k/q*(Math.PI/2))+p+m},easeOutSine:function(n,k,m,p,q){return p*Math.sin(k/q*(Math.PI/2))+m},easeInOutSine:function(n,k,m,p,q){return-p/2*(Math.cos(Math.PI*k/q)-1)+m},easeInExpo:function(n,k,m,p,q){return k==0?m:p*Math.pow(2,10*(k/q-1))+m},easeOutExpo:function(n, -k,m,p,q){return k==q?m+p:p*(-Math.pow(2,-10*k/q)+1)+m},easeInOutExpo:function(n,k,m,p,q){if(k==0)return m;if(k==q)return m+p;if((k/=q/2)<1)return p/2*Math.pow(2,10*(k-1))+m;return p/2*(-Math.pow(2,-10*--k)+2)+m},easeInCirc:function(n,k,m,p,q){return-p*(Math.sqrt(1-(k/=q)*k)-1)+m},easeOutCirc:function(n,k,m,p,q){return p*Math.sqrt(1-(k=k/q-1)*k)+m},easeInOutCirc:function(n,k,m,p,q){if((k/=q/2)<1)return-p/2*(Math.sqrt(1-k*k)-1)+m;return p/2*(Math.sqrt(1-(k-=2)*k)+1)+m},easeInElastic:function(n,k,m, -p,q){n=1.70158;var s=0,r=p;if(k==0)return m;if((k/=q)==1)return m+p;s||(s=q*0.3);if(r
        ").css({position:"absolute",visibility:"visible",left:-j*(i/e),top:-f*(b/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:i/e,height:b/c,left:g.left+j*(i/e)+(d.options.mode=="show"?(j-Math.floor(e/2))*(i/e):0),top:g.top+f*(b/c)+(d.options.mode=="show"?(f-Math.floor(c/2))*(b/c):0),opacity:d.options.mode=="show"?0:1}).animate({left:g.left+j*(i/e)+(d.options.mode=="show"?0:(j-Math.floor(e/2))*(i/e)),top:g.top+ -f*(b/c)+(d.options.mode=="show"?0:(f-Math.floor(c/2))*(b/c)),opacity:d.options.mode=="show"?1:0},d.duration||500);setTimeout(function(){d.options.mode=="show"?h.css({visibility:"visible"}):h.css({visibility:"visible"}).hide();d.callback&&d.callback.apply(h[0]);h.dequeue();a("div.ui-effects-explode").remove()},d.duration||500)})}})(jQuery); -(function(a){a.effects.fade=function(d){return this.queue(function(){var c=a(this),e=a.effects.setMode(c,d.options.mode||"hide");c.animate({opacity:e},{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){d.callback&&d.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); -(function(a){a.effects.fold=function(d){return this.queue(function(){var c=a(this),e=["position","top","bottom","left","right"],h=a.effects.setMode(c,d.options.mode||"hide"),g=d.options.size||15,i=!!d.options.horizFirst,b=d.duration?d.duration/2:a.fx.speeds._default/2;a.effects.save(c,e);c.show();var f=a.effects.createWrapper(c).css({overflow:"hidden"}),j=h=="show"!=i,l=j?["width","height"]:["height","width"];j=j?[f.width(),f.height()]:[f.height(),f.width()];var o=/([0-9]+)%/.exec(g);if(o)g=parseInt(o[1], -10)/100*j[h=="hide"?0:1];if(h=="show")f.css(i?{height:0,width:g}:{height:g,width:0});i={};o={};i[l[0]]=h=="show"?j[0]:g;o[l[1]]=h=="show"?j[1]:0;f.animate(i,b,d.options.easing).animate(o,b,d.options.easing,function(){h=="hide"&&c.hide();a.effects.restore(c,e);a.effects.removeWrapper(c);d.callback&&d.callback.apply(c[0],arguments);c.dequeue()})})}})(jQuery); -(function(a){a.effects.highlight=function(d){return this.queue(function(){var c=a(this),e=["backgroundImage","backgroundColor","opacity"],h=a.effects.setMode(c,d.options.mode||"show"),g={backgroundColor:c.css("backgroundColor")};if(h=="hide")g.opacity=0;a.effects.save(c,e);c.show().css({backgroundImage:"none",backgroundColor:d.options.color||"#ffff99"}).animate(g,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){h=="hide"&&c.hide();a.effects.restore(c,e);h=="show"&&!a.support.opacity&& -this.style.removeAttribute("filter");d.callback&&d.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); -(function(a){a.effects.pulsate=function(d){return this.queue(function(){var c=a(this),e=a.effects.setMode(c,d.options.mode||"show");times=(d.options.times||5)*2-1;duration=d.duration?d.duration/2:a.fx.speeds._default/2;isVisible=c.is(":visible");animateTo=0;if(!isVisible){c.css("opacity",0).show();animateTo=1}if(e=="hide"&&isVisible||e=="show"&&!isVisible)times--;for(e=0;e
        ').appendTo(document.body).addClass(d.options.className).css({top:h.top,left:h.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(e,d.duration,d.options.easing,function(){g.remove();d.callback&&d.callback.apply(c[0],arguments); -c.dequeue()})})}})(jQuery); -(function(a){a.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var d=this,c=d.options;d.running=0;d.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix");d.headers= -d.element.find(c.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c.disabled||a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c.disabled||a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c.disabled||a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c.disabled||a(this).removeClass("ui-state-focus")});d.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); -if(c.navigation){var e=d.element.find("a").filter(c.navigationFilter).eq(0);if(e.length){var h=e.closest(".ui-accordion-header");d.active=h.length?h:e.closest(".ui-accordion-content").prev()}}d.active=d._findActive(d.active||c.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");d.active.next().addClass("ui-accordion-content-active");d._createIcons();d.resize();d.element.attr("role","tablist");d.headers.attr("role","tab").bind("keydown.accordion", -function(g){return d._keydown(g)}).next().attr("role","tabpanel");d.headers.not(d.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide();d.active.length?d.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):d.headers.eq(0).attr("tabIndex",0);a.browser.safari||d.headers.find("a").attr("tabIndex",-1);c.event&&d.headers.bind(c.event.split(" ").join(".accordion ")+".accordion",function(g){d._clickHandler.call(d,g,this);g.preventDefault()})},_createIcons:function(){var d= -this.options;if(d.icons){a("").addClass("ui-icon "+d.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(d.icons.header).toggleClass(d.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var d=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"); -this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var c=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(d.autoHeight||d.fillHeight)c.css("height","");return a.Widget.prototype.destroy.call(this)},_setOption:function(d,c){a.Widget.prototype._setOption.apply(this,arguments);d=="active"&&this.activate(c);if(d=="icons"){this._destroyIcons(); -c&&this._createIcons()}if(d=="disabled")this.headers.add(this.headers.next())[c?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(d){if(!(this.options.disabled||d.altKey||d.ctrlKey)){var c=a.ui.keyCode,e=this.headers.length,h=this.headers.index(d.target),g=false;switch(d.keyCode){case c.RIGHT:case c.DOWN:g=this.headers[(h+1)%e];break;case c.LEFT:case c.UP:g=this.headers[(h-1+e)%e];break;case c.SPACE:case c.ENTER:this._clickHandler({target:d.target},d.target); -d.preventDefault()}if(g){a(d.target).attr("tabIndex",-1);a(g).attr("tabIndex",0);g.focus();return false}return true}},resize:function(){var d=this.options,c;if(d.fillSpace){if(a.browser.msie){var e=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}c=this.element.parent().height();a.browser.msie&&this.element.parent().css("overflow",e);this.headers.each(function(){c-=a(this).outerHeight(true)});this.headers.next().each(function(){a(this).height(Math.max(0,c-a(this).innerHeight()+ -a(this).height()))}).css("overflow","auto")}else if(d.autoHeight){c=0;this.headers.next().each(function(){c=Math.max(c,a(this).height("").height())}).height(c)}return this},activate:function(d){this.options.active=d;d=this._findActive(d)[0];this._clickHandler({target:d},d);return this},_findActive:function(d){return d?typeof d==="number"?this.headers.filter(":eq("+d+")"):this.headers.not(this.headers.not(d)):d===false?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(d,c){var e=this.options; -if(!e.disabled)if(d.target){d=a(d.currentTarget||c);c=d[0]===this.active[0];e.active=e.collapsible&&c?false:this.headers.index(d);if(!(this.running||!e.collapsible&&c)){var h=this.active;f=d.next();i=this.active.next();b={options:e,newHeader:c&&e.collapsible?a([]):d,oldHeader:this.active,newContent:c&&e.collapsible?a([]):f,oldContent:i};var g=this.headers.index(this.active[0])>this.headers.index(d[0]);this.active=c?a([]):d;this._toggle(f,i,b,c,g);h.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(e.icons.headerSelected).addClass(e.icons.header); -if(!c){d.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(e.icons.header).addClass(e.icons.headerSelected);d.next().addClass("ui-accordion-content-active")}}}else if(e.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(e.icons.headerSelected).addClass(e.icons.header);this.active.next().addClass("ui-accordion-content-active");var i=this.active.next(), -b={options:e,newHeader:a([]),oldHeader:e.active,newContent:a([]),oldContent:i},f=this.active=a([]);this._toggle(f,i,b)}},_toggle:function(d,c,e,h,g){var i=this,b=i.options;i.toShow=d;i.toHide=c;i.data=e;var f=function(){if(i)return i._completed.apply(i,arguments)};i._trigger("changestart",null,i.data);i.running=c.size()===0?d.size():c.size();if(b.animated){e={};e=b.collapsible&&h?{toShow:a([]),toHide:c,complete:f,down:g,autoHeight:b.autoHeight||b.fillSpace}:{toShow:d,toHide:c,complete:f,down:g,autoHeight:b.autoHeight|| -b.fillSpace};if(!b.proxied)b.proxied=b.animated;if(!b.proxiedDuration)b.proxiedDuration=b.duration;b.animated=a.isFunction(b.proxied)?b.proxied(e):b.proxied;b.duration=a.isFunction(b.proxiedDuration)?b.proxiedDuration(e):b.proxiedDuration;h=a.ui.accordion.animations;var j=b.duration,l=b.animated;if(l&&!h[l]&&!a.easing[l])l="slide";h[l]||(h[l]=function(o){this.slide(o,{easing:l,duration:j||700})});h[l](e)}else{if(b.collapsible&&h)d.toggle();else{c.hide();d.show()}f(true)}c.prev().attr({"aria-expanded":"false", -"aria-selected":"false",tabIndex:-1}).blur();d.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(d){this.running=d?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});a.extend(a.ui.accordion,{version:"1.8.16", -animations:{slide:function(d,c){d=a.extend({easing:"swing",duration:300},d,c);if(d.toHide.size())if(d.toShow.size()){var e=d.toShow.css("overflow"),h=0,g={},i={},b;c=d.toShow;b=c[0].style.width;c.width(parseInt(c.parent().width(),10)-parseInt(c.css("paddingLeft"),10)-parseInt(c.css("paddingRight"),10)-(parseInt(c.css("borderLeftWidth"),10)||0)-(parseInt(c.css("borderRightWidth"),10)||0));a.each(["height","paddingTop","paddingBottom"],function(f,j){i[j]="hide";f=(""+a.css(d.toShow[0],j)).match(/^([\d+-.]+)(.*)$/); -g[j]={value:f[1],unit:f[2]||"px"}});d.toShow.css({height:0,overflow:"hidden"}).show();d.toHide.filter(":hidden").each(d.complete).end().filter(":visible").animate(i,{step:function(f,j){if(j.prop=="height")h=j.end-j.start===0?0:(j.now-j.start)/(j.end-j.start);d.toShow[0].style[j.prop]=h*g[j.prop].value+g[j.prop].unit},duration:d.duration,easing:d.easing,complete:function(){d.autoHeight||d.toShow.css("height","");d.toShow.css({width:b,overflow:e});d.complete()}})}else d.toHide.animate({height:"hide", -paddingTop:"hide",paddingBottom:"hide"},d);else d.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},d)},bounceslide:function(d){this.slide(d,{easing:d.down?"easeOutBounce":"swing",duration:d.down?1E3:200})}}})})(jQuery); -(function(a){var d=0;a.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var c=this,e=this.element[0].ownerDocument,h;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(g){if(!(c.options.disabled||c.element.propAttr("readOnly"))){h= -false;var i=a.ui.keyCode;switch(g.keyCode){case i.PAGE_UP:c._move("previousPage",g);break;case i.PAGE_DOWN:c._move("nextPage",g);break;case i.UP:c._move("previous",g);g.preventDefault();break;case i.DOWN:c._move("next",g);g.preventDefault();break;case i.ENTER:case i.NUMPAD_ENTER:if(c.menu.active){h=true;g.preventDefault()}case i.TAB:if(!c.menu.active)return;c.menu.select(g);break;case i.ESCAPE:c.element.val(c.term);c.close(g);break;default:clearTimeout(c.searching);c.searching=setTimeout(function(){if(c.term!= -c.element.val()){c.selectedItem=null;c.search(null,g)}},c.options.delay);break}}}).bind("keypress.autocomplete",function(g){if(h){h=false;g.preventDefault()}}).bind("focus.autocomplete",function(){if(!c.options.disabled){c.selectedItem=null;c.previous=c.element.val()}}).bind("blur.autocomplete",function(g){if(!c.options.disabled){clearTimeout(c.searching);c.closing=setTimeout(function(){c.close(g);c._change(g)},150)}});this._initSource();this.response=function(){return c._response.apply(c,arguments)}; -this.menu=a("
          ").addClass("ui-autocomplete").appendTo(a(this.options.appendTo||"body",e)[0]).mousedown(function(g){var i=c.menu.element[0];a(g.target).closest(".ui-menu-item").length||setTimeout(function(){a(document).one("mousedown",function(b){b.target!==c.element[0]&&b.target!==i&&!a.ui.contains(i,b.target)&&c.close()})},1);setTimeout(function(){clearTimeout(c.closing)},13)}).menu({focus:function(g,i){i=i.item.data("item.autocomplete");false!==c._trigger("focus",g,{item:i})&&/^key/.test(g.originalEvent.type)&& -c.element.val(i.value)},selected:function(g,i){var b=i.item.data("item.autocomplete"),f=c.previous;if(c.element[0]!==e.activeElement){c.element.focus();c.previous=f;setTimeout(function(){c.previous=f;c.selectedItem=b},1)}false!==c._trigger("select",g,{item:b})&&c.element.val(b.value);c.term=c.element.val();c.close(g);c.selectedItem=b},blur:function(){c.menu.element.is(":visible")&&c.element.val()!==c.term&&c.element.val(c.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"); -a.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();a.Widget.prototype.destroy.call(this)},_setOption:function(c,e){a.Widget.prototype._setOption.apply(this,arguments);c==="source"&&this._initSource();if(c==="appendTo")this.menu.element.appendTo(a(e||"body",this.element[0].ownerDocument)[0]);c==="disabled"&& -e&&this.xhr&&this.xhr.abort()},_initSource:function(){var c=this,e,h;if(a.isArray(this.options.source)){e=this.options.source;this.source=function(g,i){i(a.ui.autocomplete.filter(e,g.term))}}else if(typeof this.options.source==="string"){h=this.options.source;this.source=function(g,i){c.xhr&&c.xhr.abort();c.xhr=a.ajax({url:h,data:g,dataType:"json",autocompleteRequest:++d,success:function(b){this.autocompleteRequest===d&&i(b)},error:function(){this.autocompleteRequest===d&&i([])}})}}else this.source= -this.options.source},search:function(c,e){c=c!=null?c:this.element.val();this.term=this.element.val();if(c.length
        • ").data("item.autocomplete",e).append(a("").text(e.label)).appendTo(c)},_move:function(c,e){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(c)||this.menu.last()&&/^next/.test(c)){this.element.val(this.term);this.menu.deactivate()}else this.menu[c](e);else this.search(null,e)},widget:function(){return this.menu.element}});a.extend(a.ui.autocomplete,{escapeRegex:function(c){return c.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, -"\\$&")},filter:function(c,e){var h=new RegExp(a.ui.autocomplete.escapeRegex(e),"i");return a.grep(c,function(g){return h.test(g.label||g.value||g)})}})})(jQuery); -(function(a){a.widget("ui.menu",{_create:function(){var d=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){if(a(c.target).closest(".ui-menu-item a").length){c.preventDefault();d.select(c)}});this.refresh()},refresh:function(){var d=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", --1).mouseenter(function(c){d.activate(c,a(this).parent())}).mouseleave(function(){d.deactivate()})},activate:function(d,c){this.deactivate();if(this.hasScroll()){var e=c.offset().top-this.element.offset().top,h=this.element.scrollTop(),g=this.element.height();if(e<0)this.element.scrollTop(h+e);else e>=g&&this.element.scrollTop(h+e-g+c.height())}this.active=c.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",d,{item:c})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); -this._trigger("blur");this.active=null}},next:function(d){this.move("next",".ui-menu-item:first",d)},previous:function(d){this.move("prev",".ui-menu-item:last",d)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(d,c,e){if(this.active){d=this.active[d+"All"](".ui-menu-item").eq(0);d.length?this.activate(e,d):this.activate(e,this.element.children(c))}else this.activate(e, -this.element.children(c))},nextPage:function(d){if(this.hasScroll())if(!this.active||this.last())this.activate(d,this.element.children(".ui-menu-item:first"));else{var c=this.active.offset().top,e=this.element.height(),h=this.element.children(".ui-menu-item").filter(function(){var g=a(this).offset().top-c-e+a(this).height();return g<10&&g>-10});h.length||(h=this.element.children(".ui-menu-item:last"));this.activate(d,h)}else this.activate(d,this.element.children(".ui-menu-item").filter(!this.active|| -this.last()?":first":":last"))},previousPage:function(d){if(this.hasScroll())if(!this.active||this.first())this.activate(d,this.element.children(".ui-menu-item:last"));else{var c=this.active.offset().top,e=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var h=a(this).offset().top-c+e-a(this).height();return h<10&&h>-10});result.length||(result=this.element.children(".ui-menu-item:first"));this.activate(d,result)}else this.activate(d,this.element.children(".ui-menu-item").filter(!this.active|| -this.first()?":last":":first"))},hasScroll:function(){return this.element.height()").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),j=this.options.icons,l=j.primary&&j.secondary,o=[];if(j.primary||j.secondary){if(this.options.text)o.push("ui-button-text-icon"+(l?"s":j.primary?"-primary":"-secondary"));j.primary&&b.prepend("");j.secondary&&b.append("");if(!this.options.text){o.push(l?"ui-button-icons-only": -"ui-button-icon-only");this.hasTitle||b.attr("title",f)}}else o.push("ui-button-text-only");b.addClass(o.join(" "))}}});a.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,f){b==="disabled"&&this.buttons.button("option",b,f);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var b=this.element.css("direction")=== -"ltr";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(b?"ui-corner-left":"ui-corner-right").end().filter(":last").addClass(b?"ui-corner-right":"ui-corner-left").end().end()},destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"); -a.Widget.prototype.destroy.call(this)}})})(jQuery); -(function(a,d){function c(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass= -"ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su", -"Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10", -minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false,disabled:false};a.extend(this._defaults,this.regional[""]);this.dpDiv=e(a('
          '))}function e(b){return b.bind("mouseout", -function(f){f=a(f.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");f.length&&f.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(f){f=a(f.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");if(!(a.datepicker._isDisabledDatepicker(i.inline?b.parent()[0]:i.input[0])||!f.length)){f.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); -f.addClass("ui-state-hover");f.hasClass("ui-datepicker-prev")&&f.addClass("ui-datepicker-prev-hover");f.hasClass("ui-datepicker-next")&&f.addClass("ui-datepicker-next-hover")}})}function h(b,f){a.extend(b,f);for(var j in f)if(f[j]==null||f[j]==d)b[j]=f[j];return b}a.extend(a.ui,{datepicker:{version:"1.8.16"}});var g=(new Date).getTime(),i;a.extend(c.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv}, -setDefaults:function(b){h(this._defaults,b||{});return this},_attachDatepicker:function(b,f){var j=null;for(var l in this._defaults){var o=b.getAttribute("date:"+l);if(o){j=j||{};try{j[l]=eval(o)}catch(n){j[l]=o}}}l=b.nodeName.toLowerCase();o=l=="div"||l=="span";if(!b.id){this.uuid+=1;b.id="dp"+this.uuid}var k=this._newInst(a(b),o);k.settings=a.extend({},f||{},j||{});if(l=="input")this._connectDatepicker(b,k);else o&&this._inlineDatepicker(b,k)},_newInst:function(b,f){return{id:b[0].id.replace(/([^A-Za-z0-9_-])/g, -"\\\\$1"),input:b,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:f,dpDiv:!f?this.dpDiv:e(a('
          '))}},_connectDatepicker:function(b,f){var j=a(b);f.append=a([]);f.trigger=a([]);if(!j.hasClass(this.markerClassName)){this._attachments(j,f);j.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker", -function(l,o,n){f.settings[o]=n}).bind("getData.datepicker",function(l,o){return this._get(f,o)});this._autoSize(f);a.data(b,"datepicker",f);f.settings.disabled&&this._disableDatepicker(b)}},_attachments:function(b,f){var j=this._get(f,"appendText"),l=this._get(f,"isRTL");f.append&&f.append.remove();if(j){f.append=a(''+j+"");b[l?"before":"after"](f.append)}b.unbind("focus",this._showDatepicker);f.trigger&&f.trigger.remove();j=this._get(f,"showOn");if(j== -"focus"||j=="both")b.focus(this._showDatepicker);if(j=="button"||j=="both"){j=this._get(f,"buttonText");var o=this._get(f,"buttonImage");f.trigger=a(this._get(f,"buttonImageOnly")?a("").addClass(this._triggerClass).attr({src:o,alt:j,title:j}):a('').addClass(this._triggerClass).html(o==""?j:a("").attr({src:o,alt:j,title:j})));b[l?"before":"after"](f.trigger);f.trigger.click(function(){a.datepicker._datepickerShowing&&a.datepicker._lastInput==b[0]?a.datepicker._hideDatepicker(): -a.datepicker._showDatepicker(b[0]);return false})}},_autoSize:function(b){if(this._get(b,"autoSize")&&!b.inline){var f=new Date(2009,11,20),j=this._get(b,"dateFormat");if(j.match(/[DM]/)){var l=function(o){for(var n=0,k=0,m=0;mn){n=o[m].length;k=m}return k};f.setMonth(l(this._get(b,j.match(/MM/)?"monthNames":"monthNamesShort")));f.setDate(l(this._get(b,j.match(/DD/)?"dayNames":"dayNamesShort"))+20-f.getDay())}b.input.attr("size",this._formatDate(b,f).length)}},_inlineDatepicker:function(b, -f){var j=a(b);if(!j.hasClass(this.markerClassName)){j.addClass(this.markerClassName).append(f.dpDiv).bind("setData.datepicker",function(l,o,n){f.settings[o]=n}).bind("getData.datepicker",function(l,o){return this._get(f,o)});a.data(b,"datepicker",f);this._setDate(f,this._getDefaultDate(f),true);this._updateDatepicker(f);this._updateAlternate(f);f.settings.disabled&&this._disableDatepicker(b);f.dpDiv.css("display","block")}},_dialogDatepicker:function(b,f,j,l,o){b=this._dialogInst;if(!b){this.uuid+= -1;this._dialogInput=a('');this._dialogInput.keydown(this._doKeyDown);a("body").append(this._dialogInput);b=this._dialogInst=this._newInst(this._dialogInput,false);b.settings={};a.data(this._dialogInput[0],"datepicker",b)}h(b.settings,l||{});f=f&&f.constructor==Date?this._formatDate(b,f):f;this._dialogInput.val(f);this._pos=o?o.length?o:[o.pageX,o.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/ -2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");b.settings.onSelect=j;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);a.blockUI&&a.blockUI(this.dpDiv);a.data(this._dialogInput[0],"datepicker",b);return this},_destroyDatepicker:function(b){var f= -a(b),j=a.data(b,"datepicker");if(f.hasClass(this.markerClassName)){var l=b.nodeName.toLowerCase();a.removeData(b,"datepicker");if(l=="input"){j.append.remove();j.trigger.remove();f.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(l=="div"||l=="span")f.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(b){var f=a(b),j=a.data(b,"datepicker");if(f.hasClass(this.markerClassName)){var l= -b.nodeName.toLowerCase();if(l=="input"){b.disabled=false;j.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(l=="div"||l=="span"){f=f.children("."+this._inlineClass);f.children().removeClass("ui-state-disabled");f.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=a.map(this._disabledInputs,function(o){return o==b?null:o})}},_disableDatepicker:function(b){var f=a(b),j=a.data(b, -"datepicker");if(f.hasClass(this.markerClassName)){var l=b.nodeName.toLowerCase();if(l=="input"){b.disabled=true;j.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(l=="div"||l=="span"){f=f.children("."+this._inlineClass);f.children().addClass("ui-state-disabled");f.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=a.map(this._disabledInputs,function(o){return o== -b?null:o});this._disabledInputs[this._disabledInputs.length]=b}},_isDisabledDatepicker:function(b){if(!b)return false;for(var f=0;f-1}},_doKeyUp:function(b){b=a.datepicker._getInst(b.target);if(b.input.val()!=b.lastVal)try{if(a.datepicker.parseDate(a.datepicker._get(b,"dateFormat"),b.input?b.input.val():null,a.datepicker._getFormatConfig(b))){a.datepicker._setDateFromField(b);a.datepicker._updateAlternate(b);a.datepicker._updateDatepicker(b)}}catch(f){a.datepicker.log(f)}return true},_showDatepicker:function(b){b=b.target||b;if(b.nodeName.toLowerCase()!="input")b=a("input", -b.parentNode)[0];if(!(a.datepicker._isDisabledDatepicker(b)||a.datepicker._lastInput==b)){var f=a.datepicker._getInst(b);if(a.datepicker._curInst&&a.datepicker._curInst!=f){a.datepicker._datepickerShowing&&a.datepicker._triggerOnClose(a.datepicker._curInst);a.datepicker._curInst.dpDiv.stop(true,true)}var j=a.datepicker._get(f,"beforeShow");j=j?j.apply(b,[b,f]):{};if(j!==false){h(f.settings,j);f.lastVal=null;a.datepicker._lastInput=b;a.datepicker._setDateFromField(f);if(a.datepicker._inDialog)b.value= -"";if(!a.datepicker._pos){a.datepicker._pos=a.datepicker._findPos(b);a.datepicker._pos[1]+=b.offsetHeight}var l=false;a(b).parents().each(function(){l|=a(this).css("position")=="fixed";return!l});if(l&&a.browser.opera){a.datepicker._pos[0]-=document.documentElement.scrollLeft;a.datepicker._pos[1]-=document.documentElement.scrollTop}j={left:a.datepicker._pos[0],top:a.datepicker._pos[1]};a.datepicker._pos=null;f.dpDiv.empty();f.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});a.datepicker._updateDatepicker(f); -j=a.datepicker._checkOffset(f,j,l);f.dpDiv.css({position:a.datepicker._inDialog&&a.blockUI?"static":l?"fixed":"absolute",display:"none",left:j.left+"px",top:j.top+"px"});if(!f.inline){j=a.datepicker._get(f,"showAnim");var o=a.datepicker._get(f,"duration"),n=function(){var k=f.dpDiv.find("iframe.ui-datepicker-cover");if(k.length){var m=a.datepicker._getBorders(f.dpDiv);k.css({left:-m[0],top:-m[1],width:f.dpDiv.outerWidth(),height:f.dpDiv.outerHeight()})}};f.dpDiv.zIndex(a(b).zIndex()+1);a.datepicker._datepickerShowing= -true;a.effects&&a.effects[j]?f.dpDiv.show(j,a.datepicker._get(f,"showOptions"),o,n):f.dpDiv[j||"show"](j?o:null,n);if(!j||!o)n();f.input.is(":visible")&&!f.input.is(":disabled")&&f.input.focus();a.datepicker._curInst=f}}}},_updateDatepicker:function(b){this.maxRows=4;var f=a.datepicker._getBorders(b.dpDiv);i=b;b.dpDiv.empty().append(this._generateHTML(b));var j=b.dpDiv.find("iframe.ui-datepicker-cover");j.length&&j.css({left:-f[0],top:-f[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()}); -b.dpDiv.find("."+this._dayOverClass+" a").mouseover();f=this._getNumberOfMonths(b);j=f[1];b.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");j>1&&b.dpDiv.addClass("ui-datepicker-multi-"+j).css("width",17*j+"em");b.dpDiv[(f[0]!=1||f[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");b.dpDiv[(this._get(b,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");b==a.datepicker._curInst&&a.datepicker._datepickerShowing&&b.input&&b.input.is(":visible")&& -!b.input.is(":disabled")&&b.input[0]!=document.activeElement&&b.input.focus();if(b.yearshtml){var l=b.yearshtml;setTimeout(function(){l===b.yearshtml&&b.yearshtml&&b.dpDiv.find("select.ui-datepicker-year:first").replaceWith(b.yearshtml);l=b.yearshtml=null},0)}},_getBorders:function(b){var f=function(j){return{thin:1,medium:2,thick:3}[j]||j};return[parseFloat(f(b.css("border-left-width"))),parseFloat(f(b.css("border-top-width")))]},_checkOffset:function(b,f,j){var l=b.dpDiv.outerWidth(),o=b.dpDiv.outerHeight(), -n=b.input?b.input.outerWidth():0,k=b.input?b.input.outerHeight():0,m=document.documentElement.clientWidth+a(document).scrollLeft(),p=document.documentElement.clientHeight+a(document).scrollTop();f.left-=this._get(b,"isRTL")?l-n:0;f.left-=j&&f.left==b.input.offset().left?a(document).scrollLeft():0;f.top-=j&&f.top==b.input.offset().top+k?a(document).scrollTop():0;f.left-=Math.min(f.left,f.left+l>m&&m>l?Math.abs(f.left+l-m):0);f.top-=Math.min(f.top,f.top+o>p&&p>o?Math.abs(o+k):0);return f},_findPos:function(b){for(var f= -this._get(this._getInst(b),"isRTL");b&&(b.type=="hidden"||b.nodeType!=1||a.expr.filters.hidden(b));)b=b[f?"previousSibling":"nextSibling"];b=a(b).offset();return[b.left,b.top]},_triggerOnClose:function(b){var f=this._get(b,"onClose");if(f)f.apply(b.input?b.input[0]:null,[b.input?b.input.val():"",b])},_hideDatepicker:function(b){var f=this._curInst;if(!(!f||b&&f!=a.data(b,"datepicker")))if(this._datepickerShowing){b=this._get(f,"showAnim");var j=this._get(f,"duration"),l=function(){a.datepicker._tidyDialog(f); -this._curInst=null};a.effects&&a.effects[b]?f.dpDiv.hide(b,a.datepicker._get(f,"showOptions"),j,l):f.dpDiv[b=="slideDown"?"slideUp":b=="fadeIn"?"fadeOut":"hide"](b?j:null,l);b||l();a.datepicker._triggerOnClose(f);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(a.blockUI){a.unblockUI();a("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(b){b.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")}, -_checkExternalClick:function(b){if(a.datepicker._curInst){b=a(b.target);b[0].id!=a.datepicker._mainDivId&&b.parents("#"+a.datepicker._mainDivId).length==0&&!b.hasClass(a.datepicker.markerClassName)&&!b.hasClass(a.datepicker._triggerClass)&&a.datepicker._datepickerShowing&&!(a.datepicker._inDialog&&a.blockUI)&&a.datepicker._hideDatepicker()}},_adjustDate:function(b,f,j){b=a(b);var l=this._getInst(b[0]);if(!this._isDisabledDatepicker(b[0])){this._adjustInstDate(l,f+(j=="M"?this._get(l,"showCurrentAtPos"): -0),j);this._updateDatepicker(l)}},_gotoToday:function(b){b=a(b);var f=this._getInst(b[0]);if(this._get(f,"gotoCurrent")&&f.currentDay){f.selectedDay=f.currentDay;f.drawMonth=f.selectedMonth=f.currentMonth;f.drawYear=f.selectedYear=f.currentYear}else{var j=new Date;f.selectedDay=j.getDate();f.drawMonth=f.selectedMonth=j.getMonth();f.drawYear=f.selectedYear=j.getFullYear()}this._notifyChange(f);this._adjustDate(b)},_selectMonthYear:function(b,f,j){b=a(b);var l=this._getInst(b[0]);l["selected"+(j=="M"? -"Month":"Year")]=l["draw"+(j=="M"?"Month":"Year")]=parseInt(f.options[f.selectedIndex].value,10);this._notifyChange(l);this._adjustDate(b)},_selectDay:function(b,f,j,l){var o=a(b);if(!(a(l).hasClass(this._unselectableClass)||this._isDisabledDatepicker(o[0]))){o=this._getInst(o[0]);o.selectedDay=o.currentDay=a("a",l).html();o.selectedMonth=o.currentMonth=f;o.selectedYear=o.currentYear=j;this._selectDate(b,this._formatDate(o,o.currentDay,o.currentMonth,o.currentYear))}},_clearDate:function(b){b=a(b); -this._getInst(b[0]);this._selectDate(b,"")},_selectDate:function(b,f){b=this._getInst(a(b)[0]);f=f!=null?f:this._formatDate(b);b.input&&b.input.val(f);this._updateAlternate(b);var j=this._get(b,"onSelect");if(j)j.apply(b.input?b.input[0]:null,[f,b]);else b.input&&b.input.trigger("change");if(b.inline)this._updateDatepicker(b);else{this._hideDatepicker();this._lastInput=b.input[0];typeof b.input[0]!="object"&&b.input.focus();this._lastInput=null}},_updateAlternate:function(b){var f=this._get(b,"altField"); -if(f){var j=this._get(b,"altFormat")||this._get(b,"dateFormat"),l=this._getDate(b),o=this.formatDate(j,l,this._getFormatConfig(b));a(f).each(function(){a(this).val(o)})}},noWeekends:function(b){b=b.getDay();return[b>0&&b<6,""]},iso8601Week:function(b){b=new Date(b.getTime());b.setDate(b.getDate()+4-(b.getDay()||7));var f=b.getTime();b.setMonth(0);b.setDate(1);return Math.floor(Math.round((f-b)/864E5)/7)+1},parseDate:function(b,f,j){if(b==null||f==null)throw"Invalid arguments";f=typeof f=="object"? -f.toString():f+"";if(f=="")return null;var l=(j?j.shortYearCutoff:null)||this._defaults.shortYearCutoff;l=typeof l!="string"?l:(new Date).getFullYear()%100+parseInt(l,10);for(var o=(j?j.dayNamesShort:null)||this._defaults.dayNamesShort,n=(j?j.dayNames:null)||this._defaults.dayNames,k=(j?j.monthNamesShort:null)||this._defaults.monthNamesShort,m=(j?j.monthNames:null)||this._defaults.monthNames,p=j=-1,q=-1,s=-1,r=false,u=function(z){(z=H+1-1){p=1;q=s;do{l=this._getDaysInMonth(j,p-1);if(q<=l)break;p++;q-=l}while(1)}C=this._daylightSavingAdjust(new Date(j,p-1,q));if(C.getFullYear()!=j||C.getMonth()+1!=p||C.getDate()!=q)throw"Invalid date";return C},ATOM:"yy-mm-dd", -COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(b,f,j){if(!f)return"";var l=(j?j.dayNamesShort:null)||this._defaults.dayNamesShort,o=(j?j.dayNames:null)||this._defaults.dayNames,n=(j?j.monthNamesShort:null)||this._defaults.monthNamesShort;j=(j?j.monthNames: -null)||this._defaults.monthNames;var k=function(u){(u=r+1 -12?b.getHours()+2:0);return b},_setDate:function(b,f,j){var l=!f,o=b.selectedMonth,n=b.selectedYear;f=this._restrictMinMax(b,this._determineDate(b,f,new Date));b.selectedDay=b.currentDay=f.getDate();b.drawMonth=b.selectedMonth=b.currentMonth=f.getMonth();b.drawYear=b.selectedYear=b.currentYear=f.getFullYear();if((o!=b.selectedMonth||n!=b.selectedYear)&&!j)this._notifyChange(b);this._adjustInstDate(b);if(b.input)b.input.val(l?"":this._formatDate(b))},_getDate:function(b){return!b.currentYear||b.input&& -b.input.val()==""?null:this._daylightSavingAdjust(new Date(b.currentYear,b.currentMonth,b.currentDay))},_generateHTML:function(b){var f=new Date;f=this._daylightSavingAdjust(new Date(f.getFullYear(),f.getMonth(),f.getDate()));var j=this._get(b,"isRTL"),l=this._get(b,"showButtonPanel"),o=this._get(b,"hideIfNoPrevNext"),n=this._get(b,"navigationAsDateFormat"),k=this._getNumberOfMonths(b),m=this._get(b,"showCurrentAtPos"),p=this._get(b,"stepMonths"),q=k[0]!=1||k[1]!=1,s=this._daylightSavingAdjust(!b.currentDay? -new Date(9999,9,9):new Date(b.currentYear,b.currentMonth,b.currentDay)),r=this._getMinMaxDate(b,"min"),u=this._getMinMaxDate(b,"max");m=b.drawMonth-m;var v=b.drawYear;if(m<0){m+=12;v--}if(u){var w=this._daylightSavingAdjust(new Date(u.getFullYear(),u.getMonth()-k[0]*k[1]+1,u.getDate()));for(w=r&&ww;){m--;if(m<0){m=11;v--}}}b.drawMonth=m;b.drawYear=v;w=this._get(b,"prevText");w=!n?w:this.formatDate(w,this._daylightSavingAdjust(new Date(v,m-p,1)),this._getFormatConfig(b)); -w=this._canAdjustMonth(b,-1,v,m)?''+w+"":o?"":''+w+"";var x=this._get(b,"nextText");x=!n?x:this.formatDate(x,this._daylightSavingAdjust(new Date(v, -m+p,1)),this._getFormatConfig(b));o=this._canAdjustMonth(b,+1,v,m)?''+x+"":o?"":''+x+"";p=this._get(b,"currentText");x=this._get(b,"gotoCurrent")&& -b.currentDay?s:f;p=!n?p:this.formatDate(p,x,this._getFormatConfig(b));n=!b.inline?'":"";l=l?'
          '+(j?n:"")+(this._isInRange(b,x)?'":"")+(j?"":n)+"
          ":"";n=parseInt(this._get(b,"firstDay"),10);n=isNaN(n)?0:n;p=this._get(b,"showWeek");x=this._get(b,"dayNames");this._get(b,"dayNamesShort");var y=this._get(b,"dayNamesMin"),H=this._get(b,"monthNames"),C=this._get(b,"monthNamesShort"),z=this._get(b,"beforeShowDay"),I=this._get(b,"showOtherMonths"),N=this._get(b,"selectOtherMonths");this._get(b,"calculateWeek");for(var J=this._getDefaultDate(b),D="",E=0;E1)switch(L){case 0:F+=" ui-datepicker-group-first";B=" ui-corner-"+(j?"right":"left");break;case k[1]-1:F+=" ui-datepicker-group-last";B=" ui-corner-"+(j?"left":"right");break;default:F+=" ui-datepicker-group-middle";B="";break}F+='">'}F+='
          '+(/all|left/.test(B)&& -E==0?j?o:w:"")+(/all|right/.test(B)&&E==0?j?w:o:"")+this._generateMonthYearHeader(b,m,v,r,u,E>0||L>0,H,C)+'
          ';var G=p?'":"";for(B=0;B<7;B++){var A=(B+n)%7;G+="=5?' class="ui-datepicker-week-end"':"")+'>'+y[A]+""}F+=G+"";G=this._getDaysInMonth(v,m);if(v==b.selectedYear&&m==b.selectedMonth)b.selectedDay=Math.min(b.selectedDay, -G);B=(this._getFirstDayOfMonth(v,m)-n+7)%7;G=Math.ceil((B+G)/7);this.maxRows=G=q?this.maxRows>G?this.maxRows:G:G;A=this._daylightSavingAdjust(new Date(v,m,1-B));for(var R=0;R";var S=!p?"":'";for(B=0;B<7;B++){var M=z?z.apply(b.input?b.input[0]:null,[A]):[true,""],K=A.getMonth()!=m,O=K&&!N||!M[0]||r&&Au;S+='";A.setDate(A.getDate()+1);A=this._daylightSavingAdjust(A)}F+=S+""}m++;if(m>11){m=0;v++}F+="
          '+this._get(b,"weekHeader")+"
          '+this._get(b,"calculateWeek")(A)+""+(K&&!I?" ":O?''+ -A.getDate()+"":''+A.getDate()+"")+"
          "+(q?"
        "+(k[0]>0&&L==k[1]-1?'
        ':""):"");P+=F}D+=P}D+=l+(a.browser.msie&&parseInt(a.browser.version,10)<7&&!b.inline?'': -"");b._keyEvent=false;return D},_generateMonthYearHeader:function(b,f,j,l,o,n,k,m){var p=this._get(b,"changeMonth"),q=this._get(b,"changeYear"),s=this._get(b,"showMonthAfterYear"),r='
        ',u="";if(n||!p)u+=''+k[f]+"";else{k=l&&l.getFullYear()==j;var v=o&&o.getFullYear()==j;u+='"}s||(r+=u+(n||!(p&&q)?" ":""));if(!b.yearshtml){b.yearshtml="";if(n||!q)r+=''+j+"";else{m=this._get(b,"yearRange").split(":");var x=(new Date).getFullYear();k=function(y){y=y.match(/c[+-].*/)?j+parseInt(y.substring(1),10):y.match(/[+-].*/)?x+parseInt(y,10):parseInt(y,10);return isNaN(y)?x:y};f=k(m[0]);m=Math.max(f,k(m[1]||""));f=l?Math.max(f, -l.getFullYear()):f;m=o?Math.min(m,o.getFullYear()):m;for(b.yearshtml+='";r+=b.yearshtml;b.yearshtml=null}}r+=this._get(b,"yearSuffix");if(s)r+=(n||!(p&&q)?" ":"")+u;r+="
        ";return r},_adjustInstDate:function(b,f,j){var l=b.drawYear+(j=="Y"?f:0),o=b.drawMonth+ -(j=="M"?f:0);f=Math.min(b.selectedDay,this._getDaysInMonth(l,o))+(j=="D"?f:0);l=this._restrictMinMax(b,this._daylightSavingAdjust(new Date(l,o,f)));b.selectedDay=l.getDate();b.drawMonth=b.selectedMonth=l.getMonth();b.drawYear=b.selectedYear=l.getFullYear();if(j=="M"||j=="Y")this._notifyChange(b)},_restrictMinMax:function(b,f){var j=this._getMinMaxDate(b,"min");b=this._getMinMaxDate(b,"max");f=j&&fb?b:f},_notifyChange:function(b){var f=this._get(b,"onChangeMonthYear");if(f)f.apply(b.input? -b.input[0]:null,[b.selectedYear,b.selectedMonth+1,b])},_getNumberOfMonths:function(b){b=this._get(b,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(b,f){return this._determineDate(b,this._get(b,f+"Date"),null)},_getDaysInMonth:function(b,f){return 32-this._daylightSavingAdjust(new Date(b,f,32)).getDate()},_getFirstDayOfMonth:function(b,f){return(new Date(b,f,1)).getDay()},_canAdjustMonth:function(b,f,j,l){var o=this._getNumberOfMonths(b);j=this._daylightSavingAdjust(new Date(j, -l+(f<0?f:o[0]*o[1]),1));f<0&&j.setDate(this._getDaysInMonth(j.getFullYear(),j.getMonth()));return this._isInRange(b,j)},_isInRange:function(b,f){var j=this._getMinMaxDate(b,"min");b=this._getMinMaxDate(b,"max");return(!j||f.getTime()>=j.getTime())&&(!b||f.getTime()<=b.getTime())},_getFormatConfig:function(b){var f=this._get(b,"shortYearCutoff");f=typeof f!="string"?f:(new Date).getFullYear()%100+parseInt(f,10);return{shortYearCutoff:f,dayNamesShort:this._get(b,"dayNamesShort"),dayNames:this._get(b, -"dayNames"),monthNamesShort:this._get(b,"monthNamesShort"),monthNames:this._get(b,"monthNames")}},_formatDate:function(b,f,j,l){if(!f){b.currentDay=b.selectedDay;b.currentMonth=b.selectedMonth;b.currentYear=b.selectedYear}f=f?typeof f=="object"?f:this._daylightSavingAdjust(new Date(l,j,f)):this._daylightSavingAdjust(new Date(b.currentYear,b.currentMonth,b.currentDay));return this.formatDate(this._get(b,"dateFormat"),f,this._getFormatConfig(b))}});a.fn.datepicker=function(b){if(!this.length)return this; -if(!a.datepicker.initialized){a(document).mousedown(a.datepicker._checkExternalClick).find("body").append(a.datepicker.dpDiv);a.datepicker.initialized=true}var f=Array.prototype.slice.call(arguments,1);if(typeof b=="string"&&(b=="isDisabled"||b=="getDate"||b=="widget"))return a.datepicker["_"+b+"Datepicker"].apply(a.datepicker,[this[0]].concat(f));if(b=="option"&&arguments.length==2&&typeof arguments[1]=="string")return a.datepicker["_"+b+"Datepicker"].apply(a.datepicker,[this[0]].concat(f));return this.each(function(){typeof b== -"string"?a.datepicker["_"+b+"Datepicker"].apply(a.datepicker,[this].concat(f)):a.datepicker._attachDatepicker(this,b)})};a.datepicker=new c;a.datepicker.initialized=false;a.datepicker.uuid=(new Date).getTime();a.datepicker.version="1.8.16";window["DP_jQuery_"+g]=a})(jQuery); -(function(a,d){var c={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},e={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true},h=a.attrFn||{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true,click:true};a.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false, -position:{my:"center",at:"center",collision:"fit",using:function(g){var i=a(this).css(g).offset().top;i<0&&a(this).css("top",g.top-i)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var g=this,i=g.options,b=i.title||" ",f=a.ui.dialog.getTitleId(g.element),j=(g.uiDialog=a("
        ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ -i.dialogClass).css({zIndex:i.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(n){if(i.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===a.ui.keyCode.ESCAPE){g.close(n);n.preventDefault()}}).attr({role:"dialog","aria-labelledby":f}).mousedown(function(n){g.moveToTop(false,n)});g.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(j);var l=(g.uiDialogTitlebar=a("
        ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(j), -o=a('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){o.addClass("ui-state-hover")},function(){o.removeClass("ui-state-hover")}).focus(function(){o.addClass("ui-state-focus")}).blur(function(){o.removeClass("ui-state-focus")}).click(function(n){g.close(n);return false}).appendTo(l);(g.uiDialogTitlebarCloseText=a("")).addClass("ui-icon ui-icon-closethick").text(i.closeText).appendTo(o);a("").addClass("ui-dialog-title").attr("id", -f).html(b).prependTo(l);if(a.isFunction(i.beforeclose)&&!a.isFunction(i.beforeClose))i.beforeClose=i.beforeclose;l.find("*").add(l).disableSelection();i.draggable&&a.fn.draggable&&g._makeDraggable();i.resizable&&a.fn.resizable&&g._makeResizable();g._createButtons(i.buttons);g._isOpen=false;a.fn.bgiframe&&j.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var g=this;g.overlay&&g.overlay.destroy();g.uiDialog.hide();g.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); -g.uiDialog.remove();g.originalTitle&&g.element.attr("title",g.originalTitle);return g},widget:function(){return this.uiDialog},close:function(g){var i=this,b,f;if(false!==i._trigger("beforeClose",g)){i.overlay&&i.overlay.destroy();i.uiDialog.unbind("keypress.ui-dialog");i._isOpen=false;if(i.options.hide)i.uiDialog.hide(i.options.hide,function(){i._trigger("close",g)});else{i.uiDialog.hide();i._trigger("close",g)}a.ui.dialog.overlay.resize();if(i.options.modal){b=0;a(".ui-dialog").each(function(){if(this!== -i.uiDialog[0]){f=a(this).css("z-index");isNaN(f)||(b=Math.max(b,f))}});a.ui.dialog.maxZ=b}return i}},isOpen:function(){return this._isOpen},moveToTop:function(g,i){var b=this,f=b.options;if(f.modal&&!g||!f.stack&&!f.modal)return b._trigger("focus",i);if(f.zIndex>a.ui.dialog.maxZ)a.ui.dialog.maxZ=f.zIndex;if(b.overlay){a.ui.dialog.maxZ+=1;b.overlay.$el.css("z-index",a.ui.dialog.overlay.maxZ=a.ui.dialog.maxZ)}g={scrollTop:b.element.scrollTop(),scrollLeft:b.element.scrollLeft()};a.ui.dialog.maxZ+=1; -b.uiDialog.css("z-index",a.ui.dialog.maxZ);b.element.attr(g);b._trigger("focus",i);return b},open:function(){if(!this._isOpen){var g=this,i=g.options,b=g.uiDialog;g.overlay=i.modal?new a.ui.dialog.overlay(g):null;g._size();g._position(i.position);b.show(i.show);g.moveToTop(true);i.modal&&b.bind("keypress.ui-dialog",function(f){if(f.keyCode===a.ui.keyCode.TAB){var j=a(":tabbable",this),l=j.filter(":first");j=j.filter(":last");if(f.target===j[0]&&!f.shiftKey){l.focus(1);return false}else if(f.target=== -l[0]&&f.shiftKey){j.focus(1);return false}}});a(g.element.find(":tabbable").get().concat(b.find(".ui-dialog-buttonpane :tabbable").get().concat(b.get()))).eq(0).focus();g._isOpen=true;g._trigger("open");return g}},_createButtons:function(g){var i=this,b=false,f=a("
        ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),j=a("
        ").addClass("ui-dialog-buttonset").appendTo(f);i.uiDialog.find(".ui-dialog-buttonpane").remove();typeof g==="object"&&g!==null&&a.each(g, -function(){return!(b=true)});if(b){a.each(g,function(l,o){o=a.isFunction(o)?{click:o,text:l}:o;var n=a('').click(function(){o.click.apply(i.element[0],arguments)}).appendTo(j);a.each(o,function(k,m){if(k!=="click")k in h?n[k](m):n.attr(k,m)});a.fn.button&&n.button()});f.appendTo(i.uiDialog)}},_makeDraggable:function(){function g(l){return{position:l.position,offset:l.offset}}var i=this,b=i.options,f=a(document),j;i.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close", -handle:".ui-dialog-titlebar",containment:"document",start:function(l,o){j=b.height==="auto"?"auto":a(this).height();a(this).height(a(this).height()).addClass("ui-dialog-dragging");i._trigger("dragStart",l,g(o))},drag:function(l,o){i._trigger("drag",l,g(o))},stop:function(l,o){b.position=[o.position.left-f.scrollLeft(),o.position.top-f.scrollTop()];a(this).removeClass("ui-dialog-dragging").height(j);i._trigger("dragStop",l,g(o));a.ui.dialog.overlay.resize()}})},_makeResizable:function(g){function i(l){return{originalPosition:l.originalPosition, -originalSize:l.originalSize,position:l.position,size:l.size}}g=g===d?this.options.resizable:g;var b=this,f=b.options,j=b.uiDialog.css("position");g=typeof g==="string"?g:"n,e,s,w,se,sw,ne,nw";b.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:b.element,maxWidth:f.maxWidth,maxHeight:f.maxHeight,minWidth:f.minWidth,minHeight:b._minHeight(),handles:g,start:function(l,o){a(this).addClass("ui-dialog-resizing");b._trigger("resizeStart",l,i(o))},resize:function(l,o){b._trigger("resize", -l,i(o))},stop:function(l,o){a(this).removeClass("ui-dialog-resizing");f.height=a(this).height();f.width=a(this).width();b._trigger("resizeStop",l,i(o));a.ui.dialog.overlay.resize()}}).css("position",j).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var g=this.options;return g.height==="auto"?g.minHeight:Math.min(g.minHeight,g.height)},_position:function(g){var i=[],b=[0,0],f;if(g){if(typeof g==="string"||typeof g==="object"&&"0"in g){i=g.split?g.split(" "): -[g[0],g[1]];if(i.length===1)i[1]=i[0];a.each(["left","top"],function(j,l){if(+i[j]===i[j]){b[j]=i[j];i[j]=l}});g={my:i.join(" "),at:i.join(" "),offset:b.join(" ")}}g=a.extend({},a.ui.dialog.prototype.options.position,g)}else g=a.ui.dialog.prototype.options.position;(f=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(a.extend({of:window},g));f||this.uiDialog.hide()},_setOptions:function(g){var i=this,b={},f=false;a.each(g,function(j,l){i._setOption(j,l); -if(j in c)f=true;if(j in e)b[j]=l});f&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",b)},_setOption:function(g,i){var b=this,f=b.uiDialog;switch(g){case "beforeclose":g="beforeClose";break;case "buttons":b._createButtons(i);break;case "closeText":b.uiDialogTitlebarCloseText.text(""+i);break;case "dialogClass":f.removeClass(b.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+i);break;case "disabled":i?f.addClass("ui-dialog-disabled"): -f.removeClass("ui-dialog-disabled");break;case "draggable":var j=f.is(":data(draggable)");j&&!i&&f.draggable("destroy");!j&&i&&b._makeDraggable();break;case "position":b._position(i);break;case "resizable":(j=f.is(":data(resizable)"))&&!i&&f.resizable("destroy");j&&typeof i==="string"&&f.resizable("option","handles",i);!j&&i!==false&&b._makeResizable(i);break;case "title":a(".ui-dialog-title",b.uiDialogTitlebar).html(""+(i||" "));break}a.Widget.prototype._setOption.apply(b,arguments)},_size:function(){var g= -this.options,i,b,f=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(g.minWidth>g.width)g.width=g.minWidth;i=this.uiDialog.css({height:"auto",width:g.width}).height();b=Math.max(0,g.minHeight-i);if(g.height==="auto")if(a.support.minHeight)this.element.css({minHeight:b,height:"auto"});else{this.uiDialog.show();g=this.element.css("height","auto").height();f||this.uiDialog.hide();this.element.height(Math.max(g,b))}else this.element.height(Math.max(g.height- -i,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});a.extend(a.ui.dialog,{version:"1.8.16",uuid:0,maxZ:0,getTitleId:function(g){g=g.attr("id");if(!g){this.uuid+=1;g=this.uuid}return"ui-dialog-title-"+g},overlay:function(g){this.$el=a.ui.dialog.overlay.create(g)}});a.extend(a.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:a.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(g){return g+".dialog-overlay"}).join(" "), -create:function(g){if(this.instances.length===0){setTimeout(function(){a.ui.dialog.overlay.instances.length&&a(document).bind(a.ui.dialog.overlay.events,function(b){if(a(b.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});a.fn.bgiframe&&i.bgiframe();this.instances.push(i);return i},destroy:function(g){var i=a.inArray(g,this.instances);i!=-1&&this.oldInstances.push(this.instances.splice(i,1)[0]);this.instances.length===0&&a([document,window]).unbind(".dialog-overlay");g.remove();var b=0;a.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var g,i;if(a.browser.msie&& -a.browser.version<7){g=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);i=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return g0?g.left-b:Math.max(g.left-i.collisionPosition.left,g.left)},top:function(g,i){var b=a(window);b=i.collisionPosition.top+i.collisionHeight-b.height()-b.scrollTop();g.top=b>0?g.top-b:Math.max(g.top-i.collisionPosition.top,g.top)}},flip:{left:function(g,i){if(i.at[0]!=="center"){var b=a(window);b=i.collisionPosition.left+i.collisionWidth-b.width()-b.scrollLeft();var f=i.my[0]==="left"?-i.elemWidth:i.my[0]==="right"?i.elemWidth:0,j=i.at[0]==="left"?i.targetWidth:-i.targetWidth,l=-2*i.offset[0];g.left+= -i.collisionPosition.left<0?f+j+l:b>0?f+j+l:0}},top:function(g,i){if(i.at[1]!=="center"){var b=a(window);b=i.collisionPosition.top+i.collisionHeight-b.height()-b.scrollTop();var f=i.my[1]==="top"?-i.elemHeight:i.my[1]==="bottom"?i.elemHeight:0,j=i.at[1]==="top"?i.targetHeight:-i.targetHeight,l=-2*i.offset[1];g.top+=i.collisionPosition.top<0?f+j+l:b>0?f+j+l:0}}}};if(!a.offset.setOffset){a.offset.setOffset=function(g,i){if(/static/.test(a.curCSS(g,"position")))g.style.position="relative";var b=a(g), -f=b.offset(),j=parseInt(a.curCSS(g,"top",true),10)||0,l=parseInt(a.curCSS(g,"left",true),10)||0;f={top:i.top-f.top+j,left:i.left-f.left+l};"using"in i?i.using.call(g,f):b.css(f)};a.fn.offset=function(g){var i=this[0];if(!i||!i.ownerDocument)return null;if(g)return this.each(function(){a.offset.setOffset(this,g)});return h.call(this)}}})(jQuery); -(function(a,d){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()});this.valueDiv=a("
        ").appendTo(this.element);this.oldValue=this._value();this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); -this.valueDiv.remove();a.Widget.prototype.destroy.apply(this,arguments)},value:function(c){if(c===d)return this._value();this._setOption("value",c);return this},_setOption:function(c,e){if(c==="value"){this.options.value=e;this._refreshValue();this._value()===this.options.max&&this._trigger("complete")}a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var c=this.options.value;if(typeof c!=="number")c=0;return Math.min(this.options.max,Math.max(this.min,c))},_percentage:function(){return 100* -this._value()/this.options.max},_refreshValue:function(){var c=this.value(),e=this._percentage();if(this.oldValue!==c){this.oldValue=c;this._trigger("change")}this.valueDiv.toggle(c>this.min).toggleClass("ui-corner-right",c===this.options.max).width(e.toFixed(0)+"%");this.element.attr("aria-valuenow",c)}});a.extend(a.ui.progressbar,{version:"1.8.16"})})(jQuery); -(function(a){a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var d=this,c=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),h=c.values&&c.values.length||1,g=[];this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+ -this.orientation+" ui-widget ui-widget-content ui-corner-all"+(c.disabled?" ui-slider-disabled ui-disabled":""));this.range=a([]);if(c.range){if(c.range===true){if(!c.values)c.values=[this._valueMin(),this._valueMin()];if(c.values.length&&c.values.length!==2)c.values=[c.values[0],c.values[0]]}this.range=a("
        ").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(c.range==="min"||c.range==="max"?" ui-slider-range-"+c.range:""))}for(var i=e.length;i"); -this.handles=e.add(a(g.join("")).appendTo(d.element));this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(b){b.preventDefault()}).hover(function(){c.disabled||a(this).addClass("ui-state-hover")},function(){a(this).removeClass("ui-state-hover")}).focus(function(){if(c.disabled)a(this).blur();else{a(".ui-slider .ui-state-focus").removeClass("ui-state-focus");a(this).addClass("ui-state-focus")}}).blur(function(){a(this).removeClass("ui-state-focus")});this.handles.each(function(b){a(this).data("index.ui-slider-handle", -b)});this.handles.keydown(function(b){var f=true,j=a(this).data("index.ui-slider-handle"),l,o,n;if(!d.options.disabled){switch(b.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.PAGE_UP:case a.ui.keyCode.PAGE_DOWN:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:f=false;if(!d._keySliding){d._keySliding=true;a(this).addClass("ui-state-active");l=d._start(b,j);if(l===false)return}break}n=d.options.step;l=d.options.values&&d.options.values.length? -(o=d.values(j)):(o=d.value());switch(b.keyCode){case a.ui.keyCode.HOME:o=d._valueMin();break;case a.ui.keyCode.END:o=d._valueMax();break;case a.ui.keyCode.PAGE_UP:o=d._trimAlignValue(l+(d._valueMax()-d._valueMin())/5);break;case a.ui.keyCode.PAGE_DOWN:o=d._trimAlignValue(l-(d._valueMax()-d._valueMin())/5);break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(l===d._valueMax())return;o=d._trimAlignValue(l+n);break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(l===d._valueMin())return;o=d._trimAlignValue(l- -n);break}d._slide(b,j,o);return f}}).keyup(function(b){var f=a(this).data("index.ui-slider-handle");if(d._keySliding){d._keySliding=false;d._stop(b,f);d._change(b,f);a(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy(); -return this},_mouseCapture:function(d){var c=this.options,e,h,g,i,b;if(c.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();e=this._normValueFromMouse({x:d.pageX,y:d.pageY});h=this._valueMax()-this._valueMin()+1;i=this;this.handles.each(function(f){var j=Math.abs(e-i.values(f));if(h>j){h=j;g=a(this);b=f}});if(c.range===true&&this.values(1)===c.min){b+=1;g=a(this.handles[b])}if(this._start(d,b)===false)return false; -this._mouseSliding=true;i._handleIndex=b;g.addClass("ui-state-active").focus();c=g.offset();this._clickOffset=!a(d.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:d.pageX-c.left-g.width()/2,top:d.pageY-c.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)};this.handles.hasClass("ui-state-hover")||this._slide(d,b,e);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(d){var c= -this._normValueFromMouse({x:d.pageX,y:d.pageY});this._slide(d,this._handleIndex,c);return false},_mouseStop:function(d){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(d,this._handleIndex);this._change(d,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(d){var c;if(this.orientation==="horizontal"){c= -this.elementSize.width;d=d.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{c=this.elementSize.height;d=d.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}c=d/c;if(c>1)c=1;if(c<0)c=0;if(this.orientation==="vertical")c=1-c;d=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+c*d)},_start:function(d,c){var e={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){e.value=this.values(c); -e.values=this.values()}return this._trigger("start",d,e)},_slide:function(d,c,e){var h;if(this.options.values&&this.options.values.length){h=this.values(c?0:1);if(this.options.values.length===2&&this.options.range===true&&(c===0&&e>h||c===1&&e1){this.options.values[d]=this._trimAlignValue(c);this._refreshValue();this._change(null,d)}else if(arguments.length)if(a.isArray(arguments[0])){e=this.options.values;h=arguments[0];for(g=0;g=this._valueMax())return this._valueMax();var c=this.options.step>0?this.options.step:1,e=(d-this._valueMin())%c;d=d-e;if(Math.abs(e)*2>=c)d+=e>0?c:-c;return parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var d= -this.options.range,c=this.options,e=this,h=!this._animateOff?c.animate:false,g,i={},b,f,j,l;if(this.options.values&&this.options.values.length)this.handles.each(function(o){g=(e.values(o)-e._valueMin())/(e._valueMax()-e._valueMin())*100;i[e.orientation==="horizontal"?"left":"bottom"]=g+"%";a(this).stop(1,1)[h?"animate":"css"](i,c.animate);if(e.options.range===true)if(e.orientation==="horizontal"){if(o===0)e.range.stop(1,1)[h?"animate":"css"]({left:g+"%"},c.animate);if(o===1)e.range[h?"animate":"css"]({width:g- -b+"%"},{queue:false,duration:c.animate})}else{if(o===0)e.range.stop(1,1)[h?"animate":"css"]({bottom:g+"%"},c.animate);if(o===1)e.range[h?"animate":"css"]({height:g-b+"%"},{queue:false,duration:c.animate})}b=g});else{f=this.value();j=this._valueMin();l=this._valueMax();g=l!==j?(f-j)/(l-j)*100:0;i[e.orientation==="horizontal"?"left":"bottom"]=g+"%";this.handle.stop(1,1)[h?"animate":"css"](i,c.animate);if(d==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[h?"animate":"css"]({width:g+"%"}, -c.animate);if(d==="max"&&this.orientation==="horizontal")this.range[h?"animate":"css"]({width:100-g+"%"},{queue:false,duration:c.animate});if(d==="min"&&this.orientation==="vertical")this.range.stop(1,1)[h?"animate":"css"]({height:g+"%"},c.animate);if(d==="max"&&this.orientation==="vertical")this.range[h?"animate":"css"]({height:100-g+"%"},{queue:false,duration:c.animate})}}});a.extend(a.ui.slider,{version:"1.8.16"})})(jQuery); -(function(a,d){function c(){return++h}function e(){return++g}var h=0,g=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
        ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
      • #{label}
      • "},_create:function(){this._tabify(true)},_setOption:function(i,b){if(i=="selected")this.options.collapsible&& -b==this.options.selected||this.select(b);else{this.options[i]=b;this._tabify()}},_tabId:function(i){return i.title&&i.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+c()},_sanitizeSelector:function(i){return i.replace(/:/g,"\\:")},_cookie:function(){var i=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+e());return a.cookie.apply(null,[i].concat(a.makeArray(arguments)))},_ui:function(i,b){return{tab:i,panel:b,index:this.anchors.index(i)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var i= -a(this);i.html(i.data("label.tabs")).removeData("label.tabs")})},_tabify:function(i){function b(r,u){r.css("display","");!a.support.opacity&&u.opacity&&r[0].style.removeAttribute("filter")}var f=this,j=this.options,l=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=a(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return a("a",this)[0]});this.panels=a([]);this.anchors.each(function(r,u){var v=a(u).attr("href"),w=v.split("#")[0],x;if(w&&(w===location.toString().split("#")[0]|| -(x=a("base")[0])&&w===x.href)){v=u.hash;u.href=v}if(l.test(v))f.panels=f.panels.add(f.element.find(f._sanitizeSelector(v)));else if(v&&v!=="#"){a.data(u,"href.tabs",v);a.data(u,"load.tabs",v.replace(/#.*$/,""));v=f._tabId(u);u.href="#"+v;u=f.element.find("#"+v);if(!u.length){u=a(j.panelTemplate).attr("id",v).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(f.panels[r-1]||f.list);u.data("destroy.tabs",true)}f.panels=f.panels.add(u)}else j.disabled.push(r)});if(i){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); -this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(j.selected===d){location.hash&&this.anchors.each(function(r,u){if(u.hash==location.hash){j.selected=r;return false}});if(typeof j.selected!=="number"&&j.cookie)j.selected=parseInt(f._cookie(),10);if(typeof j.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)j.selected= -this.lis.index(this.lis.filter(".ui-tabs-selected"));j.selected=j.selected||(this.lis.length?0:-1)}else if(j.selected===null)j.selected=-1;j.selected=j.selected>=0&&this.anchors[j.selected]||j.selected<0?j.selected:0;j.disabled=a.unique(j.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(r){return f.lis.index(r)}))).sort();a.inArray(j.selected,j.disabled)!=-1&&j.disabled.splice(a.inArray(j.selected,j.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); -if(j.selected>=0&&this.anchors.length){f.element.find(f._sanitizeSelector(f.anchors[j.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(j.selected).addClass("ui-tabs-selected ui-state-active");f.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[j.selected],f.element.find(f._sanitizeSelector(f.anchors[j.selected].hash))[0]))});this.load(j.selected)}a(window).bind("unload",function(){f.lis.add(f.anchors).unbind(".tabs");f.lis=f.anchors=f.panels=null})}else j.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")); -this.element[j.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");j.cookie&&this._cookie(j.selected,j.cookie);i=0;for(var o;o=this.lis[i];i++)a(o)[a.inArray(i,j.disabled)!=-1&&!a(o).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");j.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(j.event!=="mouseover"){var n=function(r,u){u.is(":not(.ui-state-disabled)")&&u.addClass("ui-state-"+r)},k=function(r,u){u.removeClass("ui-state-"+ -r)};this.lis.bind("mouseover.tabs",function(){n("hover",a(this))});this.lis.bind("mouseout.tabs",function(){k("hover",a(this))});this.anchors.bind("focus.tabs",function(){n("focus",a(this).closest("li"))});this.anchors.bind("blur.tabs",function(){k("focus",a(this).closest("li"))})}var m,p;if(j.fx)if(a.isArray(j.fx)){m=j.fx[0];p=j.fx[1]}else m=p=j.fx;var q=p?function(r,u){a(r).closest("li").addClass("ui-tabs-selected ui-state-active");u.hide().removeClass("ui-tabs-hide").animate(p,p.duration||"normal", -function(){b(u,p);f._trigger("show",null,f._ui(r,u[0]))})}:function(r,u){a(r).closest("li").addClass("ui-tabs-selected ui-state-active");u.removeClass("ui-tabs-hide");f._trigger("show",null,f._ui(r,u[0]))},s=m?function(r,u){u.animate(m,m.duration||"normal",function(){f.lis.removeClass("ui-tabs-selected ui-state-active");u.addClass("ui-tabs-hide");b(u,m);f.element.dequeue("tabs")})}:function(r,u){f.lis.removeClass("ui-tabs-selected ui-state-active");u.addClass("ui-tabs-hide");f.element.dequeue("tabs")}; -this.anchors.bind(j.event+".tabs",function(){var r=this,u=a(r).closest("li"),v=f.panels.filter(":not(.ui-tabs-hide)"),w=f.element.find(f._sanitizeSelector(r.hash));if(u.hasClass("ui-tabs-selected")&&!j.collapsible||u.hasClass("ui-state-disabled")||u.hasClass("ui-state-processing")||f.panels.filter(":animated").length||f._trigger("select",null,f._ui(this,w[0]))===false){this.blur();return false}j.selected=f.anchors.index(this);f.abort();if(j.collapsible)if(u.hasClass("ui-tabs-selected")){j.selected= --1;j.cookie&&f._cookie(j.selected,j.cookie);f.element.queue("tabs",function(){s(r,v)}).dequeue("tabs");this.blur();return false}else if(!v.length){j.cookie&&f._cookie(j.selected,j.cookie);f.element.queue("tabs",function(){q(r,w)});f.load(f.anchors.index(this));this.blur();return false}j.cookie&&f._cookie(j.selected,j.cookie);if(w.length){v.length&&f.element.queue("tabs",function(){s(r,v)});f.element.queue("tabs",function(){q(r,w)});f.load(f.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier."; -a.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(i){if(typeof i=="string")i=this.anchors.index(this.anchors.filter("[href$="+i+"]"));return i},destroy:function(){var i=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var b= -a.data(this,"href.tabs");if(b)this.href=b;var f=a(this).unbind(".tabs");a.each(["href","load","cache"],function(j,l){f.removeData(l+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});i.cookie&&this._cookie(null,i.cookie);return this},add:function(i, -b,f){if(f===d)f=this.anchors.length;var j=this,l=this.options;b=a(l.tabTemplate.replace(/#\{href\}/g,i).replace(/#\{label\}/g,b));i=!i.indexOf("#")?i.replace("#",""):this._tabId(a("a",b)[0]);b.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var o=j.element.find("#"+i);o.length||(o=a(l.panelTemplate).attr("id",i).data("destroy.tabs",true));o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(f>=this.lis.length){b.appendTo(this.list);o.appendTo(this.list[0].parentNode)}else{b.insertBefore(this.lis[f]); -o.insertBefore(this.panels[f])}l.disabled=a.map(l.disabled,function(n){return n>=f?++n:n});this._tabify();if(this.anchors.length==1){l.selected=0;b.addClass("ui-tabs-selected ui-state-active");o.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){j._trigger("show",null,j._ui(j.anchors[0],j.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[f],this.panels[f]));return this},remove:function(i){i=this._getIndex(i);var b=this.options,f=this.lis.eq(i).remove(),j=this.panels.eq(i).remove(); -if(f.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(i+(i+1=i?--l:l});this._tabify();this._trigger("remove",null,this._ui(f.find("a")[0],j[0]));return this},enable:function(i){i=this._getIndex(i);var b=this.options;if(a.inArray(i,b.disabled)!=-1){this.lis.eq(i).removeClass("ui-state-disabled");b.disabled=a.grep(b.disabled,function(f){return f!=i});this._trigger("enable",null, -this._ui(this.anchors[i],this.panels[i]));return this}},disable:function(i){i=this._getIndex(i);var b=this.options;if(i!=b.selected){this.lis.eq(i).addClass("ui-state-disabled");b.disabled.push(i);b.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[i],this.panels[i]))}return this},select:function(i){i=this._getIndex(i);if(i==-1)if(this.options.collapsible&&this.options.selected!=-1)i=this.options.selected;else return this;this.anchors.eq(i).trigger(this.options.event+".tabs");return this}, -load:function(i){i=this._getIndex(i);var b=this,f=this.options,j=this.anchors.eq(i)[0],l=a.data(j,"load.tabs");this.abort();if(!l||this.element.queue("tabs").length!==0&&a.data(j,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(i).addClass("ui-state-processing");if(f.spinner){var o=a("span",j);o.data("label.tabs",o.html()).html(f.spinner)}this.xhr=a.ajax(a.extend({},f.ajaxOptions,{url:l,success:function(n,k){b.element.find(b._sanitizeSelector(j.hash)).html(n);b._cleanup();f.cache&&a.data(j, -"cache.tabs",true);b._trigger("load",null,b._ui(b.anchors[i],b.panels[i]));try{f.ajaxOptions.success(n,k)}catch(m){}},error:function(n,k){b._cleanup();b._trigger("load",null,b._ui(b.anchors[i],b.panels[i]));try{f.ajaxOptions.error(n,k,i,j)}catch(m){}}}));b.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this}, -url:function(i,b){this.anchors.eq(i).removeData("cache.tabs").data("load.tabs",b);return this},length:function(){return this.anchors.length}});a.extend(a.ui.tabs,{version:"1.8.16"});a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(i,b){var f=this,j=this.options,l=f._rotate||(f._rotate=function(o){clearTimeout(f.rotation);f.rotation=setTimeout(function(){var n=j.selected;f.select(++n=0)&&i(t,!r)}}),e(function(){var t=document.body,n=t.appendChild(n=document.createElement("div"));n.offsetHeight,e.extend(n.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),e.support.minHeight=n.offsetHeight===100,e.support.selectstart="onselectstart"in n,t.removeChild(n).style.display="none"}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),function(){var t=/msie ([\w.]+)/.exec(navigator.userAgent.toLowerCase())||[];e.ui.ie=t.length?!0:!1,e.ui.ie6=parseFloat(t[1],10)===6}(),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)},isOverAxis:function(e,t,n){return e>t&&e",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u=9||!!t.button?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(e){return this.mouseDelayMet},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("
        "),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};lr(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)a&&(v<0||v0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)10&&i<11,t.innerHTML="",n.removeChild(t)}(),e.uiBackCompat!==!1&&function(e){var n=e.fn.position;e.fn.position=function(r){if(!r||!r.offset)return n.call(this,r);var i=r.offset.split(" "),s=r.at.split(" ");return i.length===1&&(i[1]=i[0]),/^\d/.test(i[0])&&(i[0]="+"+i[0]),/^\d/.test(i[1])&&(i[1]="+"+i[1]),s.length===1&&(/left|center|right/.test(s[0])?s[1]="center":(s[1]=s[0],s[0]="center")),n.call(this,e.extend(r,{at:s[0]+i[0]+" "+s[1]+i[1],offset:t}))}}(jQuery)})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.9.2",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n),r=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset"),this.headers=this.element.find(r.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this._hoverable(this.headers),this._focusable(this.headers),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide(),!r.collapsible&&(r.active===!1||r.active==null)&&(r.active=0),r.active<0&&(r.active+=this.headers.length),this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this._createIcons(),this.refresh(),this.element.attr("role","tablist"),this.headers.attr("role","tab").each(function(n){var r=e(this),i=r.attr("id"),s=r.next(),o=s.attr("id");i||(i=t+"-header-"+n,r.attr("id",i)),o||(o=t+"-panel-"+n,s.attr("id",o)),r.attr("aria-controls",o),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._on(this.headers,{keydown:"_keydown"}),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._setupEvents(r.event)},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&e.css("height","")},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t,n,r=this.options.heightStyle,i=this.element.parent();r==="fill"?(e.support.minHeight||(n=i.css("overflow"),i.css("overflow","hidden")),t=i.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),n&&i.css("overflow",n),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):r==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={};if(!t)return;e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._on(this.headers,n)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()",options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("
          ").addClass("ui-autocomplete").appendTo(this.document.find(this.options.appendTo||"body")[0]).menu({input:e(),role:null}).zIndex(this.element.zIndex()+1).hide().data("menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var n=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(r){r.target!==t.element[0]&&r.target!==n&&!e.contains(n,r.target)&&t.close()})})},menufocus:function(t,n){if(this.isNewMenu){this.isNewMenu=!1;if(t.originalEvent&&/^mouse/.test(t.originalEvent.type)){this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)});return}}var r=n.item.data("ui-autocomplete-item")||n.item.data("item.autocomplete");!1!==this._trigger("focus",t,{item:r})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(r.value):this.liveRegion.text(r.value)},menuselect:function(e,t){var n=t.item.data("ui-autocomplete-item")||t.item.data("item.autocomplete"),r=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=r,this._delay(function(){this.previous=r,this.selectedItem=n})),!1!==this._trigger("select",e,{item:n})&&this._value(n.value),this.term=this._value(),this.close(e),this.selectedItem=n}}),this.liveRegion=e("",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertAfter(this.element),e.fn.bgiframe&&this.menu.element.bgiframe(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),e==="source"&&this._initSource(),e==="appendTo"&&this.menu.element.appendTo(this.document.find(t||"body")[0]),e==="disabled"&&t&&this.xhr&&this.xhr.abort()},_isMultiLine:function(){return this.element.is("textarea")?!0:this.element.is("input")?!1:this.element.prop("isContentEditable")},_initSource:function(){var t,n,r=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(n,r){r(e.ui.autocomplete.filter(t,n.term))}):typeof this.options.source=="string"?(n=this.options.source,this.source=function(t,i){r.xhr&&r.xhr.abort(),r.xhr=e.ajax({url:n,data:t,dataType:"json",success:function(e){i(e)},error:function(){i([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){e=e!=null?e:this._value(),this.term=this._value();if(e.length").append(e("").text(n.label)).appendTo(t)},_move:function(e,t){if(!this.menu.element.is(":visible")){this.search(null,t);return}if(this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)){this._value(this.term),this.menu.blur();return}this.menu[e](t)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(e,t),t.preventDefault()}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,n){var r=new RegExp(e.ui.autocomplete.escapeRegex(n),"i");return e.grep(t,function(e){return r.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments);if(this.options.disabled||this.cancelSearch)return;e&&e.length?t=this.options.messages.results(e.length):t=this.options.messages.noResults,this.liveRegion.text(t)}})})(jQuery);(function(e,t){var n,r,i,s,o="ui-button ui-widget ui-state-default ui-corner-all",u="ui-state-hover ui-state-active ",a="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",f=function(){var t=e(this).find(":ui-button");setTimeout(function(){t.button("refresh")},1)},l=function(t){var n=t.name,r=t.form,i=e([]);return n&&(r?i=e(r).find("[name='"+n+"']"):i=e("[name='"+n+"']",t.ownerDocument).filter(function(){return!this.form})),i};e.widget("ui.button",{version:"1.9.2",defaultElement:"').addClass(this._triggerClass).html(o==""?s:$("").attr({src:o,alt:s,title:s}))),e[r?"before":"after"](t.trigger),t.trigger.click(function(){return $.datepicker._datepickerShowing&&$.datepicker._lastInput==e[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=e[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(e[0])):$.datepicker._showDatepicker(e[0]),!1})}},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t=new Date(2009,11,20),n=this._get(e,"dateFormat");if(n.match(/[DM]/)){var r=function(e){var t=0,n=0;for(var r=0;rt&&(t=e[r].length,n=r);return n};t.setMonth(r(this._get(e,n.match(/MM/)?"monthNames":"monthNamesShort"))),t.setDate(r(this._get(e,n.match(/DD/)?"dayNames":"dayNamesShort"))+20-t.getDay())}e.input.attr("size",this._formatDate(e,t).length)}},_inlineDatepicker:function(e,t){var n=$(e);if(n.hasClass(this.markerClassName))return;n.addClass(this.markerClassName).append(t.dpDiv).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),$.data(e,PROP_NAME,t),this._setDate(t,this._getDefaultDate(t),!0),this._updateDatepicker(t),this._updateAlternate(t),t.settings.disabled&&this._disableDatepicker(e),t.dpDiv.css("display","block")},_dialogDatepicker:function(e,t,n,r,i){var s=this._dialogInst;if(!s){this.uuid+=1;var o="dp"+this.uuid;this._dialogInput=$(''),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),s=this._dialogInst=this._newInst(this._dialogInput,!1),s.settings={},$.data(this._dialogInput[0],PROP_NAME,s)}extendRemove(s.settings,r||{}),t=t&&t.constructor==Date?this._formatDate(s,t):t,this._dialogInput.val(t),this._pos=i?i.length?i:[i.pageX,i.pageY]:null;if(!this._pos){var u=document.documentElement.clientWidth,a=document.documentElement.clientHeight,f=document.documentElement.scrollLeft||document.body.scrollLeft,l=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[u/2-100+f,a/2-150+l]}return this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),s.settings.onSelect=n,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,s),this},_destroyDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();$.removeData(e,PROP_NAME),r=="input"?(n.append.remove(),n.trigger.remove(),t.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(r=="div"||r=="span")&&t.removeClass(this.markerClassName).empty()},_enableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!1,n.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t})},_disableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!0,n.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t}),this._disabledInputs[this._disabledInputs.length]=e},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;t-1}},_doKeyUp:function(e){var t=$.datepicker._getInst(e.target);if(t.input.val()!=t.lastVal)try{var n=$.datepicker.parseDate($.datepicker._get(t,"dateFormat"),t.input?t.input.val():null,$.datepicker._getFormatConfig(t));n&&($.datepicker._setDateFromField(t),$.datepicker._updateAlternate(t),$.datepicker._updateDatepicker(t))}catch(r){$.datepicker.log(r)}return!0},_showDatepicker:function(e){e=e.target||e,e.nodeName.toLowerCase()!="input"&&(e=$("input",e.parentNode)[0]);if($.datepicker._isDisabledDatepicker(e)||$.datepicker._lastInput==e)return;var t=$.datepicker._getInst(e);$.datepicker._curInst&&$.datepicker._curInst!=t&&($.datepicker._curInst.dpDiv.stop(!0,!0),t&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var n=$.datepicker._get(t,"beforeShow"),r=n?n.apply(e,[e,t]):{};if(r===!1)return;extendRemove(t.settings,r),t.lastVal=null,$.datepicker._lastInput=e,$.datepicker._setDateFromField(t),$.datepicker._inDialog&&(e.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(e),$.datepicker._pos[1]+=e.offsetHeight);var i=!1;$(e).parents().each(function(){return i|=$(this).css("position")=="fixed",!i});var s={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,t.dpDiv.empty(),t.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(t),s=$.datepicker._checkOffset(t,s,i),t.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":i?"fixed":"absolute",display:"none",left:s.left+"px",top:s.top+"px"});if(!t.inline){var o=$.datepicker._get(t,"showAnim"),u=$.datepicker._get(t,"duration"),a=function(){var e=t.dpDiv.find("iframe.ui-datepicker-cover");if(!!e.length){var n=$.datepicker._getBorders(t.dpDiv);e.css({left:-n[0],top:-n[1],width:t.dpDiv.outerWidth(),height:t.dpDiv.outerHeight()})}};t.dpDiv.zIndex($(e).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&($.effects.effect[o]||$.effects[o])?t.dpDiv.show(o,$.datepicker._get(t,"showOptions"),u,a):t.dpDiv[o||"show"](o?u:null,a),(!o||!u)&&a(),t.input.is(":visible")&&!t.input.is(":disabled")&&t.input.focus(),$.datepicker._curInst=t}},_updateDatepicker:function(e){this.maxRows=4;var t=$.datepicker._getBorders(e.dpDiv);instActive=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e);var n=e.dpDiv.find("iframe.ui-datepicker-cover");!n.length||n.css({left:-t[0],top:-t[1],width:e.dpDiv.outerWidth(),height:e.dpDiv.outerHeight()}),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var r=this._getNumberOfMonths(e),i=r[1],s=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),i>1&&e.dpDiv.addClass("ui-datepicker-multi-"+i).css("width",s*i+"em"),e.dpDiv[(r[0]!=1||r[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e==$.datepicker._curInst&&$.datepicker._datepickerShowing&&e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&e.input[0]!=document.activeElement&&e.input.focus();if(e.yearshtml){var o=e.yearshtml;setTimeout(function(){o===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),o=e.yearshtml=null},0)}},_getBorders:function(e){var t=function(e){return{thin:1,medium:2,thick:3}[e]||e};return[parseFloat(t(e.css("border-left-width"))),parseFloat(t(e.css("border-top-width")))]},_checkOffset:function(e,t,n){var r=e.dpDiv.outerWidth(),i=e.dpDiv.outerHeight(),s=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,u=document.documentElement.clientWidth+(n?0:$(document).scrollLeft()),a=document.documentElement.clientHeight+(n?0:$(document).scrollTop());return t.left-=this._get(e,"isRTL")?r-s:0,t.left-=n&&t.left==e.input.offset().left?$(document).scrollLeft():0,t.top-=n&&t.top==e.input.offset().top+o?$(document).scrollTop():0,t.left-=Math.min(t.left,t.left+r>u&&u>r?Math.abs(t.left+r-u):0),t.top-=Math.min(t.top,t.top+i>a&&a>i?Math.abs(i+o):0),t},_findPos:function(e){var t=this._getInst(e),n=this._get(t,"isRTL");while(e&&(e.type=="hidden"||e.nodeType!=1||$.expr.filters.hidden(e)))e=e[n?"previousSibling":"nextSibling"];var r=$(e).offset();return[r.left,r.top]},_hideDatepicker:function(e){var t=this._curInst;if(!t||e&&t!=$.data(e,PROP_NAME))return;if(this._datepickerShowing){var n=this._get(t,"showAnim"),r=this._get(t,"duration"),i=function(){$.datepicker._tidyDialog(t)};$.effects&&($.effects.effect[n]||$.effects[n])?t.dpDiv.hide(n,$.datepicker._get(t,"showOptions"),r,i):t.dpDiv[n=="slideDown"?"slideUp":n=="fadeIn"?"fadeOut":"hide"](n?r:null,i),n||i(),this._datepickerShowing=!1;var s=this._get(t,"onClose");s&&s.apply(t.input?t.input[0]:null,[t.input?t.input.val():"",t]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(!$.datepicker._curInst)return;var t=$(e.target),n=$.datepicker._getInst(t[0]);(t[0].id!=$.datepicker._mainDivId&&t.parents("#"+$.datepicker._mainDivId).length==0&&!t.hasClass($.datepicker.markerClassName)&&!t.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||t.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=n)&&$.datepicker._hideDatepicker()},_adjustDate:function(e,t,n){var r=$(e),i=this._getInst(r[0]);if(this._isDisabledDatepicker(r[0]))return;this._adjustInstDate(i,t+(n=="M"?this._get(i,"showCurrentAtPos"):0),n),this._updateDatepicker(i)},_gotoToday:function(e){var t=$(e),n=this._getInst(t[0]);if(this._get(n,"gotoCurrent")&&n.currentDay)n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear;else{var r=new Date;n.selectedDay=r.getDate(),n.drawMonth=n.selectedMonth=r.getMonth(),n.drawYear=n.selectedYear=r.getFullYear()}this._notifyChange(n),this._adjustDate(t)},_selectMonthYear:function(e,t,n){var r=$(e),i=this._getInst(r[0]);i["selected"+(n=="M"?"Month":"Year")]=i["draw"+(n=="M"?"Month":"Year")]=parseInt(t.options[t.selectedIndex].value,10),this._notifyChange(i),this._adjustDate(r)},_selectDay:function(e,t,n,r){var i=$(e);if($(r).hasClass(this._unselectableClass)||this._isDisabledDatepicker(i[0]))return;var s=this._getInst(i[0]);s.selectedDay=s.currentDay=$("a",r).html(),s.selectedMonth=s.currentMonth=t,s.selectedYear=s.currentYear=n,this._selectDate(e,this._formatDate(s,s.currentDay,s.currentMonth,s.currentYear))},_clearDate:function(e){var t=$(e),n=this._getInst(t[0]);this._selectDate(t,"")},_selectDate:function(e,t){var n=$(e),r=this._getInst(n[0]);t=t!=null?t:this._formatDate(r),r.input&&r.input.val(t),this._updateAlternate(r);var i=this._get(r,"onSelect");i?i.apply(r.input?r.input[0]:null,[t,r]):r.input&&r.input.trigger("change"),r.inline?this._updateDatepicker(r):(this._hideDatepicker(),this._lastInput=r.input[0],typeof r.input[0]!="object"&&r.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var t=this._get(e,"altField");if(t){var n=this._get(e,"altFormat")||this._get(e,"dateFormat"),r=this._getDate(e),i=this.formatDate(n,r,this._getFormatConfig(e));$(t).each(function(){$(this).val(i)})}},noWeekends:function(e){var t=e.getDay();return[t>0&&t<6,""]},iso8601Week:function(e){var t=new Date(e.getTime());t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1},parseDate:function(e,t,n){if(e==null||t==null)throw"Invalid arguments";t=typeof t=="object"?t.toString():t+"";if(t=="")return null;var r=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff;r=typeof r!="string"?r:(new Date).getFullYear()%100+parseInt(r,10);var i=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,s=(n?n.dayNames:null)||this._defaults.dayNames,o=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,u=(n?n.monthNames:null)||this._defaults.monthNames,a=-1,f=-1,l=-1,c=-1,h=!1,p=function(t){var n=y+1-1){f=1,l=c;do{var E=this._getDaysInMonth(a,f-1);if(l<=E)break;f++,l-=E}while(!0)}var b=this._daylightSavingAdjust(new Date(a,f-1,l));if(b.getFullYear()!=a||b.getMonth()+1!=f||b.getDate()!=l)throw"Invalid date";return b},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(e,t,n){if(!t)return"";var r=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,i=(n?n.dayNames:null)||this._defaults.dayNames,s=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,o=(n?n.monthNames:null)||this._defaults.monthNames,u=function(t){var n=h+112?e.getHours()+2:0),e):null},_setDate:function(e,t,n){var r=!t,i=e.selectedMonth,s=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),(i!=e.selectedMonth||s!=e.selectedYear)&&!n&&this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(r?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&e.input.val()==""?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(e){var t=this._get(e,"stepMonths"),n="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,-t,"M")},next:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,+t,"M")},hide:function(){window["DP_jQuery_"+dpuuid].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+dpuuid].datepicker._gotoToday(n)},selectDay:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectDay(n,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"Y"),!1}};$(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t=new Date;t=this._daylightSavingAdjust(new Date(t.getFullYear(),t.getMonth(),t.getDate()));var n=this._get(e,"isRTL"),r=this._get(e,"showButtonPanel"),i=this._get(e,"hideIfNoPrevNext"),s=this._get(e,"navigationAsDateFormat"),o=this._getNumberOfMonths(e),u=this._get(e,"showCurrentAtPos"),a=this._get(e,"stepMonths"),f=o[0]!=1||o[1]!=1,l=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),c=this._getMinMaxDate(e,"min"),h=this._getMinMaxDate(e,"max"),p=e.drawMonth-u,d=e.drawYear;p<0&&(p+=12,d--);if(h){var v=this._daylightSavingAdjust(new Date(h.getFullYear(),h.getMonth()-o[0]*o[1]+1,h.getDate()));v=c&&vv)p--,p<0&&(p=11,d--)}e.drawMonth=p,e.drawYear=d;var m=this._get(e,"prevText");m=s?this.formatDate(m,this._daylightSavingAdjust(new Date(d,p-a,1)),this._getFormatConfig(e)):m;var g=this._canAdjustMonth(e,-1,d,p)?''+m+"":i?"":''+m+"",y=this._get(e,"nextText");y=s?this.formatDate(y,this._daylightSavingAdjust(new Date(d,p+a,1)),this._getFormatConfig(e)):y;var b=this._canAdjustMonth(e,1,d,p)?''+y+"":i?"":''+y+"",w=this._get(e,"currentText"),E=this._get(e,"gotoCurrent")&&e.currentDay?l:t;w=s?this.formatDate(w,E,this._getFormatConfig(e)):w;var S=e.inline?"":'",x=r?'
          '+(n?S:"")+(this._isInRange(e,E)?'":"")+(n?"":S)+"
          ":"",T=parseInt(this._get(e,"firstDay"),10);T=isNaN(T)?0:T;var N=this._get(e,"showWeek"),C=this._get(e,"dayNames"),k=this._get(e,"dayNamesShort"),L=this._get(e,"dayNamesMin"),A=this._get(e,"monthNames"),O=this._get(e,"monthNamesShort"),M=this._get(e,"beforeShowDay"),_=this._get(e,"showOtherMonths"),D=this._get(e,"selectOtherMonths"),P=this._get(e,"calculateWeek")||this.iso8601Week,H=this._getDefaultDate(e),B="";for(var j=0;j1)switch(I){case 0:U+=" ui-datepicker-group-first",R=" ui-corner-"+(n?"right":"left");break;case o[1]-1:U+=" ui-datepicker-group-last",R=" ui-corner-"+(n?"left":"right");break;default:U+=" ui-datepicker-group-middle",R=""}U+='">'}U+='
          '+(/all|left/.test(R)&&j==0?n?b:g:"")+(/all|right/.test(R)&&j==0?n?g:b:"")+this._generateMonthYearHeader(e,p,d,c,h,j>0||I>0,A,O)+'
          '+"";var z=N?'":"";for(var W=0;W<7;W++){var X=(W+T)%7;z+="=5?' class="ui-datepicker-week-end"':"")+">"+''+L[X]+""}U+=z+"";var V=this._getDaysInMonth(d,p);d==e.selectedYear&&p==e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,V));var J=(this._getFirstDayOfMonth(d,p)-T+7)%7,K=Math.ceil((J+V)/7),Q=f?this.maxRows>K?this.maxRows:K:K;this.maxRows=Q;var G=this._daylightSavingAdjust(new Date(d,p,1-J));for(var Y=0;Y";var Z=N?'":"";for(var W=0;W<7;W++){var et=M?M.apply(e.input?e.input[0]:null,[G]):[!0,""],tt=G.getMonth()!=p,nt=tt&&!D||!et[0]||c&&Gh;Z+='",G.setDate(G.getDate()+1),G=this._daylightSavingAdjust(G)}U+=Z+""}p++,p>11&&(p=0,d++),U+="
          '+this._get(e,"weekHeader")+"
          '+this._get(e,"calculateWeek")(G)+""+(tt&&!_?" ":nt?''+G.getDate()+"":''+G.getDate()+"")+"
          "+(f?""+(o[0]>0&&I==o[1]-1?'
          ':""):""),F+=U}B+=F}return B+=x+($.ui.ie6&&!e.inline?'':""),e._keyEvent=!1,B},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a=this._get(e,"changeMonth"),f=this._get(e,"changeYear"),l=this._get(e,"showMonthAfterYear"),c='
          ',h="";if(s||!a)h+=''+o[t]+"";else{var p=r&&r.getFullYear()==n,d=i&&i.getFullYear()==n;h+='"}l||(c+=h+(s||!a||!f?" ":""));if(!e.yearshtml){e.yearshtml="";if(s||!f)c+=''+n+"";else{var m=this._get(e,"yearRange").split(":"),g=(new Date).getFullYear(),y=function(e){var t=e.match(/c[+-].*/)?n+parseInt(e.substring(1),10):e.match(/[+-].*/)?g+parseInt(e,10):parseInt(e,10);return isNaN(t)?g:t},b=y(m[0]),w=Math.max(b,y(m[1]||""));b=r?Math.max(b,r.getFullYear()):b,w=i?Math.min(w,i.getFullYear()):w,e.yearshtml+='",c+=e.yearshtml,e.yearshtml=null}}return c+=this._get(e,"yearSuffix"),l&&(c+=(s||!a||!f?" ":"")+h),c+="
          ",c},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n=="Y"?t:0),i=e.drawMonth+(n=="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n=="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n=="M"||n=="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&tr?r:i,i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max");return(!n||t.getTime()>=n.getTime())&&(!r||t.getTime()<=r.getTime())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),$.fn.datepicker=function(e){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv),$.datepicker.initialized=!0);var t=Array.prototype.slice.call(arguments,1);return typeof e!="string"||e!="isDisabled"&&e!="getDate"&&e!="widget"?e=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t)):this.each(function(){typeof e=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this].concat(t)):$.datepicker._attachDatepicker(this,e)}):$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.9.2",window["DP_jQuery_"+dpuuid]=$})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.2",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||" ",s,o,u,a,f;s=(this.uiDialog=e("
          ")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),o=(this.uiDialogTitlebar=e("
          ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").bind("mousedown",function(){s.focus()}).prependTo(s),u=e("").addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(o),(this.uiDialogTitlebarCloseText=e("")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(u),a=e("").uniqueId().addClass("ui-dialog-title").html(i).prependTo(o),f=(this.uiDialogButtonPane=e("
          ")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),(this.uiButtonSet=e("
          ")).addClass("ui-dialog-buttonset").appendTo(f),s.attr({role:"dialog","aria-labelledby":a.attr("id")}),o.find("*").add(o).disableSelection(),this._hoverable(u),this._focusable(u),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n=this,r=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(r=!0)}),r?(e.each(t,function(t,r){var i,s;r=e.isFunction(r)?{click:r,text:t}:r,r=e.extend({type:"button"},r),s=r.click,r.click=function(){s.apply(n.element[0],arguments)},i=e("",r).appendTo(n.uiButtonSet),e.fn.button&&i.button()}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)):this.uiDialog.removeClass("ui-dialog-buttons")},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._trigger("dragStop",i,r(s)),e.ui.dialog.overlay.resize()}})},_makeResizable:function(n){function u(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}n=n===t?this.options.resizable:n;var r=this,i=this.options,s=this.uiDialog.css("position"),o=typeof n=="string"?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:i.maxWidth,maxHeight:i.maxHeight,minWidth:i.minWidth,minHeight:this._minHeight(),handles:o,start:function(t,n){e(this).addClass("ui-dialog-resizing"),r._trigger("resizeStart",t,u(n))},resize:function(e,t){r._trigger("resize",e,u(t))},stop:function(t,n){e(this).removeClass("ui-dialog-resizing"),i.height=e(this).height(),i.width=e(this).width(),r._trigger("resizeStop",t,u(n)),e.ui.dialog.overlay.resize()}}).css("position",s).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(t){var n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()},_setOptions:function(t){var n=this,s={},o=!1;e.each(t,function(e,t){n._setOption(e,t),e in r&&(o=!0),e in i&&(s[e]=t)}),o&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",s)},_setOption:function(t,r){var i,s,o=this.uiDialog;switch(t){case"buttons":this._createButtons(r);break;case"closeText":this.uiDialogTitlebarCloseText.text(""+r);break;case"dialogClass":o.removeClass(this.options.dialogClass).addClass(n+r);break;case"disabled":r?o.addClass("ui-dialog-disabled"):o.removeClass("ui-dialog-disabled");break;case"draggable":i=o.is(":data(draggable)"),i&&!r&&o.draggable("destroy"),!i&&r&&this._makeDraggable();break;case"position":this._position(r);break;case"resizable":s=o.is(":data(resizable)"),s&&!r&&o.resizable("destroy"),s&&typeof r=="string"&&o.resizable("option","handles",r),!s&&r!==!1&&this._makeResizable(r);break;case"title":e(".ui-dialog-title",this.uiDialogTitlebar).html(""+(r||" "))}this._super(t,r)},_size:function(){var t,n,r,i=this.options,s=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),i.minWidth>i.width&&(i.width=i.minWidth),t=this.uiDialog.css({height:"auto",width:i.width}).outerHeight(),n=Math.max(0,i.minHeight-t),i.height==="auto"?e.support.minHeight?this.element.css({minHeight:n,height:"auto"}):(this.uiDialog.show(),r=this.element.css("height","auto").height(),s||this.uiDialog.hide(),this.element.height(Math.max(r,n))):this.element.height(Math.max(i.height-t,0)),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),e.extend(e.ui.dialog,{uuid:0,maxZ:0,getTitleId:function(e){var t=e.attr("id");return t||(this.uuid+=1,t=this.uuid),"ui-dialog-title-"+t},overlay:function(t){this.$el=e.ui.dialog.overlay.create(t)}}),e.extend(e.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:e.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(e){return e+".dialog-overlay"}).join(" "),create:function(t){this.instances.length===0&&(setTimeout(function(){e.ui.dialog.overlay.instances.length&&e(document).bind(e.ui.dialog.overlay.events,function(t){if(e(t.target).zIndex()").addClass("ui-widget-overlay");return e(document).bind("keydown.dialog-overlay",function(r){var i=e.ui.dialog.overlay.instances;i.length!==0&&i[i.length-1]===n&&t.options.closeOnEscape&&!r.isDefaultPrevented()&&r.keyCode&&r.keyCode===e.ui.keyCode.ESCAPE&&(t.close(r),r.preventDefault())}),n.appendTo(document.body).css({width:this.width(),height:this.height()}),e.fn.bgiframe&&n.bgiframe(),this.instances.push(n),n},destroy:function(t){var n=e.inArray(t,this.instances),r=0;n!==-1&&this.oldInstances.push(this.instances.splice(n,1)[0]),this.instances.length===0&&e([document,window]).unbind(".dialog-overlay"),t.height(0).width(0).remove(),e.each(this.instances,function(){r=Math.max(r,this.css("z-index"))}),this.maxZ=r},height:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),n=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),t
          ').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(n=e.ui.ddmanager.drop(this,t)),this.dropped&&(n=this.dropped,this.dropped=!1);var r=this.element[0],i=!1;while(r&&(r=r.parentNode))r==document&&(i=!0);if(!i&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!n||this.options.revert=="valid"&&n||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,n)){var s=this;e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){s._trigger("stop",t)!==!1&&s._clear()})}else this._trigger("stop",t)!==!1&&this._clear();return!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").andSelf().each(function(){this==t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo=="parent"?this.element[0].parentNode:n.appendTo),r[0]!=this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[t.containment=="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t.containment=="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(t.containment=="document"?0:e(window).scrollLeft())+e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(t.containment=="document"?0:e(window).scrollTop())+(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)&&t.containment.constructor!=Array){var n=e(t.containment),r=n[0];if(!r)return;var i=n.offset(),s=e(r).css("overflow")!="hidden";this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(s?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(s?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else t.containment.constructor==Array&&(this.containment=t.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName),s=t.pageX,o=t.pageY;if(this.originalPosition){var u;if(this.containment){if(this.relative_container){var a=this.relative_container.offset();u=[this.containment[0]+a.left,this.containment[1]+a.top,this.containment[2]+a.left,this.containment[3]+a.top]}else u=this.containment;t.pageX-this.offset.click.leftu[2]&&(s=u[2]+this.offset.click.left),t.pageY-this.offset.click.top>u[3]&&(o=u[3]+this.offset.click.top)}if(n.grid){var f=n.grid[1]?this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY;o=u?f-this.offset.click.topu[3]?f-this.offset.click.topu[2]?l-this.offset.click.left=0;l--){var c=r.snapElements[l].left,h=c+r.snapElements[l].width,p=r.snapElements[l].top,d=p+r.snapElements[l].height;if(!(c-s=l&&o<=c||u>=l&&u<=c||oc)&&(i>=a&&i<=f||s>=a&&s<=f||if);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r=e.ui.ddmanager.droppables[t.options.scope]||[],i=n?n.type:null,s=(t.currentItem||t.element).find(":data(droppable)").andSelf();e:for(var o=0;oe?0:r.max")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[];i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(l){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i;if(t&&t.length&&t[0]&&t[t[0]]){i=t.length;while(i--)r=t[i],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.2",save:function(e,t){for(var n=0;n
          ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function a(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,s=t.mode;(r.is(":hidden")?s==="hide":s==="show")?u():o.call(r[0],t,u)}var t=i.apply(this,arguments),r=t.mode,s=t.queue,o=e.effects.effect[t.effect],u=!o&&n&&e.effects[t.effect];return e.fx.off||!o&&!u?r?this[r](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):o?s===!1?this.each(a):this.queue(s||"fx",a):u.call(this,{options:t,duration:t.duration,callback:t.complete,mode:t.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h
          ").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u,outerHeight:a.outerHeight*u,outerWidth:a.outerWidth*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0,outerHeight:0,outerWidth:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r,i,s,o=e(this),u=["position","top","bottom","left","right","width","height","overflow","opacity"],a=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],l=["fontSize"],c=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),d=t.restore||p!=="effect",v=t.scale||"both",m=t.origin||["middle","center"],g=o.css("position"),y=d?u:a,b={height:0,width:0,outerHeight:0,outerWidth:0};p==="show"&&o.show(),r={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},t.mode==="toggle"&&p==="show"?(o.from=t.to||b,o.to=t.from||r):(o.from=t.from||(p==="show"?b:r),o.to=t.to||(p==="hide"?b:r)),s={from:{y:o.from.height/r.height,x:o.from.width/r.width},to:{y:o.to.height/r.height,x:o.to.width/r.width}};if(v==="box"||v==="both")s.from.y!==s.to.y&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,s.from.y,o.from),o.to=e.effects.setTransition(o,c,s.to.y,o.to)),s.from.x!==s.to.x&&(y=y.concat(h),o.from=e.effects.setTransition(o,h,s.from.x,o.from),o.to=e.effects.setTransition(o,h,s.to.x,o.to));(v==="content"||v==="both")&&s.from.y!==s.to.y&&(y=y.concat(l).concat(f),o.from=e.effects.setTransition(o,l,s.from.y,o.from),o.to=e.effects.setTransition(o,l,s.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(i=e.effects.getBaseline(m,r),o.from.top=(r.outerHeight-o.outerHeight())*i.y,o.from.left=(r.outerWidth-o.outerWidth())*i.x,o.to.top=(r.outerHeight-o.to.outerHeight)*i.y,o.to.left=(r.outerWidth-o.to.outerWidth)*i.x),o.css(o.from);if(v==="content"||v==="both")c=c.concat(["marginTop","marginBottom"]).concat(l),h=h.concat(["marginLeft","marginRight"]),f=u.concat(c).concat(h),o.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width(),outerHeight:n.outerHeight(),outerWidth:n.outerWidth()};d&&e.effects.save(n,f),n.from={height:r.height*s.from.y,width:r.width*s.from.x,outerHeight:r.outerHeight*s.from.y,outerWidth:r.outerWidth*s.from.x},n.to={height:r.height*s.to.y,width:r.width*s.to.x,outerHeight:r.height*s.to.y,outerWidth:r.width*s.to.x},s.from.y!==s.to.y&&(n.from=e.effects.setTransition(n,c,s.from.y,n.from),n.to=e.effects.setTransition(n,c,s.to.y,n.to)),s.from.x!==s.to.x&&(n.from=e.effects.setTransition(n,h,s.from.x,n.from),n.to=e.effects.setTransition(n,h,s.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){d&&e.effects.restore(n,f)})});o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o.to.opacity===0&&o.css("opacity",o.from.opacity),p==="hide"&&o.hide(),e.effects.restore(o,y),d||(g==="static"?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,n){var r=parseInt(n,10),i=e?o.to.left:o.to.top;return n==="auto"?i+"px":r+i+"px"})})),e.effects.removeWrapper(o),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e('
          ').appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery);(function(e,t){var n=!1;e.widget("ui.menu",{version:"1.9.2",defaultElement:"
            ",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var r=e(t.target).closest(".ui-menu-item");!n&&r.not(".ui-state-disabled").length&&(n=!0,this.select(t),r.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()
          ").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return e===t?this._value():(this._setOption("value",e),this)},_setOption:function(e,t){e==="value"&&(this.options.value=t,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),this._super(e,t)},_value:function(){var e=this.options.value;return typeof e!="number"&&(e=0),Math.min(this.options.max,Math.max(this.min,e))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var e=this.value(),t=this._percentage();this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),this.valueDiv.toggle(e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(t.toFixed(0)+"%"),this.element.attr("aria-valuenow",e)}})})(jQuery);(function(e,t){e.widget("ui.resizable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var t=this,n=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!n.aspectRatio,aspectRatio:n.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:n.helper||n.ghost||n.animate?n.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e('
          ').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=n.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var r=this.handles.split(",");this.handles={};for(var i=0;i');u.css({zIndex:n.zIndex}),"se"==s&&u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(u)}}this._renderAxis=function(t){t=t||this.element;for(var n in this.handles){this.handles[n].constructor==String&&(this.handles[n]=e(this.handles[n],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var r=e(this.handles[n],this.element),i=0;i=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth();var s=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");t.css(s,i),this._proportionallyResize()}if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!t.resizing){if(this.className)var e=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);t.axis=e&&e[1]?e[1]:"se"}}),n.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(n.disabled)return;e(this).removeClass("ui-resizable-autohide"),t._handles.show()}).mouseleave(function(){if(n.disabled)return;t.resizing||(e(this).addClass("ui-resizable-autohide"),t._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){t(this.element);var n=this.element;this.originalElement.css({position:n.css("position"),width:n.outerWidth(),height:n.outerHeight(),top:n.css("top"),left:n.css("left")}).insertAfter(n),n.remove()}return this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_mouseCapture:function(t){var n=!1;for(var r in this.handles)e(this.handles[r])[0]==t.target&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var r=this.options,i=this.element.position(),s=this.element;this.resizing=!0,this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()},(s.is(".ui-draggable")||/absolute/.test(s.css("position")))&&s.css({position:"absolute",top:i.top,left:i.left}),this._renderProxy();var o=n(this.helper.css("left")),u=n(this.helper.css("top"));r.containment&&(o+=e(r.containment).scrollLeft()||0,u+=e(r.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:o,top:u},this.size=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalSize=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalPosition={left:o,top:u},this.sizeDiff={width:s.outerWidth()-s.width(),height:s.outerHeight()-s.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof r.aspectRatio=="number"?r.aspectRatio:this.originalSize.width/this.originalSize.height||1;var a=e(".ui-resizable-"+this.axis).css("cursor");return e("body").css("cursor",a=="auto"?this.axis+"-resize":a),s.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(e){var t=this.helper,n=this.options,r={},i=this,s=this.originalMousePosition,o=this.axis,u=e.pageX-s.left||0,a=e.pageY-s.top||0,f=this._change[o];if(!f)return!1;var l=f.apply(this,[e,u,a]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)l=this._updateRatio(l,e);return l=this._respectSize(l,e),this._propagate("resize",e),t.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",e,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n=this.options,r=this;if(this._helper){var i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:r.sizeDiff.height,u=s?0:r.sizeDiff.width,a={width:r.helper.width()-u,height:r.helper.height()-o},f=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,l=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;n.animate||this.element.css(e.extend(a,{top:l,left:f})),r.helper.height(r.size.height),r.helper.width(r.size.width),this._helper&&!n.animate&&this._proportionallyResize()}return e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t=this.options,n,i,s,o,u;u={minWidth:r(t.minWidth)?t.minWidth:0,maxWidth:r(t.maxWidth)?t.maxWidth:Infinity,minHeight:r(t.minHeight)?t.minHeight:0,maxHeight:r(t.maxHeight)?t.maxHeight:Infinity};if(this._aspectRatio||e)n=u.minHeight*this.aspectRatio,s=u.minWidth/this.aspectRatio,i=u.maxHeight*this.aspectRatio,o=u.maxWidth/this.aspectRatio,n>u.minWidth&&(u.minWidth=n),s>u.minHeight&&(u.minHeight=s),ie.width,l=r(e.height)&&i.minHeight&&i.minHeight>e.height;f&&(e.width=i.minWidth),l&&(e.height=i.minHeight),u&&(e.width=i.maxWidth),a&&(e.height=i.maxHeight);var c=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,p=/sw|nw|w/.test(o),d=/nw|ne|n/.test(o);f&&p&&(e.left=c-i.minWidth),u&&p&&(e.left=c-i.maxWidth),l&&d&&(e.top=h-i.minHeight),a&&d&&(e.top=h-i.maxHeight);var v=!e.width&&!e.height;return v&&!e.left&&e.top?e.top=null:v&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){var t=this.options;if(!this._proportionallyResizeElements.length)return;var n=this.helper||this.element;for(var r=0;r');var r=e.ui.ie6?1:0,i=e.ui.ie6?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+i,height:this.element.outerHeight()+i,position:"absolute",left:this.elementOffset.left-r+"px",top:this.elementOffset.top-r+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,t,n){return{width:this.originalSize.width+t}},w:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{top:s.top+n,height:i.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","alsoResize",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=function(t){e(t).each(function(){var t=e(this);t.data("resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof i.alsoResize=="object"&&!i.alsoResize.parentNode?i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)}):s(i.alsoResize)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(t,n){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","animate",{stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r._proportionallyResizeElements,o=s.length&&/textarea/i.test(s[0].nodeName),u=o&&e.ui.hasScroll(s[0],"left")?0:r.sizeDiff.height,a=o?0:r.sizeDiff.width,f={width:r.size.width-a,height:r.size.height-u},l=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,c=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;r.element.animate(e.extend(f,c&&l?{top:c,left:l}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var n={width:parseInt(r.element.css("width"),10),height:parseInt(r.element.css("height"),10),top:parseInt(r.element.css("top"),10),left:parseInt(r.element.css("left"),10)};s&&s.length&&e(s[0]).css({width:n.width,height:n.height}),r._updateCache(n),r._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(t,r){var i=e(this).data("resizable"),s=i.options,o=i.element,u=s.containment,a=u instanceof e?u.get(0):/parent/.test(u)?o.parent().get(0):u;if(!a)return;i.containerElement=e(a);if(/document/.test(u)||u==document)i.containerOffset={left:0,top:0},i.containerPosition={left:0,top:0},i.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight};else{var f=e(a),l=[];e(["Top","Right","Left","Bottom"]).each(function(e,t){l[e]=n(f.css("padding"+t))}),i.containerOffset=f.offset(),i.containerPosition=f.position(),i.containerSize={height:f.innerHeight()-l[3],width:f.innerWidth()-l[1]};var c=i.containerOffset,h=i.containerSize.height,p=i.containerSize.width,d=e.ui.hasScroll(a,"left")?a.scrollWidth:p,v=e.ui.hasScroll(a)?a.scrollHeight:h;i.parentData={element:a,left:c.left,top:c.top,width:d,height:v}}},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.containerSize,o=r.containerOffset,u=r.size,a=r.position,f=r._aspectRatio||t.shiftKey,l={top:0,left:0},c=r.containerElement;c[0]!=document&&/static/.test(c.css("position"))&&(l=o),a.left<(r._helper?o.left:0)&&(r.size.width=r.size.width+(r._helper?r.position.left-o.left:r.position.left-l.left),f&&(r.size.height=r.size.width/r.aspectRatio),r.position.left=i.helper?o.left:0),a.top<(r._helper?o.top:0)&&(r.size.height=r.size.height+(r._helper?r.position.top-o.top:r.position.top),f&&(r.size.width=r.size.height*r.aspectRatio),r.position.top=r._helper?o.top:0),r.offset.left=r.parentData.left+r.position.left,r.offset.top=r.parentData.top+r.position.top;var h=Math.abs((r._helper?r.offset.left-l.left:r.offset.left-l.left)+r.sizeDiff.width),p=Math.abs((r._helper?r.offset.top-l.top:r.offset.top-o.top)+r.sizeDiff.height),d=r.containerElement.get(0)==r.element.parent().get(0),v=/relative|absolute/.test(r.containerElement.css("position"));d&&v&&(h-=r.parentData.left),h+r.size.width>=r.parentData.width&&(r.size.width=r.parentData.width-h,f&&(r.size.height=r.size.width/r.aspectRatio)),p+r.size.height>=r.parentData.height&&(r.size.height=r.parentData.height-p,f&&(r.size.width=r.size.height*r.aspectRatio))},stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.position,o=r.containerOffset,u=r.containerPosition,a=r.containerElement,f=e(r.helper),l=f.offset(),c=f.outerWidth()-r.sizeDiff.width,h=f.outerHeight()-r.sizeDiff.height;r._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h}),r._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h})}}),e.ui.plugin.add("resizable","ghost",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size;r.ghost=r.originalElement.clone(),r.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:""),r.ghost.appendTo(r.helper)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.ghost.css({position:"relative",height:r.size.height,width:r.size.width})},stop:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.helper&&r.helper.get(0).removeChild(r.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size,o=r.originalSize,u=r.originalPosition,a=r.axis,f=i._aspectRatio||t.shiftKey;i.grid=typeof i.grid=="number"?[i.grid,i.grid]:i.grid;var l=Math.round((s.width-o.width)/(i.grid[0]||1))*(i.grid[0]||1),c=Math.round((s.height-o.height)/(i.grid[1]||1))*(i.grid[1]||1);/^(se|s|e)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c):/^(ne)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c):/^(sw)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.left=u.left-l):(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c,r.position.left=u.left-l)}});var n=function(e){return parseInt(e,10)||0},r=function(e){return!isNaN(parseInt(e,10))}})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.9.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var t=this;this.element.addClass("ui-selectable"),this.dragged=!1;var n;this.refresh=function(){n=e(t.options.filter,t.element[0]),n.addClass("ui-selectee"),n.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=n.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
          ")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;var r=this.options;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.clientX,top:t.clientY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().andSelf().each(function(){var r=e.data(this,"selectable-item");if(r){var i=!t.metaKey&&!t.ctrlKey||!r.$element.hasClass("ui-selected");return r.$element.removeClass(i?"ui-unselecting":"ui-selected").addClass(i?"ui-selecting":"ui-unselecting"),r.unselecting=!i,r.selecting=i,r.selected=i,i?n._trigger("selecting",t,{selecting:r.element}):n._trigger("unselecting",t,{unselecting:r.element}),!1}})},_mouseDrag:function(t){var n=this;this.dragged=!0;if(this.options.disabled)return;var r=this.options,i=this.opos[0],s=this.opos[1],o=t.pageX,u=t.pageY;if(i>o){var a=o;o=i,i=a}if(s>u){var a=u;u=s,s=a}return this.helper.css({left:i,top:s,width:o-i,height:u-s}),this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!a||a.element==n.element[0])return;var f=!1;r.tolerance=="touch"?f=!(a.left>o||a.rightu||a.bottomi&&a.rights&&a.bottom").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(i.range==="min"||i.range==="max"?" ui-slider-range-"+i.range:""))),r=i.values&&i.values.length||1;for(t=s.length;tn&&(i=n,s=e(this),o=t)}),c.range===!0&&this.values(1)===c.min&&(o+=1,s=e(this.handles[o])),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))}})})(jQuery);(function(e,t){e.widget("ui.sortable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(t);var i=null,s=e(t.target).parents().each(function(){if(e.data(this,r.widgetName+"-item")==r)return i=e(this),!1});e.data(t.target,r.widgetName+"-item")==r&&(i=e(t.target));if(!i)return!1;if(this.options.handle&&!n){var o=!1;e(this.options.handle,i).find("*").andSelf().each(function(){this==t.target&&(o=!0)});if(!o)return!1}return this.currentItem=i,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),i.containment&&this._setContainment(),i.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",i.cursor)),i.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",i.opacity)),i.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",i.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(var s=this.containers.length-1;s>=0;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var n=this.options,r=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY=0;i--){var s=this.items[i],o=s.item[0],u=this._intersectsWithPointer(s);if(!u)continue;if(s.instance!==this.currentContainer)continue;if(o!=this.currentItem[0]&&this.placeholder[u==1?"next":"prev"]()[0]!=o&&!e.contains(this.placeholder[0],o)&&(this.options.type=="semi-dynamic"?!e.contains(this.element[0],o):!0)){this.direction=u==1?"down":"up";if(this.options.tolerance!="pointer"&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+fs&&t+le[this.floating?"width":"height"]?c:s0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!=0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor==String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n=[],r=[],i=this._connectWith();if(i&&t)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&r.push([e.isFunction(a.options.items)?a.options.items.call(a.element):e(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a])}}r.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var s=r.length-1;s>=0;s--)r[s][0].each(function(){n.push(this)});return e(n)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&(r.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a))}}for(var s=r.length-1;s>=0;s--){var f=r[s][1],l=r[s][0];for(var u=0,c=l.length;u=0;n--){var r=this.items[n];if(r.instance!=this.currentContainer&&this.currentContainer&&r.item[0]!=this.currentItem[0])continue;var i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item;t||(r.width=i.outerWidth(),r.height=i.outerHeight());var s=i.offset();r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var n=this.containers.length-1;n>=0;n--){var s=this.containers[n].element.offset();this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight()}return this},_createPlaceholder:function(t){t=t||this;var n=t.options;if(!n.placeholder||n.placeholder.constructor==String){var r=n.placeholder;n.placeholder={element:function(){var n=e(document.createElement(t.currentItem[0].nodeName)).addClass(r||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return r||(n.style.visibility="hidden"),n},update:function(e,i){if(r&&!n.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}}}t.placeholder=e(n.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),n.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n=null,r=null;for(var i=this.containers.length-1;i>=0;i--){if(e.contains(this.currentItem[0],this.containers[i].element[0]))continue;if(this._intersectsWith(this.containers[i].containerCache)){if(n&&e.contains(this.containers[i].element[0],n.element[0]))continue;n=this.containers[i],r=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0)}if(!n)return;if(this.containers.length===1)this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1;else{var s=1e4,o=null,u=this.containers[r].floating?"left":"top",a=this.containers[r].floating?"width":"height",f=this.positionAbs[u]+this.offset.click[u];for(var l=this.items.length-1;l>=0;l--){if(!e.contains(this.containers[r].element[0],this.items[l].item[0]))continue;if(this.items[l].item[0]==this.currentItem[0])continue;var c=this.items[l].item.offset()[u],h=!1;Math.abs(c-f)>Math.abs(c+this.items[l][a]-f)&&(h=!0,c+=this.items[l][a]),Math.abs(c-f)this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top));if(n.grid){var u=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1];o=this.containment?u-this.offset.click.topthis.containment[3]?u-this.offset.click.topthis.containment[2]?a-this.offset.click.left=0;i--)n||r.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(var i=0;i",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""+""+""+""+""},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e1&&e.href.replace(r,"")===location.href.replace(r,"").replace(/\s/g,"%20")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options,r=n.active,i=location.hash.substring(1);this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(r===null){i&&this.tabs.each(function(t,n){if(e(n).attr("aria-controls")===i)return r=t,!1}),r===null&&(r=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(r===null||r===-1)r=this.tabs.length?0:!1}r!==!1&&(r=this.tabs.index(this.tabs.eq(r)),r===-1&&(r=n.collapsible?!1:0)),n.active=r,!n.collapsible&&n.active===!1&&this.anchors.length&&(n.active=0),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("
          ").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"Loading…"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"
        • #{label}
        • "},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"
          "},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r,i,s=this._superApply(arguments);return s?(e==="beforeActivate"?(r=n.newTab.length?n.newTab:n.oldTab,i=n.newPanel.length?n.newPanel:n.oldPanel,s=this._super("select",t,{tab:r.find(".ui-tabs-anchor")[0],panel:i[0],index:r.closest("li").index()})):e==="activate"&&n.newTab.length&&(s=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),s):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.9.2",options:{content:function(){return e(this).attr("title")},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=this,r=e(t?t.target:this.element).closest(this.options.items);if(!r.length||r.data("ui-tooltip-id"))return;r.attr("title")&&r.data("ui-tooltip-title",r.attr("title")),r.data("ui-tooltip-open",!0),t&&t.type==="mouseover"&&r.parents().each(function(){var t=e(this),r;t.data("ui-tooltip-open")&&(r=e.Event("blur"),r.target=r.currentTarget=this,n.close(r,!0)),t.attr("title")&&(t.uniqueId(),n.parents[this.id]={element:this,title:t.attr("title")},t.attr("title",""))}),this._updateContent(r,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this,s=t?t.type:null;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("ui-tooltip-open"))return;i._delay(function(){t&&(t.type=s),this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function f(e){a.of=e;if(s.is(":hidden"))return;s.position(a)}var s,o,u,a=e.extend({},this.options.position);if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:f}),f(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(u=setInterval(function(){s.is(":visible")&&(f(a.of),clearInterval(u))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),o={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}},remove:function(){this._removeTooltip(s)}};if(!t||t.type==="mouseover")o.mouseleave="close";if(!t||t.type==="focusin")o.focusout="close";this._on(!0,r,o)},close:function(t){var n=this,i=e(t?t.currentTarget:this.element),s=this._find(i);if(this.closing)return;i.data("ui-tooltip-title")&&i.attr("title",i.data("ui-tooltip-title")),r(i),s.stop(!0),this._hide(s,this.options.hide,function(){n._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&t.type==="mouseleave"&&e.each(this.parents,function(t,r){e(r.element).attr("title",r.title),delete n.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:s}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("
          ").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("
          ").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),e.fn.bgiframe&&i.bgiframe(),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery); \ No newline at end of file diff --git a/lib/scripts/jquery/jquery.cookie.js b/lib/scripts/jquery/jquery.cookie.js index 6a3e394b4..2d4c05a84 100644 --- a/lib/scripts/jquery/jquery.cookie.js +++ b/lib/scripts/jquery/jquery.cookie.js @@ -1,41 +1,72 @@ -/** - * jQuery Cookie plugin +/*! + * jQuery Cookie Plugin v1.3 + * https://github.com/carhartl/jquery-cookie * - * Copyright (c) 2010 Klaus Hartl (stilbuero.de) - * Dual licensed under the MIT and GPL licenses: + * Copyright 2011, Klaus Hartl + * Dual licensed under the MIT or GPL Version 2 licenses. * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * + * http://www.opensource.org/licenses/GPL-2.0 */ -jQuery.cookie = function (key, value, options) { - - // key and at least value given, set cookie... - if (arguments.length > 1 && String(value) !== "[object Object]") { - options = jQuery.extend({}, options); - - if (value === null || value === undefined) { - options.expires = -1; - } - - if (typeof options.expires === 'number') { - var days = options.expires, t = options.expires = new Date(); - t.setDate(t.getDate() + days); - } - - value = String(value); - - return (document.cookie = [ - encodeURIComponent(key), '=', - options.raw ? value : encodeURIComponent(value), - options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE - options.path ? '; path=' + options.path : '', - options.domain ? '; domain=' + options.domain : '', - options.secure ? '; secure' : '' - ].join('')); - } - - // key and possibly options given, get cookie... - options = value || {}; - var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent; - return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null; -}; +(function ($, document, undefined) { + + var pluses = /\+/g; + + function raw(s) { + return s; + } + + function decoded(s) { + return decodeURIComponent(s.replace(pluses, ' ')); + } + + var config = $.cookie = function (key, value, options) { + + // write + if (value !== undefined) { + options = $.extend({}, config.defaults, options); + + if (value === null) { + options.expires = -1; + } + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setDate(t.getDate() + days); + } + + value = config.json ? JSON.stringify(value) : String(value); + + return (document.cookie = [ + encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join('')); + } + + // read + var decode = config.raw ? raw : decoded; + var cookies = document.cookie.split('; '); + for (var i = 0, l = cookies.length; i < l; i++) { + var parts = cookies[i].split('='); + if (decode(parts.shift()) === key) { + var cookie = decode(parts.join('=')); + return config.json ? JSON.parse(cookie) : cookie; + } + } + + return null; + }; + + config.defaults = {}; + + $.removeCookie = function (key, options) { + if ($.cookie(key) !== null) { + $.cookie(key, null, options); + return true; + } + return false; + }; + +})(jQuery, document); diff --git a/lib/scripts/jquery/jquery.js b/lib/scripts/jquery/jquery.js deleted file mode 100644 index 719e1d4ec..000000000 --- a/lib/scripts/jquery/jquery.js +++ /dev/null @@ -1,9046 +0,0 @@ -/*! - * jQuery JavaScript Library v1.6.4 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Mon Sep 12 18:54:48 2011 -0400 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document, - navigator = window.navigator, - location = window.location; -var jQuery = (function() { - -// Define a local copy of jQuery -var jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // A central reference to the root jQuery(document) - rootjQuery, - - // A simple way to check for HTML strings or ID strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Check for digits - rdigit = /\d/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Matches dashed string for camelizing - rdashAlpha = /-([a-z]|[0-9])/ig, - rmsPrefix = /^-ms-/, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return ( letter + "" ).toUpperCase(); - }, - - // Keep a UserAgent string for use with jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // The deferred used on DOM ready - readyList, - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = selector; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = quickExpr.exec( selector ); - } - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = (context ? context.ownerDocument || context : document); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; - } - - return jQuery.merge( this, selector ); - - // HANDLE: $("#id") - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return (context || rootjQuery).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if (selector.selector !== undefined) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.6.4", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return slice.call( this, 0 ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = this.constructor(); - - if ( jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - jQuery.merge( ret, elems ); - } - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + (this.selector ? " " : "") + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Attach the listeners - jQuery.bindReady(); - - // Add the callback - readyList.done( fn ); - - return this; - }, - - eq: function( i ) { - return i === -1 ? - this.slice( i ) : - this.slice( i, +i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ), - "slice", slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - // Either a released hold or an DOMready/load event and not yet ready - if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger( "ready" ).unbind( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyList ) { - return; - } - - readyList = jQuery._Deferred(); - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", DOMContentLoaded ); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - // A crude way of determining if an object is a window - isWindow: function( obj ) { - return obj && typeof obj === "object" && "setInterval" in obj; - }, - - isNaN: function( obj ) { - return obj == null || !rdigit.test( obj ) || isNaN( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - try { - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw msg; - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Attempt to parse using the native JSON parser first - if ( window.JSON && window.JSON.parse ) { - return window.JSON.parse( data ); - } - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return (new Function( "return " + data ))(); - - } - jQuery.error( "Invalid JSON: " + data ); - }, - - // Cross-browser xml parsing - parseXML: function( data ) { - var xml, tmp; - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; - }, - - noop: function() {}, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && rnotwhite.test( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || jQuery.isFunction( object ); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { - break; - } - } - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // The extra typeof function check is to prevent crashes - // in Safari 2 (See: #3039) - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type( array ); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array ) { - if ( !array ) { - return -1; - } - - if ( indexOf ) { - return indexOf.call( array, elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, key, ret = [], - i = 0, - length = elems.length, - // jquery objects are treated as arrays - isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; - - // Go through the array, translating each of the items to their - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Go through every key on the object, - } else { - for ( key in elems ) { - value = callback( elems[ key ], key, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - if ( typeof context === "string" ) { - var tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - var args = slice.call( arguments, 2 ), - proxy = function() { - return fn.apply( context, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; - - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can optionally be executed if it's a function - access: function( elems, key, value, exec, fn, pass ) { - var length = elems.length; - - // Setting many attributes - if ( typeof key === "object" ) { - for ( var k in key ) { - jQuery.access( elems, k, key[k], exec, fn, value ); - } - return elems; - } - - // Setting one attribute - if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = !pass && exec && jQuery.isFunction(value); - - for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - - return elems; - } - - // Getting an attribute - return length ? fn( elems[0], key ) : undefined; - }, - - now: function() { - return (new Date()).getTime(); - }, - - // Use of jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - sub: function() { - function jQuerySub( selector, context ) { - return new jQuerySub.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySub, this ); - jQuerySub.superclass = this; - jQuerySub.fn = jQuerySub.prototype = this(); - jQuerySub.fn.constructor = jQuerySub; - jQuerySub.sub = this.sub; - jQuerySub.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { - context = jQuerySub( context ); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); - }; - jQuerySub.fn.init.prototype = jQuerySub.fn; - var rootjQuerySub = jQuerySub(document); - return jQuerySub; - }, - - browser: {} -}); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - jQuery.browser[ browserMatch.browser ] = true; - jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use jQuery.browser.webkit instead -if ( jQuery.browser.webkit ) { - jQuery.browser.safari = true; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - jQuery.ready(); -} - -return jQuery; - -})(); - - -var // Promise methods - promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), - // Static reference to slice - sliceDeferred = [].slice; - -jQuery.extend({ - // Create a simple deferred (one callbacks list) - _Deferred: function() { - var // callbacks list - callbacks = [], - // stored [ context , args ] - fired, - // to avoid firing when already doing so - firing, - // flag to know if the deferred has been cancelled - cancelled, - // the deferred itself - deferred = { - - // done( f1, f2, ...) - done: function() { - if ( !cancelled ) { - var args = arguments, - i, - length, - elem, - type, - _fired; - if ( fired ) { - _fired = fired; - fired = 0; - } - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - deferred.done.apply( deferred, elem ); - } else if ( type === "function" ) { - callbacks.push( elem ); - } - } - if ( _fired ) { - deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); - } - } - return this; - }, - - // resolve with given context and args - resolveWith: function( context, args ) { - if ( !cancelled && !fired && !firing ) { - // make sure args are available (#8421) - args = args || []; - firing = 1; - try { - while( callbacks[ 0 ] ) { - callbacks.shift().apply( context, args ); - } - } - finally { - fired = [ context, args ]; - firing = 0; - } - } - return this; - }, - - // resolve with this as context and given arguments - resolve: function() { - deferred.resolveWith( this, arguments ); - return this; - }, - - // Has this deferred been resolved? - isResolved: function() { - return !!( firing || fired ); - }, - - // Cancel - cancel: function() { - cancelled = 1; - callbacks = []; - return this; - } - }; - - return deferred; - }, - - // Full fledged deferred (two callbacks list) - Deferred: function( func ) { - var deferred = jQuery._Deferred(), - failDeferred = jQuery._Deferred(), - promise; - // Add errorDeferred methods, then and promise - jQuery.extend( deferred, { - then: function( doneCallbacks, failCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ); - return this; - }, - always: function() { - return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); - }, - fail: failDeferred.done, - rejectWith: failDeferred.resolveWith, - reject: failDeferred.resolve, - isRejected: failDeferred.isResolved, - pipe: function( fnDone, fnFail ) { - return jQuery.Deferred(function( newDefer ) { - jQuery.each( { - done: [ fnDone, "resolve" ], - fail: [ fnFail, "reject" ] - }, function( handler, data ) { - var fn = data[ 0 ], - action = data[ 1 ], - returned; - if ( jQuery.isFunction( fn ) ) { - deferred[ handler ](function() { - returned = fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise().then( newDefer.resolve, newDefer.reject ); - } else { - newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); - } - }); - } else { - deferred[ handler ]( newDefer[ action ] ); - } - }); - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - if ( promise ) { - return promise; - } - promise = obj = {}; - } - var i = promiseMethods.length; - while( i-- ) { - obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; - } - return obj; - } - }); - // Make sure only one callback list will be used - deferred.done( failDeferred.cancel ).fail( deferred.cancel ); - // Unexpose cancel - delete deferred.cancel; - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - return deferred; - }, - - // Deferred helper - when: function( firstParam ) { - var args = arguments, - i = 0, - length = args.length, - count = length, - deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? - firstParam : - jQuery.Deferred(); - function resolveFunc( i ) { - return function( value ) { - args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; - if ( !( --count ) ) { - // Strange bug in FF4: - // Values changed onto the arguments object sometimes end up as undefined values - // outside the $.when method. Cloning the object into a fresh array solves the issue - deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); - } - }; - } - if ( length > 1 ) { - for( ; i < length; i++ ) { - if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { - args[ i ].promise().then( resolveFunc(i), deferred.reject ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( deferred, args ); - } - } else if ( deferred !== firstParam ) { - deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); - } - return deferred.promise(); - } -}); - - - -jQuery.support = (function() { - - var div = document.createElement( "div" ), - documentElement = document.documentElement, - all, - a, - select, - opt, - input, - marginDiv, - support, - fragment, - body, - testElementParent, - testElement, - testElementStyle, - tds, - events, - eventName, - i, - isSupported; - - // Preliminary tests - div.setAttribute("className", "t"); - div.innerHTML = "
          a"; - - - all = div.getElementsByTagName( "*" ); - a = div.getElementsByTagName( "a" )[ 0 ]; - - // Can't get basic test support - if ( !all || !all.length || !a ) { - return {}; - } - - // First batch of supports tests - select = document.createElement( "select" ); - opt = select.appendChild( document.createElement("option") ); - input = div.getElementsByTagName( "input" )[ 0 ]; - - support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: ( div.firstChild.nodeType === 3 ), - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName( "tbody" ).length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName( "link" ).length, - - // Get the style information from getAttribute - // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.55$/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: ( input.value === "on" ), - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - getSetAttribute: div.className !== "t", - - // Will be defined later - submitBubbles: true, - changeBubbles: true, - focusinBubbles: false, - deleteExpando: true, - noCloneEvent: true, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableMarginRight: true - }; - - // Make sure checked status is properly cloned - input.checked = true; - support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent( "onclick", function() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - support.noCloneEvent = false; - }); - div.cloneNode( true ).fireEvent( "onclick" ); - } - - // Check if a radio maintains it's value - // after being appended to the DOM - input = document.createElement("input"); - input.value = "t"; - input.setAttribute("type", "radio"); - support.radioValue = input.value === "t"; - - input.setAttribute("checked", "checked"); - div.appendChild( input ); - fragment = document.createDocumentFragment(); - fragment.appendChild( div.firstChild ); - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - - div.innerHTML = ""; - - // Figure out if the W3C box model works as expected - div.style.width = div.style.paddingLeft = "1px"; - - body = document.getElementsByTagName( "body" )[ 0 ]; - // We use our own, invisible, body unless the body is already present - // in which case we use a div (#9239) - testElement = document.createElement( body ? "div" : "body" ); - testElementStyle = { - visibility: "hidden", - width: 0, - height: 0, - border: 0, - margin: 0, - background: "none" - }; - if ( body ) { - jQuery.extend( testElementStyle, { - position: "absolute", - left: "-1000px", - top: "-1000px" - }); - } - for ( i in testElementStyle ) { - testElement.style[ i ] = testElementStyle[ i ]; - } - testElement.appendChild( div ); - testElementParent = body || documentElement; - testElementParent.insertBefore( testElement, testElementParent.firstChild ); - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - support.appendChecked = input.checked; - - support.boxModel = div.offsetWidth === 2; - - if ( "zoom" in div.style ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.style.display = "inline"; - div.style.zoom = 1; - support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = ""; - div.innerHTML = "
          "; - support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); - } - - div.innerHTML = "
          t
          "; - tds = div.getElementsByTagName( "td" ); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - isSupported = ( tds[ 0 ].offsetHeight === 0 ); - - tds[ 0 ].style.display = ""; - tds[ 1 ].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE < 8 fail this test) - support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); - div.innerHTML = ""; - - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. For more - // info see bug #3333 - // Fails in WebKit before Feb 2011 nightlies - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - if ( document.defaultView && document.defaultView.getComputedStyle ) { - marginDiv = document.createElement( "div" ); - marginDiv.style.width = "0"; - marginDiv.style.marginRight = "0"; - div.appendChild( marginDiv ); - support.reliableMarginRight = - ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; - } - - // Remove the body element we added - testElement.innerHTML = ""; - testElementParent.removeChild( testElement ); - - // Technique from Juriy Zaytsev - // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( div.attachEvent ) { - for( i in { - submit: 1, - change: 1, - focusin: 1 - } ) { - eventName = "on" + i; - isSupported = ( eventName in div ); - if ( !isSupported ) { - div.setAttribute( eventName, "return;" ); - isSupported = ( typeof div[ eventName ] === "function" ); - } - support[ i + "Bubbles" ] = isSupported; - } - } - - // Null connected elements to avoid leaks in IE - testElement = fragment = select = opt = body = marginDiv = div = input = null; - - return support; -})(); - -// Keep track of boxModel -jQuery.boxModel = jQuery.support.boxModel; - - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/, - rmultiDash = /([A-Z])/g; - -jQuery.extend({ - cache: {}, - - // Please use with caution - uuid: 0, - - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, ret, - internalKey = jQuery.expando, - getByName = typeof name === "string", - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ jQuery.expando ] = id = ++jQuery.uuid; - } else { - id = jQuery.expando; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); - } else { - cache[ id ] = jQuery.extend(cache[ id ], name); - } - } - - thisCache = cache[ id ]; - - // Internal jQuery data is stored in a separate object inside the object's data - // cache in order to avoid key collisions between internal data and user-defined - // data - if ( pvt ) { - if ( !thisCache[ internalKey ] ) { - thisCache[ internalKey ] = {}; - } - - thisCache = thisCache[ internalKey ]; - } - - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } - - // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should - // not attempt to inspect the internal events object using jQuery.data, as this - // internal data object is undocumented and subject to change. - if ( name === "events" && !thisCache[name] ) { - return thisCache[ internalKey ] && thisCache[ internalKey ].events; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( getByName ) { - - // First Try to find as-is property data - ret = thisCache[ name ]; - - // Test for null|undefined property data - if ( ret == null ) { - - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } - - return ret; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, - - // Reference to internal data cache key - internalKey = jQuery.expando, - - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - - // See jQuery.data for more information - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - - thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; - - if ( thisCache ) { - - // Support interoperable removal of hyphenated or camelcased keys - if ( !thisCache[ name ] ) { - name = jQuery.camelCase( name ); - } - - delete thisCache[ name ]; - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !isEmptyDataObject(thisCache) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( pvt ) { - delete cache[ id ][ internalKey ]; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject(cache[ id ]) ) { - return; - } - } - - var internalCache = cache[ id ][ internalKey ]; - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - // Ensure that `cache` is not a window object #10080 - if ( jQuery.support.deleteExpando || !cache.setInterval ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the entire user cache at once because it's faster than - // iterating through each key, but we need to continue to persist internal - // data if it existed - if ( internalCache ) { - cache[ id ] = {}; - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - - cache[ id ][ internalKey ] = internalCache; - - // Otherwise, we need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - } else if ( isNode ) { - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( jQuery.support.deleteExpando ) { - delete elem[ jQuery.expando ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( jQuery.expando ); - } else { - elem[ jQuery.expando ] = null; - } - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - if ( elem.nodeName ) { - var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var data = null; - - if ( typeof key === "undefined" ) { - if ( this.length ) { - data = jQuery.data( this[0] ); - - if ( this[0].nodeType === 1 ) { - var attr = this[0].attributes, name; - for ( var i = 0, l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.substring(5) ); - - dataAttr( this[0], name, data[ name ] ); - } - } - } - } - - return data; - - } else if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - var parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - // Try to fetch any internally stored data first - if ( data === undefined && this.length ) { - data = jQuery.data( this[0], key ); - data = dataAttr( this[0], key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - - } else { - return this.each(function() { - var $this = jQuery( this ), - args = [ parts[0], value ]; - - $this.triggerHandler( "setData" + parts[1] + "!", args ); - jQuery.data( this, key, value ); - $this.triggerHandler( "changeData" + parts[1] + "!", args ); - }); - } - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - !jQuery.isNaN( data ) ? parseFloat( data ) : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON -// property to be considered empty objects; this property always exists in -// order to make sure JSON.stringify does not expose internal metadata -function isEmptyDataObject( obj ) { - for ( var name in obj ) { - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} - - - - -function handleQueueMarkDefer( elem, type, src ) { - var deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - defer = jQuery.data( elem, deferDataKey, undefined, true ); - if ( defer && - ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && - ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { - // Give room for hard-coded callbacks to fire first - // and eventually mark/queue something else on the element - setTimeout( function() { - if ( !jQuery.data( elem, queueDataKey, undefined, true ) && - !jQuery.data( elem, markDataKey, undefined, true ) ) { - jQuery.removeData( elem, deferDataKey, true ); - defer.resolve(); - } - }, 0 ); - } -} - -jQuery.extend({ - - _mark: function( elem, type ) { - if ( elem ) { - type = (type || "fx") + "mark"; - jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); - } - }, - - _unmark: function( force, elem, type ) { - if ( force !== true ) { - type = elem; - elem = force; - force = false; - } - if ( elem ) { - type = type || "fx"; - var key = type + "mark", - count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); - if ( count ) { - jQuery.data( elem, key, count, true ); - } else { - jQuery.removeData( elem, key, true ); - handleQueueMarkDefer( elem, type, "mark" ); - } - } - }, - - queue: function( elem, type, data ) { - if ( elem ) { - type = (type || "fx") + "queue"; - var q = jQuery.data( elem, type, undefined, true ); - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !q || jQuery.isArray(data) ) { - q = jQuery.data( elem, type, jQuery.makeArray(data), true ); - } else { - q.push( data ); - } - } - return q || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - fn = queue.shift(), - defer; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift("inprogress"); - } - - fn.call(elem, function() { - jQuery.dequeue(elem, type); - }); - } - - if ( !queue.length ) { - jQuery.removeData( elem, type + "queue", true ); - handleQueueMarkDefer( elem, type, "queue" ); - } - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) { - return jQuery.queue( this[0], type ); - } - return this.each(function() { - var queue = jQuery.queue( this, type, data ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; - type = type || "fx"; - - return this.queue( type, function() { - var elem = this; - setTimeout(function() { - jQuery.dequeue( elem, type ); - }, time ); - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, object ) { - if ( typeof type !== "string" ) { - object = type; - type = undefined; - } - type = type || "fx"; - var defer = jQuery.Deferred(), - elements = this, - i = elements.length, - count = 1, - deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - tmp; - function resolve() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - } - while( i-- ) { - if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || - ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || - jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && - jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { - count++; - tmp.done( resolve ); - } - } - resolve(); - return defer.promise(); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspace = /\s+/, - rreturn = /\r/g, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea)?$/i, - rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, - nodeHook, boolHook; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.attr ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - }, - - prop: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.prop ); - }, - - removeProp: function( name ) { - name = jQuery.propFix[ name ] || name; - return this.each(function() { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[ name ] = undefined; - delete this[ name ]; - } catch( e ) {} - }); - }, - - addClass: function( value ) { - var classNames, i, l, elem, - setClass, c, cl; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call(this, j, this.className) ); - }); - } - - if ( value && typeof value === "string" ) { - classNames = value.split( rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className && classNames.length === 1 ) { - elem.className = value; - - } else { - setClass = " " + elem.className + " "; - - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { - setClass += classNames[ c ] + " "; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classNames, i, l, elem, className, c, cl; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call(this, j, this.className) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - classNames = (value || "").split( rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - className = (" " + elem.className + " ").replace( rclass, " " ); - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[ c ] + " ", " "); - } - elem.className = jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( rspace ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " "; - for ( var i = 0, l = this.length; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - var hooks, ret, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return undefined; - } - - var isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var self = jQuery(this), val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, self.val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map(val, function ( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - }, - select: { - get: function( elem ) { - var value, - index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - - return values; - }, - - set: function( elem, value ) { - var values = jQuery.makeArray( value ); - - jQuery(elem).find("option").each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - elem.selectedIndex = -1; - } - return values; - } - } - }, - - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attrFix: { - // Always normalize to ensure hook usage - tabindex: "tabIndex" - }, - - attr: function( elem, name, value, pass ) { - var nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return undefined; - } - - if ( pass && name in jQuery.attrFn ) { - return jQuery( elem )[ name ]( value ); - } - - // Fallback to prop when attributes are not supported - if ( !("getAttribute" in elem) ) { - return jQuery.prop( elem, name, value ); - } - - var ret, hooks, - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - // Normalize the name if needed - if ( notxml ) { - name = jQuery.attrFix[ name ] || name; - - hooks = jQuery.attrHooks[ name ]; - - if ( !hooks ) { - // Use boolHook for boolean attributes - if ( rboolean.test( name ) ) { - hooks = boolHook; - - // Use nodeHook if available( IE6/7 ) - } else if ( nodeHook ) { - hooks = nodeHook; - } - } - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return undefined; - - } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, "" + value ); - return value; - } - - } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - - ret = elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return ret === null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, name ) { - var propName; - if ( elem.nodeType === 1 ) { - name = jQuery.attrFix[ name ] || name; - - jQuery.attr( elem, name, "" ); - elem.removeAttribute( name ); - - // Set corresponding property to false for boolean attributes - if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { - elem[ propName ] = false; - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to it's default in case type is set after value - // This is for element creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - }, - // Use the value property for back compat - // Use the nodeHook for button elements in IE6/7 (#1954) - value: { - get: function( elem, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.get( elem, name ); - } - return name in elem ? - elem.value : - null; - }, - set: function( elem, value, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.set( elem, value, name ); - } - // Does not return so that setAttribute is also used - elem.value = value; - } - } - }, - - propFix: { - tabindex: "tabIndex", - readonly: "readOnly", - "for": "htmlFor", - "class": "className", - maxlength: "maxLength", - cellspacing: "cellSpacing", - cellpadding: "cellPadding", - rowspan: "rowSpan", - colspan: "colSpan", - usemap: "useMap", - frameborder: "frameBorder", - contenteditable: "contentEditable" - }, - - prop: function( elem, name, value ) { - var nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return undefined; - } - - var ret, hooks, - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - return (elem[ name ] = value); - } - - } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - return elem[ name ]; - } - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode("tabindex"); - - return attributeNode && attributeNode.specified ? - parseInt( attributeNode.value, 10 ) : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - } - } -}); - -// Add the tabindex propHook to attrHooks for back-compat -jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex; - -// Hook for boolean attributes -boolHook = { - get: function( elem, name ) { - // Align boolean attributes with corresponding properties - // Fall back to attribute presence where some booleans are not supported - var attrNode; - return jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ? - name.toLowerCase() : - undefined; - }, - set: function( elem, value, name ) { - var propName; - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - // value is true since we know at this point it's type boolean and not false - // Set boolean attributes to the same name and set the DOM property - propName = jQuery.propFix[ name ] || name; - if ( propName in elem ) { - // Only set the IDL specifically if it already exists on the element - elem[ propName ] = true; - } - - elem.setAttribute( name, name.toLowerCase() ); - } - return name; - } -}; - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !jQuery.support.getSetAttribute ) { - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = jQuery.valHooks.button = { - get: function( elem, name ) { - var ret; - ret = elem.getAttributeNode( name ); - // Return undefined if nodeValue is empty string - return ret && ret.nodeValue !== "" ? - ret.nodeValue : - undefined; - }, - set: function( elem, value, name ) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode( name ); - if ( !ret ) { - ret = document.createAttribute( name ); - elem.setAttributeNode( ret ); - } - return (ret.nodeValue = value + ""); - } - }; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - jQuery.each([ "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - set: function( elem, value ) { - if ( value === "" ) { - elem.setAttribute( name, "auto" ); - return value; - } - } - }); - }); -} - - -// Some attributes require a special call on IE -if ( !jQuery.support.hrefNormalized ) { - jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - get: function( elem ) { - var ret = elem.getAttribute( name, 2 ); - return ret === null ? undefined : ret; - } - }); - }); -} - -if ( !jQuery.support.style ) { - jQuery.attrHooks.style = { - get: function( elem ) { - // Return undefined in the case of empty string - // Normalize to lowercase since IE uppercases css property names - return elem.style.cssText.toLowerCase() || undefined; - }, - set: function( elem, value ) { - return (elem.style.cssText = "" + value); - } - }; -} - -// Safari mis-reports the default selected property of an option -// Accessing the parent's selectedIndex property fixes it -if ( !jQuery.support.optSelected ) { - jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { - get: function( elem ) { - var parent = elem.parentNode; - - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - return null; - } - }); -} - -// Radios and checkboxes getter/setter -if ( !jQuery.support.checkOn ) { - jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - get: function( elem ) { - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - } - }; - }); -} -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); - } - } - }); -}); - - - - -var rnamespaces = /\.(.*)$/, - rformElems = /^(?:textarea|input|select)$/i, - rperiod = /\./g, - rspaces = / /g, - rescape = /[^\w\s.|`]/g, - fcleanup = function( nm ) { - return nm.replace(rescape, "\\$&"); - }; - -/* - * A number of helper functions used for managing events. - * Many of the ideas behind this code originated from - * Dean Edwards' addEvent library. - */ -jQuery.event = { - - // Bind an event to an element - // Original by Dean Edwards - add: function( elem, types, handler, data ) { - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - if ( handler === false ) { - handler = returnFalse; - } else if ( !handler ) { - // Fixes bug #7229. Fix recommended by jdalton - return; - } - - var handleObjIn, handleObj; - - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - } - - // Make sure that the function being executed has a unique ID - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure - var elemData = jQuery._data( elem ); - - // If no elemData is found then we must be trying to bind to one of the - // banned noData elements - if ( !elemData ) { - return; - } - - var events = elemData.events, - eventHandle = elemData.handle; - - if ( !events ) { - elemData.events = events = {}; - } - - if ( !eventHandle ) { - elemData.handle = eventHandle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.handle.apply( eventHandle.elem, arguments ) : - undefined; - }; - } - - // Add elem as a property of the handle function - // This is to prevent a memory leak with non-native events in IE. - eventHandle.elem = elem; - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = types.split(" "); - - var type, i = 0, namespaces; - - while ( (type = types[ i++ ]) ) { - handleObj = handleObjIn ? - jQuery.extend({}, handleObjIn) : - { handler: handler, data: data }; - - // Namespaced event handlers - if ( type.indexOf(".") > -1 ) { - namespaces = type.split("."); - type = namespaces.shift(); - handleObj.namespace = namespaces.slice(0).sort().join("."); - - } else { - namespaces = []; - handleObj.namespace = ""; - } - - handleObj.type = type; - if ( !handleObj.guid ) { - handleObj.guid = handler.guid; - } - - // Get the current list of functions bound to this event - var handlers = events[ type ], - special = jQuery.event.special[ type ] || {}; - - // Init the event handler queue - if ( !handlers ) { - handlers = events[ type ] = []; - - // Check for a special event handler - // Only use addEventListener/attachEvent if the special - // events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add the function to the element's handler list - handlers.push( handleObj ); - - // Keep track of which events have been used, for event optimization - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, pos ) { - // don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - if ( handler === false ) { - handler = returnFalse; - } - - var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ), - events = elemData && elemData.events; - - if ( !elemData || !events ) { - return; - } - - // types is actually an event object here - if ( types && types.type ) { - handler = types.handler; - types = types.type; - } - - // Unbind all events for the element - if ( !types || typeof types === "string" && types.charAt(0) === "." ) { - types = types || ""; - - for ( type in events ) { - jQuery.event.remove( elem, type + types ); - } - - return; - } - - // Handle multiple events separated by a space - // jQuery(...).unbind("mouseover mouseout", fn); - types = types.split(" "); - - while ( (type = types[ i++ ]) ) { - origType = type; - handleObj = null; - all = type.indexOf(".") < 0; - namespaces = []; - - if ( !all ) { - // Namespaced event handlers - namespaces = type.split("."); - type = namespaces.shift(); - - namespace = new RegExp("(^|\\.)" + - jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - eventType = events[ type ]; - - if ( !eventType ) { - continue; - } - - if ( !handler ) { - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( all || namespace.test( handleObj.namespace ) ) { - jQuery.event.remove( elem, origType, handleObj.handler, j ); - eventType.splice( j--, 1 ); - } - } - - continue; - } - - special = jQuery.event.special[ type ] || {}; - - for ( j = pos || 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( handler.guid === handleObj.guid ) { - // remove the given handler for the given type - if ( all || namespace.test( handleObj.namespace ) ) { - if ( pos == null ) { - eventType.splice( j--, 1 ); - } - - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - - if ( pos != null ) { - break; - } - } - } - - // remove generic event handler if no more handlers exist - if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - ret = null; - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - var handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - delete elemData.events; - delete elemData.handle; - - if ( jQuery.isEmptyObject( elemData ) ) { - jQuery.removeData( elem, undefined, true ); - } - } - }, - - // Events that are safe to short-circuit if no handlers are attached. - // Native DOM events should not be added, they may have inline handlers. - customEvent: { - "getData": true, - "setData": true, - "changeData": true - }, - - trigger: function( event, data, elem, onlyHandlers ) { - // Event object or event type - var type = event.type || event, - namespaces = [], - exclusive; - - if ( type.indexOf("!") >= 0 ) { - // Exclusive events trigger only for the exact event (no namespaces) - type = type.slice(0, -1); - exclusive = true; - } - - if ( type.indexOf(".") >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - - if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { - // No jQuery handlers for this event type, and it can't have inline handlers - return; - } - - // Caller can pass in an Event, Object, or just an event type string - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - new jQuery.Event( type, event ) : - // Just the event type (string) - new jQuery.Event( type ); - - event.type = type; - event.exclusive = exclusive; - event.namespace = namespaces.join("."); - event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); - - // triggerHandler() and global events don't bubble or run the default action - if ( onlyHandlers || !elem ) { - event.preventDefault(); - event.stopPropagation(); - } - - // Handle a global trigger - if ( !elem ) { - // TODO: Stop taunting the data cache; remove global events and always attach to document - jQuery.each( jQuery.cache, function() { - // internalKey variable is just used to make it easier to find - // and potentially change this stuff later; currently it just - // points to jQuery.expando - var internalKey = jQuery.expando, - internalCache = this[ internalKey ]; - if ( internalCache && internalCache.events && internalCache.events[ type ] ) { - jQuery.event.trigger( event, data, internalCache.handle.elem ); - } - }); - return; - } - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // Clean up the event in case it is being reused - event.result = undefined; - event.target = elem; - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data != null ? jQuery.makeArray( data ) : []; - data.unshift( event ); - - var cur = elem, - // IE doesn't like method names with a colon (#3533, #8272) - ontype = type.indexOf(":") < 0 ? "on" + type : ""; - - // Fire event on the current element, then bubble up the DOM tree - do { - var handle = jQuery._data( cur, "handle" ); - - event.currentTarget = cur; - if ( handle ) { - handle.apply( cur, data ); - } - - // Trigger an inline bound script - if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { - event.result = false; - event.preventDefault(); - } - - // Bubble up to document, then to window - cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; - } while ( cur && !event.isPropagationStopped() ); - - // If nobody prevented the default action, do it now - if ( !event.isDefaultPrevented() ) { - var old, - special = jQuery.event.special[ type ] || {}; - - if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction)() check here because IE6/7 fails that test. - // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. - try { - if ( ontype && elem[ type ] ) { - // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; - - if ( old ) { - elem[ ontype ] = null; - } - - jQuery.event.triggered = type; - elem[ type ](); - } - } catch ( ieError ) {} - - if ( old ) { - elem[ ontype ] = old; - } - - jQuery.event.triggered = undefined; - } - } - - return event.result; - }, - - handle: function( event ) { - event = jQuery.event.fix( event || window.event ); - // Snapshot the handlers list since a called handler may add/remove events. - var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), - run_all = !event.exclusive && !event.namespace, - args = Array.prototype.slice.call( arguments, 0 ); - - // Use the fix-ed Event rather than the (read-only) native event - args[0] = event; - event.currentTarget = this; - - for ( var j = 0, l = handlers.length; j < l; j++ ) { - var handleObj = handlers[ j ]; - - // Triggered event must 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event. - if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handleObj.handler; - event.data = handleObj.data; - event.handleObj = handleObj; - - var ret = handleObj.handler.apply( this, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - return event.result; - }, - - props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // store a copy of the original event object - // and "clone" to set read-only properties - var originalEvent = event; - event = jQuery.Event( originalEvent ); - - for ( var i = this.props.length, prop; i; ) { - prop = this.props[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary - if ( !event.target ) { - // Fixes #1925 where srcElement might not be defined either - event.target = event.srcElement || document; - } - - // check if target is a textnode (safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && event.fromElement ) { - event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; - } - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && event.clientX != null ) { - var eventDocument = event.target.ownerDocument || document, - doc = eventDocument.documentElement, - body = eventDocument.body; - - event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Add which for key events - if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { - event.which = event.charCode != null ? event.charCode : event.keyCode; - } - - // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) - if ( !event.metaKey && event.ctrlKey ) { - event.metaKey = event.ctrlKey; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && event.button !== undefined ) { - event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); - } - - return event; - }, - - // Deprecated, use jQuery.guid instead - guid: 1E8, - - // Deprecated, use jQuery.proxy instead - proxy: jQuery.proxy, - - special: { - ready: { - // Make sure the ready event is setup - setup: jQuery.bindReady, - teardown: jQuery.noop - }, - - live: { - add: function( handleObj ) { - jQuery.event.add( this, - liveConvert( handleObj.origType, handleObj.selector ), - jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); - }, - - remove: function( handleObj ) { - jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); - } - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - } -}; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !this.preventDefault ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // timeStamp is buggy for some events on Firefox(#3843) - // So we won't rely on the native value - this.timeStamp = jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Checks if an event happened on an element within another element -// Used in jQuery.event.special.mouseenter and mouseleave handlers -var withinElement = function( event ) { - - // Check if mouse(over|out) are still within the same parent element - var related = event.relatedTarget, - inside = false, - eventType = event.type; - - event.type = event.data; - - if ( related !== this ) { - - if ( related ) { - inside = jQuery.contains( this, related ); - } - - if ( !inside ) { - - jQuery.event.handle.apply( this, arguments ); - - event.type = eventType; - } - } -}, - -// In case of event delegation, we only need to rename the event.type, -// liveHandler will take care of the rest. -delegate = function( event ) { - event.type = event.data; - jQuery.event.handle.apply( this, arguments ); -}; - -// Create mouseenter and mouseleave events -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - setup: function( data ) { - jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); - }, - teardown: function( data ) { - jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); - } - }; -}); - -// submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function( data, namespaces ) { - if ( !jQuery.nodeName( this, "form" ) ) { - jQuery.event.add(this, "click.specialSubmit", function( e ) { - // Avoid triggering error on non-existent type attribute in IE VML (#7071) - var elem = e.target, - type = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.type : ""; - - if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { - trigger( "submit", this, arguments ); - } - }); - - jQuery.event.add(this, "keypress.specialSubmit", function( e ) { - var elem = e.target, - type = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.type : ""; - - if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { - trigger( "submit", this, arguments ); - } - }); - - } else { - return false; - } - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialSubmit" ); - } - }; - -} - -// change delegation, happens here so we have bind. -if ( !jQuery.support.changeBubbles ) { - - var changeFilters, - - getVal = function( elem ) { - var type = jQuery.nodeName( elem, "input" ) ? elem.type : "", - val = elem.value; - - if ( type === "radio" || type === "checkbox" ) { - val = elem.checked; - - } else if ( type === "select-multiple" ) { - val = elem.selectedIndex > -1 ? - jQuery.map( elem.options, function( elem ) { - return elem.selected; - }).join("-") : - ""; - - } else if ( jQuery.nodeName( elem, "select" ) ) { - val = elem.selectedIndex; - } - - return val; - }, - - testChange = function testChange( e ) { - var elem = e.target, data, val; - - if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { - return; - } - - data = jQuery._data( elem, "_change_data" ); - val = getVal(elem); - - // the current data will be also retrieved by beforeactivate - if ( e.type !== "focusout" || elem.type !== "radio" ) { - jQuery._data( elem, "_change_data", val ); - } - - if ( data === undefined || val === data ) { - return; - } - - if ( data != null || val ) { - e.type = "change"; - e.liveFired = undefined; - jQuery.event.trigger( e, arguments[1], elem ); - } - }; - - jQuery.event.special.change = { - filters: { - focusout: testChange, - - beforedeactivate: testChange, - - click: function( e ) { - var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; - - if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { - testChange.call( this, e ); - } - }, - - // Change has to be called before submit - // Keydown will be called before keypress, which is used in submit-event delegation - keydown: function( e ) { - var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; - - if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || - (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || - type === "select-multiple" ) { - testChange.call( this, e ); - } - }, - - // Beforeactivate happens also before the previous element is blurred - // with this event you can't trigger a change event, but you can store - // information - beforeactivate: function( e ) { - var elem = e.target; - jQuery._data( elem, "_change_data", getVal(elem) ); - } - }, - - setup: function( data, namespaces ) { - if ( this.type === "file" ) { - return false; - } - - for ( var type in changeFilters ) { - jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); - } - - return rformElems.test( this.nodeName ); - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialChange" ); - - return rformElems.test( this.nodeName ); - } - }; - - changeFilters = jQuery.event.special.change.filters; - - // Handle when the input is .focus()'d - changeFilters.focus = changeFilters.beforeactivate; -} - -function trigger( type, elem, args ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - // Don't pass args or remember liveFired; they apply to the donor event. - var event = jQuery.extend( {}, args[ 0 ] ); - event.type = type; - event.originalEvent = {}; - event.liveFired = undefined; - jQuery.event.handle.call( elem, event ); - if ( event.isDefaultPrevented() ) { - args[ 0 ].preventDefault(); - } -} - -// Create "bubbling" focus and blur events -if ( !jQuery.support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler while someone wants focusin/focusout - var attaches = 0; - - jQuery.event.special[ fix ] = { - setup: function() { - if ( attaches++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --attaches === 0 ) { - document.removeEventListener( orig, handler, true ); - } - } - }; - - function handler( donor ) { - // Donor event is always a native one; fix it and switch its type. - // Let focusin/out handler cancel the donor focus/blur event. - var e = jQuery.event.fix( donor ); - e.type = fix; - e.originalEvent = {}; - jQuery.event.trigger( e, null, e.target ); - if ( e.isDefaultPrevented() ) { - donor.preventDefault(); - } - } - }); -} - -jQuery.each(["bind", "one"], function( i, name ) { - jQuery.fn[ name ] = function( type, data, fn ) { - var handler; - - // Handle object literals - if ( typeof type === "object" ) { - for ( var key in type ) { - this[ name ](key, data, type[key], fn); - } - return this; - } - - if ( arguments.length === 2 || data === false ) { - fn = data; - data = undefined; - } - - if ( name === "one" ) { - handler = function( event ) { - jQuery( this ).unbind( event, handler ); - return fn.apply( this, arguments ); - }; - handler.guid = fn.guid || jQuery.guid++; - } else { - handler = fn; - } - - if ( type === "unload" && name !== "one" ) { - this.one( type, data, fn ); - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.add( this[i], type, handler, data ); - } - } - - return this; - }; -}); - -jQuery.fn.extend({ - unbind: function( type, fn ) { - // Handle object literals - if ( typeof type === "object" && !type.preventDefault ) { - for ( var key in type ) { - this.unbind(key, type[key]); - } - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.remove( this[i], type, fn ); - } - } - - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.live( types, data, fn, selector ); - }, - - undelegate: function( selector, types, fn ) { - if ( arguments.length === 0 ) { - return this.unbind( "live" ); - - } else { - return this.die( types, null, fn, selector ); - } - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - - triggerHandler: function( type, data ) { - if ( this[0] ) { - return jQuery.event.trigger( type, data, this[0], true ); - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - guid = fn.guid || jQuery.guid++, - i = 0, - toggler = function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - }; - - // link all the functions, so any of them can unbind this click handler - toggler.guid = guid; - while ( i < args.length ) { - args[ i++ ].guid = guid; - } - - return this.click( toggler ); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -var liveMap = { - focus: "focusin", - blur: "focusout", - mouseenter: "mouseover", - mouseleave: "mouseout" -}; - -jQuery.each(["live", "die"], function( i, name ) { - jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { - var type, i = 0, match, namespaces, preType, - selector = origSelector || this.selector, - context = origSelector ? this : jQuery( this.context ); - - if ( typeof types === "object" && !types.preventDefault ) { - for ( var key in types ) { - context[ name ]( key, data, types[key], selector ); - } - - return this; - } - - if ( name === "die" && !types && - origSelector && origSelector.charAt(0) === "." ) { - - context.unbind( origSelector ); - - return this; - } - - if ( data === false || jQuery.isFunction( data ) ) { - fn = data || returnFalse; - data = undefined; - } - - types = (types || "").split(" "); - - while ( (type = types[ i++ ]) != null ) { - match = rnamespaces.exec( type ); - namespaces = ""; - - if ( match ) { - namespaces = match[0]; - type = type.replace( rnamespaces, "" ); - } - - if ( type === "hover" ) { - types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); - continue; - } - - preType = type; - - if ( liveMap[ type ] ) { - types.push( liveMap[ type ] + namespaces ); - type = type + namespaces; - - } else { - type = (liveMap[ type ] || type) + namespaces; - } - - if ( name === "live" ) { - // bind live handler - for ( var j = 0, l = context.length; j < l; j++ ) { - jQuery.event.add( context[j], "live." + liveConvert( type, selector ), - { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); - } - - } else { - // unbind live handler - context.unbind( "live." + liveConvert( type, selector ), fn ); - } - } - - return this; - }; -}); - -function liveHandler( event ) { - var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, - elems = [], - selectors = [], - events = jQuery._data( this, "events" ); - - // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) - if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { - return; - } - - if ( event.namespace ) { - namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.liveFired = this; - - var live = events.live.slice(0); - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { - selectors.push( handleObj.selector ); - - } else { - live.splice( j--, 1 ); - } - } - - match = jQuery( event.target ).closest( selectors, event.currentTarget ); - - for ( i = 0, l = match.length; i < l; i++ ) { - close = match[i]; - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { - elem = close.elem; - related = null; - - // Those two events require additional checking - if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { - event.type = handleObj.preType; - related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; - - // Make sure not to accidentally match a child element with the same selector - if ( related && jQuery.contains( elem, related ) ) { - related = elem; - } - } - - if ( !related || related !== elem ) { - elems.push({ elem: elem, handleObj: handleObj, level: close.level }); - } - } - } - } - - for ( i = 0, l = elems.length; i < l; i++ ) { - match = elems[i]; - - if ( maxLevel && match.level > maxLevel ) { - break; - } - - event.currentTarget = match.elem; - event.data = match.handleObj.data; - event.handleObj = match.handleObj; - - ret = match.handleObj.origHandler.apply( match.elem, arguments ); - - if ( ret === false || event.isPropagationStopped() ) { - maxLevel = match.level; - - if ( ret === false ) { - stop = false; - } - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - - return stop; -} - -function liveConvert( type, selector ) { - return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); -} - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.bind( name, data, fn ) : - this.trigger( name ); - }; - - if ( jQuery.attrFn ) { - jQuery.attrFn[ name ] = true; - } -}); - - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var match, - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - var left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - var found, item, - filter = Expr.filter[ type ], - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw "Syntax error, unrecognized expression: " + msg; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); - }, - - radio: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; - }, - - checkbox: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; - }, - - file: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; - }, - - password: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; - }, - - submit: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "submit" === elem.type; - }, - - image: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; - }, - - reset: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "reset" === elem.type; - }, - - button: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && "button" === elem.type || name === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - }, - - focus: function( elem ) { - return elem === elem.ownerDocument.activeElement; - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - var first = match[2], - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Utility function for retreiving the text value of an array of DOM nodes -Sizzle.getText = function( elems ) { - var ret = "", elem; - - for ( var i = 0; elems[i]; i++ ) { - elem = elems[i]; - - // Get the text from text nodes and CDATA nodes - if ( elem.nodeType === 3 || elem.nodeType === 4 ) { - ret += elem.nodeValue; - - // Traverse everything else, except comment nodes - } else if ( elem.nodeType !== 8 ) { - ret += Sizzle.getText( elem.childNodes ); - } - } - - return ret; -}; - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

          "; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; - - if ( matches ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9 fails this) - var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - var ret = matches.call( node, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || !disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9, so check for that - node.document && node.document.nodeType !== 11 ) { - return ret; - } - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
          "; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = jQuery.expr.match.POS, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var self = this, - i, l; - - if ( typeof selector !== "string" ) { - return jQuery( selector ).filter(function() { - for ( i = 0, l = self.length; i < l; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }); - } - - var ret = this.pushStack( "", "find", selector ), - length, n, r; - - for ( i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( n = length; n < ret.length; n++ ) { - for ( r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var targets = jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && ( typeof selector === "string" ? - jQuery.filter( selector, this ).length > 0 : - this.filter( selector ).length > 0 ); - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - // Array - if ( jQuery.isArray( selectors ) ) { - var match, selector, - matches = {}, - level = 1; - - if ( cur && selectors.length ) { - for ( i = 0, l = selectors.length; i < l; i++ ) { - selector = selectors[i]; - - if ( !matches[ selector ] ) { - matches[ selector ] = POS.test( selector ) ? - jQuery( selector, context || this.context ) : - selector; - } - } - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( selector in matches ) { - match = matches[ selector ]; - - if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { - ret.push({ selector: selector, elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - } - - return ret; - } - - // String - var pos = POS.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { - break; - } - } - } - } - - ret = ret.length > 1 ? jQuery.unique( ret ) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return jQuery.inArray( this[0], jQuery( elem ) ); - } - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return jQuery.nth( elem, 2, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( elem.parentNode.firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ), - // The variable 'args' was introduced in - // https://github.com/jquery/jquery/commit/52a0238 - // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. - // http://code.google.com/p/v8/issues/detail?id=1050 - args = slice.call(arguments); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, args.join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - - // Can't pass null or undefined to indexOf in Firefox 4 - // Set to 0 to skip string check - qualifier = qualifier || 0; - - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return (elem === qualifier) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return (jQuery.inArray( elem, qualifier ) >= 0) === keep; - }); -} - - - - -var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /", "" ], - legend: [ 1, "
          ", "
          " ], - thead: [ 1, "", "
          " ], - tr: [ 2, "", "
          " ], - td: [ 3, "", "
          " ], - col: [ 2, "", "
          " ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }; - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and "; + } } - } - function get_latitude() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) - { - return (float) $return[0]['data']; - } - elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) - { - return (float) $match[1]; - } - else + // Flash Media Player file types. + // Preferred handler for MP3 file types. + elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== '')) { - return null; + $height += 20; + if ($native) + { + $embed .= "get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\">"; + } + else + { + $embed .= ""; + } } - } - function get_longitude() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) - { - return (float) $return[0]['data']; - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) - { - return (float) $return[0]['data']; - } - elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) - { - return (float) $match[2]; - } - else + // QuickTime 7 file types. Need to test with QuickTime 6. + // Only handle MP3's if the Flash Media Player is not present. + elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === '')) { - return null; + $height += 16; + if ($native) + { + if ($placeholder !== '') + { + $embed .= "get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\">"; + } + else + { + $embed .= "get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\">"; + } + } + else + { + $embed .= ""; + } } - } - function get_image_url() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image')) - { - return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); - } - else + // Windows Media + elseif ($handler === 'wmedia') { - return null; + $height += 45; + if ($native) + { + $embed .= "get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\">"; + } + else + { + $embed .= ""; + } } - } -} -class SimplePie_Author -{ - var $name; - var $link; - var $email; + // Everything else + else $embed .= '' . $alt . ''; - // Constructor, used to input the data - function SimplePie_Author($name = null, $link = null, $email = null) - { - $this->name = $name; - $this->link = $link; - $this->email = $email; + return $embed; } - function __toString() + /** + * Get the real media type + * + * Often, feeds lie to us, necessitating a bit of deeper inspection. This + * converts types to their canonical representations based on the file + * extension + * + * @see get_type() + * @param bool $find_handler Internal use only, use {@see get_handler()} instead + * @return string MIME type + */ + public function get_real_type($find_handler = false) { - // There is no $this->data here - return md5(serialize($this)); - } + // Mime-types by handler. + $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash + $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player + $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime + $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media + $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3 - function get_name() - { - if ($this->name !== null) + if ($this->get_type() !== null) { - return $this->name; + $type = strtolower($this->type); } else { - return null; + $type = null; } - } - function get_link() - { - if ($this->link !== null) - { - return $this->link; - } - else + // If we encounter an unsupported mime-type, check the file extension and guess intelligently. + if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3))) { - return null; - } - } + switch (strtolower($this->get_extension())) + { + // Audio mime-types + case 'aac': + case 'adts': + $type = 'audio/acc'; + break; - function get_email() - { - if ($this->email !== null) - { - return $this->email; - } - else - { - return null; - } - } -} + case 'aif': + case 'aifc': + case 'aiff': + case 'cdda': + $type = 'audio/aiff'; + break; -class SimplePie_Category -{ - var $term; - var $scheme; - var $label; + case 'bwf': + $type = 'audio/wav'; + break; - // Constructor, used to input the data - function SimplePie_Category($term = null, $scheme = null, $label = null) - { - $this->term = $term; - $this->scheme = $scheme; - $this->label = $label; - } + case 'kar': + case 'mid': + case 'midi': + case 'smf': + $type = 'audio/midi'; + break; - function __toString() - { - // There is no $this->data here - return md5(serialize($this)); - } + case 'm4a': + $type = 'audio/x-m4a'; + break; - function get_term() - { - if ($this->term !== null) - { - return $this->term; - } - else - { - return null; - } - } + case 'mp3': + case 'swa': + $type = 'audio/mp3'; + break; - function get_scheme() - { - if ($this->scheme !== null) - { - return $this->scheme; - } - else - { - return null; + case 'wav': + $type = 'audio/wav'; + break; + + case 'wax': + $type = 'audio/x-ms-wax'; + break; + + case 'wma': + $type = 'audio/x-ms-wma'; + break; + + // Video mime-types + case '3gp': + case '3gpp': + $type = 'video/3gpp'; + break; + + case '3g2': + case '3gp2': + $type = 'video/3gpp2'; + break; + + case 'asf': + $type = 'video/x-ms-asf'; + break; + + case 'flv': + $type = 'video/x-flv'; + break; + + case 'm1a': + case 'm1s': + case 'm1v': + case 'm15': + case 'm75': + case 'mp2': + case 'mpa': + case 'mpeg': + case 'mpg': + case 'mpm': + case 'mpv': + $type = 'video/mpeg'; + break; + + case 'm4v': + $type = 'video/x-m4v'; + break; + + case 'mov': + case 'qt': + $type = 'video/quicktime'; + break; + + case 'mp4': + case 'mpg4': + $type = 'video/mp4'; + break; + + case 'sdv': + $type = 'video/sd-video'; + break; + + case 'wm': + $type = 'video/x-ms-wm'; + break; + + case 'wmv': + $type = 'video/x-ms-wmv'; + break; + + case 'wvx': + $type = 'video/x-ms-wvx'; + break; + + // Flash mime-types + case 'spl': + $type = 'application/futuresplash'; + break; + + case 'swf': + $type = 'application/x-shockwave-flash'; + break; + } } - } - function get_label() - { - if ($this->label !== null) + if ($find_handler) { - return $this->label; + if (in_array($type, $types_flash)) + { + return 'flash'; + } + elseif (in_array($type, $types_fmedia)) + { + return 'fmedia'; + } + elseif (in_array($type, $types_quicktime)) + { + return 'quicktime'; + } + elseif (in_array($type, $types_wmedia)) + { + return 'wmedia'; + } + elseif (in_array($type, $types_mp3)) + { + return 'mp3'; + } + else + { + return null; + } } else { - return $this->get_term(); + return $type; } } } -class SimplePie_Enclosure +/** + * General SimplePie exception class + * + * @package SimplePie + */ +class SimplePie_Exception extends Exception { - var $bitrate; - var $captions; - var $categories; - var $channels; - var $copyright; - var $credits; - var $description; - var $duration; - var $expression; - var $framerate; - var $handler; - var $hashes; - var $height; - var $javascript; - var $keywords; - var $lang; - var $length; - var $link; - var $medium; - var $player; - var $ratings; - var $restrictions; - var $samplingrate; - var $thumbnails; - var $title; - var $type; - var $width; +} + +/** + * Used for fetching remote files and reading local files + * + * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support + * + * This class can be overloaded with {@see SimplePie::set_file_class()} + * + * @package SimplePie + * @subpackage HTTP + * @todo Move to properly supporting RFC2616 (HTTP/1.1) + */ +class SimplePie_File +{ + var $url; + var $useragent; + var $success = true; + var $headers = array(); + var $body; + var $status_code; + var $redirects = 0; + var $error; + var $method = SIMPLEPIE_FILE_SOURCE_NONE; - // Constructor, used to input the data - function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null) + public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) { - $this->bitrate = $bitrate; - $this->captions = $captions; - $this->categories = $categories; - $this->channels = $channels; - $this->copyright = $copyright; - $this->credits = $credits; - $this->description = $description; - $this->duration = $duration; - $this->expression = $expression; - $this->framerate = $framerate; - $this->hashes = $hashes; - $this->height = $height; - $this->javascript = $javascript; - $this->keywords = $keywords; - $this->lang = $lang; - $this->length = $length; - $this->link = $link; - $this->medium = $medium; - $this->player = $player; - $this->ratings = $ratings; - $this->restrictions = $restrictions; - $this->samplingrate = $samplingrate; - $this->thumbnails = $thumbnails; - $this->title = $title; - $this->type = $type; - $this->width = $width; if (class_exists('idna_convert')) { - $idn = new idna_convert; - $parsed = SimplePie_Misc::parse_url($link); - $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']); + $idn = new idna_convert(); + $parsed = SimplePie_Misc::parse_url($url); + $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']); } - $this->handler = $this->get_handler(); // Needs to load last - } + $this->url = $url; + $this->useragent = $useragent; + if (preg_match('/^http(s)?:\/\//i', $url)) + { + if ($useragent === null) + { + $useragent = ini_get('user_agent'); + $this->useragent = $useragent; + } + if (!is_array($headers)) + { + $headers = array(); + } + if (!$force_fsockopen && function_exists('curl_exec')) + { + $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL; + $fp = curl_init(); + $headers2 = array(); + foreach ($headers as $key => $value) + { + $headers2[] = "$key: $value"; + } + if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>=')) + { + curl_setopt($fp, CURLOPT_ENCODING, ''); + } + curl_setopt($fp, CURLOPT_URL, $url); + curl_setopt($fp, CURLOPT_HEADER, 1); + curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($fp, CURLOPT_TIMEOUT, $timeout); + curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout); + curl_setopt($fp, CURLOPT_REFERER, $url); + curl_setopt($fp, CURLOPT_USERAGENT, $useragent); + curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2); + if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>=')) + { + curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects); + } - function __toString() - { - // There is no $this->data here - return md5(serialize($this)); - } + $this->headers = curl_exec($fp); + if (curl_errno($fp) === 23 || curl_errno($fp) === 61) + { + curl_setopt($fp, CURLOPT_ENCODING, 'none'); + $this->headers = curl_exec($fp); + } + if (curl_errno($fp)) + { + $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp); + $this->success = false; + } + else + { + $info = curl_getinfo($fp); + curl_close($fp); + $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1); + $this->headers = array_pop($this->headers); + $parser = new SimplePie_HTTP_Parser($this->headers); + if ($parser->parse()) + { + $this->headers = $parser->headers; + $this->body = $parser->body; + $this->status_code = $parser->status_code; + if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) + { + $this->redirects++; + $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url); + return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen); + } + } + } + } + else + { + $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN; + $url_parts = parse_url($url); + $socket_host = $url_parts['host']; + if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') + { + $socket_host = "ssl://$url_parts[host]"; + $url_parts['port'] = 443; + } + if (!isset($url_parts['port'])) + { + $url_parts['port'] = 80; + } + $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout); + if (!$fp) + { + $this->error = 'fsockopen error: ' . $errstr; + $this->success = false; + } + else + { + stream_set_timeout($fp, $timeout); + if (isset($url_parts['path'])) + { + if (isset($url_parts['query'])) + { + $get = "$url_parts[path]?$url_parts[query]"; + } + else + { + $get = $url_parts['path']; + } + } + else + { + $get = '/'; + } + $out = "GET $get HTTP/1.1\r\n"; + $out .= "Host: $url_parts[host]\r\n"; + $out .= "User-Agent: $useragent\r\n"; + if (extension_loaded('zlib')) + { + $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n"; + } - function get_bitrate() - { - if ($this->bitrate !== null) - { - return $this->bitrate; - } - else - { - return null; - } - } + if (isset($url_parts['user']) && isset($url_parts['pass'])) + { + $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n"; + } + foreach ($headers as $key => $value) + { + $out .= "$key: $value\r\n"; + } + $out .= "Connection: Close\r\n\r\n"; + fwrite($fp, $out); - function get_caption($key = 0) - { - $captions = $this->get_captions(); - if (isset($captions[$key])) - { - return $captions[$key]; - } - else - { - return null; - } - } + $info = stream_get_meta_data($fp); - function get_captions() - { - if ($this->captions !== null) - { - return $this->captions; + $this->headers = ''; + while (!$info['eof'] && !$info['timed_out']) + { + $this->headers .= fread($fp, 1160); + $info = stream_get_meta_data($fp); + } + if (!$info['timed_out']) + { + $parser = new SimplePie_HTTP_Parser($this->headers); + if ($parser->parse()) + { + $this->headers = $parser->headers; + $this->body = $parser->body; + $this->status_code = $parser->status_code; + if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) + { + $this->redirects++; + $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url); + return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen); + } + if (isset($this->headers['content-encoding'])) + { + // Hey, we act dumb elsewhere, so let's do that here too + switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20"))) + { + case 'gzip': + case 'x-gzip': + $decoder = new SimplePie_gzdecode($this->body); + if (!$decoder->parse()) + { + $this->error = 'Unable to decode HTTP "gzip" stream'; + $this->success = false; + } + else + { + $this->body = $decoder->data; + } + break; + + case 'deflate': + if (($decompressed = gzinflate($this->body)) !== false) + { + $this->body = $decompressed; + } + else if (($decompressed = gzuncompress($this->body)) !== false) + { + $this->body = $decompressed; + } + else if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false) + { + $this->body = $decompressed; + } + else + { + $this->error = 'Unable to decode HTTP "deflate" stream'; + $this->success = false; + } + break; + + default: + $this->error = 'Unknown content coding'; + $this->success = false; + } + } + } + } + else + { + $this->error = 'fsocket timed out'; + $this->success = false; + } + fclose($fp); + } + } } else { - return null; + $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS; + if (!$this->body = file_get_contents($url)) + { + $this->error = 'file_get_contents could not read the file'; + $this->success = false; + } } } +} - function get_category($key = 0) - { - $categories = $this->get_categories(); - if (isset($categories[$key])) - { - return $categories[$key]; - } - else - { - return null; - } - } +/** + * Decode 'gzip' encoded HTTP data + * + * @package SimplePie + * @subpackage HTTP + * @link http://www.gzip.org/format.txt + */ +class SimplePie_gzdecode +{ + /** + * Compressed data + * + * @access private + * @var string + * @see gzdecode::$data + */ + var $compressed_data; - function get_categories() - { - if ($this->categories !== null) - { - return $this->categories; - } - else - { - return null; - } - } + /** + * Size of compressed data + * + * @access private + * @var int + */ + var $compressed_size; - function get_channels() - { - if ($this->channels !== null) - { - return $this->channels; - } - else - { - return null; - } - } + /** + * Minimum size of a valid gzip string + * + * @access private + * @var int + */ + var $min_compressed_size = 18; - function get_copyright() - { - if ($this->copyright !== null) - { - return $this->copyright; - } - else - { - return null; - } - } + /** + * Current position of pointer + * + * @access private + * @var int + */ + var $position = 0; - function get_credit($key = 0) - { - $credits = $this->get_credits(); - if (isset($credits[$key])) - { - return $credits[$key]; - } - else - { - return null; - } - } + /** + * Flags (FLG) + * + * @access private + * @var int + */ + var $flags; + + /** + * Uncompressed data + * + * @access public + * @see gzdecode::$compressed_data + * @var string + */ + var $data; + + /** + * Modified time + * + * @access public + * @var int + */ + var $MTIME; + + /** + * Extra Flags + * + * @access public + * @var int + */ + var $XFL; + + /** + * Operating System + * + * @access public + * @var int + */ + var $OS; + + /** + * Subfield ID 1 + * + * @access public + * @see gzdecode::$extra_field + * @see gzdecode::$SI2 + * @var string + */ + var $SI1; + + /** + * Subfield ID 2 + * + * @access public + * @see gzdecode::$extra_field + * @see gzdecode::$SI1 + * @var string + */ + var $SI2; + + /** + * Extra field content + * + * @access public + * @see gzdecode::$SI1 + * @see gzdecode::$SI2 + * @var string + */ + var $extra_field; + + /** + * Original filename + * + * @access public + * @var string + */ + var $filename; + + /** + * Human readable comment + * + * @access public + * @var string + */ + var $comment; - function get_credits() + /** + * Don't allow anything to be set + * + * @param string $name + * @param mixed $value + */ + public function __set($name, $value) { - if ($this->credits !== null) - { - return $this->credits; - } - else - { - return null; - } + trigger_error("Cannot write property $name", E_USER_ERROR); } - function get_description() + /** + * Set the compressed string and related properties + * + * @param string $data + */ + public function __construct($data) { - if ($this->description !== null) - { - return $this->description; - } - else - { - return null; - } + $this->compressed_data = $data; + $this->compressed_size = strlen($data); } - function get_duration($convert = false) + /** + * Decode the GZIP stream + * + * @return bool Successfulness + */ + public function parse() { - if ($this->duration !== null) + if ($this->compressed_size >= $this->min_compressed_size) { - if ($convert) + // Check ID1, ID2, and CM + if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08") { - $time = SimplePie_Misc::time_hms($this->duration); - return $time; + return false; } - else + + // Get the FLG (FLaGs) + $this->flags = ord($this->compressed_data[3]); + + // FLG bits above (1 << 4) are reserved + if ($this->flags > 0x1F) { - return $this->duration; + return false; } - } - else - { - return null; - } - } - function get_expression() - { - if ($this->expression !== null) - { - return $this->expression; - } - else - { - return 'full'; - } - } + // Advance the pointer after the above + $this->position += 4; - function get_extension() - { - if ($this->link !== null) - { - $url = SimplePie_Misc::parse_url($this->link); - if ($url['path'] !== '') + // MTIME + $mtime = substr($this->compressed_data, $this->position, 4); + // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness + if (current(unpack('S', "\x00\x01")) === 1) { - return pathinfo($url['path'], PATHINFO_EXTENSION); + $mtime = strrev($mtime); } - } - return null; - } + $this->MTIME = current(unpack('l', $mtime)); + $this->position += 4; - function get_framerate() - { - if ($this->framerate !== null) - { - return $this->framerate; + // Get the XFL (eXtra FLags) + $this->XFL = ord($this->compressed_data[$this->position++]); + + // Get the OS (Operating System) + $this->OS = ord($this->compressed_data[$this->position++]); + + // Parse the FEXTRA + if ($this->flags & 4) + { + // Read subfield IDs + $this->SI1 = $this->compressed_data[$this->position++]; + $this->SI2 = $this->compressed_data[$this->position++]; + + // SI2 set to zero is reserved for future use + if ($this->SI2 === "\x00") + { + return false; + } + + // Get the length of the extra field + $len = current(unpack('v', substr($this->compressed_data, $this->position, 2))); + $this->position += 2; + + // Check the length of the string is still valid + $this->min_compressed_size += $len + 4; + if ($this->compressed_size >= $this->min_compressed_size) + { + // Set the extra field to the given data + $this->extra_field = substr($this->compressed_data, $this->position, $len); + $this->position += $len; + } + else + { + return false; + } + } + + // Parse the FNAME + if ($this->flags & 8) + { + // Get the length of the filename + $len = strcspn($this->compressed_data, "\x00", $this->position); + + // Check the length of the string is still valid + $this->min_compressed_size += $len + 1; + if ($this->compressed_size >= $this->min_compressed_size) + { + // Set the original filename to the given string + $this->filename = substr($this->compressed_data, $this->position, $len); + $this->position += $len + 1; + } + else + { + return false; + } + } + + // Parse the FCOMMENT + if ($this->flags & 16) + { + // Get the length of the comment + $len = strcspn($this->compressed_data, "\x00", $this->position); + + // Check the length of the string is still valid + $this->min_compressed_size += $len + 1; + if ($this->compressed_size >= $this->min_compressed_size) + { + // Set the original comment to the given string + $this->comment = substr($this->compressed_data, $this->position, $len); + $this->position += $len + 1; + } + else + { + return false; + } + } + + // Parse the FHCRC + if ($this->flags & 2) + { + // Check the length of the string is still valid + $this->min_compressed_size += $len + 2; + if ($this->compressed_size >= $this->min_compressed_size) + { + // Read the CRC + $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2))); + + // Check the CRC matches + if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc) + { + $this->position += 2; + } + else + { + return false; + } + } + else + { + return false; + } + } + + // Decompress the actual data + if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false) + { + return false; + } + else + { + $this->position = $this->compressed_size - 8; + } + + // Check CRC of data + $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4))); + $this->position += 4; + /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc)) + { + return false; + }*/ + + // Check ISIZE of data + $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4))); + $this->position += 4; + if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize)) + { + return false; + } + + // Wow, against all odds, we've actually got a valid gzip string + return true; } else { - return null; + return false; } } +} - function get_handler() - { - return $this->get_real_type(true); - } +/** + * HTTP Response Parser + * + * @package SimplePie + * @subpackage HTTP + */ +class SimplePie_HTTP_Parser +{ + /** + * HTTP Version + * + * @var float + */ + public $http_version = 0.0; + + /** + * Status code + * + * @var int + */ + public $status_code = 0; + + /** + * Reason phrase + * + * @var string + */ + public $reason = ''; + + /** + * Key/value pairs of the headers + * + * @var array + */ + public $headers = array(); + + /** + * Body of the response + * + * @var string + */ + public $body = ''; + + /** + * Current state of the state machine + * + * @var string + */ + protected $state = 'http_version'; + + /** + * Input data + * + * @var string + */ + protected $data = ''; + + /** + * Input data length (to avoid calling strlen() everytime this is needed) + * + * @var int + */ + protected $data_length = 0; + + /** + * Current position of the pointer + * + * @var int + */ + protected $position = 0; + + /** + * Name of the hedaer currently being parsed + * + * @var string + */ + protected $name = ''; + + /** + * Value of the hedaer currently being parsed + * + * @var string + */ + protected $value = ''; - function get_hash($key = 0) + /** + * Create an instance of the class with the input data + * + * @param string $data Input data + */ + public function __construct($data) { - $hashes = $this->get_hashes(); - if (isset($hashes[$key])) - { - return $hashes[$key]; - } - else - { - return null; - } + $this->data = $data; + $this->data_length = strlen($this->data); } - function get_hashes() + /** + * Parse the input data + * + * @return bool true on success, false on failure + */ + public function parse() { - if ($this->hashes !== null) - { - return $this->hashes; - } - else + while ($this->state && $this->state !== 'emit' && $this->has_data()) { - return null; + $state = $this->state; + $this->$state(); } - } - - function get_height() - { - if ($this->height !== null) + $this->data = ''; + if ($this->state === 'emit' || $this->state === 'body') { - return $this->height; + return true; } else { - return null; + $this->http_version = ''; + $this->status_code = ''; + $this->reason = ''; + $this->headers = array(); + $this->body = ''; + return false; } } - function get_language() - { - if ($this->lang !== null) - { - return $this->lang; - } - else - { - return null; - } + /** + * Check whether there is data beyond the pointer + * + * @return bool true if there is further data, false if not + */ + protected function has_data() + { + return (bool) ($this->position < $this->data_length); } - function get_keyword($key = 0) + /** + * See if the next character is LWS + * + * @return bool true if the next character is LWS, false if not + */ + protected function is_linear_whitespace() { - $keywords = $this->get_keywords(); - if (isset($keywords[$key])) - { - return $keywords[$key]; - } - else - { - return null; - } + return (bool) ($this->data[$this->position] === "\x09" + || $this->data[$this->position] === "\x20" + || ($this->data[$this->position] === "\x0A" + && isset($this->data[$this->position + 1]) + && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20"))); } - function get_keywords() + /** + * Parse the HTTP version + */ + protected function http_version() { - if ($this->keywords !== null) + if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/') { - return $this->keywords; + $len = strspn($this->data, '0123456789.', 5); + $this->http_version = substr($this->data, 5, $len); + $this->position += 5 + $len; + if (substr_count($this->http_version, '.') <= 1) + { + $this->http_version = (float) $this->http_version; + $this->position += strspn($this->data, "\x09\x20", $this->position); + $this->state = 'status'; + } + else + { + $this->state = false; + } } else { - return null; + $this->state = false; } } - function get_length() + /** + * Parse the status code + */ + protected function status() { - if ($this->length !== null) + if ($len = strspn($this->data, '0123456789', $this->position)) { - return $this->length; + $this->status_code = (int) substr($this->data, $this->position, $len); + $this->position += $len; + $this->state = 'reason'; } else { - return null; + $this->state = false; } } - function get_link() + /** + * Parse the reason phrase + */ + protected function reason() { - if ($this->link !== null) - { - return urldecode($this->link); - } - else - { - return null; - } + $len = strcspn($this->data, "\x0A", $this->position); + $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20"); + $this->position += $len + 1; + $this->state = 'new_line'; } - function get_medium() + /** + * Deal with a new line, shifting data around as needed + */ + protected function new_line() { - if ($this->medium !== null) + $this->value = trim($this->value, "\x0D\x20"); + if ($this->name !== '' && $this->value !== '') { - return $this->medium; + $this->name = strtolower($this->name); + // We should only use the last Content-Type header. c.f. issue #1 + if (isset($this->headers[$this->name]) && $this->name !== 'content-type') + { + $this->headers[$this->name] .= ', ' . $this->value; + } + else + { + $this->headers[$this->name] = $this->value; + } } - else + $this->name = ''; + $this->value = ''; + if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A") { - return null; + $this->position += 2; + $this->state = 'body'; } - } - - function get_player() - { - if ($this->player !== null) + elseif ($this->data[$this->position] === "\x0A") { - return $this->player; + $this->position++; + $this->state = 'body'; } else { - return null; + $this->state = 'name'; } } - function get_rating($key = 0) + /** + * Parse a header name + */ + protected function name() { - $ratings = $this->get_ratings(); - if (isset($ratings[$key])) + $len = strcspn($this->data, "\x0A:", $this->position); + if (isset($this->data[$this->position + $len])) { - return $ratings[$key]; + if ($this->data[$this->position + $len] === "\x0A") + { + $this->position += $len; + $this->state = 'new_line'; + } + else + { + $this->name = substr($this->data, $this->position, $len); + $this->position += $len + 1; + $this->state = 'value'; + } } else { - return null; + $this->state = false; } } - function get_ratings() + /** + * Parse LWS, replacing consecutive LWS characters with a single space + */ + protected function linear_whitespace() { - if ($this->ratings !== null) - { - return $this->ratings; - } - else + do { - return null; - } + if (substr($this->data, $this->position, 2) === "\x0D\x0A") + { + $this->position += 2; + } + elseif ($this->data[$this->position] === "\x0A") + { + $this->position++; + } + $this->position += strspn($this->data, "\x09\x20", $this->position); + } while ($this->has_data() && $this->is_linear_whitespace()); + $this->value .= "\x20"; } - function get_restriction($key = 0) + /** + * See what state to move to while within non-quoted header values + */ + protected function value() { - $restrictions = $this->get_restrictions(); - if (isset($restrictions[$key])) + if ($this->is_linear_whitespace()) { - return $restrictions[$key]; + $this->linear_whitespace(); } else { - return null; + switch ($this->data[$this->position]) + { + case '"': + // Workaround for ETags: we have to include the quotes as + // part of the tag. + if (strtolower($this->name) === 'etag') + { + $this->value .= '"'; + $this->position++; + $this->state = 'value_char'; + break; + } + $this->position++; + $this->state = 'quote'; + break; + + case "\x0A": + $this->position++; + $this->state = 'new_line'; + break; + + default: + $this->state = 'value_char'; + break; + } } } - function get_restrictions() + /** + * Parse a header value while outside quotes + */ + protected function value_char() { - if ($this->restrictions !== null) - { - return $this->restrictions; - } - else - { - return null; - } + $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position); + $this->value .= substr($this->data, $this->position, $len); + $this->position += $len; + $this->state = 'value'; } - function get_sampling_rate() + /** + * See what state to move to while within quoted header values + */ + protected function quote() { - if ($this->samplingrate !== null) + if ($this->is_linear_whitespace()) { - return $this->samplingrate; + $this->linear_whitespace(); } else { - return null; + switch ($this->data[$this->position]) + { + case '"': + $this->position++; + $this->state = 'value'; + break; + + case "\x0A": + $this->position++; + $this->state = 'new_line'; + break; + + case '\\': + $this->position++; + $this->state = 'quote_escaped'; + break; + + default: + $this->state = 'quote_char'; + break; + } } } - function get_size() + /** + * Parse a header value while within quotes + */ + protected function quote_char() { - $length = $this->get_length(); - if ($length !== null) + $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position); + $this->value .= substr($this->data, $this->position, $len); + $this->position += $len; + $this->state = 'value'; + } + + /** + * Parse an escaped character within quotes + */ + protected function quote_escaped() + { + $this->value .= $this->data[$this->position]; + $this->position++; + $this->state = 'quote'; + } + + /** + * Parse the body + */ + protected function body() + { + $this->body = substr($this->data, $this->position); + if (!empty($this->headers['transfer-encoding'])) { - return round($length/1048576, 2); + unset($this->headers['transfer-encoding']); + $this->state = 'chunked'; } else { - return null; + $this->state = 'emit'; } } - function get_thumbnail($key = 0) + /** + * Parsed a "Transfer-Encoding: chunked" body + */ + protected function chunked() { - $thumbnails = $this->get_thumbnails(); - if (isset($thumbnails[$key])) + if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($this->body))) { - return $thumbnails[$key]; + $this->state = 'emit'; + return; } - else + + $decoded = ''; + $encoded = $this->body; + + while (true) { - return null; + $is_chunked = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches ); + if (!$is_chunked) + { + // Looks like it's not chunked after all + $this->state = 'emit'; + return; + } + + $length = hexdec(trim($matches[1])); + if ($length === 0) + { + // Ignore trailer headers + $this->state = 'emit'; + $this->body = $decoded; + return; + } + + $chunk_length = strlen($matches[0]); + $decoded .= $part = substr($encoded, $chunk_length, $length); + $encoded = substr($encoded, $chunk_length + $length + 2); + + if (trim($encoded) === '0' || empty($encoded)) + { + $this->state = 'emit'; + $this->body = $decoded; + return; + } } } +} + +/** + * IRI parser/serialiser/normaliser + * + * @package SimplePie + * @subpackage HTTP + * @author Geoffrey Sneddon + * @author Steve Minutillo + * @author Ryan McCue + * @copyright 2007-2012 Geoffrey Sneddon, Steve Minutillo, Ryan McCue + * @license http://www.opensource.org/licenses/bsd-license.php + */ +class SimplePie_IRI +{ + /** + * Scheme + * + * @var string + */ + protected $scheme = null; + + /** + * User Information + * + * @var string + */ + protected $iuserinfo = null; + + /** + * ihost + * + * @var string + */ + protected $ihost = null; + + /** + * Port + * + * @var string + */ + protected $port = null; + + /** + * ipath + * + * @var string + */ + protected $ipath = ''; + + /** + * iquery + * + * @var string + */ + protected $iquery = null; + + /** + * ifragment + * + * @var string + */ + protected $ifragment = null; + + /** + * Normalization database + * + * Each key is the scheme, each value is an array with each key as the IRI + * part and value as the default value for that part. + */ + protected $normalization = array( + 'acap' => array( + 'port' => 674 + ), + 'dict' => array( + 'port' => 2628 + ), + 'file' => array( + 'ihost' => 'localhost' + ), + 'http' => array( + 'port' => 80, + 'ipath' => '/' + ), + 'https' => array( + 'port' => 443, + 'ipath' => '/' + ), + ); + + /** + * Return the entire IRI when you try and read the object as a string + * + * @return string + */ + public function __toString() + { + return $this->get_iri(); + } - function get_thumbnails() + /** + * Overload __set() to provide access via properties + * + * @param string $name Property name + * @param mixed $value Property value + */ + public function __set($name, $value) { - if ($this->thumbnails !== null) + if (method_exists($this, 'set_' . $name)) { - return $this->thumbnails; + call_user_func(array($this, 'set_' . $name), $value); } - else + elseif ( + $name === 'iauthority' + || $name === 'iuserinfo' + || $name === 'ihost' + || $name === 'ipath' + || $name === 'iquery' + || $name === 'ifragment' + ) { - return null; + call_user_func(array($this, 'set_' . substr($name, 1)), $value); } } - function get_title() + /** + * Overload __get() to provide access via properties + * + * @param string $name Property name + * @return mixed + */ + public function __get($name) { - if ($this->title !== null) + // isset() returns false for null, we don't want to do that + // Also why we use array_key_exists below instead of isset() + $props = get_object_vars($this); + + if ( + $name === 'iri' || + $name === 'uri' || + $name === 'iauthority' || + $name === 'authority' + ) { - return $this->title; + $return = $this->{"get_$name"}(); + } + elseif (array_key_exists($name, $props)) + { + $return = $this->$name; + } + // host -> ihost + elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) + { + $name = $prop; + $return = $this->$prop; + } + // ischeme -> scheme + elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) + { + $name = $prop; + $return = $this->$prop; } else { - return null; + trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE); + $return = null; } - } - function get_type() - { - if ($this->type !== null) + if ($return === null && isset($this->normalization[$this->scheme][$name])) { - return $this->type; + return $this->normalization[$this->scheme][$name]; } else { - return null; + return $return; } } - function get_width() + /** + * Overload __isset() to provide access via properties + * + * @param string $name Property name + * @return bool + */ + public function __isset($name) { - if ($this->width !== null) + if (method_exists($this, 'get_' . $name) || isset($this->$name)) { - return $this->width; + return true; } else { - return null; + return false; } } - function native_embed($options='') + /** + * Overload __unset() to provide access via properties + * + * @param string $name Property name + */ + public function __unset($name) { - return $this->embed($options, true); + if (method_exists($this, 'set_' . $name)) + { + call_user_func(array($this, 'set_' . $name), ''); + } } /** - * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'. + * Create a new IRI object, from a specified string + * + * @param string $iri */ - function embed($options = '', $native = false) + public function __construct($iri = null) { - // Set up defaults - $audio = ''; - $video = ''; - $alt = ''; - $altclass = ''; - $loop = 'false'; - $width = 'auto'; - $height = 'auto'; - $bgcolor = '#ffffff'; - $mediaplayer = ''; - $widescreen = false; - $handler = $this->get_handler(); - $type = $this->get_real_type(); + $this->set_iri($iri); + } - // Process options and reassign values as necessary - if (is_array($options)) + /** + * Create a new IRI object by resolving a relative IRI + * + * Returns false if $base is not absolute, otherwise an IRI. + * + * @param IRI|string $base (Absolute) Base IRI + * @param IRI|string $relative Relative IRI + * @return IRI|false + */ + public static function absolutize($base, $relative) + { + if (!($relative instanceof SimplePie_IRI)) { - extract($options); + $relative = new SimplePie_IRI($relative); + } + if (!$relative->is_valid()) + { + return false; + } + elseif ($relative->scheme !== null) + { + return clone $relative; } else { - $options = explode(',', $options); - foreach($options as $option) + if (!($base instanceof SimplePie_IRI)) { - $opt = explode(':', $option, 2); - if (isset($opt[0], $opt[1])) - { - $opt[0] = trim($opt[0]); - $opt[1] = trim($opt[1]); - switch ($opt[0]) - { - case 'audio': - $audio = $opt[1]; - break; - - case 'video': - $video = $opt[1]; - break; - - case 'alt': - $alt = $opt[1]; - break; - - case 'altclass': - $altclass = $opt[1]; - break; - - case 'loop': - $loop = $opt[1]; - break; - - case 'width': - $width = $opt[1]; - break; - - case 'height': - $height = $opt[1]; - break; - - case 'bgcolor': - $bgcolor = $opt[1]; - break; - - case 'mediaplayer': - $mediaplayer = $opt[1]; - break; - - case 'widescreen': - $widescreen = $opt[1]; - break; - } - } + $base = new SimplePie_IRI($base); } - } - - $mime = explode('/', $type, 2); - $mime = $mime[0]; - - // Process values for 'auto' - if ($width === 'auto') - { - if ($mime === 'video') + if ($base->scheme !== null && $base->is_valid()) { - if ($height === 'auto') - { - $width = 480; - } - elseif ($widescreen) + if ($relative->get_iri() !== '') { - $width = round((intval($height)/9)*16); + if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) + { + $target = clone $relative; + $target->scheme = $base->scheme; + } + else + { + $target = new SimplePie_IRI; + $target->scheme = $base->scheme; + $target->iuserinfo = $base->iuserinfo; + $target->ihost = $base->ihost; + $target->port = $base->port; + if ($relative->ipath !== '') + { + if ($relative->ipath[0] === '/') + { + $target->ipath = $relative->ipath; + } + elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') + { + $target->ipath = '/' . $relative->ipath; + } + elseif (($last_segment = strrpos($base->ipath, '/')) !== false) + { + $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath; + } + else + { + $target->ipath = $relative->ipath; + } + $target->ipath = $target->remove_dot_segments($target->ipath); + $target->iquery = $relative->iquery; + } + else + { + $target->ipath = $base->ipath; + if ($relative->iquery !== null) + { + $target->iquery = $relative->iquery; + } + elseif ($base->iquery !== null) + { + $target->iquery = $base->iquery; + } + } + $target->ifragment = $relative->ifragment; + } } else { - $width = round((intval($height)/3)*4); + $target = clone $base; + $target->ifragment = null; } + $target->scheme_normalization(); + return $target; } else { - $width = '100%'; + return false; } } + } - if ($height === 'auto') + /** + * Parse an IRI into scheme/authority/path/query/fragment segments + * + * @param string $iri + * @return array + */ + protected function parse_iri($iri) + { + $iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); + if (preg_match('/^((?P[^:\/?#]+):)?(\/\/(?P[^\/?#]*))?(?P[^?#]*)(\?(?P[^#]*))?(#(?P.*))?$/', $iri, $match)) { - if ($mime === 'audio') + if ($match[1] === '') { - $height = 0; + $match['scheme'] = null; } - elseif ($mime === 'video') + if (!isset($match[3]) || $match[3] === '') { - if ($width === 'auto') - { - if ($widescreen) - { - $height = 270; - } - else - { - $height = 360; - } - } - elseif ($widescreen) - { - $height = round((intval($width)/16)*9); - } - else - { - $height = round((intval($width)/4)*3); - } + $match['authority'] = null; } - else + if (!isset($match[5])) { - $height = 376; + $match['path'] = ''; } + if (!isset($match[6]) || $match[6] === '') + { + $match['query'] = null; + } + if (!isset($match[8]) || $match[8] === '') + { + $match['fragment'] = null; + } + return $match; } - elseif ($mime === 'audio') - { - $height = 0; - } - - // Set proper placeholder value - if ($mime === 'audio') - { - $placeholder = $audio; - } - elseif ($mime === 'video') + else { - $placeholder = $video; + // This can occur when a paragraph is accidentally parsed as a URI + return false; } + } - $embed = ''; - - // Make sure the JS library is included - if (!$native) + /** + * Remove dot segments from a path + * + * @param string $input + * @return string + */ + protected function remove_dot_segments($input) + { + $output = ''; + while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') { - static $javascript_outputted = null; - if (!$javascript_outputted && $this->javascript) + // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise, + if (strpos($input, '../') === 0) { - $embed .= ''; - $javascript_outputted = true; + $input = substr($input, 3); } - } - - // Odeo Feed MP3's - if ($handler === 'odeo') - { - if ($native) + elseif (strpos($input, './') === 0) { - $embed .= ''; + $input = substr($input, 2); } - else + // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise, + elseif (strpos($input, '/./') === 0) { - $embed .= ''; + $input = substr($input, 2); } - } - - // Flash - elseif ($handler === 'flash') - { - if ($native) + elseif ($input === '/.') { - $embed .= "get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\">"; + $input = '/'; + } + // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise, + elseif (strpos($input, '/../') === 0) + { + $input = substr($input, 3); + $output = substr_replace($output, '', strrpos($output, '/')); + } + elseif ($input === '/..') + { + $input = '/'; + $output = substr_replace($output, '', strrpos($output, '/')); + } + // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise, + elseif ($input === '.' || $input === '..') + { + $input = ''; + } + // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer + elseif (($pos = strpos($input, '/', 1)) !== false) + { + $output .= substr($input, 0, $pos); + $input = substr_replace($input, '', 0, $pos); } else { - $embed .= ""; + $output .= $input; + $input = ''; } } + return $output . $input; + } - // Flash Media Player file types. - // Preferred handler for MP3 file types. - elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== '')) + /** + * Replace invalid character with percent encoding + * + * @param string $string Input string + * @param string $extra_chars Valid characters not in iunreserved or + * iprivate (this is ASCII-only) + * @param bool $iprivate Allow iprivate + * @return string + */ + protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) + { + // Normalize as many pct-encoded sections as possible + $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string); + + // Replace invalid percent characters + $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string); + + // Add unreserved and % to $extra_chars (the latter is safe because all + // pct-encoded sections are now valid). + $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; + + // Now replace any bytes that aren't allowed with their pct-encoded versions + $position = 0; + $strlen = strlen($string); + while (($position += strspn($string, $extra_chars, $position)) < $strlen) { - $height += 20; - if ($native) + $value = ord($string[$position]); + + // Start position + $start = $position; + + // By default we are valid + $valid = true; + + // No one byte sequences are valid due to the while. + // Two byte sequence: + if (($value & 0xE0) === 0xC0) { - $embed .= "get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\">"; + $character = ($value & 0x1F) << 6; + $length = 2; + $remaining = 1; + } + // Three byte sequence: + elseif (($value & 0xF0) === 0xE0) + { + $character = ($value & 0x0F) << 12; + $length = 3; + $remaining = 2; + } + // Four byte sequence: + elseif (($value & 0xF8) === 0xF0) + { + $character = ($value & 0x07) << 18; + $length = 4; + $remaining = 3; } + // Invalid byte: else { - $embed .= ""; + $valid = false; + $length = 1; + $remaining = 0; } - } - // QuickTime 7 file types. Need to test with QuickTime 6. - // Only handle MP3's if the Flash Media Player is not present. - elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === '')) - { - $height += 16; - if ($native) + if ($remaining) { - if ($placeholder !== '') + if ($position + $length <= $strlen) { - $embed .= "get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\">"; + for ($position++; $remaining; $position++) + { + $value = ord($string[$position]); + + // Check that the byte is valid, then add it to the character: + if (($value & 0xC0) === 0x80) + { + $character |= ($value & 0x3F) << (--$remaining * 6); + } + // If it is invalid, count the sequence as invalid and reprocess the current byte: + else + { + $valid = false; + $position--; + break; + } + } } else { - $embed .= "get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\">"; + $position = $strlen - 1; + $valid = false; } } - else - { - $embed .= ""; - } - } - // Windows Media - elseif ($handler === 'wmedia') - { - $height += 45; - if ($native) - { - $embed .= "get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\">"; - } - else + // Percent encode anything invalid or not in ucschar + if ( + // Invalid sequences + !$valid + // Non-shortest form sequences are invalid + || $length > 1 && $character <= 0x7F + || $length > 2 && $character <= 0x7FF + || $length > 3 && $character <= 0xFFFF + // Outside of range of ucschar codepoints + // Noncharacters + || ($character & 0xFFFE) === 0xFFFE + || $character >= 0xFDD0 && $character <= 0xFDEF + || ( + // Everything else not in ucschar + $character > 0xD7FF && $character < 0xF900 + || $character < 0xA0 + || $character > 0xEFFFD + ) + && ( + // Everything not in iprivate, if it applies + !$iprivate + || $character < 0xE000 + || $character > 0x10FFFD + ) + ) { - $embed .= ""; + // If we were a character, pretend we weren't, but rather an error. + if ($valid) + $position--; + + for ($j = $start; $j <= $position; $j++) + { + $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1); + $j += 2; + $position += 2; + $strlen += 2; + } } } - // Everything else - else $embed .= '' . $alt . ''; - - return $embed; + return $string; } - function get_real_type($find_handler = false) + /** + * Callback function for preg_replace_callback. + * + * Removes sequences of percent encoded bytes that represent UTF-8 + * encoded characters in iunreserved + * + * @param array $match PCRE match + * @return string Replacement + */ + protected function remove_iunreserved_percent_encoded($match) { - // If it's Odeo, let's get it out of the way. - if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com') - { - return 'odeo'; - } - - // Mime-types by handler. - $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash - $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player - $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime - $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media - $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3 + // As we just have valid percent encoded sequences we can just explode + // and ignore the first member of the returned array (an empty string). + $bytes = explode('%', $match[0]); - if ($this->get_type() !== null) - { - $type = strtolower($this->type); - } - else - { - $type = null; - } + // Initialize the new string (this is what will be returned) and that + // there are no bytes remaining in the current sequence (unsurprising + // at the first byte!). + $string = ''; + $remaining = 0; - // If we encounter an unsupported mime-type, check the file extension and guess intelligently. - if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3))) + // Loop over each and every byte, and set $value to its value + for ($i = 1, $len = count($bytes); $i < $len; $i++) { - switch (strtolower($this->get_extension())) - { - // Audio mime-types - case 'aac': - case 'adts': - $type = 'audio/acc'; - break; - - case 'aif': - case 'aifc': - case 'aiff': - case 'cdda': - $type = 'audio/aiff'; - break; - - case 'bwf': - $type = 'audio/wav'; - break; + $value = hexdec($bytes[$i]); - case 'kar': - case 'mid': - case 'midi': - case 'smf': - $type = 'audio/midi'; - break; + // If we're the first byte of sequence: + if (!$remaining) + { + // Start position + $start = $i; - case 'm4a': - $type = 'audio/x-m4a'; - break; + // By default we are valid + $valid = true; - case 'mp3': - case 'swa': - $type = 'audio/mp3'; - break; + // One byte sequence: + if ($value <= 0x7F) + { + $character = $value; + $length = 1; + } + // Two byte sequence: + elseif (($value & 0xE0) === 0xC0) + { + $character = ($value & 0x1F) << 6; + $length = 2; + $remaining = 1; + } + // Three byte sequence: + elseif (($value & 0xF0) === 0xE0) + { + $character = ($value & 0x0F) << 12; + $length = 3; + $remaining = 2; + } + // Four byte sequence: + elseif (($value & 0xF8) === 0xF0) + { + $character = ($value & 0x07) << 18; + $length = 4; + $remaining = 3; + } + // Invalid byte: + else + { + $valid = false; + $remaining = 0; + } + } + // Continuation byte: + else + { + // Check that the byte is valid, then add it to the character: + if (($value & 0xC0) === 0x80) + { + $remaining--; + $character |= ($value & 0x3F) << ($remaining * 6); + } + // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence: + else + { + $valid = false; + $remaining = 0; + $i--; + } + } - case 'wav': - $type = 'audio/wav'; - break; + // If we've reached the end of the current byte sequence, append it to Unicode::$data + if (!$remaining) + { + // Percent encode anything invalid or not in iunreserved + if ( + // Invalid sequences + !$valid + // Non-shortest form sequences are invalid + || $length > 1 && $character <= 0x7F + || $length > 2 && $character <= 0x7FF + || $length > 3 && $character <= 0xFFFF + // Outside of range of iunreserved codepoints + || $character < 0x2D + || $character > 0xEFFFD + // Noncharacters + || ($character & 0xFFFE) === 0xFFFE + || $character >= 0xFDD0 && $character <= 0xFDEF + // Everything else not in iunreserved (this is all BMP) + || $character === 0x2F + || $character > 0x39 && $character < 0x41 + || $character > 0x5A && $character < 0x61 + || $character > 0x7A && $character < 0x7E + || $character > 0x7E && $character < 0xA0 + || $character > 0xD7FF && $character < 0xF900 + ) + { + for ($j = $start; $j <= $i; $j++) + { + $string .= '%' . strtoupper($bytes[$j]); + } + } + else + { + for ($j = $start; $j <= $i; $j++) + { + $string .= chr(hexdec($bytes[$j])); + } + } + } + } - case 'wax': - $type = 'audio/x-ms-wax'; - break; + // If we have any bytes left over they are invalid (i.e., we are + // mid-way through a multi-byte sequence) + if ($remaining) + { + for ($j = $start; $j < $len; $j++) + { + $string .= '%' . strtoupper($bytes[$j]); + } + } - case 'wma': - $type = 'audio/x-ms-wma'; - break; + return $string; + } - // Video mime-types - case '3gp': - case '3gpp': - $type = 'video/3gpp'; - break; + protected function scheme_normalization() + { + if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) + { + $this->iuserinfo = null; + } + if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) + { + $this->ihost = null; + } + if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) + { + $this->port = null; + } + if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) + { + $this->ipath = ''; + } + if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) + { + $this->iquery = null; + } + if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) + { + $this->ifragment = null; + } + } - case '3g2': - case '3gp2': - $type = 'video/3gpp2'; - break; + /** + * Check if the object represents a valid IRI. This needs to be done on each + * call as some things change depending on another part of the IRI. + * + * @return bool + */ + public function is_valid() + { + $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null; + if ($this->ipath !== '' && + ( + $isauthority && ( + $this->ipath[0] !== '/' || + substr($this->ipath, 0, 2) === '//' + ) || + ( + $this->scheme === null && + !$isauthority && + strpos($this->ipath, ':') !== false && + (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/')) + ) + ) + ) + { + return false; + } - case 'asf': - $type = 'video/x-ms-asf'; - break; + return true; + } - case 'flv': - $type = 'video/x-flv'; - break; + /** + * Set the entire IRI. Returns true on success, false on failure (if there + * are any invalid characters). + * + * @param string $iri + * @return bool + */ + public function set_iri($iri) + { + static $cache; + if (!$cache) + { + $cache = array(); + } - case 'm1a': - case 'm1s': - case 'm1v': - case 'm15': - case 'm75': - case 'mp2': - case 'mpa': - case 'mpeg': - case 'mpg': - case 'mpm': - case 'mpv': - $type = 'video/mpeg'; - break; + if ($iri === null) + { + return true; + } + elseif (isset($cache[$iri])) + { + list($this->scheme, + $this->iuserinfo, + $this->ihost, + $this->port, + $this->ipath, + $this->iquery, + $this->ifragment, + $return) = $cache[$iri]; + return $return; + } + else + { + $parsed = $this->parse_iri((string) $iri); + if (!$parsed) + { + return false; + } - case 'm4v': - $type = 'video/x-m4v'; - break; + $return = $this->set_scheme($parsed['scheme']) + && $this->set_authority($parsed['authority']) + && $this->set_path($parsed['path']) + && $this->set_query($parsed['query']) + && $this->set_fragment($parsed['fragment']); + + $cache[$iri] = array($this->scheme, + $this->iuserinfo, + $this->ihost, + $this->port, + $this->ipath, + $this->iquery, + $this->ifragment, + $return); + return $return; + } + } - case 'mov': - case 'qt': - $type = 'video/quicktime'; - break; - - case 'mp4': - case 'mpg4': - $type = 'video/mp4'; - break; - - case 'sdv': - $type = 'video/sd-video'; - break; - - case 'wm': - $type = 'video/x-ms-wm'; - break; - - case 'wmv': - $type = 'video/x-ms-wmv'; - break; - - case 'wvx': - $type = 'video/x-ms-wvx'; - break; + /** + * Set the scheme. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $scheme + * @return bool + */ + public function set_scheme($scheme) + { + if ($scheme === null) + { + $this->scheme = null; + } + elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) + { + $this->scheme = null; + return false; + } + else + { + $this->scheme = strtolower($scheme); + } + return true; + } - // Flash mime-types - case 'spl': - $type = 'application/futuresplash'; - break; + /** + * Set the authority. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $authority + * @return bool + */ + public function set_authority($authority) + { + static $cache; + if (!$cache) + $cache = array(); - case 'swf': - $type = 'application/x-shockwave-flash'; - break; - } + if ($authority === null) + { + $this->iuserinfo = null; + $this->ihost = null; + $this->port = null; + return true; } + elseif (isset($cache[$authority])) + { + list($this->iuserinfo, + $this->ihost, + $this->port, + $return) = $cache[$authority]; - if ($find_handler) + return $return; + } + else { - if (in_array($type, $types_flash)) - { - return 'flash'; - } - elseif (in_array($type, $types_fmedia)) - { - return 'fmedia'; - } - elseif (in_array($type, $types_quicktime)) + $remaining = $authority; + if (($iuserinfo_end = strrpos($remaining, '@')) !== false) { - return 'quicktime'; + $iuserinfo = substr($remaining, 0, $iuserinfo_end); + $remaining = substr($remaining, $iuserinfo_end + 1); } - elseif (in_array($type, $types_wmedia)) + else { - return 'wmedia'; + $iuserinfo = null; } - elseif (in_array($type, $types_mp3)) + if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false) { - return 'mp3'; + if (($port = substr($remaining, $port_start + 1)) === false) + { + $port = null; + } + $remaining = substr($remaining, 0, $port_start); } else { - return null; + $port = null; } - } - else - { - return $type; - } - } -} -class SimplePie_Caption -{ - var $type; - var $lang; - var $startTime; - var $endTime; - var $text; + $return = $this->set_userinfo($iuserinfo) && + $this->set_host($remaining) && + $this->set_port($port); - // Constructor, used to input the data - function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null) - { - $this->type = $type; - $this->lang = $lang; - $this->startTime = $startTime; - $this->endTime = $endTime; - $this->text = $text; - } + $cache[$authority] = array($this->iuserinfo, + $this->ihost, + $this->port, + $return); - function __toString() - { - // There is no $this->data here - return md5(serialize($this)); + return $return; + } } - function get_endtime() + /** + * Set the iuserinfo. + * + * @param string $iuserinfo + * @return bool + */ + public function set_userinfo($iuserinfo) { - if ($this->endTime !== null) + if ($iuserinfo === null) { - return $this->endTime; + $this->iuserinfo = null; } else { - return null; + $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:'); + $this->scheme_normalization(); } + + return true; } - function get_language() + /** + * Set the ihost. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $ihost + * @return bool + */ + public function set_host($ihost) { - if ($this->lang !== null) + if ($ihost === null) { - return $this->lang; + $this->ihost = null; + return true; + } + elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') + { + if (SimplePie_Net_IPv6::check_ipv6(substr($ihost, 1, -1))) + { + $this->ihost = '[' . SimplePie_Net_IPv6::compress(substr($ihost, 1, -1)) . ']'; + } + else + { + $this->ihost = null; + return false; + } } else { - return null; + $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;='); + + // Lowercase, but ignore pct-encoded sections (as they should + // remain uppercase). This must be done after the previous step + // as that can add unescaped characters. + $position = 0; + $strlen = strlen($ihost); + while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) + { + if ($ihost[$position] === '%') + { + $position += 3; + } + else + { + $ihost[$position] = strtolower($ihost[$position]); + $position++; + } + } + + $this->ihost = $ihost; } + + $this->scheme_normalization(); + + return true; } - function get_starttime() + /** + * Set the port. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $port + * @return bool + */ + public function set_port($port) { - if ($this->startTime !== null) + if ($port === null) { - return $this->startTime; + $this->port = null; + return true; + } + elseif (strspn($port, '0123456789') === strlen($port)) + { + $this->port = (int) $port; + $this->scheme_normalization(); + return true; } else { - return null; + $this->port = null; + return false; } } - function get_text() + /** + * Set the ipath. + * + * @param string $ipath + * @return bool + */ + public function set_path($ipath) { - if ($this->text !== null) - { - return $this->text; - } - else + static $cache; + if (!$cache) { - return null; + $cache = array(); } - } - function get_type() - { - if ($this->type !== null) + $ipath = (string) $ipath; + + if (isset($cache[$ipath])) { - return $this->type; + $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)]; } else { - return null; - } - } -} + $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/'); + $removed = $this->remove_dot_segments($valid); -class SimplePie_Credit -{ - var $role; - var $scheme; - var $name; - - // Constructor, used to input the data - function SimplePie_Credit($role = null, $scheme = null, $name = null) - { - $this->role = $role; - $this->scheme = $scheme; - $this->name = $name; - } + $cache[$ipath] = array($valid, $removed); + $this->ipath = ($this->scheme !== null) ? $removed : $valid; + } - function __toString() - { - // There is no $this->data here - return md5(serialize($this)); + $this->scheme_normalization(); + return true; } - function get_role() + /** + * Set the iquery. + * + * @param string $iquery + * @return bool + */ + public function set_query($iquery) { - if ($this->role !== null) + if ($iquery === null) { - return $this->role; + $this->iquery = null; } else { - return null; + $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true); + $this->scheme_normalization(); } + return true; } - function get_scheme() + /** + * Set the ifragment. + * + * @param string $ifragment + * @return bool + */ + public function set_fragment($ifragment) { - if ($this->scheme !== null) + if ($ifragment === null) { - return $this->scheme; + $this->ifragment = null; } else { - return null; + $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?'); + $this->scheme_normalization(); } + return true; } - function get_name() + /** + * Convert an IRI to a URI (or parts thereof) + * + * @return string + */ + public function to_uri($string) { - if ($this->name !== null) + static $non_ascii; + if (!$non_ascii) { - return $this->name; + $non_ascii = implode('', range("\x80", "\xFF")); } - else + + $position = 0; + $strlen = strlen($string); + while (($position += strcspn($string, $non_ascii, $position)) < $strlen) { - return null; + $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1); + $position += 3; + $strlen += 2; } - } -} - -class SimplePie_Copyright -{ - var $url; - var $label; - - // Constructor, used to input the data - function SimplePie_Copyright($url = null, $label = null) - { - $this->url = $url; - $this->label = $label; - } - function __toString() - { - // There is no $this->data here - return md5(serialize($this)); + return $string; } - function get_url() + /** + * Get the complete IRI + * + * @return string + */ + public function get_iri() { - if ($this->url !== null) + if (!$this->is_valid()) { - return $this->url; + return false; } - else + + $iri = ''; + if ($this->scheme !== null) { - return null; + $iri .= $this->scheme . ':'; } - } - - function get_attribution() - { - if ($this->label !== null) + if (($iauthority = $this->get_iauthority()) !== null) { - return $this->label; + $iri .= '//' . $iauthority; } - else + if ($this->ipath !== '') { - return null; + $iri .= $this->ipath; + } + elseif (!empty($this->normalization[$this->scheme]['ipath']) && $iauthority !== null && $iauthority !== '') + { + $iri .= $this->normalization[$this->scheme]['ipath']; + } + if ($this->iquery !== null) + { + $iri .= '?' . $this->iquery; + } + if ($this->ifragment !== null) + { + $iri .= '#' . $this->ifragment; } - } -} - -class SimplePie_Rating -{ - var $scheme; - var $value; - // Constructor, used to input the data - function SimplePie_Rating($scheme = null, $value = null) - { - $this->scheme = $scheme; - $this->value = $value; + return $iri; } - function __toString() + /** + * Get the complete URI + * + * @return string + */ + public function get_uri() { - // There is no $this->data here - return md5(serialize($this)); + return $this->to_uri($this->get_iri()); } - function get_scheme() + /** + * Get the complete iauthority + * + * @return string + */ + protected function get_iauthority() { - if ($this->scheme !== null) + if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null) { - return $this->scheme; + $iauthority = ''; + if ($this->iuserinfo !== null) + { + $iauthority .= $this->iuserinfo . '@'; + } + if ($this->ihost !== null) + { + $iauthority .= $this->ihost; + } + if ($this->port !== null) + { + $iauthority .= ':' . $this->port; + } + return $iauthority; } else { @@ -7569,56 +8996,125 @@ class SimplePie_Rating } } - function get_value() + /** + * Get the complete authority + * + * @return string + */ + protected function get_authority() { - if ($this->value !== null) - { - return $this->value; - } + $iauthority = $this->get_iauthority(); + if (is_string($iauthority)) + return $this->to_uri($iauthority); else - { - return null; - } + return $iauthority; } } -class SimplePie_Restriction +/** + * Manages all item-related data + * + * Used by {@see SimplePie::get_item()} and {@see SimplePie::get_items()} + * + * This class can be overloaded with {@see SimplePie::set_item_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Item { - var $relationship; - var $type; - var $value; + /** + * Parent feed + * + * @access private + * @var SimplePie + */ + var $feed; + + /** + * Raw data + * + * @access private + * @var array + */ + var $data = array(); + + /** + * Registry object + * + * @see set_registry + * @var SimplePie_Registry + */ + protected $registry; - // Constructor, used to input the data - function SimplePie_Restriction($relationship = null, $type = null, $value = null) + /** + * Create a new item object + * + * This is usually used by {@see SimplePie::get_items} and + * {@see SimplePie::get_item}. Avoid creating this manually. + * + * @param SimplePie $feed Parent feed + * @param array $data Raw data + */ + public function __construct($feed, $data) { - $this->relationship = $relationship; - $this->type = $type; - $this->value = $value; + $this->feed = $feed; + $this->data = $data; } - function __toString() + /** + * Set the registry handler + * + * This is usually used by {@see SimplePie_Registry::create} + * + * @since 1.3 + * @param SimplePie_Registry $registry + */ + public function set_registry(SimplePie_Registry $registry) { - // There is no $this->data here - return md5(serialize($this)); + $this->registry = $registry; } - function get_relationship() + /** + * Get a string representation of the item + * + * @return string + */ + public function __toString() { - if ($this->relationship !== null) - { - return $this->relationship; - } - else + return md5(serialize($this->data)); + } + + /** + * Remove items that link back to this before destroying this object + */ + public function __destruct() + { + if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode')) { - return null; + unset($this->feed); } } - function get_type() + /** + * Get data for an item-level element + * + * This method allows you to get access to ANY element/attribute that is a + * sub-element of the item/entry tag. + * + * See {@see SimplePie::get_feed_tags()} for a description of the return value + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_item_tags($namespace, $tag) { - if ($this->type !== null) + if (isset($this->data['child'][$namespace][$tag])) { - return $this->type; + return $this->data['child'][$namespace][$tag]; } else { @@ -7626,7674 +9122,8647 @@ class SimplePie_Restriction } } - function get_value() + /** + * Get the base URL value from the parent feed + * + * Uses `` + * + * @param array $element + * @return string + */ + public function get_base($element = array()) { - if ($this->value !== null) + return $this->feed->get_base($element); + } + + /** + * Sanitize feed data + * + * @access private + * @see SimplePie::sanitize() + * @param string $data Data to sanitize + * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants + * @param string $base Base URL to resolve URLs against + * @return string Sanitized data + */ + public function sanitize($data, $type, $base = '') + { + return $this->feed->sanitize($data, $type, $base); + } + + /** + * Get the parent feed + * + * Note: this may not work as you think for multifeeds! + * + * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed + * @since 1.0 + * @return SimplePie + */ + public function get_feed() + { + return $this->feed; + } + + /** + * Get the unique identifier for the item + * + * This is usually used when writing code to check for new items in a feed. + * + * Uses ``, ``, `` or the `about` attribute + * for RDF. If none of these are supplied (or `$hash` is true), creates an + * MD5 hash based on the permalink and title. If either of those are not + * supplied, creates a hash based on the full feed data. + * + * @since Beta 2 + * @param boolean $hash Should we force using a hash instead of the supplied ID? + * @return string + */ + public function get_id($hash = false) + { + if (!$hash) { - return $this->value; + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'])) + { + return $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (($return = $this->get_permalink()) !== null) + { + return $return; + } + elseif (($return = $this->get_title()) !== null) + { + return $return; + } + } + if ($this->get_permalink() !== null || $this->get_title() !== null) + { + return md5($this->get_permalink() . $this->get_title()); } else { - return null; + return md5(serialize($this->data)); } } -} - -/** - * @todo Move to properly supporting RFC2616 (HTTP/1.1) - */ -class SimplePie_File -{ - var $url; - var $useragent; - var $success = true; - var $headers = array(); - var $body; - var $status_code; - var $redirects = 0; - var $error; - var $method = SIMPLEPIE_FILE_SOURCE_NONE; - function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) + /** + * Get the title of the item + * + * Uses ``, `` or `<dc:title>` + * + * @since Beta 2 (previously called `get_item_title` since 0.8) + * @return string|null + */ + public function get_title() { - if (class_exists('idna_convert')) - { - $idn = new idna_convert; - $parsed = SimplePie_Misc::parse_url($url); - $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']); - } - $this->url = $url; - $this->useragent = $useragent; - if (preg_match('/^http(s)?:\/\//i', $url)) + if (!isset($this->data['title'])) { - if ($useragent === null) + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) { - $useragent = ini_get('user_agent'); - $this->useragent = $useragent; + $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); } - if (!is_array($headers)) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) { - $headers = array(); + $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); } - if (!$force_fsockopen && function_exists('curl_exec')) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) { - $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL; - $fp = curl_init(); - $headers2 = array(); - foreach ($headers as $key => $value) - { - $headers2[] = "$key: $value"; - } - if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>=')) - { - curl_setopt($fp, CURLOPT_ENCODING, ''); - } - curl_setopt($fp, CURLOPT_URL, $url); - curl_setopt($fp, CURLOPT_HEADER, 1); - curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($fp, CURLOPT_TIMEOUT, $timeout); - curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout); - curl_setopt($fp, CURLOPT_REFERER, $url); - curl_setopt($fp, CURLOPT_USERAGENT, $useragent); - curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2); - if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>=')) - { - curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1); - curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects); - } - - $this->headers = curl_exec($fp); - if (curl_errno($fp) === 23 || curl_errno($fp) === 61) - { - curl_setopt($fp, CURLOPT_ENCODING, 'none'); - $this->headers = curl_exec($fp); - } - if (curl_errno($fp)) - { - $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp); - $this->success = false; - } - else - { - $info = curl_getinfo($fp); - curl_close($fp); - $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1); - $this->headers = array_pop($this->headers); - $parser = new SimplePie_HTTP_Parser($this->headers); - if ($parser->parse()) - { - $this->headers = $parser->headers; - $this->body = $parser->body; - $this->status_code = $parser->status_code; - if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) - { - $this->redirects++; - $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url); - return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen); - } - } - } + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } - else + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) { - $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN; - $url_parts = parse_url($url); - $socket_host = $url_parts['host']; - if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') - { - $socket_host = "ssl://$url_parts[host]"; - $url_parts['port'] = 443; - } - if (!isset($url_parts['port'])) - { - $url_parts['port'] = 80; - } - $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout); - if (!$fp) - { - $this->error = 'fsockopen error: ' . $errstr; - $this->success = false; - } - else - { - stream_set_timeout($fp, $timeout); - if (isset($url_parts['path'])) - { - if (isset($url_parts['query'])) - { - $get = "$url_parts[path]?$url_parts[query]"; - } - else - { - $get = $url_parts['path']; - } - } - else - { - $get = '/'; - } - $out = "GET $get HTTP/1.0\r\n"; - $out .= "Host: $url_parts[host]\r\n"; - $out .= "User-Agent: $useragent\r\n"; - if (extension_loaded('zlib')) - { - $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n"; - } - - if (isset($url_parts['user']) && isset($url_parts['pass'])) - { - $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n"; - } - foreach ($headers as $key => $value) - { - $out .= "$key: $value\r\n"; - } - $out .= "Connection: Close\r\n\r\n"; - fwrite($fp, $out); - - $info = stream_get_meta_data($fp); - - $this->headers = ''; - while (!$info['eof'] && !$info['timed_out']) - { - $this->headers .= fread($fp, 1160); - $info = stream_get_meta_data($fp); - } - if (!$info['timed_out']) - { - $parser = new SimplePie_HTTP_Parser($this->headers); - if ($parser->parse()) - { - $this->headers = $parser->headers; - $this->body = $parser->body; - $this->status_code = $parser->status_code; - if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) - { - $this->redirects++; - $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url); - return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen); - } - if (isset($this->headers['content-encoding'])) - { - // Hey, we act dumb elsewhere, so let's do that here too - switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20"))) - { - case 'gzip': - case 'x-gzip': - $decoder = new SimplePie_gzdecode($this->body); - if (!$decoder->parse()) - { - $this->error = 'Unable to decode HTTP "gzip" stream'; - $this->success = false; - } - else - { - $this->body = $decoder->data; - } - break; - - case 'deflate': - if (($body = gzuncompress($this->body)) === false) - { - if (($body = gzinflate($this->body)) === false) - { - $this->error = 'Unable to decode HTTP "deflate" stream'; - $this->success = false; - } - } - $this->body = $body; - break; - - default: - $this->error = 'Unknown content coding'; - $this->success = false; - } - } - } - } - else - { - $this->error = 'fsocket timed out'; - $this->success = false; - } - fclose($fp); - } + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } - } - else - { - $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS; - if (!$this->body = file_get_contents($url)) + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) { - $this->error = 'file_get_contents could not read the file'; - $this->success = false; + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $this->data['title'] = null; } } + return $this->data['title']; } -} -/** - * HTTP Response Parser - * - * @package SimplePie - */ -class SimplePie_HTTP_Parser -{ /** - * HTTP Version + * Get the content for the item * - * @access public - * @var float - */ - var $http_version = 0.0; - - /** - * Status code + * Prefers summaries over full content , but will return full content if a + * summary does not exist. * - * @access public - * @var int - */ - var $status_code = 0; - - /** - * Reason phrase + * To prefer full content instead, use {@see get_content} * - * @access public - * @var string - */ - var $reason = ''; - - /** - * Key/value pairs of the headers + * Uses `<atom:summary>`, `<description>`, `<dc:description>` or + * `<itunes:subtitle>` * - * @access public - * @var array + * @since 0.8 + * @param boolean $description_only Should we avoid falling back to the content? + * @return string|null */ - var $headers = array(); + public function get_description($description_only = false) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML); + } + + elseif (!$description_only) + { + return $this->get_content(true); + } + else + { + return null; + } + } /** - * Body of the response - * - * @access public - * @var string - */ - var $body = ''; - - /** - * Current state of the state machine - * - * @access private - * @var string - */ - var $state = 'http_version'; - - /** - * Input data - * - * @access private - * @var string - */ - var $data = ''; - - /** - * Input data length (to avoid calling strlen() everytime this is needed) - * - * @access private - * @var int - */ - var $data_length = 0; - - /** - * Current position of the pointer - * - * @var int - * @access private - */ - var $position = 0; - - /** - * Name of the hedaer currently being parsed + * Get the content for the item * - * @access private - * @var string - */ - var $name = ''; - - /** - * Value of the hedaer currently being parsed + * Prefers full content over summaries, but will return a summary if full + * content does not exist. * - * @access private - * @var string - */ - var $value = ''; - - /** - * Create an instance of the class with the input data + * To prefer summaries instead, use {@see get_description} * - * @access public - * @param string $data Input data - */ - function SimplePie_HTTP_Parser($data) - { - $this->data = $data; - $this->data_length = strlen($this->data); - } - - /** - * Parse the input data + * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module) * - * @access public - * @return bool true on success, false on failure + * @since 1.0 + * @param boolean $content_only Should we avoid falling back to the description? + * @return string|null */ - function parse() + public function get_content($content_only = false) { - while ($this->state && $this->state !== 'emit' && $this->has_data()) + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content')) { - $state = $this->state; - $this->$state(); + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); } - $this->data = ''; - if ($this->state === 'emit' || $this->state === 'body') + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content')) { - return true; + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif (!$content_only) + { + return $this->get_description(true); } else { - $this->http_version = ''; - $this->status_code = ''; - $this->reason = ''; - $this->headers = array(); - $this->body = ''; - return false; + return null; } } /** - * Check whether there is data beyond the pointer + * Get a category for the item * - * @access private - * @return bool true if there is further data, false if not + * @since Beta 3 (previously called `get_categories()` since Beta 2) + * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Category|null */ - function has_data() + public function get_category($key = 0) { - return (bool) ($this->position < $this->data_length); + $categories = $this->get_categories(); + if (isset($categories[$key])) + { + return $categories[$key]; + } + else + { + return null; + } } /** - * See if the next character is LWS + * Get all categories for the item * - * @access private - * @return bool true if the next character is LWS, false if not - */ - function is_linear_whitespace() - { - return (bool) ($this->data[$this->position] === "\x09" - || $this->data[$this->position] === "\x20" - || ($this->data[$this->position] === "\x0A" - && isset($this->data[$this->position + 1]) - && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20"))); - } - - /** - * Parse the HTTP version + * Uses `<atom:category>`, `<category>` or `<dc:subject>` * - * @access private + * @since Beta 3 + * @return array|null List of {@see SimplePie_Category} objects */ - function http_version() + public function get_categories() { - if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/') + $categories = array(); + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) { - $len = strspn($this->data, '0123456789.', 5); - $this->http_version = substr($this->data, 5, $len); - $this->position += 5 + $len; - if (substr_count($this->http_version, '.') <= 1) + $term = null; + $scheme = null; + $label = null; + if (isset($category['attribs']['']['term'])) { - $this->http_version = (float) $this->http_version; - $this->position += strspn($this->data, "\x09\x20", $this->position); - $this->state = 'status'; + $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) + { + // This is really the label, but keep this as the term also for BC. + // Label will also work on retrieving because that falls back to term. + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + if (isset($category['attribs']['']['domain'])) + { + $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); } else { - $this->state = false; + $scheme = null; } + $categories[] = $this->registry->create('Category', array($term, $scheme, null)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($categories)) + { + return array_unique($categories); } else { - $this->state = false; + return null; } } /** - * Parse the status code + * Get an author for the item * - * @access private + * @since Beta 2 + * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null */ - function status() + public function get_author($key = 0) { - if ($len = strspn($this->data, '0123456789', $this->position)) + $authors = $this->get_authors(); + if (isset($authors[$key])) { - $this->status_code = (int) substr($this->data, $this->position, $len); - $this->position += $len; - $this->state = 'reason'; + return $authors[$key]; } else { - $this->state = false; + return null; } } /** - * Parse the reason phrase + * Get a contributor for the item * - * @access private + * @since 1.1 + * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null */ - function reason() + public function get_contributor($key = 0) { - $len = strcspn($this->data, "\x0A", $this->position); - $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20"); - $this->position += $len + 1; - $this->state = 'new_line'; + $contributors = $this->get_contributors(); + if (isset($contributors[$key])) + { + return $contributors[$key]; + } + else + { + return null; + } } /** - * Deal with a new line, shifting data around as needed + * Get all contributors for the item * - * @access private + * Uses `<atom:contributor>` + * + * @since 1.1 + * @return array|null List of {@see SimplePie_Author} objects */ - function new_line() + public function get_contributors() { - $this->value = trim($this->value, "\x0D\x20"); - if ($this->name !== '' && $this->value !== '') + $contributors = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) { - $this->name = strtolower($this->name); - if (isset($this->headers[$this->name])) + $name = null; + $uri = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) { - $this->headers[$this->name] .= ', ' . $this->value; + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - else + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) { - $this->headers[$this->name] = $this->value; + $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $uri, $email)); } } - $this->name = ''; - $this->value = ''; - if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A") + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) { - $this->position += 2; - $this->state = 'body'; + $name = null; + $url = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $url, $email)); + } } - elseif ($this->data[$this->position] === "\x0A") + + if (!empty($contributors)) { - $this->position++; - $this->state = 'body'; + return array_unique($contributors); } else { - $this->state = 'name'; + return null; } } /** - * Parse a header name + * Get all authors for the item * - * @access private + * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>` + * + * @since Beta 2 + * @return array|null List of {@see SimplePie_Author} objects */ - function name() + public function get_authors() { - $len = strcspn($this->data, "\x0A:", $this->position); - if (isset($this->data[$this->position + $len])) + $authors = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) { - if ($this->data[$this->position + $len] === "\x0A") - { - $this->position += $len; - $this->state = 'new_line'; + $name = null; + $uri = null; + $email = null; + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - else + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) { - $this->name = substr($this->data, $this->position, $len); - $this->position += $len + 1; - $this->state = 'value'; + $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $authors[] = $this->registry->create('Author', array($name, $uri, $email)); + } + } + if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) + { + $name = null; + $url = null; + $email = null; + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $authors[] = $this->registry->create('Author', array($name, $url, $email)); } } + if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author')) + { + $authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT))); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($authors)) + { + return array_unique($authors); + } + elseif (($source = $this->get_source()) && ($authors = $source->get_authors())) + { + return $authors; + } + elseif ($authors = $this->feed->get_authors()) + { + return $authors; + } else { - $this->state = false; + return null; } } /** - * Parse LWS, replacing consecutive LWS characters with a single space + * Get the copyright info for the item * - * @access private + * Uses `<atom:rights>` or `<dc:rights>` + * + * @since 1.1 + * @return string */ - function linear_whitespace() + public function get_copyright() { - do + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) { - if (substr($this->data, $this->position, 2) === "\x0D\x0A") - { - $this->position += 2; - } - elseif ($this->data[$this->position] === "\x0A") - { - $this->position++; - } - $this->position += strspn($this->data, "\x09\x20", $this->position); - } while ($this->has_data() && $this->is_linear_whitespace()); - $this->value .= "\x20"; + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } } /** - * See what state to move to while within non-quoted header values + * Get the posting date/time for the item * - * @access private + * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`, + * `<atom:modified>`, `<pubDate>` or `<dc:date>` + * + * Note: obeys PHP's timezone setting. To get a UTC date/time, use + * {@see get_gmdate} + * + * @since Beta 2 (previously called `get_item_date` since 0.8) + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data) + * @return int|string|null */ - function value() + public function get_date($date_format = 'j F Y, g:i a') { - if ($this->is_linear_whitespace()) + if (!isset($this->data['date'])) { - $this->linear_whitespace(); + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + + if (!empty($this->data['date']['raw'])) + { + $parser = $this->registry->call('Parse_Date', 'get'); + $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']); + } + else + { + $this->data['date'] = null; + } } - else + if ($this->data['date']) { - switch ($this->data[$this->position]) + $date_format = (string) $date_format; + switch ($date_format) { - case '"': - $this->position++; - $this->state = 'quote'; - break; + case '': + return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT); - case "\x0A": - $this->position++; - $this->state = 'new_line'; - break; + case 'U': + return $this->data['date']['parsed']; default: - $this->state = 'value_char'; - break; + return date($date_format, $this->data['date']['parsed']); } } + else + { + return null; + } } /** - * Parse a header value while outside quotes + * Get the update date/time for the item * - * @access private - */ - function value_char() - { - $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position); - $this->value .= substr($this->data, $this->position, $len); - $this->position += $len; - $this->state = 'value'; - } - - /** - * See what state to move to while within quoted header values + * Uses `<atom:updated>` * - * @access private + * Note: obeys PHP's timezone setting. To get a UTC date/time, use + * {@see get_gmdate} + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data) + * @return int|string|null */ - function quote() + public function get_updated_date($date_format = 'j F Y, g:i a') { - if ($this->is_linear_whitespace()) + if (!isset($this->data['updated'])) { - $this->linear_whitespace(); + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated')) + { + $this->data['updated']['raw'] = $return[0]['data']; + } + + if (!empty($this->data['updated']['raw'])) + { + $parser = $this->registry->call('Parse_Date', 'get'); + $this->data['updated']['parsed'] = $parser->parse($this->data['date']['raw']); + } + else + { + $this->data['updated'] = null; + } } - else + if ($this->data['updated']) { - switch ($this->data[$this->position]) + $date_format = (string) $date_format; + switch ($date_format) { - case '"': - $this->position++; - $this->state = 'value'; - break; - - case "\x0A": - $this->position++; - $this->state = 'new_line'; - break; + case '': + return $this->sanitize($this->data['updated']['raw'], SIMPLEPIE_CONSTRUCT_TEXT); - case '\\': - $this->position++; - $this->state = 'quote_escaped'; - break; + case 'U': + return $this->data['updated']['parsed']; default: - $this->state = 'quote_char'; - break; + return date($date_format, $this->data['updated']['parsed']); } } + else + { + return null; + } } /** - * Parse a header value while within quotes + * Get the localized posting date/time for the item * - * @access private + * Returns the date formatted in the localized language. To display in + * languages other than the server's default, you need to change the locale + * with {@link http://php.net/setlocale setlocale()}. The available + * localizations depend on which ones are installed on your web server. + * + * @since 1.0 + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data) + * @return int|string|null */ - function quote_char() + public function get_local_date($date_format = '%c') { - $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position); - $this->value .= substr($this->data, $this->position, $len); - $this->position += $len; - $this->state = 'value'; + if (!$date_format) + { + return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (($date = $this->get_date('U')) !== null && $date !== false) + { + return strftime($date_format, $date); + } + else + { + return null; + } } /** - * Parse an escaped character within quotes + * Get the posting date/time for the item (UTC time) * - * @access private + * @see get_date + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} + * @return int|string|null */ - function quote_escaped() + public function get_gmdate($date_format = 'j F Y, g:i a') { - $this->value .= $this->data[$this->position]; - $this->position++; - $this->state = 'quote'; + $date = $this->get_date('U'); + if ($date === null) + { + return null; + } + + return gmdate($date_format, $date); } /** - * Parse the body + * Get the update date/time for the item (UTC time) * - * @access private + * @see get_updated_date + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} + * @return int|string|null */ - function body() + public function get_updated_gmdate($date_format = 'j F Y, g:i a') { - $this->body = substr($this->data, $this->position); - $this->state = 'emit'; - } -} - -/** - * gzdecode - * - * @package SimplePie - */ -class SimplePie_gzdecode -{ - /** - * Compressed data - * - * @access private - * @see gzdecode::$data - */ - var $compressed_data; - - /** - * Size of compressed data - * - * @access private - */ - var $compressed_size; - - /** - * Minimum size of a valid gzip string - * - * @access private - */ - var $min_compressed_size = 18; - - /** - * Current position of pointer - * - * @access private - */ - var $position = 0; - - /** - * Flags (FLG) - * - * @access private - */ - var $flags; - - /** - * Uncompressed data - * - * @access public - * @see gzdecode::$compressed_data - */ - var $data; - - /** - * Modified time - * - * @access public - */ - var $MTIME; - - /** - * Extra Flags - * - * @access public - */ - var $XFL; - - /** - * Operating System - * - * @access public - */ - var $OS; - - /** - * Subfield ID 1 - * - * @access public - * @see gzdecode::$extra_field - * @see gzdecode::$SI2 - */ - var $SI1; - - /** - * Subfield ID 2 - * - * @access public - * @see gzdecode::$extra_field - * @see gzdecode::$SI1 - */ - var $SI2; - - /** - * Extra field content - * - * @access public - * @see gzdecode::$SI1 - * @see gzdecode::$SI2 - */ - var $extra_field; + $date = $this->get_updated_date('U'); + if ($date === null) + { + return null; + } - /** - * Original filename - * - * @access public - */ - var $filename; + return gmdate($date_format, $date); + } /** - * Human readable comment + * Get the permalink for the item * - * @access public - */ - var $comment; - - /** - * Don't allow anything to be set + * Returns the first link available with a relationship of "alternate". + * Identical to {@see get_link()} with key 0 * - * @access public + * @see get_link + * @since 0.8 + * @return string|null Permalink URL */ - function __set($name, $value) + public function get_permalink() { - trigger_error("Cannot write property $name", E_USER_ERROR); + $link = $this->get_link(); + $enclosure = $this->get_enclosure(0); + if ($link !== null) + { + return $link; + } + elseif ($enclosure !== null) + { + return $enclosure->get_link(); + } + else + { + return null; + } } /** - * Set the compressed string and related properties + * Get a single link for the item * - * @access public + * @since Beta 3 + * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 + * @param string $rel The relationship of the link to return + * @return string|null Link URL */ - function SimplePie_gzdecode($data) + public function get_link($key = 0, $rel = 'alternate') { - $this->compressed_data = $data; - $this->compressed_size = strlen($data); + $links = $this->get_links($rel); + if ($links[$key] !== null) + { + return $links[$key]; + } + else + { + return null; + } } /** - * Decode the GZIP stream + * Get all links for the item * - * @access public + * Uses `<atom:link>`, `<link>` or `<guid>` + * + * @since Beta 2 + * @param string $rel The relationship of links to return + * @return array|null Links found for the item (strings) */ - function parse() + public function get_links($rel = 'alternate') { - if ($this->compressed_size >= $this->min_compressed_size) + if (!isset($this->data['links'])) { - // Check ID1, ID2, and CM - if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08") + $this->data['links'] = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link) { - return false; - } - - // Get the FLG (FLaGs) - $this->flags = ord($this->compressed_data[3]); + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); - // FLG bits above (1 << 4) are reserved - if ($this->flags > 0x1F) + } + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link) { - return false; + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + } } - - // Advance the pointer after the above - $this->position += 4; - - // MTIME - $mtime = substr($this->compressed_data, $this->position, 4); - // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness - if (current(unpack('S', "\x00\x01")) === 1) + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) { - $mtime = strrev($mtime); + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); } - $this->MTIME = current(unpack('l', $mtime)); - $this->position += 4; - - // Get the XFL (eXtra FLags) - $this->XFL = ord($this->compressed_data[$this->position++]); - - // Get the OS (Operating System) - $this->OS = ord($this->compressed_data[$this->position++]); - - // Parse the FEXTRA - if ($this->flags & 4) + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) { - // Read subfield IDs - $this->SI1 = $this->compressed_data[$this->position++]; - $this->SI2 = $this->compressed_data[$this->position++]; - - // SI2 set to zero is reserved for future use - if ($this->SI2 === "\x00") - { - return false; - } - - // Get the length of the extra field - $len = current(unpack('v', substr($this->compressed_data, $this->position, 2))); - $this->position += 2; - - // Check the length of the string is still valid - $this->min_compressed_size += $len + 4; - if ($this->compressed_size >= $this->min_compressed_size) - { - // Set the extra field to the given data - $this->extra_field = substr($this->compressed_data, $this->position, $len); - $this->position += $len; - } - else + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) + { + if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true') { - return false; + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); } } - // Parse the FNAME - if ($this->flags & 8) + $keys = array_keys($this->data['links']); + foreach ($keys as $key) { - // Get the length of the filename - $len = strcspn($this->compressed_data, "\x00", $this->position); - - // Check the length of the string is still valid - $this->min_compressed_size += $len + 1; - if ($this->compressed_size >= $this->min_compressed_size) + if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key))) { - // Set the original filename to the given string - $this->filename = substr($this->compressed_data, $this->position, $len); - $this->position += $len + 1; + if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); + $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; + } + else + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; + } } - else + elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) { - return false; + $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; } + $this->data['links'][$key] = array_unique($this->data['links'][$key]); } - - // Parse the FCOMMENT - if ($this->flags & 16) - { - // Get the length of the comment - $len = strcspn($this->compressed_data, "\x00", $this->position); - - // Check the length of the string is still valid - $this->min_compressed_size += $len + 1; - if ($this->compressed_size >= $this->min_compressed_size) - { - // Set the original comment to the given string - $this->comment = substr($this->compressed_data, $this->position, $len); - $this->position += $len + 1; - } - else - { - return false; - } - } - - // Parse the FHCRC - if ($this->flags & 2) - { - // Check the length of the string is still valid - $this->min_compressed_size += $len + 2; - if ($this->compressed_size >= $this->min_compressed_size) - { - // Read the CRC - $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2))); - - // Check the CRC matches - if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc) - { - $this->position += 2; - } - else - { - return false; - } - } - else - { - return false; - } - } - - // Decompress the actual data - if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false) - { - return false; - } - else - { - $this->position = $this->compressed_size - 8; - } - - // Check CRC of data - $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4))); - $this->position += 4; - /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc)) - { - return false; - }*/ - - // Check ISIZE of data - $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4))); - $this->position += 4; - if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize)) - { - return false; - } - - // Wow, against all odds, we've actually got a valid gzip string - return true; + } + if (isset($this->data['links'][$rel])) + { + return $this->data['links'][$rel]; } else { - return false; + return null; } } -} -class SimplePie_Cache -{ /** - * Don't call the constructor. Please. + * Get an enclosure from the item * - * @access private + * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS. + * + * @since Beta 2 + * @todo Add ability to prefer one type of content over another (in a media group). + * @param int $key The enclosure that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Enclosure|null */ - function SimplePie_Cache() + public function get_enclosure($key = 0, $prefer = null) { - trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR); + $enclosures = $this->get_enclosures(); + if (isset($enclosures[$key])) + { + return $enclosures[$key]; + } + else + { + return null; + } } /** - * Create a new SimplePie_Cache object + * Get all available enclosures (podcasts, etc.) * - * @static - * @access public + * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS. + * + * At this point, we're pretty much assuming that all enclosures for an item + * are the same content. Anything else is too complicated to + * properly support. + * + * @since Beta 2 + * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4). + * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists). + * @return array|null List of SimplePie_Enclosure items */ - function create($location, $filename, $extension) + public function get_enclosures() { - $location_iri = new SimplePie_IRI($location); - switch ($location_iri->get_scheme()) + if (!isset($this->data['enclosures'])) { - case 'mysql': - if (extension_loaded('mysql')) - { - return new SimplePie_Cache_MySQL($location_iri, $filename, $extension); - } - break; - - default: - return new SimplePie_Cache_File($location, $filename, $extension); - } - } -} - -class SimplePie_Cache_File -{ - var $location; - var $filename; - var $extension; - var $name; - - function SimplePie_Cache_File($location, $filename, $extension) - { - $this->location = $location; - $this->filename = $filename; - $this->extension = $extension; - $this->name = "$this->location/$this->filename.$this->extension"; - } + $this->data['enclosures'] = array(); - function save($data) - { - if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location)) - { - if (is_a($data, 'SimplePie')) - { - $data = $data->data; - } + // Elements + $captions_parent = null; + $categories_parent = null; + $copyrights_parent = null; + $credits_parent = null; + $description_parent = null; + $duration_parent = null; + $hashes_parent = null; + $keywords_parent = null; + $player_parent = null; + $ratings_parent = null; + $restrictions_parent = null; + $thumbnails_parent = null; + $title_parent = null; - $data = serialize($data); + // Let's do the channel and item-level ones first, and just re-use them if we need to. + $parent = $this->get_feed(); - if (function_exists('file_put_contents')) + // CAPTIONS + if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text')) { - return (bool) file_put_contents($this->name, $data); + foreach ($captions as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } } - else + elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text')) { - $fp = fopen($this->name, 'wb'); - if ($fp) + foreach ($captions as $caption) { - fwrite($fp, $data); - fclose($fp); - return true; + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); } } - } - return false; - } - - function load() - { - if (file_exists($this->name) && is_readable($this->name)) - { - return unserialize(file_get_contents($this->name)); - } - return false; - } - - function mtime() - { - if (file_exists($this->name)) - { - return filemtime($this->name); - } - return false; - } - - function touch() - { - if (file_exists($this->name)) - { - return touch($this->name); - } - return false; - } - - function unlink() - { - if (file_exists($this->name)) - { - return unlink($this->name); - } - return false; - } -} - -class SimplePie_Cache_DB -{ - function prepare_simplepie_object_for_cache($data) - { - $items = $data->get_items(); - $items_by_id = array(); - - if (!empty($items)) - { - foreach ($items as $item) + if (is_array($captions_parent)) { - $items_by_id[$item->get_id()] = $item; + $captions_parent = array_values(array_unique($captions_parent)); } - if (count($items_by_id) !== count($items)) + // CATEGORIES + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category) { - $items_by_id = array(); - foreach ($items as $item) + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) { - $items_by_id[$item->get_id(true)] = $item; + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - } - - if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0])) - { - $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]; - } - elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0])) - { - $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]; - } - elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0])) - { - $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]; - } - elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0])) - { - $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]; - } - else - { - $channel = null; - } - - if ($channel !== null) - { - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'])) + if (isset($category['attribs']['']['scheme'])) { - unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']); + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); } - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry'])) + else { - unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']); + $scheme = 'http://search.yahoo.com/mrss/category_schema'; } - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])) + if (isset($category['attribs']['']['label'])) { - unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']); + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); } - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])) + $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) { - unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']); + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item'])) + if (isset($category['attribs']['']['scheme'])) { - unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']); + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); } - } - if (isset($data->data['items'])) - { - unset($data->data['items']); - } - if (isset($data->data['ordered_items'])) - { - unset($data->data['ordered_items']); - } - } - return array(serialize($data->data), $items_by_id); - } -} - -class SimplePie_Cache_MySQL extends SimplePie_Cache_DB -{ - var $mysql; - var $options; - var $id; - - function SimplePie_Cache_MySQL($mysql_location, $name, $extension) - { - $host = $mysql_location->get_host(); - if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')') - { - $server = ':' . substr($host, 5, -1); - } - else - { - $server = $host; - if ($mysql_location->get_port() !== null) - { - $server .= ':' . $mysql_location->get_port(); - } - } - - if (strpos($mysql_location->get_userinfo(), ':') !== false) - { - list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2); - } - else - { - $username = $mysql_location->get_userinfo(); - $password = null; - } - - if ($this->mysql = mysql_connect($server, $username, $password)) - { - $this->id = $name . $extension; - $this->options = SimplePie_Misc::parse_str($mysql_location->get_query()); - if (!isset($this->options['prefix'][0])) - { - $this->options['prefix'][0] = ''; - } - - if (mysql_select_db(ltrim($mysql_location->get_path(), '/')) - && mysql_query('SET NAMES utf8') - && ($query = mysql_unbuffered_query('SHOW TABLES'))) - { - $db = array(); - while ($row = mysql_fetch_row($query)) + else { - $db[] = $row[0]; + $scheme = 'http://search.yahoo.com/mrss/category_schema'; } - - if (!in_array($this->options['prefix'][0] . 'cache_data', $db)) + if (isset($category['attribs']['']['label'])) { - if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))')) - { - $this->mysql = null; - } + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category) + { + $term = null; + $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; + $label = null; + if (isset($category['attribs']['']['text'])) + { + $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT); } + $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label)); - if (!in_array($this->options['prefix'][0] . 'items', $db)) + if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'])) { - if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))')) + foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory) { - $this->mysql = null; + if (isset($subcategory['attribs']['']['text'])) + { + $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label)); } } } - else + if (is_array($categories_parent)) { - $this->mysql = null; + $categories_parent = array_values(array_unique($categories_parent)); } - } - } - - function save($data) - { - if ($this->mysql) - { - $feed_id = "'" . mysql_real_escape_string($this->id) . "'"; - if (is_a($data, 'SimplePie')) + // COPYRIGHT + if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright')) { - if (SIMPLEPIE_PHP5) + $copyright_url = null; + $copyright_label = null; + if (isset($copyright[0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($copyright[0]['data'])) { - // This keyword needs to defy coding standards for PHP4 compatibility - $data = clone($data); + $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } + $copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright')) + { + $copyright_url = null; + $copyright_label = null; + if (isset($copyright[0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($copyright[0]['data'])) + { + $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } - $prepared = $this->prepare_simplepie_object_for_cache($data); - - if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql)) + // CREDITS + if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit')) + { + foreach ($credits as $credit) { - if (mysql_num_rows($query)) + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) { - $items = count($prepared[1]); - if ($items) - { - $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id; - } - else - { - $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id; - } - - if (!mysql_query($sql, $this->mysql)) - { - return false; - } + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); } - elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql)) + if (isset($credit['attribs']['']['scheme'])) { - return false; + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); } - - $ids = array_keys($prepared[1]); - if (!empty($ids)) + else { - foreach ($ids as $id) - { - $database_ids[] = mysql_real_escape_string($id); - } - - if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql)) - { - $existing_ids = array(); - while ($row = mysql_fetch_row($query)) - { - $existing_ids[] = $row[0]; - } - - $new_ids = array_diff($ids, $existing_ids); - - foreach ($new_ids as $new_id) - { - if (!($date = $prepared[1][$new_id]->get_date('U'))) - { - $date = time(); - } - - if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql)) - { - return false; - } - } - return true; - } + $credit_scheme = 'urn:ebu'; } - else + if (isset($credit['data'])) { - return true; + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); } + $credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); } } - elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql)) + elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit')) { - if (mysql_num_rows($query)) + foreach ($credits as $credit) { - if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql)) + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) { - return true; + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); } - elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql)) - { - return true; - } - } - } - return false; - } - - function load() - { - if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query))) - { - $data = unserialize($row[1]); - - if (isset($this->options['items'][0])) - { - $items = (int) $this->options['items'][0]; } - else + if (is_array($credits_parent)) { - $items = (int) $row[0]; + $credits_parent = array_values(array_unique($credits_parent)); } - if ($items !== 0) + // DESCRIPTION + if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description')) { - if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0])) - { - $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]; - } - elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0])) + if (isset($description_parent[0]['data'])) { - $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]; + $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0])) + } + elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description')) + { + if (isset($description_parent[0]['data'])) { - $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]; - } - elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0])) - { - $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]; - } - else - { - $feed = null; + $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } + } - if ($feed !== null) + // DURATION + if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration')) + { + $seconds = null; + $minutes = null; + $hours = null; + if (isset($duration_parent[0]['data'])) { - $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC'; - if ($items > 0) + $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + if (sizeof($temp) > 0) { - $sql .= ' LIMIT ' . $items; + $seconds = (int) array_pop($temp); } - - if ($query = mysql_unbuffered_query($sql, $this->mysql)) + if (sizeof($temp) > 0) { - while ($row = mysql_fetch_row($query)) - { - $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]); - } + $minutes = (int) array_pop($temp); + $seconds += $minutes * 60; } - else + if (sizeof($temp) > 0) { - return false; + $hours = (int) array_pop($temp); + $seconds += $hours * 3600; } + unset($temp); + $duration_parent = $seconds; } } - return $data; - } - return false; - } - - function mtime() - { - if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query))) - { - return $row[0]; - } - else - { - return false; - } - } - - function touch() - { - if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql)) - { - return true; - } - else - { - return false; - } - } - - function unlink() - { - if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql))) - { - return true; - } - else - { - return false; - } - } -} - -class SimplePie_Misc -{ - function time_hms($seconds) - { - $time = ''; - - $hours = floor($seconds / 3600); - $remainder = $seconds % 3600; - if ($hours > 0) - { - $time .= $hours.':'; - } - - $minutes = floor($remainder / 60); - $seconds = $remainder % 60; - if ($minutes < 10 && $hours > 0) - { - $minutes = '0' . $minutes; - } - if ($seconds < 10) - { - $seconds = '0' . $seconds; - } - - $time .= $minutes.':'; - $time .= $seconds; - - return $time; - } - function absolutize_url($relative, $base) - { - $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative); - return $iri->get_iri(); - } - - function remove_dot_segments($input) - { - $output = ''; - while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') - { - // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise, - if (strpos($input, '../') === 0) - { - $input = substr($input, 3); - } - elseif (strpos($input, './') === 0) + // HASHES + if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash')) { - $input = substr($input, 2); + foreach ($hashes_iterator as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes_parent[] = $algo.':'.$value; + } } - // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise, - elseif (strpos($input, '/./') === 0) + elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash')) { - $input = substr_replace($input, '/', 0, 3); + foreach ($hashes_iterator as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes_parent[] = $algo.':'.$value; + } } - elseif ($input === '/.') + if (is_array($hashes_parent)) { - $input = '/'; + $hashes_parent = array_values(array_unique($hashes_parent)); } - // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise, - elseif (strpos($input, '/../') === 0) + + // KEYWORDS + if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords')) { - $input = substr_replace($input, '/', 0, 4); - $output = substr_replace($output, '', strrpos($output, '/')); + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); } - elseif ($input === '/..') + elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords')) { - $input = '/'; - $output = substr_replace($output, '', strrpos($output, '/')); + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); } - // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise, - elseif ($input === '.' || $input === '..') + elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords')) { - $input = ''; + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); } - // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer - elseif (($pos = strpos($input, '/', 1)) !== false) + elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords')) { - $output .= substr($input, 0, $pos); - $input = substr_replace($input, '', 0, $pos); + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); } - else + if (is_array($keywords_parent)) { - $output .= $input; - $input = ''; + $keywords_parent = array_values(array_unique($keywords_parent)); } - } - return $output . $input; - } - function get_element($realname, $string) - { - $return = array(); - $name = preg_quote($realname, '/'); - if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) - { - for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++) + // PLAYER + if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player')) { - $return[$i]['tag'] = $realname; - $return[$i]['full'] = $matches[$i][0][0]; - $return[$i]['offset'] = $matches[$i][0][1]; - if (strlen($matches[$i][3][0]) <= 2) - { - $return[$i]['self_closing'] = true; - } - else + if (isset($player_parent[0]['attribs']['']['url'])) { - $return[$i]['self_closing'] = false; - $return[$i]['content'] = $matches[$i][4][0]; + $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); } - $return[$i]['attribs'] = array(); - if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER)) + } + elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player')) + { + if (isset($player_parent[0]['attribs']['']['url'])) { - for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++) - { - if (count($attribs[$j]) === 2) - { - $attribs[$j][2] = $attribs[$j][1]; - } - $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8'); - } + $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); } } - } - return $return; - } - function element_implode($element) - { - $full = "<$element[tag]"; - foreach ($element['attribs'] as $key => $value) - { - $key = strtolower($key); - $full .= " $key=\"" . htmlspecialchars($value['data']) . '"'; - } - if ($element['self_closing']) - { - $full .= ' />'; - } - else - { - $full .= ">$element[content]</$element[tag]>"; - } - return $full; - } - - function error($message, $level, $file, $line) - { - if ((ini_get('error_reporting') & $level) > 0) - { - switch ($level) + // RATINGS + if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating')) { - case E_USER_ERROR: - $note = 'PHP Error'; - break; - case E_USER_WARNING: - $note = 'PHP Warning'; - break; - case E_USER_NOTICE: - $note = 'PHP Notice'; - break; - default: - $note = 'Unknown Error'; - break; + foreach ($ratings as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } } - - $log_error = true; - if (!function_exists('error_log')) + elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit')) { - $log_error = false; + foreach ($ratings as $rating) + { + $rating_scheme = 'urn:itunes'; + $rating_value = null; + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } } - - $log_file = @ini_get('error_log'); - if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file)) + elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating')) { - $log_error = false; + foreach ($ratings as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } } - - if ($log_error) + elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit')) { - @error_log("$note: $message in $file on line $line", 0); + foreach ($ratings as $rating) + { + $rating_scheme = 'urn:itunes'; + $rating_value = null; + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + } + if (is_array($ratings_parent)) + { + $ratings_parent = array_values(array_unique($ratings_parent)); } - } - - return $message; - } - - /** - * If a file has been cached, retrieve and display it. - * - * This is most useful for caching images (get_favicon(), etc.), - * however it works for all cached files. This WILL NOT display ANY - * file/image/page/whatever, but rather only display what has already - * been cached by SimplePie. - * - * @access public - * @see SimplePie::get_favicon() - * @param str $identifier_url URL that is used to identify the content. - * This may or may not be the actual URL of the live content. - * @param str $cache_location Location of SimplePie's cache. Defaults - * to './cache'. - * @param str $cache_extension The file extension that the file was - * cached with. Defaults to 'spc'. - * @param str $cache_class Name of the cache-handling class being used - * in SimplePie. Defaults to 'SimplePie_Cache', and should be left - * as-is unless you've overloaded the class. - * @param str $cache_name_function Obsolete. Exists for backwards - * compatibility reasons only. - */ - function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5') - { - $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension); - if ($file = $cache->load()) - { - if (isset($file['headers']['content-type'])) + // RESTRICTIONS + if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + } + elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = 'allow'; + $restriction_type = null; + $restriction_value = 'itunes'; + if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') + { + $restriction_relationship = 'deny'; + } + $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + } + elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + } + elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = 'allow'; + $restriction_type = null; + $restriction_value = 'itunes'; + if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') + { + $restriction_relationship = 'deny'; + } + $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + } + if (is_array($restrictions_parent)) { - header('Content-type:' . $file['headers']['content-type']); + $restrictions_parent = array_values(array_unique($restrictions_parent)); } else { - header('Content-type: application/octet-stream'); + $restrictions_parent = array(new SimplePie_Restriction('allow', null, 'default')); } - header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days - echo $file['body']; - exit; - } - - die('Cached file for ' . $identifier_url . ' cannot be found.'); - } - function fix_protocol($url, $http = 1) - { - $url = SimplePie_Misc::normalize_url($url); - $parsed = SimplePie_Misc::parse_url($url); - if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') - { - return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http); - } + // THUMBNAILS + if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) + { + foreach ($thumbnails as $thumbnail) + { + if (isset($thumbnail['attribs']['']['url'])) + { + $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + } + elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) + { + foreach ($thumbnails as $thumbnail) + { + if (isset($thumbnail['attribs']['']['url'])) + { + $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + } - if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url)) - { - return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http); - } + // TITLES + if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title')) + { + if (isset($title_parent[0]['data'])) + { + $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title')) + { + if (isset($title_parent[0]['data'])) + { + $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } - if ($http === 2 && $parsed['scheme'] !== '') - { - return "feed:$url"; - } - elseif ($http === 3 && strtolower($parsed['scheme']) === 'http') - { - return substr_replace($url, 'podcast', 0, 4); - } - elseif ($http === 4 && strtolower($parsed['scheme']) === 'http') - { - return substr_replace($url, 'itpc', 0, 4); - } - else - { - return $url; - } - } + // Clear the memory + unset($parent); - function parse_url($url) - { - $iri = new SimplePie_IRI($url); - return array( - 'scheme' => (string) $iri->get_scheme(), - 'authority' => (string) $iri->get_authority(), - 'path' => (string) $iri->get_path(), - 'query' => (string) $iri->get_query(), - 'fragment' => (string) $iri->get_fragment() - ); - } - - function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '') - { - $iri = new SimplePie_IRI(''); - $iri->set_scheme($scheme); - $iri->set_authority($authority); - $iri->set_path($path); - $iri->set_query($query); - $iri->set_fragment($fragment); - return $iri->get_iri(); - } - - function normalize_url($url) - { - $iri = new SimplePie_IRI($url); - return $iri->get_iri(); - } - - function percent_encoding_normalization($match) - { - $integer = hexdec($match[1]); - if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E) - { - return chr($integer); - } - else - { - return strtoupper($match[0]); - } - } - - /** - * Remove bad UTF-8 bytes - * - * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C - * FAQ: Multilingual Forms (modified to include full ASCII range) - * - * @author Geoffrey Sneddon - * @see http://www.w3.org/International/questions/qa-forms-utf-8 - * @param string $str String to remove bad UTF-8 bytes from - * @return string UTF-8 string - */ - function utf8_bad_replace($str) - { - if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str))) - { - return $return; - } - elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8'))) - { - return $return; - } - elseif (preg_match_all('/(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})+/', $str, $matches)) - { - return implode("\xEF\xBF\xBD", $matches[0]); - } - elseif ($str !== '') - { - return "\xEF\xBF\xBD"; - } - else - { - return ''; - } - } - - /** - * Converts a Windows-1252 encoded string to a UTF-8 encoded string - * - * @static - * @access public - * @param string $string Windows-1252 encoded string - * @return string UTF-8 encoded string - */ - function windows_1252_to_utf8($string) - { - static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF"); - - return strtr($string, $convert_table); - } + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; - function change_encoding($data, $input, $output) - { - $input = SimplePie_Misc::encoding($input); - $output = SimplePie_Misc::encoding($output); + // Elements + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; - // We fail to fail on non US-ASCII bytes - if ($input === 'US-ASCII') - { - static $non_ascii_octects = ''; - if (!$non_ascii_octects) + // If we have media:group tags, loop through them. + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group) { - for ($i = 0x80; $i <= 0xFF; $i++) + if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'])) { - $non_ascii_octects .= chr($i); - } - } - $data = substr($data, 0, strcspn($data, $non_ascii_octects)); - } - - // This is first, as behaviour of this is completely predictable - if ($input === 'windows-1252' && $output === 'UTF-8') - { - return SimplePie_Misc::windows_1252_to_utf8($data); - } - // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported). - elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && in_array($input, mb_list_encodings()) && ($return = @mb_convert_encoding($data, $output, $input))) - { - return $return; - } - // This is last, as behaviour of this varies with OS userland and PHP version - elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data))) - { - return $return; - } - // If we can't do anything, just fail - else - { - return false; - } - } - - /** - * Normalize an encoding name - * - * This is automatically generated by create.php - * - * To generate it, run `php create.php` on the command line, and copy the - * output to replace this function. - * - * @param string $charset Character set to standardise - * @return string Standardised name - */ - function encoding($charset) - { - // Normalization from UTS #22 - switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset))) - { - case 'adobestandardencoding': - case 'csadobestandardencoding': - return 'Adobe-Standard-Encoding'; - - case 'adobesymbolencoding': - case 'cshppsmath': - return 'Adobe-Symbol-Encoding'; - - case 'ami1251': - case 'amiga1251': - return 'Amiga-1251'; + // If we have media:content tags, loop through them. + foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content) + { + if (isset($content['attribs']['']['url'])) + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; - case 'ansix31101983': - case 'csat5001983': - case 'csiso99naplps': - case 'isoir99': - case 'naplps': - return 'ANSI_X3.110-1983'; + // Elements + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; - case 'arabic7': - case 'asmo449': - case 'csiso89asmo449': - case 'iso9036': - case 'isoir89': - return 'ASMO_449'; + // Start checking the attributes of media:content + if (isset($content['attribs']['']['bitrate'])) + { + $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['channels'])) + { + $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['duration'])) + { + $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $duration = $duration_parent; + } + if (isset($content['attribs']['']['expression'])) + { + $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['framerate'])) + { + $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['height'])) + { + $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['lang'])) + { + $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['fileSize'])) + { + $length = ceil($content['attribs']['']['fileSize']); + } + if (isset($content['attribs']['']['medium'])) + { + $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['samplingrate'])) + { + $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['type'])) + { + $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['width'])) + { + $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - case 'big5': - case 'csbig5': - return 'Big5'; + // Checking the other optional media: elements. Priority: media:content, media:group, item, channel - case 'big5hkscs': - return 'Big5-HKSCS'; + // CAPTIONS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } + if (is_array($captions)) + { + $captions = array_values(array_unique($captions)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } + if (is_array($captions)) + { + $captions = array_values(array_unique($captions)); + } + } + else + { + $captions = $captions_parent; + } - case 'bocu1': - case 'csbocu1': - return 'BOCU-1'; + // CATEGORIES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + } + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + } + if (is_array($categories) && is_array($categories_parent)) + { + $categories = array_values(array_unique(array_merge($categories, $categories_parent))); + } + elseif (is_array($categories)) + { + $categories = array_values(array_unique($categories)); + } + elseif (is_array($categories_parent)) + { + $categories = array_values(array_unique($categories_parent)); + } - case 'brf': - case 'csbrf': - return 'BRF'; + // COPYRIGHTS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + else + { + $copyrights = $copyrights_parent; + } - case 'bs4730': - case 'csiso4unitedkingdom': - case 'gb': - case 'iso646gb': - case 'isoir4': - case 'uk': - return 'BS_4730'; + // CREDITS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); + } + if (is_array($credits)) + { + $credits = array_values(array_unique($credits)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); + } + if (is_array($credits)) + { + $credits = array_values(array_unique($credits)); + } + } + else + { + $credits = $credits_parent; + } - case 'bsviewdata': - case 'csiso47bsviewdata': - case 'isoir47': - return 'BS_viewdata'; + // DESCRIPTION + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $description = $description_parent; + } - case 'cesu8': - case 'cscesu8': - return 'CESU-8'; - - case 'ca': - case 'csa71': - case 'csaz243419851': - case 'csiso121canadian1': - case 'iso646ca': - case 'isoir121': - return 'CSA_Z243.4-1985-1'; - - case 'csa72': - case 'csaz243419852': - case 'csiso122canadian2': - case 'iso646ca2': - case 'isoir122': - return 'CSA_Z243.4-1985-2'; - - case 'csaz24341985gr': - case 'csiso123csaz24341985gr': - case 'isoir123': - return 'CSA_Z243.4-1985-gr'; - - case 'csiso139csn369103': - case 'csn369103': - case 'isoir139': - return 'CSN_369103'; - - case 'csdecmcs': - case 'dec': - case 'decmcs': - return 'DEC-MCS'; + // HASHES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(array_unique($hashes)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(array_unique($hashes)); + } + } + else + { + $hashes = $hashes_parent; + } - case 'csiso21german': - case 'de': - case 'din66003': - case 'iso646de': - case 'isoir21': - return 'DIN_66003'; + // KEYWORDS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(array_unique($keywords)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(array_unique($keywords)); + } + } + else + { + $keywords = $keywords_parent; + } - case 'csdkus': - case 'dkus': - return 'dk-us'; + // PLAYER + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + else + { + $player = $player_parent; + } - case 'csiso646danish': - case 'dk': - case 'ds2089': - case 'iso646dk': - return 'DS_2089'; + // RATINGS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + if (is_array($ratings)) + { + $ratings = array_values(array_unique($ratings)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + if (is_array($ratings)) + { + $ratings = array_values(array_unique($ratings)); + } + } + else + { + $ratings = $ratings_parent; + } - case 'csibmebcdicatde': - case 'ebcdicatde': - return 'EBCDIC-AT-DE'; + // RESTRICTIONS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + if (is_array($restrictions)) + { + $restrictions = array_values(array_unique($restrictions)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + if (is_array($restrictions)) + { + $restrictions = array_values(array_unique($restrictions)); + } + } + else + { + $restrictions = $restrictions_parent; + } - case 'csebcdicatdea': - case 'ebcdicatdea': - return 'EBCDIC-AT-DE-A'; + // THUMBNAILS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(array_unique($thumbnails)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(array_unique($thumbnails)); + } + } + else + { + $thumbnails = $thumbnails_parent; + } - case 'csebcdiccafr': - case 'ebcdiccafr': - return 'EBCDIC-CA-FR'; + // TITLES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $title = $title_parent; + } - case 'csebcdicdkno': - case 'ebcdicdkno': - return 'EBCDIC-DK-NO'; + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width)); + } + } + } + } - case 'csebcdicdknoa': - case 'ebcdicdknoa': - return 'EBCDIC-DK-NO-A'; + // If we have standalone media:content tags, loop through them. + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'])) + { + foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content) + { + if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; - case 'csebcdices': - case 'ebcdices': - return 'EBCDIC-ES'; + // Elements + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; - case 'csebcdicesa': - case 'ebcdicesa': - return 'EBCDIC-ES-A'; + // Start checking the attributes of media:content + if (isset($content['attribs']['']['bitrate'])) + { + $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['channels'])) + { + $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['duration'])) + { + $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $duration = $duration_parent; + } + if (isset($content['attribs']['']['expression'])) + { + $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['framerate'])) + { + $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['height'])) + { + $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['lang'])) + { + $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['fileSize'])) + { + $length = ceil($content['attribs']['']['fileSize']); + } + if (isset($content['attribs']['']['medium'])) + { + $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['samplingrate'])) + { + $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['type'])) + { + $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['width'])) + { + $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['url'])) + { + $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + // Checking the other optional media: elements. Priority: media:content, media:group, item, channel - case 'csebcdicess': - case 'ebcdicess': - return 'EBCDIC-ES-S'; + // CAPTIONS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } + if (is_array($captions)) + { + $captions = array_values(array_unique($captions)); + } + } + else + { + $captions = $captions_parent; + } - case 'csebcdicfise': - case 'ebcdicfise': - return 'EBCDIC-FI-SE'; + // CATEGORIES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + } + if (is_array($categories) && is_array($categories_parent)) + { + $categories = array_values(array_unique(array_merge($categories, $categories_parent))); + } + elseif (is_array($categories)) + { + $categories = array_values(array_unique($categories)); + } + elseif (is_array($categories_parent)) + { + $categories = array_values(array_unique($categories_parent)); + } + else + { + $categories = null; + } - case 'csebcdicfisea': - case 'ebcdicfisea': - return 'EBCDIC-FI-SE-A'; + // COPYRIGHTS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + else + { + $copyrights = $copyrights_parent; + } - case 'csebcdicfr': - case 'ebcdicfr': - return 'EBCDIC-FR'; - - case 'csebcdicit': - case 'ebcdicit': - return 'EBCDIC-IT'; + // CREDITS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); + } + if (is_array($credits)) + { + $credits = array_values(array_unique($credits)); + } + } + else + { + $credits = $credits_parent; + } - case 'csebcdicpt': - case 'ebcdicpt': - return 'EBCDIC-PT'; + // DESCRIPTION + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $description = $description_parent; + } - case 'csebcdicuk': - case 'ebcdicuk': - return 'EBCDIC-UK'; + // HASHES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(array_unique($hashes)); + } + } + else + { + $hashes = $hashes_parent; + } - case 'csebcdicus': - case 'ebcdicus': - return 'EBCDIC-US'; + // KEYWORDS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(array_unique($keywords)); + } + } + else + { + $keywords = $keywords_parent; + } - case 'csiso111ecmacyrillic': - case 'ecmacyrillic': - case 'isoir111': - case 'koi8e': - return 'ECMA-cyrillic'; + // PLAYER + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + else + { + $player = $player_parent; + } - case 'csiso17spanish': - case 'es': - case 'iso646es': - case 'isoir17': - return 'ES'; + // RATINGS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + if (is_array($ratings)) + { + $ratings = array_values(array_unique($ratings)); + } + } + else + { + $ratings = $ratings_parent; + } - case 'csiso85spanish2': - case 'es2': - case 'iso646es2': - case 'isoir85': - return 'ES2'; + // RESTRICTIONS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + if (is_array($restrictions)) + { + $restrictions = array_values(array_unique($restrictions)); + } + } + else + { + $restrictions = $restrictions_parent; + } - case 'cseucpkdfmtjapanese': - case 'eucjp': - case 'extendedunixcodepackedformatforjapanese': - return 'EUC-JP'; + // THUMBNAILS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(array_unique($thumbnails)); + } + } + else + { + $thumbnails = $thumbnails_parent; + } - case 'cseucfixwidjapanese': - case 'extendedunixcodefixedwidthforjapanese': - return 'Extended_UNIX_Code_Fixed_Width_for_Japanese'; + // TITLES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $title = $title_parent; + } - case 'gb18030': - return 'GB18030'; + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width)); + } + } + } - case 'chinese': - case 'cp936': - case 'csgb2312': - case 'csiso58gb231280': - case 'gb2312': - case 'gb231280': - case 'gbk': - case 'isoir58': - case 'ms936': - case 'windows936': - return 'GBK'; + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link) + { + if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; - case 'cn': - case 'csiso57gb1988': - case 'gb198880': - case 'iso646cn': - case 'isoir57': - return 'GB_1988-80'; + $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + if (isset($link['attribs']['']['type'])) + { + $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($link['attribs']['']['length'])) + { + $length = ceil($link['attribs']['']['length']); + } - case 'csiso153gost1976874': - case 'gost1976874': - case 'isoir153': - case 'stsev35888': - return 'GOST_19768-74'; + // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + } + } - case 'csiso150': - case 'csiso150greekccitt': - case 'greekccitt': - case 'isoir150': - return 'greek-ccitt'; + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link) + { + if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; - case 'csiso88greek7': - case 'greek7': - case 'isoir88': - return 'greek7'; + $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + if (isset($link['attribs']['']['type'])) + { + $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($link['attribs']['']['length'])) + { + $length = ceil($link['attribs']['']['length']); + } - case 'csiso18greek7old': - case 'greek7old': - case 'isoir18': - return 'greek7-old'; + // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + } + } - case 'cshpdesktop': - case 'hpdesktop': - return 'HP-DeskTop'; + if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure')) + { + if (isset($enclosure[0]['attribs']['']['url'])) + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; - case 'cshplegal': - case 'hplegal': - return 'HP-Legal'; + $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0])); + if (isset($enclosure[0]['attribs']['']['type'])) + { + $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($enclosure[0]['attribs']['']['length'])) + { + $length = ceil($enclosure[0]['attribs']['']['length']); + } - case 'cshpmath8': - case 'hpmath8': - return 'HP-Math8'; + // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + } + } - case 'cshppifont': - case 'hppifont': - return 'HP-Pi-font'; + if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width)) + { + // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + } - case 'cshproman8': - case 'hproman8': - case 'r8': - case 'roman8': - return 'hp-roman8'; + $this->data['enclosures'] = array_values(array_unique($this->data['enclosures'])); + } + if (!empty($this->data['enclosures'])) + { + return $this->data['enclosures']; + } + else + { + return null; + } + } - case 'hzgb2312': - return 'HZ-GB-2312'; + /** + * Get the latitude coordinates for the item + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:lat>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_latitude() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[1]; + } + else + { + return null; + } + } - case 'csibmsymbols': - case 'ibmsymbols': - return 'IBM-Symbols'; + /** + * Get the longitude coordinates for the item + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_longitude() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) + { + return (float) $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[2]; + } + else + { + return null; + } + } - case 'csibmthai': - case 'ibmthai': - return 'IBM-Thai'; + /** + * Get the `<atom:source>` for the item + * + * @since 1.1 + * @return SimplePie_Source|null + */ + public function get_source() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source')) + { + return $this->registry->create('Source', array($this, $return[0])); + } + else + { + return null; + } + } +} - case 'cp37': - case 'csibm37': - case 'ebcdiccpca': - case 'ebcdiccpnl': - case 'ebcdiccpus': - case 'ebcdiccpwt': - case 'ibm37': - return 'IBM037'; +/** + * Used for feed auto-discovery + * + * + * This class can be overloaded with {@see SimplePie::set_locator_class()} + * + * @package SimplePie + */ +class SimplePie_Locator +{ + var $useragent; + var $timeout; + var $file; + var $local = array(); + var $elsewhere = array(); + var $cached_entities = array(); + var $http_base; + var $base; + var $base_location = 0; + var $checked_feeds = 0; + var $max_checked_feeds = 10; + protected $registry; - case 'cp38': - case 'csibm38': - case 'ebcdicint': - case 'ibm38': - return 'IBM038'; + public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10) + { + $this->file = $file; + $this->useragent = $useragent; + $this->timeout = $timeout; + $this->max_checked_feeds = $max_checked_feeds; - case 'cp273': - case 'csibm273': - case 'ibm273': - return 'IBM273'; + if (class_exists('DOMDocument')) + { + $this->dom = new DOMDocument(); - case 'cp274': - case 'csibm274': - case 'ebcdicbe': - case 'ibm274': - return 'IBM274'; + set_error_handler(array('SimplePie_Misc', 'silence_errors')); + $this->dom->loadHTML($this->file->body); + restore_error_handler(); + } + else + { + $this->dom = null; + } + } - case 'cp275': - case 'csibm275': - case 'ebcdicbr': - case 'ibm275': - return 'IBM275'; + public function set_registry(SimplePie_Registry $registry) + { + $this->registry = $registry; + } - case 'csibm277': - case 'ebcdiccpdk': - case 'ebcdiccpno': - case 'ibm277': - return 'IBM277'; + public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working) + { + if ($this->is_feed($this->file)) + { + return $this->file; + } - case 'cp278': - case 'csibm278': - case 'ebcdiccpfi': - case 'ebcdiccpse': - case 'ibm278': - return 'IBM278'; + if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) + { + $sniffer = $this->registry->create('Content_Type_Sniffer', array($this->file)); + if ($sniffer->get_type() !== 'text/html') + { + return null; + } + } - case 'cp280': - case 'csibm280': - case 'ebcdiccpit': - case 'ibm280': - return 'IBM280'; + if ($type & ~SIMPLEPIE_LOCATOR_NONE) + { + $this->get_base(); + } - case 'cp281': - case 'csibm281': - case 'ebcdicjpe': - case 'ibm281': - return 'IBM281'; + if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery()) + { + return $working[0]; + } - case 'cp284': - case 'csibm284': - case 'ebcdiccpes': - case 'ibm284': - return 'IBM284'; + if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links()) + { + if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) + { + return $working; + } - case 'cp285': - case 'csibm285': - case 'ebcdiccpgb': - case 'ibm285': - return 'IBM285'; + if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) + { + return $working; + } - case 'cp290': - case 'csibm290': - case 'ebcdicjpkana': - case 'ibm290': - return 'IBM290'; + if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) + { + return $working; + } - case 'cp297': - case 'csibm297': - case 'ebcdiccpfr': - case 'ibm297': - return 'IBM297'; + if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) + { + return $working; + } + } + return null; + } - case 'cp420': - case 'csibm420': - case 'ebcdiccpar1': - case 'ibm420': - return 'IBM420'; + public function is_feed($file) + { + if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) + { + $sniffer = $this->registry->create('Content_Type_Sniffer', array($file)); + $sniffed = $sniffer->get_type(); + if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml'))) + { + return true; + } + else + { + return false; + } + } + elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL) + { + return true; + } + else + { + return false; + } + } - case 'cp423': - case 'csibm423': - case 'ebcdiccpgr': - case 'ibm423': - return 'IBM423'; + public function get_base() + { + if ($this->dom === null) + { + throw new SimplePie_Exception('DOMDocument not found, unable to use locator'); + } + $this->http_base = $this->file->url; + $this->base = $this->http_base; + $elements = $this->dom->getElementsByTagName('base'); + foreach ($elements as $element) + { + if ($element->hasAttribute('href')) + { + $base = $this->registry->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base)); + if ($base === false) + { + continue; + } + $this->base = $base; + $this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0; + break; + } + } + } - case 'cp424': - case 'csibm424': - case 'ebcdiccphe': - case 'ibm424': - return 'IBM424'; + public function autodiscovery() + { + $done = array(); + $feeds = array(); + $feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds)); + $feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds)); + $feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds)); - case '437': - case 'cp437': - case 'cspc8codepage437': - case 'ibm437': - return 'IBM437'; + if (!empty($feeds)) + { + return array_values($feeds); + } + else + { + return null; + } + } - case 'cp500': - case 'csibm500': - case 'ebcdiccpbe': - case 'ebcdiccpch': - case 'ibm500': - return 'IBM500'; + protected function search_elements_by_tag($name, &$done, $feeds) + { + if ($this->dom === null) + { + throw new SimplePie_Exception('DOMDocument not found, unable to use locator'); + } - case 'cp775': - case 'cspc775baltic': - case 'ibm775': - return 'IBM775'; + $links = $this->dom->getElementsByTagName($name); + foreach ($links as $link) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if ($link->hasAttribute('href') && $link->hasAttribute('rel')) + { + $rel = array_unique($this->registry->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel'))))); + $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1; - case '850': - case 'cp850': - case 'cspc850multilingual': - case 'ibm850': - return 'IBM850'; + if ($this->base_location < $line) + { + $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base)); + } + else + { + $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base)); + } + if ($href === false) + { + continue; + } - case '851': - case 'cp851': - case 'csibm851': - case 'ibm851': - return 'IBM851'; + if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href])) + { + $this->checked_feeds++; + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent)); + if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + { + $feeds[$href] = $feed; + } + } + $done[] = $href; + } + } - case '852': - case 'cp852': - case 'cspcp852': - case 'ibm852': - return 'IBM852'; + return $feeds; + } - case '855': - case 'cp855': - case 'csibm855': - case 'ibm855': - return 'IBM855'; + public function get_links() + { + if ($this->dom === null) + { + throw new SimplePie_Exception('DOMDocument not found, unable to use locator'); + } - case '857': - case 'cp857': - case 'csibm857': - case 'ibm857': - return 'IBM857'; + $links = $this->dom->getElementsByTagName('a'); + foreach ($links as $link) + { + if ($link->hasAttribute('href')) + { + $href = trim($link->getAttribute('href')); + $parsed = $this->registry->call('Misc', 'parse_url', array($href)); + if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme'])) + { + if ($this->base_location < $link->getLineNo()) + { + $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base)); + } + else + { + $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base)); + } + if ($href === false) + { + continue; + } - case 'ccsid858': - case 'cp858': - case 'ibm858': - case 'pcmultilingual850euro': - return 'IBM00858'; + $current = $this->registry->call('Misc', 'parse_url', array($this->file->url)); - case '860': - case 'cp860': - case 'csibm860': - case 'ibm860': - return 'IBM860'; + if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority']) + { + $this->local[] = $href; + } + else + { + $this->elsewhere[] = $href; + } + } + } + } + $this->local = array_unique($this->local); + $this->elsewhere = array_unique($this->elsewhere); + if (!empty($this->local) || !empty($this->elsewhere)) + { + return true; + } + return null; + } - case '861': - case 'cp861': - case 'cpis': - case 'csibm861': - case 'ibm861': - return 'IBM861'; - - case '862': - case 'cp862': - case 'cspc862latinhebrew': - case 'ibm862': - return 'IBM862'; + public function extension(&$array) + { + foreach ($array as $key => $value) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml'))) + { + $this->checked_feeds++; - case '863': - case 'cp863': - case 'csibm863': - case 'ibm863': - return 'IBM863'; + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent)); + if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + { + return $feed; + } + else + { + unset($array[$key]); + } + } + } + return null; + } - case 'cp864': - case 'csibm864': - case 'ibm864': - return 'IBM864'; + public function body(&$array) + { + foreach ($array as $key => $value) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if (preg_match('/(rss|rdf|atom|xml)/i', $value)) + { + $this->checked_feeds++; + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent)); + if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + { + return $feed; + } + else + { + unset($array[$key]); + } + } + } + return null; + } +} - case '865': - case 'cp865': - case 'csibm865': - case 'ibm865': - return 'IBM865'; +/** + * Miscellanous utilities + * + * @package SimplePie + */ +class SimplePie_Misc +{ + public static function time_hms($seconds) + { + $time = ''; - case '866': - case 'cp866': - case 'csibm866': - case 'ibm866': - return 'IBM866'; + $hours = floor($seconds / 3600); + $remainder = $seconds % 3600; + if ($hours > 0) + { + $time .= $hours.':'; + } - case 'cp868': - case 'cpar': - case 'csibm868': - case 'ibm868': - return 'IBM868'; + $minutes = floor($remainder / 60); + $seconds = $remainder % 60; + if ($minutes < 10 && $hours > 0) + { + $minutes = '0' . $minutes; + } + if ($seconds < 10) + { + $seconds = '0' . $seconds; + } - case '869': - case 'cp869': - case 'cpgr': - case 'csibm869': - case 'ibm869': - return 'IBM869'; + $time .= $minutes.':'; + $time .= $seconds; - case 'cp870': - case 'csibm870': - case 'ebcdiccproece': - case 'ebcdiccpyu': - case 'ibm870': - return 'IBM870'; + return $time; + } - case 'cp871': - case 'csibm871': - case 'ebcdiccpis': - case 'ibm871': - return 'IBM871'; + public static function absolutize_url($relative, $base) + { + $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative); + if ($iri === false) + { + return false; + } + return $iri->get_uri(); + } - case 'cp880': - case 'csibm880': - case 'ebcdiccyrillic': - case 'ibm880': - return 'IBM880'; + /** + * Get a HTML/XML element from a HTML string + * + * @deprecated Use DOMDocument instead (parsing HTML with regex is bad!) + * @param string $realname Element name (including namespace prefix if applicable) + * @param string $string HTML document + * @return array + */ + public static function get_element($realname, $string) + { + $return = array(); + $name = preg_quote($realname, '/'); + if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) + { + for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++) + { + $return[$i]['tag'] = $realname; + $return[$i]['full'] = $matches[$i][0][0]; + $return[$i]['offset'] = $matches[$i][0][1]; + if (strlen($matches[$i][3][0]) <= 2) + { + $return[$i]['self_closing'] = true; + } + else + { + $return[$i]['self_closing'] = false; + $return[$i]['content'] = $matches[$i][4][0]; + } + $return[$i]['attribs'] = array(); + if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER)) + { + for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++) + { + if (count($attribs[$j]) === 2) + { + $attribs[$j][2] = $attribs[$j][1]; + } + $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8'); + } + } + } + } + return $return; + } - case 'cp891': - case 'csibm891': - case 'ibm891': - return 'IBM891'; + public static function element_implode($element) + { + $full = "<$element[tag]"; + foreach ($element['attribs'] as $key => $value) + { + $key = strtolower($key); + $full .= " $key=\"" . htmlspecialchars($value['data']) . '"'; + } + if ($element['self_closing']) + { + $full .= ' />'; + } + else + { + $full .= ">$element[content]</$element[tag]>"; + } + return $full; + } - case 'cp903': - case 'csibm903': - case 'ibm903': - return 'IBM903'; + public static function error($message, $level, $file, $line) + { + if ((ini_get('error_reporting') & $level) > 0) + { + switch ($level) + { + case E_USER_ERROR: + $note = 'PHP Error'; + break; + case E_USER_WARNING: + $note = 'PHP Warning'; + break; + case E_USER_NOTICE: + $note = 'PHP Notice'; + break; + default: + $note = 'Unknown Error'; + break; + } - case '904': - case 'cp904': - case 'csibbm904': - case 'ibm904': - return 'IBM904'; + $log_error = true; + if (!function_exists('error_log')) + { + $log_error = false; + } - case 'cp905': - case 'csibm905': - case 'ebcdiccptr': - case 'ibm905': - return 'IBM905'; + $log_file = @ini_get('error_log'); + if (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable($log_file)) + { + $log_error = false; + } - case 'cp918': - case 'csibm918': - case 'ebcdiccpar2': - case 'ibm918': - return 'IBM918'; + if ($log_error) + { + @error_log("$note: $message in $file on line $line", 0); + } + } - case 'ccsid924': - case 'cp924': - case 'ebcdiclatin9euro': - case 'ibm924': - return 'IBM00924'; + return $message; + } - case 'cp1026': - case 'csibm1026': - case 'ibm1026': - return 'IBM1026'; + public static function fix_protocol($url, $http = 1) + { + $url = SimplePie_Misc::normalize_url($url); + $parsed = SimplePie_Misc::parse_url($url); + if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') + { + return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http); + } - case 'ibm1047': - return 'IBM1047'; + if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url)) + { + return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http); + } - case 'ccsid1140': - case 'cp1140': - case 'ebcdicus37euro': - case 'ibm1140': - return 'IBM01140'; + if ($http === 2 && $parsed['scheme'] !== '') + { + return "feed:$url"; + } + elseif ($http === 3 && strtolower($parsed['scheme']) === 'http') + { + return substr_replace($url, 'podcast', 0, 4); + } + elseif ($http === 4 && strtolower($parsed['scheme']) === 'http') + { + return substr_replace($url, 'itpc', 0, 4); + } + else + { + return $url; + } + } - case 'ccsid1141': - case 'cp1141': - case 'ebcdicde273euro': - case 'ibm1141': - return 'IBM01141'; + public static function parse_url($url) + { + $iri = new SimplePie_IRI($url); + return array( + 'scheme' => (string) $iri->scheme, + 'authority' => (string) $iri->authority, + 'path' => (string) $iri->path, + 'query' => (string) $iri->query, + 'fragment' => (string) $iri->fragment + ); + } - case 'ccsid1142': - case 'cp1142': - case 'ebcdicdk277euro': - case 'ebcdicno277euro': - case 'ibm1142': - return 'IBM01142'; + public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '') + { + $iri = new SimplePie_IRI(''); + $iri->scheme = $scheme; + $iri->authority = $authority; + $iri->path = $path; + $iri->query = $query; + $iri->fragment = $fragment; + return $iri->get_uri(); + } - case 'ccsid1143': - case 'cp1143': - case 'ebcdicfi278euro': - case 'ebcdicse278euro': - case 'ibm1143': - return 'IBM01143'; + public static function normalize_url($url) + { + $iri = new SimplePie_IRI($url); + return $iri->get_uri(); + } - case 'ccsid1144': - case 'cp1144': - case 'ebcdicit280euro': - case 'ibm1144': - return 'IBM01144'; + public static function percent_encoding_normalization($match) + { + $integer = hexdec($match[1]); + if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E) + { + return chr($integer); + } + else + { + return strtoupper($match[0]); + } + } - case 'ccsid1145': - case 'cp1145': - case 'ebcdices284euro': - case 'ibm1145': - return 'IBM01145'; + /** + * Converts a Windows-1252 encoded string to a UTF-8 encoded string + * + * @static + * @param string $string Windows-1252 encoded string + * @return string UTF-8 encoded string + */ + public static function windows_1252_to_utf8($string) + { + static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF"); - case 'ccsid1146': - case 'cp1146': - case 'ebcdicgb285euro': - case 'ibm1146': - return 'IBM01146'; + return strtr($string, $convert_table); + } - case 'ccsid1147': - case 'cp1147': - case 'ebcdicfr297euro': - case 'ibm1147': - return 'IBM01147'; + /** + * Change a string from one encoding to another + * + * @param string $data Raw data in $input encoding + * @param string $input Encoding of $data + * @param string $output Encoding you want + * @return string|boolean False if we can't convert it + */ + public static function change_encoding($data, $input, $output) + { + $input = SimplePie_Misc::encoding($input); + $output = SimplePie_Misc::encoding($output); - case 'ccsid1148': - case 'cp1148': - case 'ebcdicinternational500euro': - case 'ibm1148': - return 'IBM01148'; + // We fail to fail on non US-ASCII bytes + if ($input === 'US-ASCII') + { + static $non_ascii_octects = ''; + if (!$non_ascii_octects) + { + for ($i = 0x80; $i <= 0xFF; $i++) + { + $non_ascii_octects .= chr($i); + } + } + $data = substr($data, 0, strcspn($data, $non_ascii_octects)); + } - case 'ccsid1149': - case 'cp1149': - case 'ebcdicis871euro': - case 'ibm1149': - return 'IBM01149'; + // This is first, as behaviour of this is completely predictable + if ($input === 'windows-1252' && $output === 'UTF-8') + { + return SimplePie_Misc::windows_1252_to_utf8($data); + } + // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported). + elseif (function_exists('mb_convert_encoding') && ($return = SimplePie_Misc::change_encoding_mbstring($data, $input, $output))) + { + return $return; + } + // This is last, as behaviour of this varies with OS userland and PHP version + elseif (function_exists('iconv') && ($return = SimplePie_Misc::change_encoding_iconv($data, $input, $output))) + { + return $return; + } + // If we can't do anything, just fail + else + { + return false; + } + } - case 'csiso143iecp271': - case 'iecp271': - case 'isoir143': - return 'IEC_P27-1'; + protected static function change_encoding_mbstring($data, $input, $output) + { + if ($input === 'windows-949') + { + $input = 'EUC-KR'; + } + if ($output === 'windows-949') + { + $output = 'EUC-KR'; + } + if ($input === 'Windows-31J') + { + $input = 'SJIS'; + } + if ($output === 'Windows-31J') + { + $output = 'SJIS'; + } - case 'csiso49inis': - case 'inis': - case 'isoir49': - return 'INIS'; + // Check that the encoding is supported + if (@mb_convert_encoding("\x80", 'UTF-16BE', $input) === "\x00\x80") + { + return false; + } + if (!in_array($input, mb_list_encodings())) + { + return false; + } - case 'csiso50inis8': - case 'inis8': - case 'isoir50': - return 'INIS-8'; + // Let's do some conversion + if ($return = @mb_convert_encoding($data, $output, $input)) + { + return $return; + } - case 'csiso51iniscyrillic': - case 'iniscyrillic': - case 'isoir51': - return 'INIS-cyrillic'; + return false; + } - case 'csinvariant': - case 'invariant': - return 'INVARIANT'; + protected static function change_encoding_iconv($data, $input, $output) + { + return @iconv($input, $output, $data); + } - case 'iso2022cn': - return 'ISO-2022-CN'; + /** + * Normalize an encoding name + * + * This is automatically generated by create.php + * + * To generate it, run `php create.php` on the command line, and copy the + * output to replace this function. + * + * @param string $charset Character set to standardise + * @return string Standardised name + */ + public static function encoding($charset) + { + // Normalization from UTS #22 + switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset))) + { + case 'adobestandardencoding': + case 'csadobestandardencoding': + return 'Adobe-Standard-Encoding'; - case 'iso2022cnext': - return 'ISO-2022-CN-EXT'; + case 'adobesymbolencoding': + case 'cshppsmath': + return 'Adobe-Symbol-Encoding'; - case 'csiso2022jp': - case 'iso2022jp': - return 'ISO-2022-JP'; + case 'ami1251': + case 'amiga1251': + return 'Amiga-1251'; - case 'csiso2022jp2': - case 'iso2022jp2': - return 'ISO-2022-JP-2'; + case 'ansix31101983': + case 'csat5001983': + case 'csiso99naplps': + case 'isoir99': + case 'naplps': + return 'ANSI_X3.110-1983'; - case 'csiso2022kr': - case 'iso2022kr': - return 'ISO-2022-KR'; + case 'arabic7': + case 'asmo449': + case 'csiso89asmo449': + case 'iso9036': + case 'isoir89': + return 'ASMO_449'; - case 'cswindows30latin1': - case 'iso88591windows30latin1': - return 'ISO-8859-1-Windows-3.0-Latin-1'; + case 'big5': + case 'csbig5': + return 'Big5'; - case 'cswindows31latin1': - case 'iso88591windows31latin1': - return 'ISO-8859-1-Windows-3.1-Latin-1'; + case 'big5hkscs': + return 'Big5-HKSCS'; - case 'csisolatin2': - case 'iso88592': - case 'iso885921987': - case 'isoir101': - case 'l2': - case 'latin2': - return 'ISO-8859-2'; - - case 'cswindows31latin2': - case 'iso88592windowslatin2': - return 'ISO-8859-2-Windows-Latin-2'; + case 'bocu1': + case 'csbocu1': + return 'BOCU-1'; - case 'csisolatin3': - case 'iso88593': - case 'iso885931988': - case 'isoir109': - case 'l3': - case 'latin3': - return 'ISO-8859-3'; + case 'brf': + case 'csbrf': + return 'BRF'; - case 'csisolatin4': - case 'iso88594': - case 'iso885941988': - case 'isoir110': - case 'l4': - case 'latin4': - return 'ISO-8859-4'; + case 'bs4730': + case 'csiso4unitedkingdom': + case 'gb': + case 'iso646gb': + case 'isoir4': + case 'uk': + return 'BS_4730'; - case 'csisolatincyrillic': - case 'cyrillic': - case 'iso88595': - case 'iso885951988': - case 'isoir144': - return 'ISO-8859-5'; + case 'bsviewdata': + case 'csiso47bsviewdata': + case 'isoir47': + return 'BS_viewdata'; - case 'arabic': - case 'asmo708': - case 'csisolatinarabic': - case 'ecma114': - case 'iso88596': - case 'iso885961987': - case 'isoir127': - return 'ISO-8859-6'; + case 'cesu8': + case 'cscesu8': + return 'CESU-8'; - case 'csiso88596e': - case 'iso88596e': - return 'ISO-8859-6-E'; + case 'ca': + case 'csa71': + case 'csaz243419851': + case 'csiso121canadian1': + case 'iso646ca': + case 'isoir121': + return 'CSA_Z243.4-1985-1'; - case 'csiso88596i': - case 'iso88596i': - return 'ISO-8859-6-I'; + case 'csa72': + case 'csaz243419852': + case 'csiso122canadian2': + case 'iso646ca2': + case 'isoir122': + return 'CSA_Z243.4-1985-2'; - case 'csisolatingreek': - case 'ecma118': - case 'elot928': - case 'greek': - case 'greek8': - case 'iso88597': - case 'iso885971987': - case 'isoir126': - return 'ISO-8859-7'; + case 'csaz24341985gr': + case 'csiso123csaz24341985gr': + case 'isoir123': + return 'CSA_Z243.4-1985-gr'; - case 'csisolatinhebrew': - case 'hebrew': - case 'iso88598': - case 'iso885981988': - case 'isoir138': - return 'ISO-8859-8'; + case 'csiso139csn369103': + case 'csn369103': + case 'isoir139': + return 'CSN_369103'; - case 'csiso88598e': - case 'iso88598e': - return 'ISO-8859-8-E'; + case 'csdecmcs': + case 'dec': + case 'decmcs': + return 'DEC-MCS'; - case 'csiso88598i': - case 'iso88598i': - return 'ISO-8859-8-I'; + case 'csiso21german': + case 'de': + case 'din66003': + case 'iso646de': + case 'isoir21': + return 'DIN_66003'; - case 'cswindows31latin5': - case 'iso88599windowslatin5': - return 'ISO-8859-9-Windows-Latin-5'; + case 'csdkus': + case 'dkus': + return 'dk-us'; - case 'csisolatin6': - case 'iso885910': - case 'iso8859101992': - case 'isoir157': - case 'l6': - case 'latin6': - return 'ISO-8859-10'; + case 'csiso646danish': + case 'dk': + case 'ds2089': + case 'iso646dk': + return 'DS_2089'; - case 'iso885913': - return 'ISO-8859-13'; + case 'csibmebcdicatde': + case 'ebcdicatde': + return 'EBCDIC-AT-DE'; - case 'iso885914': - case 'iso8859141998': - case 'isoceltic': - case 'isoir199': - case 'l8': - case 'latin8': - return 'ISO-8859-14'; + case 'csebcdicatdea': + case 'ebcdicatdea': + return 'EBCDIC-AT-DE-A'; - case 'iso885915': - case 'latin9': - return 'ISO-8859-15'; + case 'csebcdiccafr': + case 'ebcdiccafr': + return 'EBCDIC-CA-FR'; - case 'iso885916': - case 'iso8859162001': - case 'isoir226': - case 'l10': - case 'latin10': - return 'ISO-8859-16'; + case 'csebcdicdkno': + case 'ebcdicdkno': + return 'EBCDIC-DK-NO'; - case 'iso10646j1': - return 'ISO-10646-J-1'; + case 'csebcdicdknoa': + case 'ebcdicdknoa': + return 'EBCDIC-DK-NO-A'; - case 'csunicode': - case 'iso10646ucs2': - return 'ISO-10646-UCS-2'; + case 'csebcdices': + case 'ebcdices': + return 'EBCDIC-ES'; - case 'csucs4': - case 'iso10646ucs4': - return 'ISO-10646-UCS-4'; + case 'csebcdicesa': + case 'ebcdicesa': + return 'EBCDIC-ES-A'; - case 'csunicodeascii': - case 'iso10646ucsbasic': - return 'ISO-10646-UCS-Basic'; + case 'csebcdicess': + case 'ebcdicess': + return 'EBCDIC-ES-S'; - case 'csunicodelatin1': - case 'iso10646': - case 'iso10646unicodelatin1': - return 'ISO-10646-Unicode-Latin1'; + case 'csebcdicfise': + case 'ebcdicfise': + return 'EBCDIC-FI-SE'; - case 'csiso10646utf1': - case 'iso10646utf1': - return 'ISO-10646-UTF-1'; + case 'csebcdicfisea': + case 'ebcdicfisea': + return 'EBCDIC-FI-SE-A'; - case 'csiso115481': - case 'iso115481': - case 'isotr115481': - return 'ISO-11548-1'; + case 'csebcdicfr': + case 'ebcdicfr': + return 'EBCDIC-FR'; - case 'csiso90': - case 'isoir90': - return 'iso-ir-90'; + case 'csebcdicit': + case 'ebcdicit': + return 'EBCDIC-IT'; - case 'csunicodeibm1261': - case 'isounicodeibm1261': - return 'ISO-Unicode-IBM-1261'; + case 'csebcdicpt': + case 'ebcdicpt': + return 'EBCDIC-PT'; - case 'csunicodeibm1264': - case 'isounicodeibm1264': - return 'ISO-Unicode-IBM-1264'; + case 'csebcdicuk': + case 'ebcdicuk': + return 'EBCDIC-UK'; - case 'csunicodeibm1265': - case 'isounicodeibm1265': - return 'ISO-Unicode-IBM-1265'; + case 'csebcdicus': + case 'ebcdicus': + return 'EBCDIC-US'; - case 'csunicodeibm1268': - case 'isounicodeibm1268': - return 'ISO-Unicode-IBM-1268'; + case 'csiso111ecmacyrillic': + case 'ecmacyrillic': + case 'isoir111': + case 'koi8e': + return 'ECMA-cyrillic'; - case 'csunicodeibm1276': - case 'isounicodeibm1276': - return 'ISO-Unicode-IBM-1276'; + case 'csiso17spanish': + case 'es': + case 'iso646es': + case 'isoir17': + return 'ES'; - case 'csiso646basic1983': - case 'iso646basic1983': - case 'ref': - return 'ISO_646.basic:1983'; + case 'csiso85spanish2': + case 'es2': + case 'iso646es2': + case 'isoir85': + return 'ES2'; - case 'csiso2intlrefversion': - case 'irv': - case 'iso646irv1983': - case 'isoir2': - return 'ISO_646.irv:1983'; - - case 'csiso2033': - case 'e13b': - case 'iso20331983': - case 'isoir98': - return 'ISO_2033-1983'; + case 'cseucpkdfmtjapanese': + case 'eucjp': + case 'extendedunixcodepackedformatforjapanese': + return 'EUC-JP'; - case 'csiso5427cyrillic': - case 'iso5427': - case 'isoir37': - return 'ISO_5427'; + case 'cseucfixwidjapanese': + case 'extendedunixcodefixedwidthforjapanese': + return 'Extended_UNIX_Code_Fixed_Width_for_Japanese'; - case 'iso5427cyrillic1981': - case 'iso54271981': - case 'isoir54': - return 'ISO_5427:1981'; + case 'gb18030': + return 'GB18030'; - case 'csiso5428greek': - case 'iso54281980': - case 'isoir55': - return 'ISO_5428:1980'; + case 'chinese': + case 'cp936': + case 'csgb2312': + case 'csiso58gb231280': + case 'gb2312': + case 'gb231280': + case 'gbk': + case 'isoir58': + case 'ms936': + case 'windows936': + return 'GBK'; - case 'csiso6937add': - case 'iso6937225': - case 'isoir152': - return 'ISO_6937-2-25'; + case 'cn': + case 'csiso57gb1988': + case 'gb198880': + case 'iso646cn': + case 'isoir57': + return 'GB_1988-80'; - case 'csisotextcomm': - case 'iso69372add': - case 'isoir142': - return 'ISO_6937-2-add'; + case 'csiso153gost1976874': + case 'gost1976874': + case 'isoir153': + case 'stsev35888': + return 'GOST_19768-74'; - case 'csiso8859supp': - case 'iso8859supp': - case 'isoir154': - case 'latin125': - return 'ISO_8859-supp'; + case 'csiso150': + case 'csiso150greekccitt': + case 'greekccitt': + case 'isoir150': + return 'greek-ccitt'; - case 'csiso10367box': - case 'iso10367box': - case 'isoir155': - return 'ISO_10367-box'; + case 'csiso88greek7': + case 'greek7': + case 'isoir88': + return 'greek7'; - case 'csiso15italian': - case 'iso646it': - case 'isoir15': - case 'it': - return 'IT'; + case 'csiso18greek7old': + case 'greek7old': + case 'isoir18': + return 'greek7-old'; - case 'csiso13jisc6220jp': - case 'isoir13': - case 'jisc62201969': - case 'jisc62201969jp': - case 'katakana': - case 'x2017': - return 'JIS_C6220-1969-jp'; + case 'cshpdesktop': + case 'hpdesktop': + return 'HP-DeskTop'; - case 'csiso14jisc6220ro': - case 'iso646jp': - case 'isoir14': - case 'jisc62201969ro': - case 'jp': - return 'JIS_C6220-1969-ro'; + case 'cshplegal': + case 'hplegal': + return 'HP-Legal'; - case 'csiso42jisc62261978': - case 'isoir42': - case 'jisc62261978': - return 'JIS_C6226-1978'; + case 'cshpmath8': + case 'hpmath8': + return 'HP-Math8'; - case 'csiso87jisx208': - case 'isoir87': - case 'jisc62261983': - case 'jisx2081983': - case 'x208': - return 'JIS_C6226-1983'; + case 'cshppifont': + case 'hppifont': + return 'HP-Pi-font'; - case 'csiso91jisc62291984a': - case 'isoir91': - case 'jisc62291984a': - case 'jpocra': - return 'JIS_C6229-1984-a'; + case 'cshproman8': + case 'hproman8': + case 'r8': + case 'roman8': + return 'hp-roman8'; - case 'csiso92jisc62991984b': - case 'iso646jpocrb': - case 'isoir92': - case 'jisc62291984b': - case 'jpocrb': - return 'JIS_C6229-1984-b'; + case 'hzgb2312': + return 'HZ-GB-2312'; - case 'csiso93jis62291984badd': - case 'isoir93': - case 'jisc62291984badd': - case 'jpocrbadd': - return 'JIS_C6229-1984-b-add'; + case 'csibmsymbols': + case 'ibmsymbols': + return 'IBM-Symbols'; - case 'csiso94jis62291984hand': - case 'isoir94': - case 'jisc62291984hand': - case 'jpocrhand': - return 'JIS_C6229-1984-hand'; + case 'csibmthai': + case 'ibmthai': + return 'IBM-Thai'; - case 'csiso95jis62291984handadd': - case 'isoir95': - case 'jisc62291984handadd': - case 'jpocrhandadd': - return 'JIS_C6229-1984-hand-add'; + case 'cp37': + case 'csibm37': + case 'ebcdiccpca': + case 'ebcdiccpnl': + case 'ebcdiccpus': + case 'ebcdiccpwt': + case 'ibm37': + return 'IBM037'; - case 'csiso96jisc62291984kana': - case 'isoir96': - case 'jisc62291984kana': - return 'JIS_C6229-1984-kana'; + case 'cp38': + case 'csibm38': + case 'ebcdicint': + case 'ibm38': + return 'IBM038'; - case 'csjisencoding': - case 'jisencoding': - return 'JIS_Encoding'; + case 'cp273': + case 'csibm273': + case 'ibm273': + return 'IBM273'; - case 'cshalfwidthkatakana': - case 'jisx201': - case 'x201': - return 'JIS_X0201'; + case 'cp274': + case 'csibm274': + case 'ebcdicbe': + case 'ibm274': + return 'IBM274'; - case 'csiso159jisx2121990': - case 'isoir159': - case 'jisx2121990': - case 'x212': - return 'JIS_X0212-1990'; + case 'cp275': + case 'csibm275': + case 'ebcdicbr': + case 'ibm275': + return 'IBM275'; - case 'csiso141jusib1002': - case 'iso646yu': - case 'isoir141': - case 'js': - case 'jusib1002': - case 'yu': - return 'JUS_I.B1.002'; + case 'csibm277': + case 'ebcdiccpdk': + case 'ebcdiccpno': + case 'ibm277': + return 'IBM277'; - case 'csiso147macedonian': - case 'isoir147': - case 'jusib1003mac': - case 'macedonian': - return 'JUS_I.B1.003-mac'; + case 'cp278': + case 'csibm278': + case 'ebcdiccpfi': + case 'ebcdiccpse': + case 'ibm278': + return 'IBM278'; - case 'csiso146serbian': - case 'isoir146': - case 'jusib1003serb': - case 'serbian': - return 'JUS_I.B1.003-serb'; + case 'cp280': + case 'csibm280': + case 'ebcdiccpit': + case 'ibm280': + return 'IBM280'; - case 'koi7switched': - return 'KOI7-switched'; + case 'cp281': + case 'csibm281': + case 'ebcdicjpe': + case 'ibm281': + return 'IBM281'; - case 'cskoi8r': - case 'koi8r': - return 'KOI8-R'; + case 'cp284': + case 'csibm284': + case 'ebcdiccpes': + case 'ibm284': + return 'IBM284'; - case 'koi8u': - return 'KOI8-U'; + case 'cp285': + case 'csibm285': + case 'ebcdiccpgb': + case 'ibm285': + return 'IBM285'; - case 'csksc5636': - case 'iso646kr': - case 'ksc5636': - return 'KSC5636'; + case 'cp290': + case 'csibm290': + case 'ebcdicjpkana': + case 'ibm290': + return 'IBM290'; - case 'cskz1048': - case 'kz1048': - case 'rk1048': - case 'strk10482002': - return 'KZ-1048'; + case 'cp297': + case 'csibm297': + case 'ebcdiccpfr': + case 'ibm297': + return 'IBM297'; - case 'csiso19latingreek': - case 'isoir19': - case 'latingreek': - return 'latin-greek'; + case 'cp420': + case 'csibm420': + case 'ebcdiccpar1': + case 'ibm420': + return 'IBM420'; - case 'csiso27latingreek1': - case 'isoir27': - case 'latingreek1': - return 'Latin-greek-1'; + case 'cp423': + case 'csibm423': + case 'ebcdiccpgr': + case 'ibm423': + return 'IBM423'; - case 'csiso158lap': - case 'isoir158': - case 'lap': - case 'latinlap': - return 'latin-lap'; + case 'cp424': + case 'csibm424': + case 'ebcdiccphe': + case 'ibm424': + return 'IBM424'; - case 'csmacintosh': - case 'mac': - case 'macintosh': - return 'macintosh'; + case '437': + case 'cp437': + case 'cspc8codepage437': + case 'ibm437': + return 'IBM437'; - case 'csmicrosoftpublishing': - case 'microsoftpublishing': - return 'Microsoft-Publishing'; + case 'cp500': + case 'csibm500': + case 'ebcdiccpbe': + case 'ebcdiccpch': + case 'ibm500': + return 'IBM500'; - case 'csmnem': - case 'mnem': - return 'MNEM'; + case 'cp775': + case 'cspc775baltic': + case 'ibm775': + return 'IBM775'; - case 'csmnemonic': - case 'mnemonic': - return 'MNEMONIC'; + case '850': + case 'cp850': + case 'cspc850multilingual': + case 'ibm850': + return 'IBM850'; - case 'csiso86hungarian': - case 'hu': - case 'iso646hu': - case 'isoir86': - case 'msz77953': - return 'MSZ_7795.3'; + case '851': + case 'cp851': + case 'csibm851': + case 'ibm851': + return 'IBM851'; - case 'csnatsdano': - case 'isoir91': - case 'natsdano': - return 'NATS-DANO'; + case '852': + case 'cp852': + case 'cspcp852': + case 'ibm852': + return 'IBM852'; - case 'csnatsdanoadd': - case 'isoir92': - case 'natsdanoadd': - return 'NATS-DANO-ADD'; + case '855': + case 'cp855': + case 'csibm855': + case 'ibm855': + return 'IBM855'; - case 'csnatssefi': - case 'isoir81': - case 'natssefi': - return 'NATS-SEFI'; + case '857': + case 'cp857': + case 'csibm857': + case 'ibm857': + return 'IBM857'; - case 'csnatssefiadd': - case 'isoir82': - case 'natssefiadd': - return 'NATS-SEFI-ADD'; + case 'ccsid858': + case 'cp858': + case 'ibm858': + case 'pcmultilingual850euro': + return 'IBM00858'; - case 'csiso151cuba': - case 'cuba': - case 'iso646cu': - case 'isoir151': - case 'ncnc1081': - return 'NC_NC00-10:81'; + case '860': + case 'cp860': + case 'csibm860': + case 'ibm860': + return 'IBM860'; - case 'csiso69french': - case 'fr': - case 'iso646fr': - case 'isoir69': - case 'nfz62010': - return 'NF_Z_62-010'; + case '861': + case 'cp861': + case 'cpis': + case 'csibm861': + case 'ibm861': + return 'IBM861'; - case 'csiso25french': - case 'iso646fr1': - case 'isoir25': - case 'nfz620101973': - return 'NF_Z_62-010_(1973)'; + case '862': + case 'cp862': + case 'cspc862latinhebrew': + case 'ibm862': + return 'IBM862'; - case 'csiso60danishnorwegian': - case 'csiso60norwegian1': - case 'iso646no': - case 'isoir60': - case 'no': - case 'ns45511': - return 'NS_4551-1'; + case '863': + case 'cp863': + case 'csibm863': + case 'ibm863': + return 'IBM863'; - case 'csiso61norwegian2': - case 'iso646no2': - case 'isoir61': - case 'no2': - case 'ns45512': - return 'NS_4551-2'; + case 'cp864': + case 'csibm864': + case 'ibm864': + return 'IBM864'; - case 'osdebcdicdf3irv': - return 'OSD_EBCDIC_DF03_IRV'; + case '865': + case 'cp865': + case 'csibm865': + case 'ibm865': + return 'IBM865'; - case 'osdebcdicdf41': - return 'OSD_EBCDIC_DF04_1'; + case '866': + case 'cp866': + case 'csibm866': + case 'ibm866': + return 'IBM866'; - case 'osdebcdicdf415': - return 'OSD_EBCDIC_DF04_15'; + case 'cp868': + case 'cpar': + case 'csibm868': + case 'ibm868': + return 'IBM868'; - case 'cspc8danishnorwegian': - case 'pc8danishnorwegian': - return 'PC8-Danish-Norwegian'; + case '869': + case 'cp869': + case 'cpgr': + case 'csibm869': + case 'ibm869': + return 'IBM869'; - case 'cspc8turkish': - case 'pc8turkish': - return 'PC8-Turkish'; + case 'cp870': + case 'csibm870': + case 'ebcdiccproece': + case 'ebcdiccpyu': + case 'ibm870': + return 'IBM870'; - case 'csiso16portuguese': - case 'iso646pt': - case 'isoir16': - case 'pt': - return 'PT'; + case 'cp871': + case 'csibm871': + case 'ebcdiccpis': + case 'ibm871': + return 'IBM871'; - case 'csiso84portuguese2': - case 'iso646pt2': - case 'isoir84': - case 'pt2': - return 'PT2'; + case 'cp880': + case 'csibm880': + case 'ebcdiccyrillic': + case 'ibm880': + return 'IBM880'; - case 'cp154': - case 'csptcp154': - case 'cyrillicasian': - case 'pt154': - case 'ptcp154': - return 'PTCP154'; + case 'cp891': + case 'csibm891': + case 'ibm891': + return 'IBM891'; - case 'scsu': - return 'SCSU'; - - case 'csiso10swedish': - case 'fi': - case 'iso646fi': - case 'iso646se': - case 'isoir10': - case 'se': - case 'sen850200b': - return 'SEN_850200_B'; + case 'cp903': + case 'csibm903': + case 'ibm903': + return 'IBM903'; - case 'csiso11swedishfornames': - case 'iso646se2': - case 'isoir11': - case 'se2': - case 'sen850200c': - return 'SEN_850200_C'; + case '904': + case 'cp904': + case 'csibbm904': + case 'ibm904': + return 'IBM904'; - case 'csiso102t617bit': - case 'isoir102': - case 't617bit': - return 'T.61-7bit'; + case 'cp905': + case 'csibm905': + case 'ebcdiccptr': + case 'ibm905': + return 'IBM905'; - case 'csiso103t618bit': - case 'isoir103': - case 't61': - case 't618bit': - return 'T.61-8bit'; + case 'cp918': + case 'csibm918': + case 'ebcdiccpar2': + case 'ibm918': + return 'IBM918'; - case 'csiso128t101g2': - case 'isoir128': - case 't101g2': - return 'T.101-G2'; + case 'ccsid924': + case 'cp924': + case 'ebcdiclatin9euro': + case 'ibm924': + return 'IBM00924'; - case 'cstscii': - case 'tscii': - return 'TSCII'; + case 'cp1026': + case 'csibm1026': + case 'ibm1026': + return 'IBM1026'; - case 'csunicode11': - case 'unicode11': - return 'UNICODE-1-1'; + case 'ibm1047': + return 'IBM1047'; - case 'csunicode11utf7': - case 'unicode11utf7': - return 'UNICODE-1-1-UTF-7'; + case 'ccsid1140': + case 'cp1140': + case 'ebcdicus37euro': + case 'ibm1140': + return 'IBM01140'; - case 'csunknown8bit': - case 'unknown8bit': - return 'UNKNOWN-8BIT'; + case 'ccsid1141': + case 'cp1141': + case 'ebcdicde273euro': + case 'ibm1141': + return 'IBM01141'; - case 'ansix341968': - case 'ansix341986': - case 'ascii': - case 'cp367': - case 'csascii': - case 'ibm367': - case 'iso646irv1991': - case 'iso646us': - case 'isoir6': - case 'us': - case 'usascii': - return 'US-ASCII'; + case 'ccsid1142': + case 'cp1142': + case 'ebcdicdk277euro': + case 'ebcdicno277euro': + case 'ibm1142': + return 'IBM01142'; - case 'csusdk': - case 'usdk': - return 'us-dk'; + case 'ccsid1143': + case 'cp1143': + case 'ebcdicfi278euro': + case 'ebcdicse278euro': + case 'ibm1143': + return 'IBM01143'; - case 'utf7': - return 'UTF-7'; + case 'ccsid1144': + case 'cp1144': + case 'ebcdicit280euro': + case 'ibm1144': + return 'IBM01144'; - case 'utf8': - return 'UTF-8'; + case 'ccsid1145': + case 'cp1145': + case 'ebcdices284euro': + case 'ibm1145': + return 'IBM01145'; - case 'utf16': - return 'UTF-16'; + case 'ccsid1146': + case 'cp1146': + case 'ebcdicgb285euro': + case 'ibm1146': + return 'IBM01146'; - case 'utf16be': - return 'UTF-16BE'; + case 'ccsid1147': + case 'cp1147': + case 'ebcdicfr297euro': + case 'ibm1147': + return 'IBM01147'; - case 'utf16le': - return 'UTF-16LE'; + case 'ccsid1148': + case 'cp1148': + case 'ebcdicinternational500euro': + case 'ibm1148': + return 'IBM01148'; - case 'utf32': - return 'UTF-32'; + case 'ccsid1149': + case 'cp1149': + case 'ebcdicis871euro': + case 'ibm1149': + return 'IBM01149'; - case 'utf32be': - return 'UTF-32BE'; + case 'csiso143iecp271': + case 'iecp271': + case 'isoir143': + return 'IEC_P27-1'; - case 'utf32le': - return 'UTF-32LE'; + case 'csiso49inis': + case 'inis': + case 'isoir49': + return 'INIS'; - case 'csventurainternational': - case 'venturainternational': - return 'Ventura-International'; + case 'csiso50inis8': + case 'inis8': + case 'isoir50': + return 'INIS-8'; - case 'csventuramath': - case 'venturamath': - return 'Ventura-Math'; + case 'csiso51iniscyrillic': + case 'iniscyrillic': + case 'isoir51': + return 'INIS-cyrillic'; - case 'csventuraus': - case 'venturaus': - return 'Ventura-US'; + case 'csinvariant': + case 'invariant': + return 'INVARIANT'; - case 'csiso70videotexsupp1': - case 'isoir70': - case 'videotexsuppl': - return 'videotex-suppl'; + case 'iso2022cn': + return 'ISO-2022-CN'; - case 'csviqr': - case 'viqr': - return 'VIQR'; + case 'iso2022cnext': + return 'ISO-2022-CN-EXT'; - case 'csviscii': - case 'viscii': - return 'VISCII'; + case 'csiso2022jp': + case 'iso2022jp': + return 'ISO-2022-JP'; - case 'csshiftjis': - case 'cswindows31j': - case 'mskanji': - case 'shiftjis': - case 'windows31j': - return 'Windows-31J'; + case 'csiso2022jp2': + case 'iso2022jp2': + return 'ISO-2022-JP-2'; - case 'iso885911': - case 'tis620': - return 'windows-874'; + case 'csiso2022kr': + case 'iso2022kr': + return 'ISO-2022-KR'; - case 'cseuckr': - case 'csksc56011987': - case 'euckr': - case 'isoir149': - case 'korean': - case 'ksc5601': - case 'ksc56011987': - case 'ksc56011989': - case 'windows949': - return 'windows-949'; + case 'cswindows30latin1': + case 'iso88591windows30latin1': + return 'ISO-8859-1-Windows-3.0-Latin-1'; - case 'windows1250': - return 'windows-1250'; + case 'cswindows31latin1': + case 'iso88591windows31latin1': + return 'ISO-8859-1-Windows-3.1-Latin-1'; - case 'windows1251': - return 'windows-1251'; + case 'csisolatin2': + case 'iso88592': + case 'iso885921987': + case 'isoir101': + case 'l2': + case 'latin2': + return 'ISO-8859-2'; - case 'cp819': - case 'csisolatin1': - case 'ibm819': - case 'iso88591': - case 'iso885911987': - case 'isoir100': - case 'l1': - case 'latin1': - case 'windows1252': - return 'windows-1252'; + case 'cswindows31latin2': + case 'iso88592windowslatin2': + return 'ISO-8859-2-Windows-Latin-2'; - case 'windows1253': - return 'windows-1253'; + case 'csisolatin3': + case 'iso88593': + case 'iso885931988': + case 'isoir109': + case 'l3': + case 'latin3': + return 'ISO-8859-3'; - case 'csisolatin5': - case 'iso88599': - case 'iso885991989': - case 'isoir148': - case 'l5': - case 'latin5': - case 'windows1254': - return 'windows-1254'; + case 'csisolatin4': + case 'iso88594': + case 'iso885941988': + case 'isoir110': + case 'l4': + case 'latin4': + return 'ISO-8859-4'; - case 'windows1255': - return 'windows-1255'; + case 'csisolatincyrillic': + case 'cyrillic': + case 'iso88595': + case 'iso885951988': + case 'isoir144': + return 'ISO-8859-5'; - case 'windows1256': - return 'windows-1256'; + case 'arabic': + case 'asmo708': + case 'csisolatinarabic': + case 'ecma114': + case 'iso88596': + case 'iso885961987': + case 'isoir127': + return 'ISO-8859-6'; - case 'windows1257': - return 'windows-1257'; + case 'csiso88596e': + case 'iso88596e': + return 'ISO-8859-6-E'; - case 'windows1258': - return 'windows-1258'; + case 'csiso88596i': + case 'iso88596i': + return 'ISO-8859-6-I'; - default: - return $charset; - } - } + case 'csisolatingreek': + case 'ecma118': + case 'elot928': + case 'greek': + case 'greek8': + case 'iso88597': + case 'iso885971987': + case 'isoir126': + return 'ISO-8859-7'; - function get_curl_version() - { - if (is_array($curl = curl_version())) - { - $curl = $curl['version']; - } - elseif (substr($curl, 0, 5) === 'curl/') - { - $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5)); - } - elseif (substr($curl, 0, 8) === 'libcurl/') - { - $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8)); - } - else - { - $curl = 0; - } - return $curl; - } + case 'csisolatinhebrew': + case 'hebrew': + case 'iso88598': + case 'iso885981988': + case 'isoir138': + return 'ISO-8859-8'; - function is_subclass_of($class1, $class2) - { - if (func_num_args() !== 2) - { - trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING); - } - elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1)) - { - return is_subclass_of($class1, $class2); - } - elseif (is_string($class1) && is_string($class2)) - { - if (class_exists($class1)) - { - if (class_exists($class2)) - { - $class2 = strtolower($class2); - while ($class1 = strtolower(get_parent_class($class1))) - { - if ($class1 === $class2) - { - return true; - } - } - } - } - else - { - trigger_error('Unknown class passed as parameter', E_USER_WARNNG); - } - } - return false; - } + case 'csiso88598e': + case 'iso88598e': + return 'ISO-8859-8-E'; - /** - * Strip HTML comments - * - * @access public - * @param string $data Data to strip comments from - * @return string Comment stripped string - */ - function strip_comments($data) - { - $output = ''; - while (($start = strpos($data, '<!--')) !== false) - { - $output .= substr($data, 0, $start); - if (($end = strpos($data, '-->', $start)) !== false) - { - $data = substr_replace($data, '', 0, $end + 3); - } - else - { - $data = ''; - } - } - return $output . $data; - } + case 'csiso88598i': + case 'iso88598i': + return 'ISO-8859-8-I'; - function parse_date($dt) - { - $parser = SimplePie_Parse_Date::get(); - return $parser->parse($dt); - } + case 'cswindows31latin5': + case 'iso88599windowslatin5': + return 'ISO-8859-9-Windows-Latin-5'; - /** - * Decode HTML entities - * - * @static - * @access public - * @param string $data Input data - * @return string Output data - */ - function entities_decode($data) - { - $decoder = new SimplePie_Decode_HTML_Entities($data); - return $decoder->parse(); - } + case 'csisolatin6': + case 'iso885910': + case 'iso8859101992': + case 'isoir157': + case 'l6': + case 'latin6': + return 'ISO-8859-10'; - /** - * Remove RFC822 comments - * - * @access public - * @param string $data Data to strip comments from - * @return string Comment stripped string - */ - function uncomment_rfc822($string) - { - $string = (string) $string; - $position = 0; - $length = strlen($string); - $depth = 0; + case 'iso885913': + return 'ISO-8859-13'; - $output = ''; + case 'iso885914': + case 'iso8859141998': + case 'isoceltic': + case 'isoir199': + case 'l8': + case 'latin8': + return 'ISO-8859-14'; - while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) - { - $output .= substr($string, $position, $pos - $position); - $position = $pos + 1; - if ($string[$pos - 1] !== '\\') - { - $depth++; - while ($depth && $position < $length) - { - $position += strcspn($string, '()', $position); - if ($string[$position - 1] === '\\') - { - $position++; - continue; - } - elseif (isset($string[$position])) - { - switch ($string[$position]) - { - case '(': - $depth++; - break; + case 'iso885915': + case 'latin9': + return 'ISO-8859-15'; - case ')': - $depth--; - break; - } - $position++; - } - else - { - break; - } - } - } - else - { - $output .= '('; - } - } - $output .= substr($string, $position); + case 'iso885916': + case 'iso8859162001': + case 'isoir226': + case 'l10': + case 'latin10': + return 'ISO-8859-16'; - return $output; - } + case 'iso10646j1': + return 'ISO-10646-J-1'; - function parse_mime($mime) - { - if (($pos = strpos($mime, ';')) === false) - { - return trim($mime); - } - else - { - return trim(substr($mime, 0, $pos)); - } - } + case 'csunicode': + case 'iso10646ucs2': + return 'ISO-10646-UCS-2'; - function htmlspecialchars_decode($string, $quote_style) - { - if (function_exists('htmlspecialchars_decode')) - { - return htmlspecialchars_decode($string, $quote_style); - } - else - { - return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style))); - } - } + case 'csucs4': + case 'iso10646ucs4': + return 'ISO-10646-UCS-4'; - function atom_03_construct_type($attribs) - { - if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64')) - { - $mode = SIMPLEPIE_CONSTRUCT_BASE64; - } - else - { - $mode = SIMPLEPIE_CONSTRUCT_NONE; - } - if (isset($attribs['']['type'])) - { - switch (strtolower(trim($attribs['']['type']))) - { - case 'text': - case 'text/plain': - return SIMPLEPIE_CONSTRUCT_TEXT | $mode; + case 'csunicodeascii': + case 'iso10646ucsbasic': + return 'ISO-10646-UCS-Basic'; - case 'html': - case 'text/html': - return SIMPLEPIE_CONSTRUCT_HTML | $mode; + case 'csunicodelatin1': + case 'iso10646': + case 'iso10646unicodelatin1': + return 'ISO-10646-Unicode-Latin1'; - case 'xhtml': - case 'application/xhtml+xml': - return SIMPLEPIE_CONSTRUCT_XHTML | $mode; + case 'csiso10646utf1': + case 'iso10646utf1': + return 'ISO-10646-UTF-1'; - default: - return SIMPLEPIE_CONSTRUCT_NONE | $mode; - } - } - else - { - return SIMPLEPIE_CONSTRUCT_TEXT | $mode; - } - } + case 'csiso115481': + case 'iso115481': + case 'isotr115481': + return 'ISO-11548-1'; - function atom_10_construct_type($attribs) - { - if (isset($attribs['']['type'])) - { - switch (strtolower(trim($attribs['']['type']))) - { - case 'text': - return SIMPLEPIE_CONSTRUCT_TEXT; + case 'csiso90': + case 'isoir90': + return 'iso-ir-90'; - case 'html': - return SIMPLEPIE_CONSTRUCT_HTML; + case 'csunicodeibm1261': + case 'isounicodeibm1261': + return 'ISO-Unicode-IBM-1261'; - case 'xhtml': - return SIMPLEPIE_CONSTRUCT_XHTML; + case 'csunicodeibm1264': + case 'isounicodeibm1264': + return 'ISO-Unicode-IBM-1264'; - default: - return SIMPLEPIE_CONSTRUCT_NONE; - } - } - return SIMPLEPIE_CONSTRUCT_TEXT; - } + case 'csunicodeibm1265': + case 'isounicodeibm1265': + return 'ISO-Unicode-IBM-1265'; - function atom_10_content_construct_type($attribs) - { - if (isset($attribs['']['type'])) - { - $type = strtolower(trim($attribs['']['type'])); - switch ($type) - { - case 'text': - return SIMPLEPIE_CONSTRUCT_TEXT; + case 'csunicodeibm1268': + case 'isounicodeibm1268': + return 'ISO-Unicode-IBM-1268'; - case 'html': - return SIMPLEPIE_CONSTRUCT_HTML; + case 'csunicodeibm1276': + case 'isounicodeibm1276': + return 'ISO-Unicode-IBM-1276'; - case 'xhtml': - return SIMPLEPIE_CONSTRUCT_XHTML; - } - if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/') - { - return SIMPLEPIE_CONSTRUCT_NONE; - } - else - { - return SIMPLEPIE_CONSTRUCT_BASE64; - } - } - else - { - return SIMPLEPIE_CONSTRUCT_TEXT; - } - } + case 'csiso646basic1983': + case 'iso646basic1983': + case 'ref': + return 'ISO_646.basic:1983'; - function is_isegment_nz_nc($string) - { - return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string); - } + case 'csiso2intlrefversion': + case 'irv': + case 'iso646irv1983': + case 'isoir2': + return 'ISO_646.irv:1983'; - function space_seperated_tokens($string) - { - $space_characters = "\x20\x09\x0A\x0B\x0C\x0D"; - $string_length = strlen($string); + case 'csiso2033': + case 'e13b': + case 'iso20331983': + case 'isoir98': + return 'ISO_2033-1983'; - $position = strspn($string, $space_characters); - $tokens = array(); + case 'csiso5427cyrillic': + case 'iso5427': + case 'isoir37': + return 'ISO_5427'; - while ($position < $string_length) - { - $len = strcspn($string, $space_characters, $position); - $tokens[] = substr($string, $position, $len); - $position += $len; - $position += strspn($string, $space_characters, $position); - } + case 'iso5427cyrillic1981': + case 'iso54271981': + case 'isoir54': + return 'ISO_5427:1981'; - return $tokens; - } + case 'csiso5428greek': + case 'iso54281980': + case 'isoir55': + return 'ISO_5428:1980'; - function array_unique($array) - { - if (version_compare(PHP_VERSION, '5.2', '>=')) - { - return array_unique($array); - } - else - { - $array = (array) $array; - $new_array = array(); - $new_array_strings = array(); - foreach ($array as $key => $value) - { - if (is_object($value)) - { - if (method_exists($value, '__toString')) - { - $cmp = $value->__toString(); - } - else - { - trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR); - } - } - elseif (is_array($value)) - { - $cmp = (string) reset($value); - } - else - { - $cmp = (string) $value; - } - if (!in_array($cmp, $new_array_strings)) - { - $new_array[$key] = $value; - $new_array_strings[] = $cmp; - } - } - return $new_array; - } - } + case 'csiso6937add': + case 'iso6937225': + case 'isoir152': + return 'ISO_6937-2-25'; - /** - * Converts a unicode codepoint to a UTF-8 character - * - * @static - * @access public - * @param int $codepoint Unicode codepoint - * @return string UTF-8 character - */ - function codepoint_to_utf8($codepoint) - { - $codepoint = (int) $codepoint; - if ($codepoint < 0) - { - return false; - } - else if ($codepoint <= 0x7f) - { - return chr($codepoint); - } - else if ($codepoint <= 0x7ff) - { - return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f)); - } - else if ($codepoint <= 0xffff) - { - return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f)); - } - else if ($codepoint <= 0x10ffff) - { - return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f)); - } - else - { - // U+FFFD REPLACEMENT CHARACTER - return "\xEF\xBF\xBD"; - } - } + case 'csisotextcomm': + case 'iso69372add': + case 'isoir142': + return 'ISO_6937-2-add'; - /** - * Re-implementation of PHP 5's stripos() - * - * Returns the numeric position of the first occurrence of needle in the - * haystack string. - * - * @static - * @access string - * @param object $haystack - * @param string $needle Note that the needle may be a string of one or more - * characters. If needle is not a string, it is converted to an integer - * and applied as the ordinal value of a character. - * @param int $offset The optional offset parameter allows you to specify which - * character in haystack to start searching. The position returned is still - * relative to the beginning of haystack. - * @return bool If needle is not found, stripos() will return boolean false. - */ - function stripos($haystack, $needle, $offset = 0) - { - if (function_exists('stripos')) - { - return stripos($haystack, $needle, $offset); - } - else - { - if (is_string($needle)) - { - $needle = strtolower($needle); - } - elseif (is_int($needle) || is_bool($needle) || is_double($needle)) - { - $needle = strtolower(chr($needle)); - } - else - { - trigger_error('needle is not a string or an integer', E_USER_WARNING); - return false; - } + case 'csiso8859supp': + case 'iso8859supp': + case 'isoir154': + case 'latin125': + return 'ISO_8859-supp'; - return strpos(strtolower($haystack), $needle, $offset); - } - } + case 'csiso10367box': + case 'iso10367box': + case 'isoir155': + return 'ISO_10367-box'; - /** - * Similar to parse_str() - * - * Returns an associative array of name/value pairs, where the value is an - * array of values that have used the same name - * - * @static - * @access string - * @param string $str The input string. - * @return array - */ - function parse_str($str) - { - $return = array(); - $str = explode('&', $str); + case 'csiso15italian': + case 'iso646it': + case 'isoir15': + case 'it': + return 'IT'; - foreach ($str as $section) - { - if (strpos($section, '=') !== false) - { - list($name, $value) = explode('=', $section, 2); - $return[urldecode($name)][] = urldecode($value); - } - else - { - $return[urldecode($section)][] = null; - } - } + case 'csiso13jisc6220jp': + case 'isoir13': + case 'jisc62201969': + case 'jisc62201969jp': + case 'katakana': + case 'x2017': + return 'JIS_C6220-1969-jp'; - return $return; - } + case 'csiso14jisc6220ro': + case 'iso646jp': + case 'isoir14': + case 'jisc62201969ro': + case 'jp': + return 'JIS_C6220-1969-ro'; - /** - * Detect XML encoding, as per XML 1.0 Appendix F.1 - * - * @todo Add support for EBCDIC - * @param string $data XML data - * @return array Possible encodings - */ - function xml_encoding($data) - { - // UTF-32 Big Endian BOM - if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") - { - $encoding[] = 'UTF-32BE'; - } - // UTF-32 Little Endian BOM - elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") - { - $encoding[] = 'UTF-32LE'; - } - // UTF-16 Big Endian BOM - elseif (substr($data, 0, 2) === "\xFE\xFF") - { - $encoding[] = 'UTF-16BE'; - } - // UTF-16 Little Endian BOM - elseif (substr($data, 0, 2) === "\xFF\xFE") - { - $encoding[] = 'UTF-16LE'; - } - // UTF-8 BOM - elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") - { - $encoding[] = 'UTF-8'; - } - // UTF-32 Big Endian Without BOM - elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C") - { - if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E")) - { - $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8')); - if ($parser->parse()) - { - $encoding[] = $parser->encoding; - } - } - $encoding[] = 'UTF-32BE'; - } - // UTF-32 Little Endian Without BOM - elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00") - { - if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00")) - { - $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8')); - if ($parser->parse()) - { - $encoding[] = $parser->encoding; - } - } - $encoding[] = 'UTF-32LE'; - } - // UTF-16 Big Endian Without BOM - elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C") - { - if ($pos = strpos($data, "\x00\x3F\x00\x3E")) - { - $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8')); - if ($parser->parse()) - { - $encoding[] = $parser->encoding; - } - } - $encoding[] = 'UTF-16BE'; - } - // UTF-16 Little Endian Without BOM - elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00") - { - if ($pos = strpos($data, "\x3F\x00\x3E\x00")) - { - $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8')); - if ($parser->parse()) - { - $encoding[] = $parser->encoding; - } - } - $encoding[] = 'UTF-16LE'; - } - // US-ASCII (or superset) - elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C") - { - if ($pos = strpos($data, "\x3F\x3E")) - { - $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5)); - if ($parser->parse()) - { - $encoding[] = $parser->encoding; - } - } - $encoding[] = 'UTF-8'; - } - // Fallback to UTF-8 - else - { - $encoding[] = 'UTF-8'; - } - return $encoding; - } + case 'csiso42jisc62261978': + case 'isoir42': + case 'jisc62261978': + return 'JIS_C6226-1978'; - function output_javascript() - { - if (function_exists('ob_gzhandler')) - { - ob_start('ob_gzhandler'); - } - header('Content-type: text/javascript; charset: UTF-8'); - header('Cache-Control: must-revalidate'); - header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days - ?> -function embed_odeo(link) { - document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>'); -} + case 'csiso87jisx208': + case 'isoir87': + case 'jisc62261983': + case 'jisx2081983': + case 'x208': + return 'JIS_C6226-1983'; -function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) { - if (placeholder != '') { - document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>'); - } - else { - document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>'); - } -} + case 'csiso91jisc62291984a': + case 'isoir91': + case 'jisc62291984a': + case 'jpocra': + return 'JIS_C6229-1984-a'; -function embed_flash(bgcolor, width, height, link, loop, type) { - document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>'); -} + case 'csiso92jisc62991984b': + case 'iso646jpocrb': + case 'isoir92': + case 'jisc62291984b': + case 'jpocrb': + return 'JIS_C6229-1984-b'; -function embed_flv(width, height, link, placeholder, loop, player) { - document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>'); -} + case 'csiso93jis62291984badd': + case 'isoir93': + case 'jisc62291984badd': + case 'jpocrbadd': + return 'JIS_C6229-1984-b-add'; -function embed_wmedia(width, height, link) { - document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>'); -} - <?php - } + case 'csiso94jis62291984hand': + case 'isoir94': + case 'jisc62291984hand': + case 'jpocrhand': + return 'JIS_C6229-1984-hand'; + case 'csiso95jis62291984handadd': + case 'isoir95': + case 'jisc62291984handadd': + case 'jpocrhandadd': + return 'JIS_C6229-1984-hand-add'; + case 'csiso96jisc62291984kana': + case 'isoir96': + case 'jisc62291984kana': + return 'JIS_C6229-1984-kana'; - /** - * Format debugging information - */ - function debug($sp) - { - $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n"; - $info .= 'PHP ' . PHP_VERSION . "\n"; - if ($sp->error() !== null) - { - $info .= 'Error occurred: ' . $sp->error() . "\n"; - } - else - { - $info .= "No error found.\n"; - } - $info .= "Extensions:\n"; - $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml'); - foreach ($extensions as $ext) - { - if (extension_loaded($ext)) - { - $info .= " $ext loaded\n"; - switch ($ext) - { - case 'pcre': - $info .= ' Version ' . PCRE_VERSION . "\n"; - break; - case 'curl': - $version = curl_version(); - $info .= ' Version ' . $version['version'] . "\n"; - break; - case 'mbstring': - $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n"; - break; - case 'iconv': - $info .= ' Version ' . ICONV_VERSION . "\n"; - break; - case 'xml': - $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n"; - break; - } - } - else - { - $info .= " $ext not loaded\n"; - } - } - return $info; - } -} + case 'csjisencoding': + case 'jisencoding': + return 'JIS_Encoding'; -/** - * Decode HTML Entities - * - * This implements HTML5 as of revision 967 (2007-06-28) - * - * @package SimplePie - */ -class SimplePie_Decode_HTML_Entities -{ - /** - * Data to be parsed - * - * @access private - * @var string - */ - var $data = ''; + case 'cshalfwidthkatakana': + case 'jisx201': + case 'x201': + return 'JIS_X0201'; - /** - * Currently consumed bytes - * - * @access private - * @var string - */ - var $consumed = ''; + case 'csiso159jisx2121990': + case 'isoir159': + case 'jisx2121990': + case 'x212': + return 'JIS_X0212-1990'; - /** - * Position of the current byte being parsed - * - * @access private - * @var int - */ - var $position = 0; + case 'csiso141jusib1002': + case 'iso646yu': + case 'isoir141': + case 'js': + case 'jusib1002': + case 'yu': + return 'JUS_I.B1.002'; - /** - * Create an instance of the class with the input data - * - * @access public - * @param string $data Input data - */ - function SimplePie_Decode_HTML_Entities($data) - { - $this->data = $data; - } + case 'csiso147macedonian': + case 'isoir147': + case 'jusib1003mac': + case 'macedonian': + return 'JUS_I.B1.003-mac'; - /** - * Parse the input data - * - * @access public - * @return string Output data - */ - function parse() - { - while (($this->position = strpos($this->data, '&', $this->position)) !== false) - { - $this->consume(); - $this->entity(); - $this->consumed = ''; - } - return $this->data; - } + case 'csiso146serbian': + case 'isoir146': + case 'jusib1003serb': + case 'serbian': + return 'JUS_I.B1.003-serb'; - /** - * Consume the next byte - * - * @access private - * @return mixed The next byte, or false, if there is no more data - */ - function consume() - { - if (isset($this->data[$this->position])) - { - $this->consumed .= $this->data[$this->position]; - return $this->data[$this->position++]; - } - else - { - return false; - } - } + case 'koi7switched': + return 'KOI7-switched'; - /** - * Consume a range of characters - * - * @access private - * @param string $chars Characters to consume - * @return mixed A series of characters that match the range, or false - */ - function consume_range($chars) - { - if ($len = strspn($this->data, $chars, $this->position)) - { - $data = substr($this->data, $this->position, $len); - $this->consumed .= $data; - $this->position += $len; - return $data; - } - else - { - return false; - } - } + case 'cskoi8r': + case 'koi8r': + return 'KOI8-R'; - /** - * Unconsume one byte - * - * @access private - */ - function unconsume() - { - $this->consumed = substr($this->consumed, 0, -1); - $this->position--; - } + case 'koi8u': + return 'KOI8-U'; - /** - * Decode an entity - * - * @access private - */ - function entity() - { - switch ($this->consume()) - { - case "\x09": - case "\x0A": - case "\x0B": - case "\x0B": - case "\x0C": - case "\x20": - case "\x3C": - case "\x26": - case false: - break; + case 'csksc5636': + case 'iso646kr': + case 'ksc5636': + return 'KSC5636'; - case "\x23": - switch ($this->consume()) - { - case "\x78": - case "\x58": - $range = '0123456789ABCDEFabcdef'; - $hex = true; - break; + case 'cskz1048': + case 'kz1048': + case 'rk1048': + case 'strk10482002': + return 'KZ-1048'; - default: - $range = '0123456789'; - $hex = false; - $this->unconsume(); - break; - } + case 'csiso19latingreek': + case 'isoir19': + case 'latingreek': + return 'latin-greek'; - if ($codepoint = $this->consume_range($range)) - { - static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8"); + case 'csiso27latingreek1': + case 'isoir27': + case 'latingreek1': + return 'Latin-greek-1'; - if ($hex) - { - $codepoint = hexdec($codepoint); - } - else - { - $codepoint = intval($codepoint); - } + case 'csiso158lap': + case 'isoir158': + case 'lap': + case 'latinlap': + return 'latin-lap'; - if (isset($windows_1252_specials[$codepoint])) - { - $replacement = $windows_1252_specials[$codepoint]; - } - else - { - $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint); - } + case 'csmacintosh': + case 'mac': + case 'macintosh': + return 'macintosh'; - if (!in_array($this->consume(), array(';', false), true)) - { - $this->unconsume(); - } + case 'csmicrosoftpublishing': + case 'microsoftpublishing': + return 'Microsoft-Publishing'; - $consumed_length = strlen($this->consumed); - $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length); - $this->position += strlen($replacement) - $consumed_length; - } - break; + case 'csmnem': + case 'mnem': + return 'MNEM'; - default: - static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C"); + case 'csmnemonic': + case 'mnemonic': + return 'MNEMONIC'; - for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++) - { - $consumed = substr($this->consumed, 1); - if (isset($entities[$consumed])) - { - $match = $consumed; - } - } + case 'csiso86hungarian': + case 'hu': + case 'iso646hu': + case 'isoir86': + case 'msz77953': + return 'MSZ_7795.3'; - if ($match !== null) - { - $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1); - $this->position += strlen($entities[$match]) - strlen($consumed) - 1; - } - break; - } - } -} + case 'csnatsdano': + case 'isoir91': + case 'natsdano': + return 'NATS-DANO'; -/** - * IRI parser/serialiser - * - * @package SimplePie - */ -class SimplePie_IRI -{ - /** - * Scheme - * - * @access private - * @var string - */ - var $scheme; + case 'csnatsdanoadd': + case 'isoir92': + case 'natsdanoadd': + return 'NATS-DANO-ADD'; - /** - * User Information - * - * @access private - * @var string - */ - var $userinfo; + case 'csnatssefi': + case 'isoir81': + case 'natssefi': + return 'NATS-SEFI'; - /** - * Host - * - * @access private - * @var string - */ - var $host; + case 'csnatssefiadd': + case 'isoir82': + case 'natssefiadd': + return 'NATS-SEFI-ADD'; - /** - * Port - * - * @access private - * @var string - */ - var $port; + case 'csiso151cuba': + case 'cuba': + case 'iso646cu': + case 'isoir151': + case 'ncnc1081': + return 'NC_NC00-10:81'; - /** - * Path - * - * @access private - * @var string - */ - var $path; + case 'csiso69french': + case 'fr': + case 'iso646fr': + case 'isoir69': + case 'nfz62010': + return 'NF_Z_62-010'; - /** - * Query - * - * @access private - * @var string - */ - var $query; + case 'csiso25french': + case 'iso646fr1': + case 'isoir25': + case 'nfz620101973': + return 'NF_Z_62-010_(1973)'; - /** - * Fragment - * - * @access private - * @var string - */ - var $fragment; + case 'csiso60danishnorwegian': + case 'csiso60norwegian1': + case 'iso646no': + case 'isoir60': + case 'no': + case 'ns45511': + return 'NS_4551-1'; - /** - * Whether the object represents a valid IRI - * - * @access private - * @var array - */ - var $valid = array(); + case 'csiso61norwegian2': + case 'iso646no2': + case 'isoir61': + case 'no2': + case 'ns45512': + return 'NS_4551-2'; - /** - * Return the entire IRI when you try and read the object as a string - * - * @access public - * @return string - */ - function __toString() - { - return $this->get_iri(); - } + case 'osdebcdicdf3irv': + return 'OSD_EBCDIC_DF03_IRV'; - /** - * Create a new IRI object, from a specified string - * - * @access public - * @param string $iri - * @return SimplePie_IRI - */ - function SimplePie_IRI($iri) - { - $iri = (string) $iri; - if ($iri !== '') - { - $parsed = $this->parse_iri($iri); - $this->set_scheme($parsed['scheme']); - $this->set_authority($parsed['authority']); - $this->set_path($parsed['path']); - $this->set_query($parsed['query']); - $this->set_fragment($parsed['fragment']); - } - } + case 'osdebcdicdf41': + return 'OSD_EBCDIC_DF04_1'; - /** - * Create a new IRI object by resolving a relative IRI - * - * @static - * @access public - * @param SimplePie_IRI $base Base IRI - * @param string $relative Relative IRI - * @return SimplePie_IRI - */ - function absolutize($base, $relative) - { - $relative = (string) $relative; - if ($relative !== '') - { - $relative = new SimplePie_IRI($relative); - if ($relative->get_scheme() !== null) - { - $target = $relative; - } - elseif ($base->get_iri() !== null) - { - if ($relative->get_authority() !== null) - { - $target = $relative; - $target->set_scheme($base->get_scheme()); - } - else - { - $target = new SimplePie_IRI(''); - $target->set_scheme($base->get_scheme()); - $target->set_userinfo($base->get_userinfo()); - $target->set_host($base->get_host()); - $target->set_port($base->get_port()); - if ($relative->get_path() !== null) - { - if (strpos($relative->get_path(), '/') === 0) - { - $target->set_path($relative->get_path()); - } - elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null) - { - $target->set_path('/' . $relative->get_path()); - } - elseif (($last_segment = strrpos($base->get_path(), '/')) !== false) - { - $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path()); - } - else - { - $target->set_path($relative->get_path()); - } - $target->set_query($relative->get_query()); - } - else - { - $target->set_path($base->get_path()); - if ($relative->get_query() !== null) - { - $target->set_query($relative->get_query()); - } - elseif ($base->get_query() !== null) - { - $target->set_query($base->get_query()); - } - } - } - $target->set_fragment($relative->get_fragment()); - } - else - { - // No base URL, just return the relative URL - $target = $relative; - } - } - else - { - $target = $base; - } - return $target; - } + case 'osdebcdicdf415': + return 'OSD_EBCDIC_DF04_15'; - /** - * Parse an IRI into scheme/authority/path/query/fragment segments - * - * @access private - * @param string $iri - * @return array - */ - function parse_iri($iri) - { - preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match); - for ($i = count($match); $i <= 9; $i++) - { - $match[$i] = ''; - } - return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]); - } + case 'cspc8danishnorwegian': + case 'pc8danishnorwegian': + return 'PC8-Danish-Norwegian'; - /** - * Remove dot segments from a path - * - * @access private - * @param string $input - * @return string - */ - function remove_dot_segments($input) - { - $output = ''; - while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') - { - // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise, - if (strpos($input, '../') === 0) - { - $input = substr($input, 3); - } - elseif (strpos($input, './') === 0) - { - $input = substr($input, 2); - } - // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise, - elseif (strpos($input, '/./') === 0) - { - $input = substr_replace($input, '/', 0, 3); - } - elseif ($input === '/.') - { - $input = '/'; - } - // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise, - elseif (strpos($input, '/../') === 0) - { - $input = substr_replace($input, '/', 0, 4); - $output = substr_replace($output, '', strrpos($output, '/')); - } - elseif ($input === '/..') - { - $input = '/'; - $output = substr_replace($output, '', strrpos($output, '/')); - } - // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise, - elseif ($input === '.' || $input === '..') - { - $input = ''; - } - // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer - elseif (($pos = strpos($input, '/', 1)) !== false) - { - $output .= substr($input, 0, $pos); - $input = substr_replace($input, '', 0, $pos); - } - else - { - $output .= $input; - $input = ''; - } - } - return $output . $input; - } + case 'cspc8turkish': + case 'pc8turkish': + return 'PC8-Turkish'; - /** - * Replace invalid character with percent encoding - * - * @param string $string Input string - * @param string $valid_chars Valid characters - * @param int $case Normalise case - * @return string - */ - function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE, $iprivate = false) - { - // Normalize as many pct-encoded sections as possible - $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string); + case 'csiso16portuguese': + case 'iso646pt': + case 'isoir16': + case 'pt': + return 'PT'; - // Replace invalid percent characters - $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string); + case 'csiso84portuguese2': + case 'iso646pt2': + case 'isoir84': + case 'pt2': + return 'PT2'; - // Add unreserved and % to $valid_chars (the latter is safe because all - // pct-encoded sections are now valid). - $valid_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; + case 'cp154': + case 'csptcp154': + case 'cyrillicasian': + case 'pt154': + case 'ptcp154': + return 'PTCP154'; - // Now replace any bytes that aren't allowed with their pct-encoded versions - $position = 0; - $strlen = strlen($string); - while (($position += strspn($string, $valid_chars, $position)) < $strlen) - { - $value = ord($string[$position]); + case 'scsu': + return 'SCSU'; - // Start position - $start = $position; + case 'csiso10swedish': + case 'fi': + case 'iso646fi': + case 'iso646se': + case 'isoir10': + case 'se': + case 'sen850200b': + return 'SEN_850200_B'; - // By default we are valid - $valid = true; + case 'csiso11swedishfornames': + case 'iso646se2': + case 'isoir11': + case 'se2': + case 'sen850200c': + return 'SEN_850200_C'; - // No one byte sequences are valid due to the while. - // Two byte sequence: - if (($value & 0xE0) === 0xC0) - { - $character = ($value & 0x1F) << 6; - $length = 2; - $remaining = 1; - } - // Three byte sequence: - elseif (($value & 0xF0) === 0xE0) - { - $character = ($value & 0x0F) << 12; - $length = 3; - $remaining = 2; - } - // Four byte sequence: - elseif (($value & 0xF8) === 0xF0) - { - $character = ($value & 0x07) << 18; - $length = 4; - $remaining = 3; - } - // Invalid byte: - else - { - $valid = false; - $length = 1; - $remaining = 0; - } + case 'csiso102t617bit': + case 'isoir102': + case 't617bit': + return 'T.61-7bit'; - if ($remaining) - { - if ($position + $length <= $strlen) - { - for ($position++; $remaining; $position++) - { - $value = ord($string[$position]); + case 'csiso103t618bit': + case 'isoir103': + case 't61': + case 't618bit': + return 'T.61-8bit'; - // Check that the byte is valid, then add it to the character: - if (($value & 0xC0) === 0x80) - { - $character |= ($value & 0x3F) << (--$remaining * 6); - } - // If it is invalid, count the sequence as invalid and reprocess the current byte: - else - { - $valid = false; - $position--; - break; - } - } - } - else - { - $position = $strlen - 1; - $valid = false; - } - } + case 'csiso128t101g2': + case 'isoir128': + case 't101g2': + return 'T.101-G2'; - // Percent encode anything invalid or not in ucschar - if ( - // Invalid sequences - !$valid - // Non-shortest form sequences are invalid - || $length > 1 && $character <= 0x7F - || $length > 2 && $character <= 0x7FF - || $length > 3 && $character <= 0xFFFF - // Outside of range of ucschar codepoints - // Noncharacters - || ($character & 0xFFFE) === 0xFFFE - || $character >= 0xFDD0 && $character <= 0xFDEF - || ( - // Everything else not in ucschar - $character > 0xD7FF && $character < 0xF900 - || $character < 0xA0 - || $character > 0xEFFFD - ) - && ( - // Everything not in iprivate, if it applies - !$iprivate - || $character < 0xE000 - || $character > 0x10FFFD - ) - ) - { - // If we were a character, pretend we weren't, but rather an error. - if ($valid) - $position--; + case 'cstscii': + case 'tscii': + return 'TSCII'; - for ($j = $start; $j <= $position; $j++) - { - $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1); - $j += 2; - $position += 2; - $strlen += 2; - } - } - } + case 'csunicode11': + case 'unicode11': + return 'UNICODE-1-1'; - // Normalise case - if ($case & SIMPLEPIE_LOWERCASE) - { - $string = strtolower($string); - } - elseif ($case & SIMPLEPIE_UPPERCASE) - { - $string = strtoupper($string); - } + case 'csunicode11utf7': + case 'unicode11utf7': + return 'UNICODE-1-1-UTF-7'; - return $string; - } + case 'csunknown8bit': + case 'unknown8bit': + return 'UNKNOWN-8BIT'; - /** - * Callback function for preg_replace_callback. - * - * Removes sequences of percent encoded bytes that represent UTF-8 - * encoded characters in iunreserved - * - * @access private - * @param array $match PCRE match - * @return string Replacement - */ - function remove_iunreserved_percent_encoded($match) - { - // As we just have valid percent encoded sequences we can just explode - // and ignore the first member of the returned array (an empty string). - $bytes = explode('%', $match[0]); + case 'ansix341968': + case 'ansix341986': + case 'ascii': + case 'cp367': + case 'csascii': + case 'ibm367': + case 'iso646irv1991': + case 'iso646us': + case 'isoir6': + case 'us': + case 'usascii': + return 'US-ASCII'; - // Initialize the new string (this is what will be returned) and that - // there are no bytes remaining in the current sequence (unsurprising - // at the first byte!). - $string = ''; - $remaining = 0; + case 'csusdk': + case 'usdk': + return 'us-dk'; - // Loop over each and every byte, and set $value to its value - for ($i = 1, $len = count($bytes); $i < $len; $i++) - { - $value = hexdec($bytes[$i]); + case 'utf7': + return 'UTF-7'; - // If we're the first byte of sequence: - if (!$remaining) - { - // Start position - $start = $i; + case 'utf8': + return 'UTF-8'; - // By default we are valid - $valid = true; + case 'utf16': + return 'UTF-16'; - // One byte sequence: - if ($value <= 0x7F) - { - $character = $value; - $length = 1; - } - // Two byte sequence: - elseif (($value & 0xE0) === 0xC0) - { - $character = ($value & 0x1F) << 6; - $length = 2; - $remaining = 1; - } - // Three byte sequence: - elseif (($value & 0xF0) === 0xE0) - { - $character = ($value & 0x0F) << 12; - $length = 3; - $remaining = 2; - } - // Four byte sequence: - elseif (($value & 0xF8) === 0xF0) - { - $character = ($value & 0x07) << 18; - $length = 4; - $remaining = 3; - } - // Invalid byte: - else - { - $valid = false; - $remaining = 0; - } - } - // Continuation byte: - else - { - // Check that the byte is valid, then add it to the character: - if (($value & 0xC0) === 0x80) - { - $remaining--; - $character |= ($value & 0x3F) << ($remaining * 6); - } - // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence: - else - { - $valid = false; - $remaining = 0; - $i--; - } - } + case 'utf16be': + return 'UTF-16BE'; - // If we've reached the end of the current byte sequence, append it to Unicode::$data - if (!$remaining) - { - // Percent encode anything invalid or not in iunreserved - if ( - // Invalid sequences - !$valid - // Non-shortest form sequences are invalid - || $length > 1 && $character <= 0x7F - || $length > 2 && $character <= 0x7FF - || $length > 3 && $character <= 0xFFFF - // Outside of range of iunreserved codepoints - || $character < 0x2D - || $character > 0xEFFFD - // Noncharacters - || ($character & 0xFFFE) === 0xFFFE - || $character >= 0xFDD0 && $character <= 0xFDEF - // Everything else not in iunreserved (this is all BMP) - || $character === 0x2F - || $character > 0x39 && $character < 0x41 - || $character > 0x5A && $character < 0x61 - || $character > 0x7A && $character < 0x7E - || $character > 0x7E && $character < 0xA0 - || $character > 0xD7FF && $character < 0xF900 - ) - { - for ($j = $start; $j <= $i; $j++) - { - $string .= '%' . strtoupper($bytes[$j]); - } - } - else - { - for ($j = $start; $j <= $i; $j++) - { - $string .= chr(hexdec($bytes[$j])); - } - } - } - } + case 'utf16le': + return 'UTF-16LE'; - // If we have any bytes left over they are invalid (i.e., we are - // mid-way through a multi-byte sequence) - if ($remaining) - { - for ($j = $start; $j < $len; $j++) - { - $string .= '%' . strtoupper($bytes[$j]); - } - } + case 'utf32': + return 'UTF-32'; - return $string; - } + case 'utf32be': + return 'UTF-32BE'; - /** - * Check if the object represents a valid IRI - * - * @access public - * @return bool - */ - function is_valid() - { - return array_sum($this->valid) === count($this->valid); - } + case 'utf32le': + return 'UTF-32LE'; - /** - * Set the scheme. Returns true on success, false on failure (if there are - * any invalid characters). - * - * @access public - * @param string $scheme - * @return bool - */ - function set_scheme($scheme) - { - if ($scheme === null || $scheme === '') - { - $this->scheme = null; - } - else - { - $len = strlen($scheme); - switch (true) - { - case $len > 1: - if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1)) - { - $this->scheme = null; - $this->valid[__FUNCTION__] = false; - return false; - } + case 'csventurainternational': + case 'venturainternational': + return 'Ventura-International'; - case $len > 0: - if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1)) - { - $this->scheme = null; - $this->valid[__FUNCTION__] = false; - return false; - } - } - $this->scheme = strtolower($scheme); + case 'csventuramath': + case 'venturamath': + return 'Ventura-Math'; + + case 'csventuraus': + case 'venturaus': + return 'Ventura-US'; + + case 'csiso70videotexsupp1': + case 'isoir70': + case 'videotexsuppl': + return 'videotex-suppl'; + + case 'csviqr': + case 'viqr': + return 'VIQR'; + + case 'csviscii': + case 'viscii': + return 'VISCII'; + + case 'csshiftjis': + case 'cswindows31j': + case 'mskanji': + case 'shiftjis': + case 'windows31j': + return 'Windows-31J'; + + case 'iso885911': + case 'tis620': + return 'windows-874'; + + case 'cseuckr': + case 'csksc56011987': + case 'euckr': + case 'isoir149': + case 'korean': + case 'ksc5601': + case 'ksc56011987': + case 'ksc56011989': + case 'windows949': + return 'windows-949'; + + case 'windows1250': + return 'windows-1250'; + + case 'windows1251': + return 'windows-1251'; + + case 'cp819': + case 'csisolatin1': + case 'ibm819': + case 'iso88591': + case 'iso885911987': + case 'isoir100': + case 'l1': + case 'latin1': + case 'windows1252': + return 'windows-1252'; + + case 'windows1253': + return 'windows-1253'; + + case 'csisolatin5': + case 'iso88599': + case 'iso885991989': + case 'isoir148': + case 'l5': + case 'latin5': + case 'windows1254': + return 'windows-1254'; + + case 'windows1255': + return 'windows-1255'; + + case 'windows1256': + return 'windows-1256'; + + case 'windows1257': + return 'windows-1257'; + + case 'windows1258': + return 'windows-1258'; + + default: + return $charset; } - $this->valid[__FUNCTION__] = true; - return true; } - /** - * Set the authority. Returns true on success, false on failure (if there are - * any invalid characters). - * - * @access public - * @param string $authority - * @return bool - */ - function set_authority($authority) + public static function get_curl_version() { - if (($userinfo_end = strrpos($authority, '@')) !== false) - { - $userinfo = substr($authority, 0, $userinfo_end); - $authority = substr($authority, $userinfo_end + 1); - } - else - { - $userinfo = null; - } - - if (($port_start = strpos($authority, ':')) !== false) + if (is_array($curl = curl_version())) { - $port = substr($authority, $port_start + 1); - $authority = substr($authority, 0, $port_start); + $curl = $curl['version']; } - else + elseif (substr($curl, 0, 5) === 'curl/') { - $port = null; + $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5)); } - - return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port); - } - - /** - * Set the userinfo. - * - * @access public - * @param string $userinfo - * @return bool - */ - function set_userinfo($userinfo) - { - if ($userinfo === null || $userinfo === '') + elseif (substr($curl, 0, 8) === 'libcurl/') { - $this->userinfo = null; + $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8)); } else { - $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:'); + $curl = 0; } - $this->valid[__FUNCTION__] = true; - return true; + return $curl; } /** - * Set the host. Returns true on success, false on failure (if there are - * any invalid characters). + * Strip HTML comments * - * @access public - * @param string $host - * @return bool + * @param string $data Data to strip comments from + * @return string Comment stripped string */ - function set_host($host) + public static function strip_comments($data) { - if ($host === null || $host === '') - { - $this->host = null; - $this->valid[__FUNCTION__] = true; - return true; - } - elseif ($host[0] === '[' && substr($host, -1) === ']') + $output = ''; + while (($start = strpos($data, '<!--')) !== false) { - if (Net_IPv6::checkIPv6(substr($host, 1, -1))) + $output .= substr($data, 0, $start); + if (($end = strpos($data, '-->', $start)) !== false) { - $this->host = $host; - $this->valid[__FUNCTION__] = true; - return true; + $data = substr_replace($data, '', 0, $end + 3); } else { - $this->host = null; - $this->valid[__FUNCTION__] = false; - return false; + $data = ''; } } - else - { - $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE); - $this->valid[__FUNCTION__] = true; - return true; - } + return $output . $data; + } + + public static function parse_date($dt) + { + $parser = SimplePie_Parse_Date::get(); + return $parser->parse($dt); } /** - * Set the port. Returns true on success, false on failure (if there are - * any invalid characters). + * Decode HTML entities * - * @access public - * @param string $port - * @return bool - */ - function set_port($port) + * @deprecated Use DOMDocument instead + * @param string $data Input data + * @return string Output data + */ + public static function entities_decode($data) + { + $decoder = new SimplePie_Decode_HTML_Entities($data); + return $decoder->parse(); + } + + /** + * Remove RFC822 comments + * + * @param string $data Data to strip comments from + * @return string Comment stripped string + */ + public static function uncomment_rfc822($string) { - if ($port === null || $port === '') + $string = (string) $string; + $position = 0; + $length = strlen($string); + $depth = 0; + + $output = ''; + + while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) { - $this->port = null; - $this->valid[__FUNCTION__] = true; - return true; + $output .= substr($string, $position, $pos - $position); + $position = $pos + 1; + if ($string[$pos - 1] !== '\\') + { + $depth++; + while ($depth && $position < $length) + { + $position += strcspn($string, '()', $position); + if ($string[$position - 1] === '\\') + { + $position++; + continue; + } + elseif (isset($string[$position])) + { + switch ($string[$position]) + { + case '(': + $depth++; + break; + + case ')': + $depth--; + break; + } + $position++; + } + else + { + break; + } + } + } + else + { + $output .= '('; + } } - elseif (strspn($port, '0123456789') === strlen($port)) + $output .= substr($string, $position); + + return $output; + } + + public static function parse_mime($mime) + { + if (($pos = strpos($mime, ';')) === false) { - $this->port = (int) $port; - $this->valid[__FUNCTION__] = true; - return true; + return trim($mime); } else { - $this->port = null; - $this->valid[__FUNCTION__] = false; + return trim(substr($mime, 0, $pos)); + } + } + + public static function atom_03_construct_type($attribs) + { + if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64')) + { + $mode = SIMPLEPIE_CONSTRUCT_BASE64; + } + else + { + $mode = SIMPLEPIE_CONSTRUCT_NONE; + } + if (isset($attribs['']['type'])) + { + switch (strtolower(trim($attribs['']['type']))) + { + case 'text': + case 'text/plain': + return SIMPLEPIE_CONSTRUCT_TEXT | $mode; + + case 'html': + case 'text/html': + return SIMPLEPIE_CONSTRUCT_HTML | $mode; + + case 'xhtml': + case 'application/xhtml+xml': + return SIMPLEPIE_CONSTRUCT_XHTML | $mode; + + default: + return SIMPLEPIE_CONSTRUCT_NONE | $mode; + } + } + else + { + return SIMPLEPIE_CONSTRUCT_TEXT | $mode; + } + } + + public static function atom_10_construct_type($attribs) + { + if (isset($attribs['']['type'])) + { + switch (strtolower(trim($attribs['']['type']))) + { + case 'text': + return SIMPLEPIE_CONSTRUCT_TEXT; + + case 'html': + return SIMPLEPIE_CONSTRUCT_HTML; + + case 'xhtml': + return SIMPLEPIE_CONSTRUCT_XHTML; + + default: + return SIMPLEPIE_CONSTRUCT_NONE; + } + } + return SIMPLEPIE_CONSTRUCT_TEXT; + } + + public static function atom_10_content_construct_type($attribs) + { + if (isset($attribs['']['type'])) + { + $type = strtolower(trim($attribs['']['type'])); + switch ($type) + { + case 'text': + return SIMPLEPIE_CONSTRUCT_TEXT; + + case 'html': + return SIMPLEPIE_CONSTRUCT_HTML; + + case 'xhtml': + return SIMPLEPIE_CONSTRUCT_XHTML; + } + if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/') + { + return SIMPLEPIE_CONSTRUCT_NONE; + } + else + { + return SIMPLEPIE_CONSTRUCT_BASE64; + } + } + else + { + return SIMPLEPIE_CONSTRUCT_TEXT; + } + } + + public static function is_isegment_nz_nc($string) + { + return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string); + } + + public static function space_seperated_tokens($string) + { + $space_characters = "\x20\x09\x0A\x0B\x0C\x0D"; + $string_length = strlen($string); + + $position = strspn($string, $space_characters); + $tokens = array(); + + while ($position < $string_length) + { + $len = strcspn($string, $space_characters, $position); + $tokens[] = substr($string, $position, $len); + $position += $len; + $position += strspn($string, $space_characters, $position); + } + + return $tokens; + } + + /** + * Converts a unicode codepoint to a UTF-8 character + * + * @static + * @param int $codepoint Unicode codepoint + * @return string UTF-8 character + */ + public static function codepoint_to_utf8($codepoint) + { + $codepoint = (int) $codepoint; + if ($codepoint < 0) + { return false; } + else if ($codepoint <= 0x7f) + { + return chr($codepoint); + } + else if ($codepoint <= 0x7ff) + { + return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f)); + } + else if ($codepoint <= 0xffff) + { + return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f)); + } + else if ($codepoint <= 0x10ffff) + { + return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f)); + } + else + { + // U+FFFD REPLACEMENT CHARACTER + return "\xEF\xBF\xBD"; + } + } + + /** + * Similar to parse_str() + * + * Returns an associative array of name/value pairs, where the value is an + * array of values that have used the same name + * + * @static + * @param string $str The input string. + * @return array + */ + public static function parse_str($str) + { + $return = array(); + $str = explode('&', $str); + + foreach ($str as $section) + { + if (strpos($section, '=') !== false) + { + list($name, $value) = explode('=', $section, 2); + $return[urldecode($name)][] = urldecode($value); + } + else + { + $return[urldecode($section)][] = null; + } + } + + return $return; } /** - * Set the path. + * Detect XML encoding, as per XML 1.0 Appendix F.1 + * + * @todo Add support for EBCDIC + * @param string $data XML data + * @param SimplePie_Registry $registry Class registry + * @return array Possible encodings + */ + public static function xml_encoding($data, $registry) + { + // UTF-32 Big Endian BOM + if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") + { + $encoding[] = 'UTF-32BE'; + } + // UTF-32 Little Endian BOM + elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") + { + $encoding[] = 'UTF-32LE'; + } + // UTF-16 Big Endian BOM + elseif (substr($data, 0, 2) === "\xFE\xFF") + { + $encoding[] = 'UTF-16BE'; + } + // UTF-16 Little Endian BOM + elseif (substr($data, 0, 2) === "\xFF\xFE") + { + $encoding[] = 'UTF-16LE'; + } + // UTF-8 BOM + elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") + { + $encoding[] = 'UTF-8'; + } + // UTF-32 Big Endian Without BOM + elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C") + { + if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E")) + { + $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-32BE'; + } + // UTF-32 Little Endian Without BOM + elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00") + { + if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00")) + { + $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-32LE'; + } + // UTF-16 Big Endian Without BOM + elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C") + { + if ($pos = strpos($data, "\x00\x3F\x00\x3E")) + { + $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-16BE'; + } + // UTF-16 Little Endian Without BOM + elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00") + { + if ($pos = strpos($data, "\x3F\x00\x3E\x00")) + { + $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-16LE'; + } + // US-ASCII (or superset) + elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C") + { + if ($pos = strpos($data, "\x3F\x3E")) + { + $parser = $registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-8'; + } + // Fallback to UTF-8 + else + { + $encoding[] = 'UTF-8'; + } + return $encoding; + } + + public static function output_javascript() + { + if (function_exists('ob_gzhandler')) + { + ob_start('ob_gzhandler'); + } + header('Content-type: text/javascript; charset: UTF-8'); + header('Cache-Control: must-revalidate'); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days + ?> +function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) { + if (placeholder != '') { + document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>'); + } + else { + document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>'); + } +} + +function embed_flash(bgcolor, width, height, link, loop, type) { + document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>'); +} + +function embed_flv(width, height, link, placeholder, loop, player) { + document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>'); +} + +function embed_wmedia(width, height, link) { + document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>'); +} + <?php + } + + /** + * Get the SimplePie build timestamp + * + * Uses the git index if it exists, otherwise uses the modification time + * of the newest file. + */ + public static function get_build() + { + $root = dirname(dirname(__FILE__)); + if (file_exists($root . '/.git/index')) + { + return filemtime($root . '/.git/index'); + } + elseif (file_exists($root . '/SimplePie')) + { + $time = 0; + foreach (glob($root . '/SimplePie/*.php') as $file) + { + if (($mtime = filemtime($file)) > $time) + { + $time = $mtime; + } + } + return $time; + } + elseif (file_exists(dirname(__FILE__) . '/Core.php')) + { + return filemtime(dirname(__FILE__) . '/Core.php'); + } + else + { + return filemtime(__FILE__); + } + } + + /** + * Format debugging information + */ + public static function debug(&$sp) + { + $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n"; + $info .= 'PHP ' . PHP_VERSION . "\n"; + if ($sp->error() !== null) + { + $info .= 'Error occurred: ' . $sp->error() . "\n"; + } + else + { + $info .= "No error found.\n"; + } + $info .= "Extensions:\n"; + $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml'); + foreach ($extensions as $ext) + { + if (extension_loaded($ext)) + { + $info .= " $ext loaded\n"; + switch ($ext) + { + case 'pcre': + $info .= ' Version ' . PCRE_VERSION . "\n"; + break; + case 'curl': + $version = curl_version(); + $info .= ' Version ' . $version['version'] . "\n"; + break; + case 'mbstring': + $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n"; + break; + case 'iconv': + $info .= ' Version ' . ICONV_VERSION . "\n"; + break; + case 'xml': + $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n"; + break; + } + } + else + { + $info .= " $ext not loaded\n"; + } + } + return $info; + } + + public static function silence_errors($num, $str) + { + // No-op + } +} + +/** + * Class to validate and to work with IPv6 addresses. + * + * @package SimplePie + * @subpackage HTTP + * @copyright 2003-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/package/Net_IPv6 + * @author Alexander Merz <alexander.merz@web.de> + * @author elfrink at introweb dot nl + * @author Josh Peck <jmp at joshpeck dot org> + * @author Geoffrey Sneddon <geoffers@gmail.com> + */ +class SimplePie_Net_IPv6 +{ + /** + * Uncompresses an IPv6 address + * + * RFC 4291 allows you to compress concecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and expands the '::' to + * the required number of zero pieces. + * + * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 + * ::1 -> 0:0:0:0:0:0:0:1 + * + * @author Alexander Merz <alexander.merz@web.de> + * @author elfrink at introweb dot nl + * @author Josh Peck <jmp at joshpeck dot org> + * @copyright 2003-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php + * @param string $ip An IPv6 address + * @return string The uncompressed IPv6 address + */ + public static function uncompress($ip) + { + $c1 = -1; + $c2 = -1; + if (substr_count($ip, '::') === 1) + { + list($ip1, $ip2) = explode('::', $ip); + if ($ip1 === '') + { + $c1 = -1; + } + else + { + $c1 = substr_count($ip1, ':'); + } + if ($ip2 === '') + { + $c2 = -1; + } + else + { + $c2 = substr_count($ip2, ':'); + } + if (strpos($ip2, '.') !== false) + { + $c2++; + } + // :: + if ($c1 === -1 && $c2 === -1) + { + $ip = '0:0:0:0:0:0:0:0'; + } + // ::xxx + else if ($c1 === -1) + { + $fill = str_repeat('0:', 7 - $c2); + $ip = str_replace('::', $fill, $ip); + } + // xxx:: + else if ($c2 === -1) + { + $fill = str_repeat(':0', 7 - $c1); + $ip = str_replace('::', $fill, $ip); + } + // xxx::xxx + else + { + $fill = ':' . str_repeat('0:', 6 - $c2 - $c1); + $ip = str_replace('::', $fill, $ip); + } + } + return $ip; + } + + /** + * Compresses an IPv6 address + * + * RFC 4291 allows you to compress concecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and compresses consecutive + * zero pieces to '::'. + * + * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 + * 0:0:0:0:0:0:0:1 -> ::1 + * + * @see uncompress() + * @param string $ip An IPv6 address + * @return string The compressed IPv6 address + */ + public static function compress($ip) + { + // Prepare the IP to be compressed + $ip = self::uncompress($ip); + $ip_parts = self::split_v6_v4($ip); + + // Replace all leading zeros + $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]); + + // Find bunches of zeros + if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE)) + { + $max = 0; + $pos = null; + foreach ($matches[0] as $match) + { + if (strlen($match[0]) > $max) + { + $max = strlen($match[0]); + $pos = $match[1]; + } + } + + $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max); + } + + if ($ip_parts[1] !== '') + { + return implode(':', $ip_parts); + } + else + { + return $ip_parts[0]; + } + } + + /** + * Splits an IPv6 address into the IPv6 and IPv4 representation parts + * + * RFC 4291 allows you to represent the last two parts of an IPv6 address + * using the standard IPv4 representation + * + * Example: 0:0:0:0:0:0:13.1.68.3 + * 0:0:0:0:0:FFFF:129.144.52.38 + * + * @param string $ip An IPv6 address + * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part + */ + private static function split_v6_v4($ip) + { + if (strpos($ip, '.') !== false) + { + $pos = strrpos($ip, ':'); + $ipv6_part = substr($ip, 0, $pos); + $ipv4_part = substr($ip, $pos + 1); + return array($ipv6_part, $ipv4_part); + } + else + { + return array($ip, ''); + } + } + + /** + * Checks an IPv6 address + * + * Checks if the given IP is a valid IPv6 address + * + * @param string $ip An IPv6 address + * @return bool true if $ip is a valid IPv6 address + */ + public static function check_ipv6($ip) + { + $ip = self::uncompress($ip); + list($ipv6, $ipv4) = self::split_v6_v4($ip); + $ipv6 = explode(':', $ipv6); + $ipv4 = explode('.', $ipv4); + if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) + { + foreach ($ipv6 as $ipv6_part) + { + // The section can't be empty + if ($ipv6_part === '') + return false; + + // Nor can it be over four characters + if (strlen($ipv6_part) > 4) + return false; + + // Remove leading zeros (this is safe because of the above) + $ipv6_part = ltrim($ipv6_part, '0'); + if ($ipv6_part === '') + $ipv6_part = '0'; + + // Check the value is valid + $value = hexdec($ipv6_part); + if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) + return false; + } + if (count($ipv4) === 4) + { + foreach ($ipv4 as $ipv4_part) + { + $value = (int) $ipv4_part; + if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) + return false; + } + } + return true; + } + else + { + return false; + } + } + + /** + * Checks if the given IP is a valid IPv6 address + * + * @codeCoverageIgnore + * @deprecated Use {@see SimplePie_Net_IPv6::check_ipv6()} instead + * @see check_ipv6 + * @param string $ip An IPv6 address + * @return bool true if $ip is a valid IPv6 address + */ + public static function checkIPv6($ip) + { + return self::check_ipv6($ip); + } +} + +/** + * Date Parser + * + * @package SimplePie + * @subpackage Parsing + */ +class SimplePie_Parse_Date +{ + /** + * Input data + * + * @access protected + * @var string + */ + var $date; + + /** + * List of days, calendar day name => ordinal day number in the week + * + * @access protected + * @var array + */ + var $day = array( + // English + 'mon' => 1, + 'monday' => 1, + 'tue' => 2, + 'tuesday' => 2, + 'wed' => 3, + 'wednesday' => 3, + 'thu' => 4, + 'thursday' => 4, + 'fri' => 5, + 'friday' => 5, + 'sat' => 6, + 'saturday' => 6, + 'sun' => 7, + 'sunday' => 7, + // Dutch + 'maandag' => 1, + 'dinsdag' => 2, + 'woensdag' => 3, + 'donderdag' => 4, + 'vrijdag' => 5, + 'zaterdag' => 6, + 'zondag' => 7, + // French + 'lundi' => 1, + 'mardi' => 2, + 'mercredi' => 3, + 'jeudi' => 4, + 'vendredi' => 5, + 'samedi' => 6, + 'dimanche' => 7, + // German + 'montag' => 1, + 'dienstag' => 2, + 'mittwoch' => 3, + 'donnerstag' => 4, + 'freitag' => 5, + 'samstag' => 6, + 'sonnabend' => 6, + 'sonntag' => 7, + // Italian + 'lunedì' => 1, + 'martedì' => 2, + 'mercoledì' => 3, + 'giovedì' => 4, + 'venerdì' => 5, + 'sabato' => 6, + 'domenica' => 7, + // Spanish + 'lunes' => 1, + 'martes' => 2, + 'miércoles' => 3, + 'jueves' => 4, + 'viernes' => 5, + 'sábado' => 6, + 'domingo' => 7, + // Finnish + 'maanantai' => 1, + 'tiistai' => 2, + 'keskiviikko' => 3, + 'torstai' => 4, + 'perjantai' => 5, + 'lauantai' => 6, + 'sunnuntai' => 7, + // Hungarian + 'hétfő' => 1, + 'kedd' => 2, + 'szerda' => 3, + 'csütörtok' => 4, + 'péntek' => 5, + 'szombat' => 6, + 'vasárnap' => 7, + // Greek + 'Δευ' => 1, + 'Τρι' => 2, + 'Τετ' => 3, + 'Πεμ' => 4, + 'Παρ' => 5, + 'Σαβ' => 6, + 'Κυρ' => 7, + ); + + /** + * List of months, calendar month name => calendar month number + * + * @access protected + * @var array + */ + var $month = array( + // English + 'jan' => 1, + 'january' => 1, + 'feb' => 2, + 'february' => 2, + 'mar' => 3, + 'march' => 3, + 'apr' => 4, + 'april' => 4, + 'may' => 5, + // No long form of May + 'jun' => 6, + 'june' => 6, + 'jul' => 7, + 'july' => 7, + 'aug' => 8, + 'august' => 8, + 'sep' => 9, + 'september' => 8, + 'oct' => 10, + 'october' => 10, + 'nov' => 11, + 'november' => 11, + 'dec' => 12, + 'december' => 12, + // Dutch + 'januari' => 1, + 'februari' => 2, + 'maart' => 3, + 'april' => 4, + 'mei' => 5, + 'juni' => 6, + 'juli' => 7, + 'augustus' => 8, + 'september' => 9, + 'oktober' => 10, + 'november' => 11, + 'december' => 12, + // French + 'janvier' => 1, + 'février' => 2, + 'mars' => 3, + 'avril' => 4, + 'mai' => 5, + 'juin' => 6, + 'juillet' => 7, + 'août' => 8, + 'septembre' => 9, + 'octobre' => 10, + 'novembre' => 11, + 'décembre' => 12, + // German + 'januar' => 1, + 'februar' => 2, + 'märz' => 3, + 'april' => 4, + 'mai' => 5, + 'juni' => 6, + 'juli' => 7, + 'august' => 8, + 'september' => 9, + 'oktober' => 10, + 'november' => 11, + 'dezember' => 12, + // Italian + 'gennaio' => 1, + 'febbraio' => 2, + 'marzo' => 3, + 'aprile' => 4, + 'maggio' => 5, + 'giugno' => 6, + 'luglio' => 7, + 'agosto' => 8, + 'settembre' => 9, + 'ottobre' => 10, + 'novembre' => 11, + 'dicembre' => 12, + // Spanish + 'enero' => 1, + 'febrero' => 2, + 'marzo' => 3, + 'abril' => 4, + 'mayo' => 5, + 'junio' => 6, + 'julio' => 7, + 'agosto' => 8, + 'septiembre' => 9, + 'setiembre' => 9, + 'octubre' => 10, + 'noviembre' => 11, + 'diciembre' => 12, + // Finnish + 'tammikuu' => 1, + 'helmikuu' => 2, + 'maaliskuu' => 3, + 'huhtikuu' => 4, + 'toukokuu' => 5, + 'kesäkuu' => 6, + 'heinäkuu' => 7, + 'elokuu' => 8, + 'suuskuu' => 9, + 'lokakuu' => 10, + 'marras' => 11, + 'joulukuu' => 12, + // Hungarian + 'január' => 1, + 'február' => 2, + 'március' => 3, + 'április' => 4, + 'május' => 5, + 'június' => 6, + 'július' => 7, + 'augusztus' => 8, + 'szeptember' => 9, + 'október' => 10, + 'november' => 11, + 'december' => 12, + // Greek + 'Ιαν' => 1, + 'Φεβ' => 2, + 'Μάώ' => 3, + 'Μαώ' => 3, + 'Απρ' => 4, + 'Μάι' => 5, + 'Μαϊ' => 5, + 'Μαι' => 5, + 'Ιούν' => 6, + 'Ιον' => 6, + 'Ιούλ' => 7, + 'Ιολ' => 7, + 'Αύγ' => 8, + 'Αυγ' => 8, + 'Σεπ' => 9, + 'Οκτ' => 10, + 'Νοέ' => 11, + 'Δεκ' => 12, + ); + + /** + * List of timezones, abbreviation => offset from UTC + * + * @access protected + * @var array + */ + var $timezone = array( + 'ACDT' => 37800, + 'ACIT' => 28800, + 'ACST' => 34200, + 'ACT' => -18000, + 'ACWDT' => 35100, + 'ACWST' => 31500, + 'AEDT' => 39600, + 'AEST' => 36000, + 'AFT' => 16200, + 'AKDT' => -28800, + 'AKST' => -32400, + 'AMDT' => 18000, + 'AMT' => -14400, + 'ANAST' => 46800, + 'ANAT' => 43200, + 'ART' => -10800, + 'AZOST' => -3600, + 'AZST' => 18000, + 'AZT' => 14400, + 'BIOT' => 21600, + 'BIT' => -43200, + 'BOT' => -14400, + 'BRST' => -7200, + 'BRT' => -10800, + 'BST' => 3600, + 'BTT' => 21600, + 'CAST' => 18000, + 'CAT' => 7200, + 'CCT' => 23400, + 'CDT' => -18000, + 'CEDT' => 7200, + 'CET' => 3600, + 'CGST' => -7200, + 'CGT' => -10800, + 'CHADT' => 49500, + 'CHAST' => 45900, + 'CIST' => -28800, + 'CKT' => -36000, + 'CLDT' => -10800, + 'CLST' => -14400, + 'COT' => -18000, + 'CST' => -21600, + 'CVT' => -3600, + 'CXT' => 25200, + 'DAVT' => 25200, + 'DTAT' => 36000, + 'EADT' => -18000, + 'EAST' => -21600, + 'EAT' => 10800, + 'ECT' => -18000, + 'EDT' => -14400, + 'EEST' => 10800, + 'EET' => 7200, + 'EGT' => -3600, + 'EKST' => 21600, + 'EST' => -18000, + 'FJT' => 43200, + 'FKDT' => -10800, + 'FKST' => -14400, + 'FNT' => -7200, + 'GALT' => -21600, + 'GEDT' => 14400, + 'GEST' => 10800, + 'GFT' => -10800, + 'GILT' => 43200, + 'GIT' => -32400, + 'GST' => 14400, + 'GST' => -7200, + 'GYT' => -14400, + 'HAA' => -10800, + 'HAC' => -18000, + 'HADT' => -32400, + 'HAE' => -14400, + 'HAP' => -25200, + 'HAR' => -21600, + 'HAST' => -36000, + 'HAT' => -9000, + 'HAY' => -28800, + 'HKST' => 28800, + 'HMT' => 18000, + 'HNA' => -14400, + 'HNC' => -21600, + 'HNE' => -18000, + 'HNP' => -28800, + 'HNR' => -25200, + 'HNT' => -12600, + 'HNY' => -32400, + 'IRDT' => 16200, + 'IRKST' => 32400, + 'IRKT' => 28800, + 'IRST' => 12600, + 'JFDT' => -10800, + 'JFST' => -14400, + 'JST' => 32400, + 'KGST' => 21600, + 'KGT' => 18000, + 'KOST' => 39600, + 'KOVST' => 28800, + 'KOVT' => 25200, + 'KRAST' => 28800, + 'KRAT' => 25200, + 'KST' => 32400, + 'LHDT' => 39600, + 'LHST' => 37800, + 'LINT' => 50400, + 'LKT' => 21600, + 'MAGST' => 43200, + 'MAGT' => 39600, + 'MAWT' => 21600, + 'MDT' => -21600, + 'MESZ' => 7200, + 'MEZ' => 3600, + 'MHT' => 43200, + 'MIT' => -34200, + 'MNST' => 32400, + 'MSDT' => 14400, + 'MSST' => 10800, + 'MST' => -25200, + 'MUT' => 14400, + 'MVT' => 18000, + 'MYT' => 28800, + 'NCT' => 39600, + 'NDT' => -9000, + 'NFT' => 41400, + 'NMIT' => 36000, + 'NOVST' => 25200, + 'NOVT' => 21600, + 'NPT' => 20700, + 'NRT' => 43200, + 'NST' => -12600, + 'NUT' => -39600, + 'NZDT' => 46800, + 'NZST' => 43200, + 'OMSST' => 25200, + 'OMST' => 21600, + 'PDT' => -25200, + 'PET' => -18000, + 'PETST' => 46800, + 'PETT' => 43200, + 'PGT' => 36000, + 'PHOT' => 46800, + 'PHT' => 28800, + 'PKT' => 18000, + 'PMDT' => -7200, + 'PMST' => -10800, + 'PONT' => 39600, + 'PST' => -28800, + 'PWT' => 32400, + 'PYST' => -10800, + 'PYT' => -14400, + 'RET' => 14400, + 'ROTT' => -10800, + 'SAMST' => 18000, + 'SAMT' => 14400, + 'SAST' => 7200, + 'SBT' => 39600, + 'SCDT' => 46800, + 'SCST' => 43200, + 'SCT' => 14400, + 'SEST' => 3600, + 'SGT' => 28800, + 'SIT' => 28800, + 'SRT' => -10800, + 'SST' => -39600, + 'SYST' => 10800, + 'SYT' => 7200, + 'TFT' => 18000, + 'THAT' => -36000, + 'TJT' => 18000, + 'TKT' => -36000, + 'TMT' => 18000, + 'TOT' => 46800, + 'TPT' => 32400, + 'TRUT' => 36000, + 'TVT' => 43200, + 'TWT' => 28800, + 'UYST' => -7200, + 'UYT' => -10800, + 'UZT' => 18000, + 'VET' => -14400, + 'VLAST' => 39600, + 'VLAT' => 36000, + 'VOST' => 21600, + 'VUT' => 39600, + 'WAST' => 7200, + 'WAT' => 3600, + 'WDT' => 32400, + 'WEST' => 3600, + 'WFT' => 43200, + 'WIB' => 25200, + 'WIT' => 32400, + 'WITA' => 28800, + 'WKST' => 18000, + 'WST' => 28800, + 'YAKST' => 36000, + 'YAKT' => 32400, + 'YAPT' => 36000, + 'YEKST' => 21600, + 'YEKT' => 18000, + ); + + /** + * Cached PCRE for SimplePie_Parse_Date::$day * - * @access public - * @param string $path - * @return bool + * @access protected + * @var string */ - function set_path($path) - { - if ($path === null || $path === '') - { - $this->path = null; - $this->valid[__FUNCTION__] = true; - return true; - } - elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null) - { - $this->path = null; - $this->valid[__FUNCTION__] = false; - return false; - } - else - { - $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/'); - if ($this->scheme !== null) - { - $this->path = $this->remove_dot_segments($this->path); - } - $this->valid[__FUNCTION__] = true; - return true; - } - } + var $day_pcre; /** - * Set the query. + * Cached PCRE for SimplePie_Parse_Date::$month * - * @access public - * @param string $query - * @return bool + * @access protected + * @var string */ - function set_query($query) - { - if ($query === null || $query === '') - { - $this->query = null; - } - else - { - $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&='); - } - $this->valid[__FUNCTION__] = true; - return true; - } + var $month_pcre; /** - * Set the fragment. + * Array of user-added callback methods * - * @access public - * @param string $fragment - * @return bool + * @access private + * @var array */ - function set_fragment($fragment) - { - if ($fragment === null || $fragment === '') - { - $this->fragment = null; - } - else - { - $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?'); - } - $this->valid[__FUNCTION__] = true; - return true; - } + var $built_in = array(); /** - * Get the complete IRI + * Array of user-added callback methods * - * @access public - * @return string + * @access private + * @var array */ - function get_iri() - { - $iri = ''; - if ($this->scheme !== null) - { - $iri .= $this->scheme . ':'; - } - if (($authority = $this->get_authority()) !== null) - { - $iri .= '//' . $authority; - } - if ($this->path !== null) - { - $iri .= $this->path; - } - if ($this->query !== null) - { - $iri .= '?' . $this->query; - } - if ($this->fragment !== null) - { - $iri .= '#' . $this->fragment; - } - - if ($iri !== '') - { - return $iri; - } - else - { - return null; - } - } + var $user = array(); /** - * Get the scheme + * Create new SimplePie_Parse_Date object, and set self::day_pcre, + * self::month_pcre, and self::built_in * - * @access public - * @return string + * @access private */ - function get_scheme() + public function __construct() { - return $this->scheme; - } + $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')'; + $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')'; - /** - * Get the complete authority - * - * @access public - * @return string - */ - function get_authority() - { - $authority = ''; - if ($this->userinfo !== null) - { - $authority .= $this->userinfo . '@'; - } - if ($this->host !== null) - { - $authority .= $this->host; - } - if ($this->port !== null) + static $cache; + if (!isset($cache[get_class($this)])) { - $authority .= ':' . $this->port; - } + $all_methods = get_class_methods($this); - if ($authority !== '') - { - return $authority; + foreach ($all_methods as $method) + { + if (strtolower(substr($method, 0, 5)) === 'date_') + { + $cache[get_class($this)][] = $method; + } + } } - else + + foreach ($cache[get_class($this)] as $method) { - return null; + $this->built_in[] = $method; } } /** - * Get the user information - * - * @access public - * @return string - */ - function get_userinfo() - { - return $this->userinfo; - } - - /** - * Get the host - * - * @access public - * @return string - */ - function get_host() - { - return $this->host; - } - - /** - * Get the port - * - * @access public - * @return string - */ - function get_port() - { - return $this->port; - } - - /** - * Get the path - * - * @access public - * @return string - */ - function get_path() - { - return $this->path; - } - - /** - * Get the query - * - * @access public - * @return string - */ - function get_query() - { - return $this->query; - } - - /** - * Get the fragment - * - * @access public - * @return string - */ - function get_fragment() - { - return $this->fragment; - } -} - -/** - * Class to validate and to work with IPv6 addresses. - * - * @package SimplePie - * @copyright 2003-2005 The PHP Group - * @license http://www.opensource.org/licenses/bsd-license.php - * @link http://pear.php.net/package/Net_IPv6 - * @author Alexander Merz <alexander.merz@web.de> - * @author elfrink at introweb dot nl - * @author Josh Peck <jmp at joshpeck dot org> - * @author Geoffrey Sneddon <geoffers@gmail.com> - */ -class SimplePie_Net_IPv6 -{ - /** - * Removes a possible existing netmask specification of an IP address. + * Get the object * - * @param string $ip the (compressed) IP as Hex representation - * @return string the IP the without netmask - * @since 1.1.0 * @access public - * @static */ - function removeNetmaskSpec($ip) + public static function get() { - if (strpos($ip, '/') !== false) - { - list($addr, $nm) = explode('/', $ip); - } - else + static $object; + if (!$object) { - $addr = $ip; + $object = new SimplePie_Parse_Date; } - return $addr; + return $object; } /** - * Uncompresses an IPv6 address - * - * RFC 2373 allows you to compress zeros in an address to '::'. This - * function expects an valid IPv6 address and expands the '::' to - * the required zeros. - * - * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 - * ::1 -> 0:0:0:0:0:0:0:1 - * - * @access public - * @static - * @param string $ip a valid IPv6-address (hex format) - * @return string the uncompressed IPv6-address (hex format) - */ - function Uncompress($ip) - { - $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip); - $c1 = -1; - $c2 = -1; - if (strpos($ip, '::') !== false) - { - list($ip1, $ip2) = explode('::', $ip); - if ($ip1 === '') - { - $c1 = -1; - } - else - { - $pos = 0; - if (($pos = substr_count($ip1, ':')) > 0) - { - $c1 = $pos; - } - else - { - $c1 = 0; - } - } - if ($ip2 === '') - { - $c2 = -1; - } - else - { - $pos = 0; - if (($pos = substr_count($ip2, ':')) > 0) - { - $c2 = $pos; - } - else - { - $c2 = 0; - } - } - if (strstr($ip2, '.')) - { - $c2++; - } - // :: - if ($c1 === -1 && $c2 === -1) - { - $uip = '0:0:0:0:0:0:0:0'; - } - // ::xxx - else if ($c1 === -1) - { - $fill = str_repeat('0:', 7 - $c2); - $uip = str_replace('::', $fill, $uip); - } - // xxx:: - else if ($c2 === -1) + * Parse a date + * + * @final + * @access public + * @param string $date Date to parse + * @return int Timestamp corresponding to date string, or false on failure + */ + public function parse($date) + { + foreach ($this->user as $method) + { + if (($returned = call_user_func($method, $date)) !== false) { - $fill = str_repeat(':0', 7 - $c1); - $uip = str_replace('::', $fill, $uip); + return $returned; } - // xxx::xxx - else + } + + foreach ($this->built_in as $method) + { + if (($returned = call_user_func(array($this, $method), $date)) !== false) { - $fill = str_repeat(':0:', 6 - $c2 - $c1); - $uip = str_replace('::', $fill, $uip); - $uip = str_replace('::', ':', $uip); + return $returned; } } - return $uip; + + return false; } /** - * Splits an IPv6 address into the IPv6 and a possible IPv4 part - * - * RFC 2373 allows you to note the last two parts of an IPv6 address as - * an IPv4 compatible address - * - * Example: 0:0:0:0:0:0:13.1.68.3 - * 0:0:0:0:0:FFFF:129.144.52.38 + * Add a callback method to parse a date * + * @final * @access public - * @static - * @param string $ip a valid IPv6-address (hex format) - * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format) + * @param callback $callback */ - function SplitV64($ip) + public function add_callback($callback) { - $ip = SimplePie_Net_IPv6::Uncompress($ip); - if (strstr($ip, '.')) + if (is_callable($callback)) { - $pos = strrpos($ip, ':'); - $ip[$pos] = '_'; - $ipPart = explode('_', $ip); - return $ipPart; + $this->user[] = $callback; } else { - return array($ip, ''); + trigger_error('User-supplied function must be a valid callback', E_USER_WARNING); } } /** - * Checks an IPv6 address - * - * Checks if the given IP is IPv6-compatible + * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as + * well as allowing any of upper or lower case "T", horizontal tabs, or + * spaces to be used as the time seperator (including more than one)) * - * @access public - * @static - * @param string $ip a valid IPv6-address - * @return bool true if $ip is an IPv6 address + * @access protected + * @return int Timestamp */ - function checkIPv6($ip) + public function date_w3cdtf($date) { - $ipPart = SimplePie_Net_IPv6::SplitV64($ip); - $count = 0; - if (!empty($ipPart[0])) + static $pcre; + if (!$pcre) + { + $year = '([0-9]{4})'; + $month = $day = $hour = $minute = $second = '([0-9]{2})'; + $decimal = '([0-9]*)'; + $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))'; + $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/'; + } + if (preg_match($pcre, $date, $match)) { - $ipv6 = explode(':', $ipPart[0]); - for ($i = 0; $i < count($ipv6); $i++) + /* + Capturing subpatterns: + 1: Year + 2: Month + 3: Day + 4: Hour + 5: Minute + 6: Second + 7: Decimal fraction of a second + 8: Zulu + 9: Timezone ± + 10: Timezone hours + 11: Timezone minutes + */ + + // Fill in empty matches + for ($i = count($match); $i <= 3; $i++) { - $dec = hexdec($ipv6[$i]); - $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i])); - if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec))) - { - $count++; - } + $match[$i] = '1'; } - if ($count === 8) + + for ($i = count($match); $i <= 7; $i++) { - return true; + $match[$i] = '0'; } - elseif ($count === 6 && !empty($ipPart[1])) + + // Numeric timezone + if (isset($match[9]) && $match[9] !== '') { - $ipv4 = explode('.', $ipPart[1]); - $count = 0; - foreach ($ipv4 as $ipv4_part) - { - if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part)) - { - $count++; - } - } - if ($count === 4) + $timezone = $match[10] * 3600; + $timezone += $match[11] * 60; + if ($match[9] === '-') { - return true; + $timezone = 0 - $timezone; } } else { - return false; + $timezone = 0; } + // Convert the number of seconds to an integer, taking decimals into account + $second = round($match[6] + $match[7] / pow(10, strlen($match[7]))); + + return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone; } else { return false; } } -} -/** - * Date Parser - * - * @package SimplePie - */ -class SimplePie_Parse_Date -{ /** - * Input data + * Remove RFC822 comments * * @access protected - * @var string + * @param string $data Data to strip comments from + * @return string Comment stripped string */ - var $date; + public function remove_rfc2822_comments($string) + { + $string = (string) $string; + $position = 0; + $length = strlen($string); + $depth = 0; + + $output = ''; + + while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) + { + $output .= substr($string, $position, $pos - $position); + $position = $pos + 1; + if ($string[$pos - 1] !== '\\') + { + $depth++; + while ($depth && $position < $length) + { + $position += strcspn($string, '()', $position); + if ($string[$position - 1] === '\\') + { + $position++; + continue; + } + elseif (isset($string[$position])) + { + switch ($string[$position]) + { + case '(': + $depth++; + break; + + case ')': + $depth--; + break; + } + $position++; + } + else + { + break; + } + } + } + else + { + $output .= '('; + } + } + $output .= substr($string, $position); + + return $output; + } /** - * List of days, calendar day name => ordinal day number in the week + * Parse RFC2822's date format * * @access protected - * @var array + * @return int Timestamp */ - var $day = array( - // English - 'mon' => 1, - 'monday' => 1, - 'tue' => 2, - 'tuesday' => 2, - 'wed' => 3, - 'wednesday' => 3, - 'thu' => 4, - 'thursday' => 4, - 'fri' => 5, - 'friday' => 5, - 'sat' => 6, - 'saturday' => 6, - 'sun' => 7, - 'sunday' => 7, - // Dutch - 'maandag' => 1, - 'dinsdag' => 2, - 'woensdag' => 3, - 'donderdag' => 4, - 'vrijdag' => 5, - 'zaterdag' => 6, - 'zondag' => 7, - // French - 'lundi' => 1, - 'mardi' => 2, - 'mercredi' => 3, - 'jeudi' => 4, - 'vendredi' => 5, - 'samedi' => 6, - 'dimanche' => 7, - // German - 'montag' => 1, - 'dienstag' => 2, - 'mittwoch' => 3, - 'donnerstag' => 4, - 'freitag' => 5, - 'samstag' => 6, - 'sonnabend' => 6, - 'sonntag' => 7, - // Italian - 'lunedì' => 1, - 'martedì' => 2, - 'mercoledì' => 3, - 'giovedì' => 4, - 'venerdì' => 5, - 'sabato' => 6, - 'domenica' => 7, - // Spanish - 'lunes' => 1, - 'martes' => 2, - 'miércoles' => 3, - 'jueves' => 4, - 'viernes' => 5, - 'sábado' => 6, - 'domingo' => 7, - // Finnish - 'maanantai' => 1, - 'tiistai' => 2, - 'keskiviikko' => 3, - 'torstai' => 4, - 'perjantai' => 5, - 'lauantai' => 6, - 'sunnuntai' => 7, - // Hungarian - 'hétfő' => 1, - 'kedd' => 2, - 'szerda' => 3, - 'csütörtok' => 4, - 'péntek' => 5, - 'szombat' => 6, - 'vasárnap' => 7, - // Greek - 'Δευ' => 1, - 'Τρι' => 2, - 'Τετ' => 3, - 'Πεμ' => 4, - 'Παρ' => 5, - 'Σαβ' => 6, - 'Κυρ' => 7, - ); + public function date_rfc2822($date) + { + static $pcre; + if (!$pcre) + { + $wsp = '[\x09\x20]'; + $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)'; + $optional_fws = $fws . '?'; + $day_name = $this->day_pcre; + $month = $this->month_pcre; + $day = '([0-9]{1,2})'; + $hour = $minute = $second = '([0-9]{2})'; + $year = '([0-9]{2,4})'; + $num_zone = '([+\-])([0-9]{2})([0-9]{2})'; + $character_zone = '([A-Z]{1,5})'; + $zone = '(?:' . $num_zone . '|' . $character_zone . ')'; + $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i'; + } + if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Day + 3: Month + 4: Year + 5: Hour + 6: Minute + 7: Second + 8: Timezone ± + 9: Timezone hours + 10: Timezone minutes + 11: Alphabetic timezone + */ + + // Find the month number + $month = $this->month[strtolower($match[3])]; + + // Numeric timezone + if ($match[8] !== '') + { + $timezone = $match[9] * 3600; + $timezone += $match[10] * 60; + if ($match[8] === '-') + { + $timezone = 0 - $timezone; + } + } + // Character timezone + elseif (isset($this->timezone[strtoupper($match[11])])) + { + $timezone = $this->timezone[strtoupper($match[11])]; + } + // Assume everything else to be -0000 + else + { + $timezone = 0; + } + + // Deal with 2/3 digit years + if ($match[4] < 50) + { + $match[4] += 2000; + } + elseif ($match[4] < 1000) + { + $match[4] += 1900; + } + + // Second is optional, if it is empty set it to zero + if ($match[7] !== '') + { + $second = $match[7]; + } + else + { + $second = 0; + } + + return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone; + } + else + { + return false; + } + } /** - * List of months, calendar month name => calendar month number + * Parse RFC850's date format * * @access protected - * @var array + * @return int Timestamp */ - var $month = array( - // English - 'jan' => 1, - 'january' => 1, - 'feb' => 2, - 'february' => 2, - 'mar' => 3, - 'march' => 3, - 'apr' => 4, - 'april' => 4, - 'may' => 5, - // No long form of May - 'jun' => 6, - 'june' => 6, - 'jul' => 7, - 'july' => 7, - 'aug' => 8, - 'august' => 8, - 'sep' => 9, - 'september' => 8, - 'oct' => 10, - 'october' => 10, - 'nov' => 11, - 'november' => 11, - 'dec' => 12, - 'december' => 12, - // Dutch - 'januari' => 1, - 'februari' => 2, - 'maart' => 3, - 'april' => 4, - 'mei' => 5, - 'juni' => 6, - 'juli' => 7, - 'augustus' => 8, - 'september' => 9, - 'oktober' => 10, - 'november' => 11, - 'december' => 12, - // French - 'janvier' => 1, - 'février' => 2, - 'mars' => 3, - 'avril' => 4, - 'mai' => 5, - 'juin' => 6, - 'juillet' => 7, - 'août' => 8, - 'septembre' => 9, - 'octobre' => 10, - 'novembre' => 11, - 'décembre' => 12, - // German - 'januar' => 1, - 'februar' => 2, - 'märz' => 3, - 'april' => 4, - 'mai' => 5, - 'juni' => 6, - 'juli' => 7, - 'august' => 8, - 'september' => 9, - 'oktober' => 10, - 'november' => 11, - 'dezember' => 12, - // Italian - 'gennaio' => 1, - 'febbraio' => 2, - 'marzo' => 3, - 'aprile' => 4, - 'maggio' => 5, - 'giugno' => 6, - 'luglio' => 7, - 'agosto' => 8, - 'settembre' => 9, - 'ottobre' => 10, - 'novembre' => 11, - 'dicembre' => 12, - // Spanish - 'enero' => 1, - 'febrero' => 2, - 'marzo' => 3, - 'abril' => 4, - 'mayo' => 5, - 'junio' => 6, - 'julio' => 7, - 'agosto' => 8, - 'septiembre' => 9, - 'setiembre' => 9, - 'octubre' => 10, - 'noviembre' => 11, - 'diciembre' => 12, - // Finnish - 'tammikuu' => 1, - 'helmikuu' => 2, - 'maaliskuu' => 3, - 'huhtikuu' => 4, - 'toukokuu' => 5, - 'kesäkuu' => 6, - 'heinäkuu' => 7, - 'elokuu' => 8, - 'suuskuu' => 9, - 'lokakuu' => 10, - 'marras' => 11, - 'joulukuu' => 12, - // Hungarian - 'január' => 1, - 'február' => 2, - 'március' => 3, - 'április' => 4, - 'május' => 5, - 'június' => 6, - 'július' => 7, - 'augusztus' => 8, - 'szeptember' => 9, - 'október' => 10, - 'november' => 11, - 'december' => 12, - // Greek - 'Ιαν' => 1, - 'Φεβ' => 2, - 'Μάώ' => 3, - 'Μαώ' => 3, - 'Απρ' => 4, - 'Μάι' => 5, - 'Μαϊ' => 5, - 'Μαι' => 5, - 'Ιούν' => 6, - 'Ιον' => 6, - 'Ιούλ' => 7, - 'Ιολ' => 7, - 'Αύγ' => 8, - 'Αυγ' => 8, - 'Σεπ' => 9, - 'Οκτ' => 10, - 'Νοέ' => 11, - 'Δεκ' => 12, - ); + public function date_rfc850($date) + { + static $pcre; + if (!$pcre) + { + $space = '[\x09\x20]+'; + $day_name = $this->day_pcre; + $month = $this->month_pcre; + $day = '([0-9]{1,2})'; + $year = $hour = $minute = $second = '([0-9]{2})'; + $zone = '([A-Z]{1,5})'; + $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i'; + } + if (preg_match($pcre, $date, $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Day + 3: Month + 4: Year + 5: Hour + 6: Minute + 7: Second + 8: Timezone + */ + + // Month + $month = $this->month[strtolower($match[3])]; + + // Character timezone + if (isset($this->timezone[strtoupper($match[8])])) + { + $timezone = $this->timezone[strtoupper($match[8])]; + } + // Assume everything else to be -0000 + else + { + $timezone = 0; + } - /** - * List of timezones, abbreviation => offset from UTC - * - * @access protected - * @var array - */ - var $timezone = array( - 'ACDT' => 37800, - 'ACIT' => 28800, - 'ACST' => 34200, - 'ACT' => -18000, - 'ACWDT' => 35100, - 'ACWST' => 31500, - 'AEDT' => 39600, - 'AEST' => 36000, - 'AFT' => 16200, - 'AKDT' => -28800, - 'AKST' => -32400, - 'AMDT' => 18000, - 'AMT' => -14400, - 'ANAST' => 46800, - 'ANAT' => 43200, - 'ART' => -10800, - 'AZOST' => -3600, - 'AZST' => 18000, - 'AZT' => 14400, - 'BIOT' => 21600, - 'BIT' => -43200, - 'BOT' => -14400, - 'BRST' => -7200, - 'BRT' => -10800, - 'BST' => 3600, - 'BTT' => 21600, - 'CAST' => 18000, - 'CAT' => 7200, - 'CCT' => 23400, - 'CDT' => -18000, - 'CEDT' => 7200, - 'CET' => 3600, - 'CGST' => -7200, - 'CGT' => -10800, - 'CHADT' => 49500, - 'CHAST' => 45900, - 'CIST' => -28800, - 'CKT' => -36000, - 'CLDT' => -10800, - 'CLST' => -14400, - 'COT' => -18000, - 'CST' => -21600, - 'CVT' => -3600, - 'CXT' => 25200, - 'DAVT' => 25200, - 'DTAT' => 36000, - 'EADT' => -18000, - 'EAST' => -21600, - 'EAT' => 10800, - 'ECT' => -18000, - 'EDT' => -14400, - 'EEST' => 10800, - 'EET' => 7200, - 'EGT' => -3600, - 'EKST' => 21600, - 'EST' => -18000, - 'FJT' => 43200, - 'FKDT' => -10800, - 'FKST' => -14400, - 'FNT' => -7200, - 'GALT' => -21600, - 'GEDT' => 14400, - 'GEST' => 10800, - 'GFT' => -10800, - 'GILT' => 43200, - 'GIT' => -32400, - 'GST' => 14400, - 'GST' => -7200, - 'GYT' => -14400, - 'HAA' => -10800, - 'HAC' => -18000, - 'HADT' => -32400, - 'HAE' => -14400, - 'HAP' => -25200, - 'HAR' => -21600, - 'HAST' => -36000, - 'HAT' => -9000, - 'HAY' => -28800, - 'HKST' => 28800, - 'HMT' => 18000, - 'HNA' => -14400, - 'HNC' => -21600, - 'HNE' => -18000, - 'HNP' => -28800, - 'HNR' => -25200, - 'HNT' => -12600, - 'HNY' => -32400, - 'IRDT' => 16200, - 'IRKST' => 32400, - 'IRKT' => 28800, - 'IRST' => 12600, - 'JFDT' => -10800, - 'JFST' => -14400, - 'JST' => 32400, - 'KGST' => 21600, - 'KGT' => 18000, - 'KOST' => 39600, - 'KOVST' => 28800, - 'KOVT' => 25200, - 'KRAST' => 28800, - 'KRAT' => 25200, - 'KST' => 32400, - 'LHDT' => 39600, - 'LHST' => 37800, - 'LINT' => 50400, - 'LKT' => 21600, - 'MAGST' => 43200, - 'MAGT' => 39600, - 'MAWT' => 21600, - 'MDT' => -21600, - 'MESZ' => 7200, - 'MEZ' => 3600, - 'MHT' => 43200, - 'MIT' => -34200, - 'MNST' => 32400, - 'MSDT' => 14400, - 'MSST' => 10800, - 'MST' => -25200, - 'MUT' => 14400, - 'MVT' => 18000, - 'MYT' => 28800, - 'NCT' => 39600, - 'NDT' => -9000, - 'NFT' => 41400, - 'NMIT' => 36000, - 'NOVST' => 25200, - 'NOVT' => 21600, - 'NPT' => 20700, - 'NRT' => 43200, - 'NST' => -12600, - 'NUT' => -39600, - 'NZDT' => 46800, - 'NZST' => 43200, - 'OMSST' => 25200, - 'OMST' => 21600, - 'PDT' => -25200, - 'PET' => -18000, - 'PETST' => 46800, - 'PETT' => 43200, - 'PGT' => 36000, - 'PHOT' => 46800, - 'PHT' => 28800, - 'PKT' => 18000, - 'PMDT' => -7200, - 'PMST' => -10800, - 'PONT' => 39600, - 'PST' => -28800, - 'PWT' => 32400, - 'PYST' => -10800, - 'PYT' => -14400, - 'RET' => 14400, - 'ROTT' => -10800, - 'SAMST' => 18000, - 'SAMT' => 14400, - 'SAST' => 7200, - 'SBT' => 39600, - 'SCDT' => 46800, - 'SCST' => 43200, - 'SCT' => 14400, - 'SEST' => 3600, - 'SGT' => 28800, - 'SIT' => 28800, - 'SRT' => -10800, - 'SST' => -39600, - 'SYST' => 10800, - 'SYT' => 7200, - 'TFT' => 18000, - 'THAT' => -36000, - 'TJT' => 18000, - 'TKT' => -36000, - 'TMT' => 18000, - 'TOT' => 46800, - 'TPT' => 32400, - 'TRUT' => 36000, - 'TVT' => 43200, - 'TWT' => 28800, - 'UYST' => -7200, - 'UYT' => -10800, - 'UZT' => 18000, - 'VET' => -14400, - 'VLAST' => 39600, - 'VLAT' => 36000, - 'VOST' => 21600, - 'VUT' => 39600, - 'WAST' => 7200, - 'WAT' => 3600, - 'WDT' => 32400, - 'WEST' => 3600, - 'WFT' => 43200, - 'WIB' => 25200, - 'WIT' => 32400, - 'WITA' => 28800, - 'WKST' => 18000, - 'WST' => 28800, - 'YAKST' => 36000, - 'YAKT' => 32400, - 'YAPT' => 36000, - 'YEKST' => 21600, - 'YEKT' => 18000, - ); + // Deal with 2 digit year + if ($match[4] < 50) + { + $match[4] += 2000; + } + else + { + $match[4] += 1900; + } + + return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone; + } + else + { + return false; + } + } /** - * Cached PCRE for SimplePie_Parse_Date::$day + * Parse C99's asctime()'s date format * * @access protected - * @var string + * @return int Timestamp */ - var $day_pcre; + public function date_asctime($date) + { + static $pcre; + if (!$pcre) + { + $space = '[\x09\x20]+'; + $wday_name = $this->day_pcre; + $mon_name = $this->month_pcre; + $day = '([0-9]{1,2})'; + $hour = $sec = $min = '([0-9]{2})'; + $year = '([0-9]{4})'; + $terminator = '\x0A?\x00?'; + $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i'; + } + if (preg_match($pcre, $date, $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Month + 3: Day + 4: Hour + 5: Minute + 6: Second + 7: Year + */ + + $month = $this->month[strtolower($match[2])]; + return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]); + } + else + { + return false; + } + } /** - * Cached PCRE for SimplePie_Parse_Date::$month + * Parse dates using strtotime() * * @access protected - * @var string + * @return int Timestamp */ - var $month_pcre; + public function date_strtotime($date) + { + $strtotime = strtotime($date); + if ($strtotime === -1 || $strtotime === false) + { + return false; + } + else + { + return $strtotime; + } + } +} - /** - * Array of user-added callback methods - * - * @access private - * @var array - */ - var $built_in = array(); +/** + * Parses XML into something sane + * + * + * This class can be overloaded with {@see SimplePie::set_parser_class()} + * + * @package SimplePie + * @subpackage Parsing + */ +class SimplePie_Parser +{ + var $error_code; + var $error_string; + var $current_line; + var $current_column; + var $current_byte; + var $separator = ' '; + var $namespace = array(''); + var $element = array(''); + var $xml_base = array(''); + var $xml_base_explicit = array(false); + var $xml_lang = array(''); + var $data = array(); + var $datas = array(array()); + var $current_xhtml_construct = -1; + var $encoding; + protected $registry; - /** - * Array of user-added callback methods - * - * @access private - * @var array - */ - var $user = array(); + public function set_registry(SimplePie_Registry $registry) + { + $this->registry = $registry; + } - /** - * Create new SimplePie_Parse_Date object, and set self::day_pcre, - * self::month_pcre, and self::built_in - * - * @access private - */ - function SimplePie_Parse_Date() + public function parse(&$data, $encoding) { - $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')'; - $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')'; + // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character + if (strtoupper($encoding) === 'US-ASCII') + { + $this->encoding = 'UTF-8'; + } + else + { + $this->encoding = $encoding; + } - static $cache; - if (!isset($cache[get_class($this)])) + // Strip BOM: + // UTF-32 Big Endian BOM + if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") { - $all_methods = get_class_methods($this); + $data = substr($data, 4); + } + // UTF-32 Little Endian BOM + elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") + { + $data = substr($data, 4); + } + // UTF-16 Big Endian BOM + elseif (substr($data, 0, 2) === "\xFE\xFF") + { + $data = substr($data, 2); + } + // UTF-16 Little Endian BOM + elseif (substr($data, 0, 2) === "\xFF\xFE") + { + $data = substr($data, 2); + } + // UTF-8 BOM + elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") + { + $data = substr($data, 3); + } - foreach ($all_methods as $method) + if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false) + { + $declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5))); + if ($declaration->parse()) { - if (strtolower(substr($method, 0, 5)) === 'date_') - { - $cache[get_class($this)][] = $method; - } + $data = substr($data, $pos + 2); + $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data; + } + else + { + $this->error_string = 'SimplePie bug! Please report this!'; + return false; } } - foreach ($cache[get_class($this)] as $method) + $return = true; + + static $xml_is_sane = null; + if ($xml_is_sane === null) { - $this->built_in[] = $method; + $parser_check = xml_parser_create(); + xml_parse_into_struct($parser_check, '<foo>&</foo>', $values); + xml_parser_free($parser_check); + $xml_is_sane = isset($values[0]['value']); } - } - /** - * Get the object - * - * @access public - */ - function get() - { - static $object; - if (!$object) + // Create the parser + if ($xml_is_sane) { - $object = new SimplePie_Parse_Date; - } - return $object; - } + $xml = xml_parser_create_ns($this->encoding, $this->separator); + xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1); + xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0); + xml_set_object($xml, $this); + xml_set_character_data_handler($xml, 'cdata'); + xml_set_element_handler($xml, 'tag_open', 'tag_close'); - /** - * Parse a date - * - * @final - * @access public - * @param string $date Date to parse - * @return int Timestamp corresponding to date string, or false on failure - */ - function parse($date) - { - foreach ($this->user as $method) + // Parse! + if (!xml_parse($xml, $data, true)) + { + $this->error_code = xml_get_error_code($xml); + $this->error_string = xml_error_string($this->error_code); + $return = false; + } + $this->current_line = xml_get_current_line_number($xml); + $this->current_column = xml_get_current_column_number($xml); + $this->current_byte = xml_get_current_byte_index($xml); + xml_parser_free($xml); + return $return; + } + else { - if (($returned = call_user_func($method, $date)) !== false) + libxml_clear_errors(); + $xml = new XMLReader(); + $xml->xml($data); + while (@$xml->read()) { - return $returned; + switch ($xml->nodeType) + { + + case constant('XMLReader::END_ELEMENT'): + if ($xml->namespaceURI !== '') + { + $tagName = $xml->namespaceURI . $this->separator . $xml->localName; + } + else + { + $tagName = $xml->localName; + } + $this->tag_close(null, $tagName); + break; + case constant('XMLReader::ELEMENT'): + $empty = $xml->isEmptyElement; + if ($xml->namespaceURI !== '') + { + $tagName = $xml->namespaceURI . $this->separator . $xml->localName; + } + else + { + $tagName = $xml->localName; + } + $attributes = array(); + while ($xml->moveToNextAttribute()) + { + if ($xml->namespaceURI !== '') + { + $attrName = $xml->namespaceURI . $this->separator . $xml->localName; + } + else + { + $attrName = $xml->localName; + } + $attributes[$attrName] = $xml->value; + } + $this->tag_open(null, $tagName, $attributes); + if ($empty) + { + $this->tag_close(null, $tagName); + } + break; + case constant('XMLReader::TEXT'): + + case constant('XMLReader::CDATA'): + $this->cdata(null, $xml->value); + break; + } + } + if ($error = libxml_get_last_error()) + { + $this->error_code = $error->code; + $this->error_string = $error->message; + $this->current_line = $error->line; + $this->current_column = $error->column; + return false; + } + else + { + return true; } } + } + + public function get_error_code() + { + return $this->error_code; + } + + public function get_error_string() + { + return $this->error_string; + } + + public function get_current_line() + { + return $this->current_line; + } - foreach ($this->built_in as $method) - { - if (($returned = call_user_func(array(&$this, $method), $date)) !== false) - { - return $returned; - } - } + public function get_current_column() + { + return $this->current_column; + } - return false; + public function get_current_byte() + { + return $this->current_byte; } - /** - * Add a callback method to parse a date - * - * @final - * @access public - * @param callback $callback - */ - function add_callback($callback) + public function get_data() { - if (is_callable($callback)) - { - $this->user[] = $callback; - } - else - { - trigger_error('User-supplied function must be a valid callback', E_USER_WARNING); - } + return $this->data; } - /** - * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as - * well as allowing any of upper or lower case "T", horizontal tabs, or - * spaces to be used as the time seperator (including more than one)) - * - * @access protected - * @return int Timestamp - */ - function date_w3cdtf($date) + public function tag_open($parser, $tag, $attributes) { - static $pcre; - if (!$pcre) + list($this->namespace[], $this->element[]) = $this->split_ns($tag); + + $attribs = array(); + foreach ($attributes as $name => $value) { - $year = '([0-9]{4})'; - $month = $day = $hour = $minute = $second = '([0-9]{2})'; - $decimal = '([0-9]*)'; - $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))'; - $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/'; + list($attrib_namespace, $attribute) = $this->split_ns($name); + $attribs[$attrib_namespace][$attribute] = $value; } - if (preg_match($pcre, $date, $match)) - { - /* - Capturing subpatterns: - 1: Year - 2: Month - 3: Day - 4: Hour - 5: Minute - 6: Second - 7: Decimal fraction of a second - 8: Zulu - 9: Timezone ± - 10: Timezone hours - 11: Timezone minutes - */ - - // Fill in empty matches - for ($i = count($match); $i <= 3; $i++) - { - $match[$i] = '1'; - } - - for ($i = count($match); $i <= 7; $i++) - { - $match[$i] = '0'; - } - // Numeric timezone - if (isset($match[9]) && $match[9] !== '') - { - $timezone = $match[10] * 3600; - $timezone += $match[11] * 60; - if ($match[9] === '-') - { - $timezone = 0 - $timezone; - } - } - else + if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base'])) + { + $base = $this->registry->call('Misc', 'absolutize_url', array($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base))); + if ($base !== false) { - $timezone = 0; + $this->xml_base[] = $base; + $this->xml_base_explicit[] = true; } - - // Convert the number of seconds to an integer, taking decimals into account - $second = round($match[6] + $match[7] / pow(10, strlen($match[7]))); - - return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone; } else { - return false; + $this->xml_base[] = end($this->xml_base); + $this->xml_base_explicit[] = end($this->xml_base_explicit); } - } - - /** - * Remove RFC822 comments - * - * @access protected - * @param string $data Data to strip comments from - * @return string Comment stripped string - */ - function remove_rfc2822_comments($string) - { - $string = (string) $string; - $position = 0; - $length = strlen($string); - $depth = 0; - $output = ''; + if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang'])) + { + $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang']; + } + else + { + $this->xml_lang[] = end($this->xml_lang); + } - while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) + if ($this->current_xhtml_construct >= 0) { - $output .= substr($string, $position, $pos - $position); - $position = $pos + 1; - if ($string[$pos - 1] !== '\\') + $this->current_xhtml_construct++; + if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML) { - $depth++; - while ($depth && $position < $length) + $this->data['data'] .= '<' . end($this->element); + if (isset($attribs[''])) { - $position += strcspn($string, '()', $position); - if ($string[$position - 1] === '\\') - { - $position++; - continue; - } - elseif (isset($string[$position])) - { - switch ($string[$position]) - { - case '(': - $depth++; - break; - - case ')': - $depth--; - break; - } - $position++; - } - else + foreach ($attribs[''] as $name => $value) { - break; + $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"'; } } + $this->data['data'] .= '>'; } - else + } + else + { + $this->datas[] =& $this->data; + $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][]; + $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang)); + if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml') + || (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml') + || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_20 && in_array(end($this->element), array('title'))) + || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_090 && in_array(end($this->element), array('title'))) + || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_10 && in_array(end($this->element), array('title')))) { - $output .= '('; + $this->current_xhtml_construct = 0; } } - $output .= substr($string, $position); - - return $output; } - /** - * Parse RFC2822's date format - * - * @access protected - * @return int Timestamp - */ - function date_rfc2822($date) + public function cdata($parser, $cdata) { - static $pcre; - if (!$pcre) - { - $wsp = '[\x09\x20]'; - $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)'; - $optional_fws = $fws . '?'; - $day_name = $this->day_pcre; - $month = $this->month_pcre; - $day = '([0-9]{1,2})'; - $hour = $minute = $second = '([0-9]{2})'; - $year = '([0-9]{2,4})'; - $num_zone = '([+\-])([0-9]{2})([0-9]{2})'; - $character_zone = '([A-Z]{1,5})'; - $zone = '(?:' . $num_zone . '|' . $character_zone . ')'; - $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i'; - } - if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match)) - { - /* - Capturing subpatterns: - 1: Day name - 2: Day - 3: Month - 4: Year - 5: Hour - 6: Minute - 7: Second - 8: Timezone ± - 9: Timezone hours - 10: Timezone minutes - 11: Alphabetic timezone - */ - - // Find the month number - $month = $this->month[strtolower($match[3])]; - - // Numeric timezone - if ($match[8] !== '') - { - $timezone = $match[9] * 3600; - $timezone += $match[10] * 60; - if ($match[8] === '-') - { - $timezone = 0 - $timezone; - } - } - // Character timezone - elseif (isset($this->timezone[strtoupper($match[11])])) - { - $timezone = $this->timezone[strtoupper($match[11])]; - } - // Assume everything else to be -0000 - else - { - $timezone = 0; - } - - // Deal with 2/3 digit years - if ($match[4] < 50) - { - $match[4] += 2000; - } - elseif ($match[4] < 1000) - { - $match[4] += 1900; - } - - // Second is optional, if it is empty set it to zero - if ($match[7] !== '') - { - $second = $match[7]; - } - else - { - $second = 0; - } - - return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone; + if ($this->current_xhtml_construct >= 0) + { + $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding); } else { - return false; + $this->data['data'] .= $cdata; } } - /** - * Parse RFC850's date format - * - * @access protected - * @return int Timestamp - */ - function date_rfc850($date) + public function tag_close($parser, $tag) { - static $pcre; - if (!$pcre) + if ($this->current_xhtml_construct >= 0) { - $space = '[\x09\x20]+'; - $day_name = $this->day_pcre; - $month = $this->month_pcre; - $day = '([0-9]{1,2})'; - $year = $hour = $minute = $second = '([0-9]{2})'; - $zone = '([A-Z]{1,5})'; - $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i'; + $this->current_xhtml_construct--; + if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param'))) + { + $this->data['data'] .= '</' . end($this->element) . '>'; + } } - if (preg_match($pcre, $date, $match)) + if ($this->current_xhtml_construct === -1) { - /* - Capturing subpatterns: - 1: Day name - 2: Day - 3: Month - 4: Year - 5: Hour - 6: Minute - 7: Second - 8: Timezone - */ + $this->data =& $this->datas[count($this->datas) - 1]; + array_pop($this->datas); + } - // Month - $month = $this->month[strtolower($match[3])]; + array_pop($this->element); + array_pop($this->namespace); + array_pop($this->xml_base); + array_pop($this->xml_base_explicit); + array_pop($this->xml_lang); + } - // Character timezone - if (isset($this->timezone[strtoupper($match[8])])) - { - $timezone = $this->timezone[strtoupper($match[8])]; - } - // Assume everything else to be -0000 - else + public function split_ns($string) + { + static $cache = array(); + if (!isset($cache[$string])) + { + if ($pos = strpos($string, $this->separator)) { - $timezone = 0; - } + static $separator_length; + if (!$separator_length) + { + $separator_length = strlen($this->separator); + } + $namespace = substr($string, 0, $pos); + $local_name = substr($string, $pos + $separator_length); + if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES) + { + $namespace = SIMPLEPIE_NAMESPACE_ITUNES; + } - // Deal with 2 digit year - if ($match[4] < 50) - { - $match[4] += 2000; + // Normalize the Media RSS namespaces + if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG || + $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 || + $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 || + $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 || + $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5 ) + { + $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS; + } + $cache[$string] = array($namespace, $local_name); } else { - $match[4] += 1900; + $cache[$string] = array('', $string); } - - return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone; - } - else - { - return false; } + return $cache[$string]; } +} + +/** + * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively + * + * Used by {@see SimplePie_Enclosure::get_rating()} and {@see SimplePie_Enclosure::get_ratings()} + * + * This class can be overloaded with {@see SimplePie::set_rating_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Rating +{ + /** + * Rating scheme + * + * @var string + * @see get_scheme() + */ + var $scheme; /** - * Parse C99's asctime()'s date format + * Rating value * - * @access protected - * @return int Timestamp + * @var string + * @see get_value() */ - function date_asctime($date) + var $value; + + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($scheme = null, $value = null) { - static $pcre; - if (!$pcre) - { - $space = '[\x09\x20]+'; - $wday_name = $this->day_pcre; - $mon_name = $this->month_pcre; - $day = '([0-9]{1,2})'; - $hour = $sec = $min = '([0-9]{2})'; - $year = '([0-9]{4})'; - $terminator = '\x0A?\x00?'; - $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i'; - } - if (preg_match($pcre, $date, $match)) - { - /* - Capturing subpatterns: - 1: Day name - 2: Month - 3: Day - 4: Hour - 5: Minute - 6: Second - 7: Year - */ + $this->scheme = $scheme; + $this->value = $value; + } - $month = $this->month[strtolower($match[2])]; - return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]); + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Get the organizational scheme for the rating + * + * @return string|null + */ + public function get_scheme() + { + if ($this->scheme !== null) + { + return $this->scheme; } else { - return false; + return null; } } /** - * Parse dates using strtotime() + * Get the value of the rating * - * @access protected - * @return int Timestamp + * @return string|null */ - function date_strtotime($date) + public function get_value() { - $strtotime = strtotime($date); - if ($strtotime === -1 || $strtotime === false) + if ($this->value !== null) { - return false; + return $this->value; } else { - return $strtotime; + return null; } } } /** - * Content-type sniffing + * Handles creating objects and calling methods + * + * Access this via {@see SimplePie::get_registry()} * * @package SimplePie */ -class SimplePie_Content_Type_Sniffer +class SimplePie_Registry { /** - * File object + * Default class mapping * - * @var SimplePie_File - * @access private + * Overriding classes *must* subclass these. + * + * @var array */ - var $file; + protected $default = array( + 'Cache' => 'SimplePie_Cache', + 'Locator' => 'SimplePie_Locator', + 'Parser' => 'SimplePie_Parser', + 'File' => 'SimplePie_File', + 'Sanitize' => 'SimplePie_Sanitize', + 'Item' => 'SimplePie_Item', + 'Author' => 'SimplePie_Author', + 'Category' => 'SimplePie_Category', + 'Enclosure' => 'SimplePie_Enclosure', + 'Caption' => 'SimplePie_Caption', + 'Copyright' => 'SimplePie_Copyright', + 'Credit' => 'SimplePie_Credit', + 'Rating' => 'SimplePie_Rating', + 'Restriction' => 'SimplePie_Restriction', + 'Content_Type_Sniffer' => 'SimplePie_Content_Type_Sniffer', + 'Source' => 'SimplePie_Source', + 'Misc' => 'SimplePie_Misc', + 'XML_Declaration_Parser' => 'SimplePie_XML_Declaration_Parser', + 'Parse_Date' => 'SimplePie_Parse_Date', + ); /** - * Create an instance of the class with the input file + * Class mapping * - * @access public - * @param SimplePie_Content_Type_Sniffer $file Input file + * @see register() + * @var array */ - function SimplePie_Content_Type_Sniffer($file) - { - $this->file = $file; - } + protected $classes = array(); /** - * Get the Content-Type of the specified file + * Legacy classes * - * @access public - * @return string Actual Content-Type + * @see register() + * @var array */ - function get_type() - { - if (isset($this->file->headers['content-type'])) - { - if (!isset($this->file->headers['content-encoding']) - && ($this->file->headers['content-type'] === 'text/plain' - || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1' - || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1')) - { - return $this->text_or_binary(); - } - - if (($pos = strpos($this->file->headers['content-type'], ';')) !== false) - { - $official = substr($this->file->headers['content-type'], 0, $pos); - } - else - { - $official = $this->file->headers['content-type']; - } - $official = strtolower($official); - - if ($official === 'unknown/unknown' - || $official === 'application/unknown') - { - return $this->unknown(); - } - elseif (substr($official, -4) === '+xml' - || $official === 'text/xml' - || $official === 'application/xml') - { - return $official; - } - elseif (substr($official, 0, 6) === 'image/') - { - if ($return = $this->image()) - { - return $return; - } - else - { - return $official; - } - } - elseif ($official === 'text/html') - { - return $this->feed_or_html(); - } - else - { - return $official; - } - } - else - { - return $this->unknown(); - } - } + protected $legacy = array(); /** - * Sniff text or binary + * Constructor * - * @access private - * @return string Actual Content-Type + * No-op + */ + public function __construct() { } + + /** + * Register a class + * + * @param string $type See {@see $default} for names + * @param string $class Class name, must subclass the corresponding default + * @param bool $legacy Whether to enable legacy support for this class + * @return bool Successfulness */ - function text_or_binary() + public function register($type, $class, $legacy = false) { - if (substr($this->file->body, 0, 2) === "\xFE\xFF" - || substr($this->file->body, 0, 2) === "\xFF\xFE" - || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF" - || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF") - { - return 'text/plain'; - } - elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body)) + if (!is_subclass_of($class, $this->default[$type])) { - return 'application/octect-stream'; + return false; } - else + + $this->classes[$type] = $class; + + if ($legacy) { - return 'text/plain'; + $this->legacy[] = $class; } + + return true; } /** - * Sniff unknown + * Get the class registered for a type * - * @access private - * @return string Actual Content-Type + * Where possible, use {@see create()} or {@see call()} instead + * + * @param string $type + * @return string|null */ - function unknown() + public function get_class($type) { - $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20"); - if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html' - || strtolower(substr($this->file->body, $ws, 5)) === '<html' - || strtolower(substr($this->file->body, $ws, 7)) === '<script') - { - return 'text/html'; - } - elseif (substr($this->file->body, 0, 5) === '%PDF-') - { - return 'application/pdf'; - } - elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-') - { - return 'application/postscript'; - } - elseif (substr($this->file->body, 0, 6) === 'GIF87a' - || substr($this->file->body, 0, 6) === 'GIF89a') - { - return 'image/gif'; - } - elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") - { - return 'image/png'; - } - elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") - { - return 'image/jpeg'; - } - elseif (substr($this->file->body, 0, 2) === "\x42\x4D") + if (!empty($this->classes[$type])) { - return 'image/bmp'; + return $this->classes[$type]; } - else + if (!empty($this->default[$type])) { - return $this->text_or_binary(); + return $this->default[$type]; } + + return null; } /** - * Sniff images + * Create a new instance of a given type * - * @access private - * @return string Actual Content-Type + * @param string $type + * @param array $parameters Parameters to pass to the constructor + * @return object Instance of class */ - function image() + public function &create($type, $parameters = array()) { - if (substr($this->file->body, 0, 6) === 'GIF87a' - || substr($this->file->body, 0, 6) === 'GIF89a') - { - return 'image/gif'; - } - elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") + $class = $this->get_class($type); + + if (in_array($class, $this->legacy)) { - return 'image/png'; + switch ($type) + { + case 'locator': + // Legacy: file, timeout, useragent, file_class, max_checked_feeds, content_type_sniffer_class + // Specified: file, timeout, useragent, max_checked_feeds + $replacement = array($this->get_class('file'), $parameters[3], $this->get_class('content_type_sniffer')); + array_splice($parameters, 3, 1, $replacement); + break; + } } - elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") + + if (!method_exists($class, '__construct')) { - return 'image/jpeg'; + $instance = new $class; } - elseif (substr($this->file->body, 0, 2) === "\x42\x4D") + else { - return 'image/bmp'; + $reflector = new ReflectionClass($class); + $instance = $reflector->newInstanceArgs($parameters); } - else + + if (method_exists($instance, 'set_registry')) { - return false; + $instance->set_registry($this); } + return $instance; } /** - * Sniff HTML + * Call a static method for a type * - * @access private - * @return string Actual Content-Type + * @param string $type + * @param string $method + * @param array $parameters + * @return mixed */ - function feed_or_html() + public function &call($type, $method, $parameters = array()) { - $len = strlen($this->file->body); - $pos = strspn($this->file->body, "\x09\x0A\x0D\x20"); + $class = $this->get_class($type); - while ($pos < $len) + if (in_array($class, $this->legacy)) { - switch ($this->file->body[$pos]) + switch ($type) { - case "\x09": - case "\x0A": - case "\x0D": - case "\x20": - $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos); - continue 2; - - case '<': - $pos++; + case 'Cache': + // For backwards compatibility with old non-static + // Cache::create() methods + if ($method === 'get_handler') + { + $result = @call_user_func_array(array($class, 'create'), $parameters); + return $result; + } break; - - default: - return 'text/html'; - } - - if (substr($this->file->body, $pos, 3) === '!--') - { - $pos += 3; - if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false) - { - $pos += 3; - } - else - { - return 'text/html'; - } - } - elseif (substr($this->file->body, $pos, 1) === '!') - { - if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false) - { - $pos++; - } - else - { - return 'text/html'; - } - } - elseif (substr($this->file->body, $pos, 1) === '?') - { - if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false) - { - $pos += 2; - } - else - { - return 'text/html'; - } - } - elseif (substr($this->file->body, $pos, 3) === 'rss' - || substr($this->file->body, $pos, 7) === 'rdf:RDF') - { - return 'application/rss+xml'; - } - elseif (substr($this->file->body, $pos, 4) === 'feed') - { - return 'application/atom+xml'; - } - else - { - return 'text/html'; } } - return 'text/html'; + $result = call_user_func_array(array($class, $method), $parameters); + return $result; } } /** - * Parses the XML Declaration + * Handles `<media:restriction>` as defined in Media RSS + * + * Used by {@see SimplePie_Enclosure::get_restriction()} and {@see SimplePie_Enclosure::get_restrictions()} + * + * This class can be overloaded with {@see SimplePie::set_restriction_class()} * * @package SimplePie + * @subpackage API */ -class SimplePie_XML_Declaration_Parser +class SimplePie_Restriction { /** - * XML Version + * Relationship ('allow'/'deny') * - * @access public * @var string + * @see get_relationship() */ - var $version = '1.0'; + var $relationship; /** - * Encoding + * Type of restriction * - * @access public * @var string + * @see get_type() */ - var $encoding = 'UTF-8'; + var $type; /** - * Standalone + * Restricted values * - * @access public - * @var bool + * @var string + * @see get_value() */ - var $standalone = false; + var $value; /** - * Current state of the state machine + * Constructor, used to input the data * - * @access private - * @var string + * For documentation on all the parameters, see the corresponding + * properties and their accessors */ - var $state = 'before_version_name'; + public function __construct($relationship = null, $type = null, $value = null) + { + $this->relationship = $relationship; + $this->type = $type; + $this->value = $value; + } /** - * Input data + * String-ified version * - * @access private - * @var string + * @return string */ - var $data = ''; + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } /** - * Input data length (to avoid calling strlen() everytime this is needed) + * Get the relationship * - * @access private - * @var int + * @return string|null Either 'allow' or 'deny' */ - var $data_length = 0; + public function get_relationship() + { + if ($this->relationship !== null) + { + return $this->relationship; + } + else + { + return null; + } + } /** - * Current position of the pointer + * Get the type * - * @var int - * @access private + * @return string|null */ - var $position = 0; + public function get_type() + { + if ($this->type !== null) + { + return $this->type; + } + else + { + return null; + } + } + + /** + * Get the list of restricted things + * + * @return string|null + */ + public function get_value() + { + if ($this->value !== null) + { + return $this->value; + } + else + { + return null; + } + } +} + +/** + * Used for data cleanup and post-processing + * + * + * This class can be overloaded with {@see SimplePie::set_sanitize_class()} + * + * @package SimplePie + * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags + */ +class SimplePie_Sanitize +{ + // Private vars + var $base; + + // Options + var $remove_div = true; + var $image_handler = ''; + var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); + var $encode_instead_of_strip = false; + var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); + var $strip_comments = false; + var $output_encoding = 'UTF-8'; + var $enable_cache = true; + var $cache_location = './cache'; + var $cache_name_function = 'md5'; + var $timeout = 10; + var $useragent = ''; + var $force_fsockopen = false; + var $replace_url_attributes = null; - /** - * Create an instance of the class with the input data - * - * @access public - * @param string $data Input data - */ - function SimplePie_XML_Declaration_Parser($data) + public function __construct() { - $this->data = $data; - $this->data_length = strlen($this->data); + // Set defaults + $this->set_url_replacements(null); } - /** - * Parse the input data - * - * @access public - * @return bool true on success, false on failure - */ - function parse() + public function remove_div($enable = true) { - while ($this->state && $this->state !== 'emit' && $this->has_data()) - { - $state = $this->state; - $this->$state(); - } - $this->data = ''; - if ($this->state === 'emit') + $this->remove_div = (bool) $enable; + } + + public function set_image_handler($page = false) + { + if ($page) { - return true; + $this->image_handler = (string) $page; } else { - $this->version = ''; - $this->encoding = ''; - $this->standalone = ''; - return false; + $this->image_handler = false; } } - /** - * Check whether there is data beyond the pointer - * - * @access private - * @return bool true if there is further data, false if not - */ - function has_data() + public function set_registry(SimplePie_Registry $registry) { - return (bool) ($this->position < $this->data_length); + $this->registry = $registry; } - /** - * Advance past any whitespace - * - * @return int Number of whitespace characters passed - */ - function skip_whitespace() + public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache') { - $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position); - $this->position += $whitespace; - return $whitespace; + if (isset($enable_cache)) + { + $this->enable_cache = (bool) $enable_cache; + } + + if ($cache_location) + { + $this->cache_location = (string) $cache_location; + } + + if ($cache_name_function) + { + $this->cache_name_function = (string) $cache_name_function; + } } - /** - * Read value - */ - function get_value() + public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false) { - $quote = substr($this->data, $this->position, 1); - if ($quote === '"' || $quote === "'") + if ($timeout) { - $this->position++; - $len = strcspn($this->data, $quote, $this->position); - if ($this->has_data()) + $this->timeout = (string) $timeout; + } + + if ($useragent) + { + $this->useragent = (string) $useragent; + } + + if ($force_fsockopen) + { + $this->force_fsockopen = (string) $force_fsockopen; + } + } + + public function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style')) + { + if ($tags) + { + if (is_array($tags)) { - $value = substr($this->data, $this->position, $len); - $this->position += $len + 1; - return $value; + $this->strip_htmltags = $tags; + } + else + { + $this->strip_htmltags = explode(',', $tags); } } - return false; + else + { + $this->strip_htmltags = false; + } } - function before_version_name() + public function encode_instead_of_strip($encode = false) { - if ($this->skip_whitespace()) + $this->encode_instead_of_strip = (bool) $encode; + } + + public function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc')) + { + if ($attribs) { - $this->state = 'version_name'; + if (is_array($attribs)) + { + $this->strip_attributes = $attribs; + } + else + { + $this->strip_attributes = explode(',', $attribs); + } } else { - $this->state = false; + $this->strip_attributes = false; + } + } + + public function strip_comments($strip = false) + { + $this->strip_comments = (bool) $strip; + } + + public function set_output_encoding($encoding = 'UTF-8') + { + $this->output_encoding = (string) $encoding; + } + + /** + * Set element/attribute key/value pairs of HTML attributes + * containing URLs that need to be resolved relative to the feed + * + * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite, + * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite, + * |q|@cite + * + * @since 1.0 + * @param array|null $element_attribute Element/attribute key/value pairs, null for default + */ + public function set_url_replacements($element_attribute = null) + { + if ($element_attribute === null) + { + $element_attribute = array( + 'a' => 'href', + 'area' => 'href', + 'blockquote' => 'cite', + 'del' => 'cite', + 'form' => 'action', + 'img' => array( + 'longdesc', + 'src' + ), + 'input' => 'src', + 'ins' => 'cite', + 'q' => 'cite' + ); + } + $this->replace_url_attributes = (array) $element_attribute; + } + + public function sanitize($data, $type, $base = '') + { + $data = trim($data); + if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI) + { + if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML) + { + if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data)) + { + $type |= SIMPLEPIE_CONSTRUCT_HTML; + } + else + { + $type |= SIMPLEPIE_CONSTRUCT_TEXT; + } + } + + if ($type & SIMPLEPIE_CONSTRUCT_BASE64) + { + $data = base64_decode($data); + } + + if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML)) + { + + $document = new DOMDocument(); + $document->encoding = 'UTF-8'; + $data = $this->preprocess($data, $type); + + set_error_handler(array('SimplePie_Misc', 'silence_errors')); + $document->loadHTML($data); + restore_error_handler(); + + // Strip comments + if ($this->strip_comments) + { + $xpath = new DOMXPath($document); + $comments = $xpath->query('//comment()'); + + foreach ($comments as $comment) + { + $comment->parentNode->removeChild($comment); + } + } + + // Strip out HTML tags and attributes that might cause various security problems. + // Based on recommendations by Mark Pilgrim at: + // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely + if ($this->strip_htmltags) + { + foreach ($this->strip_htmltags as $tag) + { + $this->strip_tag($tag, $document, $type); + } + } + + if ($this->strip_attributes) + { + foreach ($this->strip_attributes as $attrib) + { + $this->strip_attr($attrib, $document); + } + } + + // Replace relative URLs + $this->base = $base; + foreach ($this->replace_url_attributes as $element => $attributes) + { + $this->replace_urls($document, $element, $attributes); + } + + // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags. + if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache) + { + $images = $document->getElementsByTagName('img'); + foreach ($images as $img) + { + if ($img->hasAttribute('src')) + { + $image_url = call_user_func($this->cache_name_function, $img->getAttribute('src')); + $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, $image_url, 'spi')); + + if ($cache->load()) + { + $img->setAttribute('src', $this->image_handler . $image_url); + } + else + { + $file = $this->registry->create('File', array($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen)); + $headers = $file->headers; + + if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) + { + if ($cache->save(array('headers' => $file->headers, 'body' => $file->body))) + { + $img->setAttribute('src', $this->image_handler . $image_url); + } + else + { + trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); + } + } + } + } + } + } + + // Remove the DOCTYPE + // Seems to cause segfaulting if we don't do this + if ($document->firstChild instanceof DOMDocumentType) + { + $document->removeChild($document->firstChild); + } + + // Move everything from the body to the root + $real_body = $document->getElementsByTagName('body')->item(0)->childNodes->item(0); + $document->replaceChild($real_body, $document->firstChild); + + // Finally, convert to a HTML string + $data = trim($document->saveHTML()); + + if ($this->remove_div) + { + $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data); + $data = preg_replace('/<\/div>$/', '', $data); + } + else + { + $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data); + } + } + + if ($type & SIMPLEPIE_CONSTRUCT_IRI) + { + $absolute = $this->registry->call('Misc', 'absolutize_url', array($data, $base)); + if ($absolute !== false) + { + $data = $absolute; + } + } + + if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI)) + { + $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8'); + } + + if ($this->output_encoding !== 'UTF-8') + { + $data = $this->registry->call('Misc', 'change_encoding', array($data, 'UTF-8', $this->output_encoding)); + } } + return $data; } - function version_name() + protected function preprocess($html, $type) { - if (substr($this->data, $this->position, 7) === 'version') + $ret = ''; + if ($type & ~SIMPLEPIE_CONSTRUCT_XHTML) { - $this->position += 7; - $this->skip_whitespace(); - $this->state = 'version_equals'; + // Atom XHTML constructs are wrapped with a div by default + // Note: No protection if $html contains a stray </div>! + $html = '<div>' . $html . '</div>'; + $ret .= '<!DOCTYPE html>'; + $content_type = 'text/html'; } else { - $this->state = false; + $ret .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; + $content_type = 'application/xhtml+xml'; } + + $ret .= '<html><head>'; + $ret .= '<meta http-equiv="Content-Type" content="' . $content_type . '; charset=utf-8" />'; + $ret .= '</head><body>' . $html . '</body></html>'; + return $ret; } - function version_equals() + public function replace_urls($document, $tag, $attributes) { - if (substr($this->data, $this->position, 1) === '=') + if (!is_array($attributes)) { - $this->position++; - $this->skip_whitespace(); - $this->state = 'version_value'; + $attributes = array($attributes); } - else + + if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags)) { - $this->state = false; + $elements = $document->getElementsByTagName($tag); + foreach ($elements as $element) + { + foreach ($attributes as $attribute) + { + if ($element->hasAttribute($attribute)) + { + $value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base)); + if ($value !== false) + { + $element->setAttribute($attribute, $value); + } + } + } + } } } - function version_value() + public function do_strip_htmltags($match) { - if ($this->version = $this->get_value()) + if ($this->encode_instead_of_strip) { - $this->skip_whitespace(); - if ($this->has_data()) + if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style'))) { - $this->state = 'encoding_name'; + $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8'); + $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8'); + return "<$match[1]$match[2]>$match[3]</$match[1]>"; } else { - $this->state = 'emit'; + return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8'); } } + elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style'))) + { + return $match[4]; + } else { - $this->state = false; + return ''; } } - function encoding_name() + protected function strip_tag($tag, $document, $type) { - if (substr($this->data, $this->position, 8) === 'encoding') + $xpath = new DOMXPath($document); + $elements = $xpath->query('body//' . $tag); + if ($this->encode_instead_of_strip) { - $this->position += 8; - $this->skip_whitespace(); - $this->state = 'encoding_equals'; + foreach ($elements as $element) + { + $fragment = $document->createDocumentFragment(); + + // For elements which aren't script or style, include the tag itself + if (!in_array($tag, array('script', 'style'))) + { + $text = '<' . $tag; + if ($element->hasAttributes()) + { + $attrs = array(); + foreach ($element->attributes as $name => $attr) + { + $value = $attr->value; + + // In XHTML, empty values should never exist, so we repeat the value + if (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_XHTML)) + { + $value = $name; + } + // For HTML, empty is fine + elseif (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_HTML)) + { + $attrs[] = $name; + continue; + } + + // Standard attribute text + $attrs[] = $name . '="' . $attr->value . '"'; + } + $text .= ' ' . implode(' ', $attrs); + } + $text .= '>'; + $fragment->appendChild(new DOMText($text)); + } + + $number = $element->childNodes->length; + for ($i = $number; $i > 0; $i--) + { + $child = $element->childNodes->item(0); + $fragment->appendChild($child); + } + + if (!in_array($tag, array('script', 'style'))) + { + $fragment->appendChild(new DOMText('</' . $tag . '>')); + } + + $element->parentNode->replaceChild($fragment, $element); + } + + return; + } + elseif (in_array($tag, array('script', 'style'))) + { + foreach ($elements as $element) + { + $element->parentNode->removeChild($element); + } + + return; } else { - $this->state = 'standalone_name'; + foreach ($elements as $element) + { + $fragment = $document->createDocumentFragment(); + $number = $element->childNodes->length; + for ($i = $number; $i > 0; $i--) + { + $child = $element->childNodes->item(0); + $fragment->appendChild($child); + } + + $element->parentNode->replaceChild($fragment, $element); + } } } - function encoding_equals() + protected function strip_attr($attrib, $document) { - if (substr($this->data, $this->position, 1) === '=') - { - $this->position++; - $this->skip_whitespace(); - $this->state = 'encoding_value'; - } - else + $xpath = new DOMXPath($document); + $elements = $xpath->query('//*[@' . $attrib . ']'); + + foreach ($elements as $element) { - $this->state = false; + $element->removeAttribute($attrib); } } +} + +/** + * Handles `<atom:source>` + * + * Used by {@see SimplePie_Item::get_source()} + * + * This class can be overloaded with {@see SimplePie::set_source_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Source +{ + var $item; + var $data = array(); + protected $registry; + + public function __construct($item, $data) + { + $this->item = $item; + $this->data = $data; + } - function encoding_value() + public function set_registry(SimplePie_Registry $registry) { - if ($this->encoding = $this->get_value()) + $this->registry = $registry; + } + + public function __toString() + { + return md5(serialize($this->data)); + } + + public function get_source_tags($namespace, $tag) + { + if (isset($this->data['child'][$namespace][$tag])) { - $this->skip_whitespace(); - if ($this->has_data()) - { - $this->state = 'standalone_name'; - } - else - { - $this->state = 'emit'; - } + return $this->data['child'][$namespace][$tag]; } else { - $this->state = false; + return null; } } - function standalone_name() + public function get_base($element = array()) { - if (substr($this->data, $this->position, 10) === 'standalone') + return $this->item->get_base($element); + } + + public function sanitize($data, $type, $base = '') + { + return $this->item->sanitize($data, $type, $base); + } + + public function get_item() + { + return $this->item; + } + + public function get_title() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) { - $this->position += 10; - $this->skip_whitespace(); - $this->state = 'standalone_equals'; + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } else { - $this->state = false; + return null; } } - function standalone_equals() + public function get_category($key = 0) { - if (substr($this->data, $this->position, 1) === '=') + $categories = $this->get_categories(); + if (isset($categories[$key])) { - $this->position++; - $this->skip_whitespace(); - $this->state = 'standalone_value'; + return $categories[$key]; } else { - $this->state = false; + return null; } } - function standalone_value() + public function get_categories() { - if ($standalone = $this->get_value()) + $categories = array(); + + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) { - switch ($standalone) + $term = null; + $scheme = null; + $label = null; + if (isset($category['attribs']['']['term'])) { - case 'yes': - $this->standalone = true; - break; - - case 'no': - $this->standalone = false; - break; - - default: - $this->state = false; - return; + $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); } - - $this->skip_whitespace(); - if ($this->has_data()) + if (isset($category['attribs']['']['scheme'])) { - $this->state = false; + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); } - else + if (isset($category['attribs']['']['label'])) { - $this->state = 'emit'; + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); } - else + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) { - $this->state = false; + // This is really the label, but keep this as the term also for BC. + // Label will also work on retrieving because that falls back to term. + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + if (isset($category['attribs']['']['domain'])) + { + $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = null; + } + $categories[] = $this->registry->create('Category', array($term, $scheme, null)); } - } -} - -class SimplePie_Locator -{ - var $useragent; - var $timeout; - var $file; - var $local = array(); - var $elsewhere = array(); - var $file_class = 'SimplePie_File'; - var $cached_entities = array(); - var $http_base; - var $base; - var $base_location = 0; - var $checked_feeds = 0; - var $max_checked_feeds = 10; - var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer'; - - function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer') - { - $this->file =& $file; - $this->file_class = $file_class; - $this->useragent = $useragent; - $this->timeout = $timeout; - $this->max_checked_feeds = $max_checked_feeds; - $this->content_type_sniffer_class = $content_type_sniffer_class; - } - - function find($type = SIMPLEPIE_LOCATOR_ALL, &$working) - { - if ($this->is_feed($this->file)) + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) { - return $this->file; + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); } - if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) + if (!empty($categories)) { - $sniffer = new $this->content_type_sniffer_class($this->file); - if ($sniffer->get_type() !== 'text/html') - { - return null; - } + return array_unique($categories); } - - if ($type & ~SIMPLEPIE_LOCATOR_NONE) + else { - $this->get_base(); + return null; } + } - if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery()) + public function get_author($key = 0) + { + $authors = $this->get_authors(); + if (isset($authors[$key])) { - return $working[0]; + return $authors[$key]; + } + else + { + return null; } + } - if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links()) + public function get_authors() + { + $authors = array(); + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) { - if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) + $name = null; + $uri = null; + $email = null; + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) { - return $working; + $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - - if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) { - return $working; + $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); } - - if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) { - return $working; + $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - - if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) + if ($name !== null || $email !== null || $uri !== null) { - return $working; + $authors[] = $this->registry->create('Author', array($name, $uri, $email)); } } - return null; - } - - function is_feed(&$file) - { - if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) + if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) { - $sniffer = new $this->content_type_sniffer_class($file); - $sniffed = $sniffer->get_type(); - if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml'))) + $name = null; + $url = null; + $email = null; + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) { - return true; + $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - else + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) { - return false; + $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $authors[] = $this->registry->create('Author', array($name, $url, $email)); } } - elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL) + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) { - return true; + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($authors)) + { + return array_unique($authors); } else { - return false; + return null; } } - function get_base() + public function get_contributor($key = 0) { - $this->http_base = $this->file->url; - $this->base = $this->http_base; - $elements = SimplePie_Misc::get_element('base', $this->file->body); - foreach ($elements as $element) + $contributors = $this->get_contributors(); + if (isset($contributors[$key])) { - if ($element['attribs']['href']['data'] !== '') - { - $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base); - $this->base_location = $element['offset']; - break; - } + return $contributors[$key]; + } + else + { + return null; } } - function autodiscovery() + public function get_contributors() { - $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body)); - $done = array(); - $feeds = array(); - foreach ($links as $link) + $contributors = array(); + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) { - if ($this->checked_feeds === $this->max_checked_feeds) + $name = null; + $uri = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) { - break; + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data'])) + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) { - $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data']))); - - if ($this->base_location < $link['offset']) - { - $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base); - } - else - { - $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base); - } - - if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href])) - { - $this->checked_feeds++; - $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent); - if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) - { - $feeds[$href] = $feed; - } - } - $done[] = $href; + $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $uri, $email)); + } + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) + { + $name = null; + $url = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $url, $email)); } } - if (!empty($feeds)) + if (!empty($contributors)) { - return array_values($feeds); + return array_unique($contributors); } - else { + else + { return null; } } - function get_links() + public function get_link($key = 0, $rel = 'alternate') { - $links = SimplePie_Misc::get_element('a', $this->file->body); - foreach ($links as $link) + $links = $this->get_links($rel); + if (isset($links[$key])) { - if (isset($link['attribs']['href']['data'])) - { - $href = trim($link['attribs']['href']['data']); - $parsed = SimplePie_Misc::parse_url($href); - if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme'])) - { - if ($this->base_location < $link['offset']) - { - $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base); - } - else - { - $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base); - } - - $current = SimplePie_Misc::parse_url($this->file->url); - - if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority']) - { - $this->local[] = $href; - } - else - { - $this->elsewhere[] = $href; - } - } - } + return $links[$key]; } - $this->local = array_unique($this->local); - $this->elsewhere = array_unique($this->elsewhere); - if (!empty($this->local) || !empty($this->elsewhere)) + else { - return true; + return null; } - return null; } - function extension(&$array) + /** + * Added for parity between the parent-level and the item/entry-level. + */ + public function get_permalink() + { + return $this->get_link(0); + } + + public function get_links($rel = 'alternate') { - foreach ($array as $key => $value) + if (!isset($this->data['links'])) { - if ($this->checked_feeds === $this->max_checked_feeds) - { - break; - } - if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml'))) + $this->data['links'] = array(); + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link')) { - $this->checked_feeds++; - $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent); - if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + foreach ($links as $link) { - return $feed; + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + } } - else + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link')) + { + foreach ($links as $link) { - unset($array[$key]); + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + + } } } - } - return null; - } - - function body(&$array) - { - foreach ($array as $key => $value) - { - if ($this->checked_feeds === $this->max_checked_feeds) + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) { - break; + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); } - if (preg_match('/(rss|rdf|atom|xml)/i', $value)) + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + + $keys = array_keys($this->data['links']); + foreach ($keys as $key) { - $this->checked_feeds++; - $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent); - if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key))) { - return $feed; + if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); + $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; + } + else + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; + } } - else + elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) { - unset($array[$key]); + $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; } + $this->data['links'][$key] = array_unique($this->data['links'][$key]); } } - return null; - } -} - -class SimplePie_Parser -{ - var $error_code; - var $error_string; - var $current_line; - var $current_column; - var $current_byte; - var $separator = ' '; - var $namespace = array(''); - var $element = array(''); - var $xml_base = array(''); - var $xml_base_explicit = array(false); - var $xml_lang = array(''); - var $data = array(); - var $datas = array(array()); - var $current_xhtml_construct = -1; - var $encoding; - function parse(&$data, $encoding) - { - // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character - if (strtoupper($encoding) === 'US-ASCII') + if (isset($this->data['links'][$rel])) { - $this->encoding = 'UTF-8'; + return $this->data['links'][$rel]; } else { - $this->encoding = $encoding; + return null; } + } - // Strip BOM: - // UTF-32 Big Endian BOM - if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") + public function get_description() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle')) { - $data = substr($data, 4); + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); } - // UTF-32 Little Endian BOM - elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline')) { - $data = substr($data, 4); + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); } - // UTF-16 Big Endian BOM - elseif (substr($data, 0, 2) === "\xFE\xFF") + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) { - $data = substr($data, 2); + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } - // UTF-16 Little Endian BOM - elseif (substr($data, 0, 2) === "\xFF\xFE") + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) { - $data = substr($data, 2); + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } - // UTF-8 BOM - elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) { - $data = substr($data, 3); + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } - - if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false) + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) { - $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5)); - if ($declaration->parse()) - { - $data = substr($data, $pos + 2); - $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data; - } - else - { - $this->error_string = 'SimplePie bug! Please report this!'; - return false; - } + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - - $return = true; - - static $xml_is_sane = null; - if ($xml_is_sane === null) + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) { - $parser_check = xml_parser_create(); - xml_parse_into_struct($parser_check, '<foo>&</foo>', $values); - xml_parser_free($parser_check); - $xml_is_sane = isset($values[0]['value']); + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - - // Create the parser - if ($xml_is_sane) + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) { - $xml = xml_parser_create_ns($this->encoding, $this->separator); - xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0); - xml_set_object($xml, $this); - xml_set_character_data_handler($xml, 'cdata'); - xml_set_element_handler($xml, 'tag_open', 'tag_close'); - - // Parse! - if (!xml_parse($xml, $data, true)) - { - $this->error_code = xml_get_error_code($xml); - $this->error_string = xml_error_string($this->error_code); - $return = false; - } - $this->current_line = xml_get_current_line_number($xml); - $this->current_column = xml_get_current_column_number($xml); - $this->current_byte = xml_get_current_byte_index($xml); - xml_parser_free($xml); - return $return; + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); } else { - libxml_clear_errors(); - $xml = new XMLReader(); - $xml->xml($data); - while (@$xml->read()) - { - switch ($xml->nodeType) - { - - case constant('XMLReader::END_ELEMENT'): - if ($xml->namespaceURI !== '') - { - $tagName = $xml->namespaceURI . $this->separator . $xml->localName; - } - else - { - $tagName = $xml->localName; - } - $this->tag_close(null, $tagName); - break; - case constant('XMLReader::ELEMENT'): - $empty = $xml->isEmptyElement; - if ($xml->namespaceURI !== '') - { - $tagName = $xml->namespaceURI . $this->separator . $xml->localName; - } - else - { - $tagName = $xml->localName; - } - $attributes = array(); - while ($xml->moveToNextAttribute()) - { - if ($xml->namespaceURI !== '') - { - $attrName = $xml->namespaceURI . $this->separator . $xml->localName; - } - else - { - $attrName = $xml->localName; - } - $attributes[$attrName] = $xml->value; - } - $this->tag_open(null, $tagName, $attributes); - if ($empty) - { - $this->tag_close(null, $tagName); - } - break; - case constant('XMLReader::TEXT'): - - case constant('XMLReader::CDATA'): - $this->cdata(null, $xml->value); - break; - } - } - if ($error = libxml_get_last_error()) - { - $this->error_code = $error->code; - $this->error_string = $error->message; - $this->current_line = $error->line; - $this->current_column = $error->column; - return false; - } - else - { - return true; - } + return null; } } - function get_error_code() - { - return $this->error_code; - } - - function get_error_string() - { - return $this->error_string; - } - - function get_current_line() - { - return $this->current_line; - } - - function get_current_column() - { - return $this->current_column; - } - - function get_current_byte() - { - return $this->current_byte; - } - - function get_data() + public function get_copyright() { - return $this->data; + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } } - function tag_open($parser, $tag, $attributes) + public function get_language() { - list($this->namespace[], $this->element[]) = $this->split_ns($tag); - - $attribs = array(); - foreach ($attributes as $name => $value) + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language')) { - list($attrib_namespace, $attribute) = $this->split_ns($name); - $attribs[$attrib_namespace][$attribute] = $value; + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - - if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base'])) + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language')) { - $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base)); - $this->xml_base_explicit[] = true; + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - else + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language')) { - $this->xml_base[] = end($this->xml_base); - $this->xml_base_explicit[] = end($this->xml_base_explicit); + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); } - - if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang'])) + elseif (isset($this->data['xml_lang'])) { - $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang']; + return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT); } else { - $this->xml_lang[] = end($this->xml_lang); + return null; } + } - if ($this->current_xhtml_construct >= 0) + public function get_latitude() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) { - $this->current_xhtml_construct++; - if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML) - { - $this->data['data'] .= '<' . end($this->element); - if (isset($attribs[''])) - { - foreach ($attribs[''] as $name => $value) - { - $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"'; - } - } - $this->data['data'] .= '>'; - } + return (float) $return[0]['data']; + } + elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[1]; } else { - $this->datas[] =& $this->data; - $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][]; - $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang)); - if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml') - || (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml')) - { - $this->current_xhtml_construct = 0; - } + return null; } } - function cdata($parser, $cdata) + public function get_longitude() { - if ($this->current_xhtml_construct >= 0) + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) { - $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding); + return (float) $return[0]['data']; + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[2]; } else { - $this->data['data'] .= $cdata; + return null; } } - function tag_close($parser, $tag) + public function get_image_url() { - if ($this->current_xhtml_construct >= 0) + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image')) { - $this->current_xhtml_construct--; - if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param'))) - { - $this->data['data'] .= '</' . end($this->element) . '>'; - } + return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI); } - if ($this->current_xhtml_construct === -1) + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo')) { - $this->data =& $this->datas[count($this->datas) - 1]; - array_pop($this->datas); + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); } - - array_pop($this->element); - array_pop($this->namespace); - array_pop($this->xml_base); - array_pop($this->xml_base_explicit); - array_pop($this->xml_lang); - } - - function split_ns($string) - { - static $cache = array(); - if (!isset($cache[$string])) + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon')) { - if ($pos = strpos($string, $this->separator)) - { - static $separator_length; - if (!$separator_length) - { - $separator_length = strlen($this->separator); - } - $namespace = substr($string, 0, $pos); - $local_name = substr($string, $pos + $separator_length); - if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES) - { - $namespace = SIMPLEPIE_NAMESPACE_ITUNES; - } - - // Normalize the Media RSS namespaces - if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG) - { - $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS; - } - $cache[$string] = array($namespace, $local_name); - } - else - { - $cache[$string] = array('', $string); - } + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + else + { + return null; } - return $cache[$string]; } } /** - * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags + * Parses the XML Declaration + * + * @package SimplePie + * @subpackage Parsing */ -class SimplePie_Sanitize +class SimplePie_XML_Declaration_Parser { - // Private vars - var $base; + /** + * XML Version + * + * @access public + * @var string + */ + var $version = '1.0'; - // Options - var $remove_div = true; - var $image_handler = ''; - var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); - var $encode_instead_of_strip = false; - var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); - var $strip_comments = false; - var $output_encoding = 'UTF-8'; - var $enable_cache = true; - var $cache_location = './cache'; - var $cache_name_function = 'md5'; - var $cache_class = 'SimplePie_Cache'; - var $file_class = 'SimplePie_File'; - var $timeout = 10; - var $useragent = ''; - var $force_fsockopen = false; + /** + * Encoding + * + * @access public + * @var string + */ + var $encoding = 'UTF-8'; - var $replace_url_attributes = array( - 'a' => 'href', - 'area' => 'href', - 'blockquote' => 'cite', - 'del' => 'cite', - 'form' => 'action', - 'img' => array('longdesc', 'src'), - 'input' => 'src', - 'ins' => 'cite', - 'q' => 'cite' - ); + /** + * Standalone + * + * @access public + * @var bool + */ + var $standalone = false; + + /** + * Current state of the state machine + * + * @access private + * @var string + */ + var $state = 'before_version_name'; + + /** + * Input data + * + * @access private + * @var string + */ + var $data = ''; + + /** + * Input data length (to avoid calling strlen() everytime this is needed) + * + * @access private + * @var int + */ + var $data_length = 0; + + /** + * Current position of the pointer + * + * @var int + * @access private + */ + var $position = 0; - function remove_div($enable = true) + /** + * Create an instance of the class with the input data + * + * @access public + * @param string $data Input data + */ + public function __construct($data) { - $this->remove_div = (bool) $enable; + $this->data = $data; + $this->data_length = strlen($this->data); } - function set_image_handler($page = false) + /** + * Parse the input data + * + * @access public + * @return bool true on success, false on failure + */ + public function parse() { - if ($page) + while ($this->state && $this->state !== 'emit' && $this->has_data()) { - $this->image_handler = (string) $page; + $state = $this->state; + $this->$state(); + } + $this->data = ''; + if ($this->state === 'emit') + { + return true; } else { - $this->image_handler = false; + $this->version = ''; + $this->encoding = ''; + $this->standalone = ''; + return false; } } - function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache') + /** + * Check whether there is data beyond the pointer + * + * @access private + * @return bool true if there is further data, false if not + */ + public function has_data() { - if (isset($enable_cache)) - { - $this->enable_cache = (bool) $enable_cache; - } + return (bool) ($this->position < $this->data_length); + } - if ($cache_location) + /** + * Advance past any whitespace + * + * @return int Number of whitespace characters passed + */ + public function skip_whitespace() + { + $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position); + $this->position += $whitespace; + return $whitespace; + } + + /** + * Read value + */ + public function get_value() + { + $quote = substr($this->data, $this->position, 1); + if ($quote === '"' || $quote === "'") { - $this->cache_location = (string) $cache_location; + $this->position++; + $len = strcspn($this->data, $quote, $this->position); + if ($this->has_data()) + { + $value = substr($this->data, $this->position, $len); + $this->position += $len + 1; + return $value; + } } + return false; + } - if ($cache_name_function) + public function before_version_name() + { + if ($this->skip_whitespace()) { - $this->cache_name_function = (string) $cache_name_function; + $this->state = 'version_name'; } - - if ($cache_class) + else { - $this->cache_class = (string) $cache_class; + $this->state = false; } } - function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false) + public function version_name() { - if ($file_class) + if (substr($this->data, $this->position, 7) === 'version') { - $this->file_class = (string) $file_class; + $this->position += 7; + $this->skip_whitespace(); + $this->state = 'version_equals'; } - - if ($timeout) + else { - $this->timeout = (string) $timeout; + $this->state = false; } + } - if ($useragent) + public function version_equals() + { + if (substr($this->data, $this->position, 1) === '=') { - $this->useragent = (string) $useragent; + $this->position++; + $this->skip_whitespace(); + $this->state = 'version_value'; } - - if ($force_fsockopen) + else { - $this->force_fsockopen = (string) $force_fsockopen; + $this->state = false; } } - function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style')) + public function version_value() { - if ($tags) + if ($this->version = $this->get_value()) { - if (is_array($tags)) + $this->skip_whitespace(); + if ($this->has_data()) { - $this->strip_htmltags = $tags; + $this->state = 'encoding_name'; } else { - $this->strip_htmltags = explode(',', $tags); + $this->state = 'emit'; } } else { - $this->strip_htmltags = false; + $this->state = false; } } - function encode_instead_of_strip($encode = false) + public function encoding_name() { - $this->encode_instead_of_strip = (bool) $encode; + if (substr($this->data, $this->position, 8) === 'encoding') + { + $this->position += 8; + $this->skip_whitespace(); + $this->state = 'encoding_equals'; + } + else + { + $this->state = 'standalone_name'; + } } - function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc')) + public function encoding_equals() { - if ($attribs) + if (substr($this->data, $this->position, 1) === '=') { - if (is_array($attribs)) + $this->position++; + $this->skip_whitespace(); + $this->state = 'encoding_value'; + } + else + { + $this->state = false; + } + } + + public function encoding_value() + { + if ($this->encoding = $this->get_value()) + { + $this->skip_whitespace(); + if ($this->has_data()) { - $this->strip_attributes = $attribs; + $this->state = 'standalone_name'; } else { - $this->strip_attributes = explode(',', $attribs); + $this->state = 'emit'; } } else { - $this->strip_attributes = false; + $this->state = false; } } - function strip_comments($strip = false) - { - $this->strip_comments = (bool) $strip; - } - - function set_output_encoding($encoding = 'UTF-8') - { - $this->output_encoding = (string) $encoding; - } - - /** - * Set element/attribute key/value pairs of HTML attributes - * containing URLs that need to be resolved relative to the feed - * - * @access public - * @since 1.0 - * @param array $element_attribute Element/attribute key/value pairs - */ - function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite')) + public function standalone_name() { - $this->replace_url_attributes = (array) $element_attribute; + if (substr($this->data, $this->position, 10) === 'standalone') + { + $this->position += 10; + $this->skip_whitespace(); + $this->state = 'standalone_equals'; + } + else + { + $this->state = false; + } } - function sanitize($data, $type, $base = '') + public function standalone_equals() { - $data = trim($data); - if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI) + if (substr($this->data, $this->position, 1) === '=') { - if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML) - { - if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data)) - { - $type |= SIMPLEPIE_CONSTRUCT_HTML; - } - else - { - $type |= SIMPLEPIE_CONSTRUCT_TEXT; - } - } - - if ($type & SIMPLEPIE_CONSTRUCT_BASE64) - { - $data = base64_decode($data); - } - - if ($type & SIMPLEPIE_CONSTRUCT_XHTML) - { - if ($this->remove_div) - { - $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data); - $data = preg_replace('/<\/div>$/', '', $data); - } - else - { - $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data); - } - } - - if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML)) - { - // Strip comments - if ($this->strip_comments) - { - $data = SimplePie_Misc::strip_comments($data); - } - - // Strip out HTML tags and attributes that might cause various security problems. - // Based on recommendations by Mark Pilgrim at: - // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely - if ($this->strip_htmltags) - { - foreach ($this->strip_htmltags as $tag) - { - $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU'; - while (preg_match($pcre, $data)) - { - $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data); - } - } - } - - if ($this->strip_attributes) - { - foreach ($this->strip_attributes as $attrib) - { - $data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data); - } - } - - // Replace relative URLs - $this->base = $base; - foreach ($this->replace_url_attributes as $element => $attributes) - { - $data = $this->replace_urls($data, $element, $attributes); - } - - // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags. - if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache) - { - $images = SimplePie_Misc::get_element('img', $data); - foreach ($images as $img) - { - if (isset($img['attribs']['src']['data'])) - { - $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']); - $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi'); - - if ($cache->load()) - { - $img['attribs']['src']['data'] = $this->image_handler . $image_url; - $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data); - } - else - { - $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen); - $headers = $file->headers; - - if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) - { - if ($cache->save(array('headers' => $file->headers, 'body' => $file->body))) - { - $img['attribs']['src']['data'] = $this->image_handler . $image_url; - $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data); - } - else - { - trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); - } - } - } - } - } - } - - // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data - $data = trim($data); - } - - if ($type & SIMPLEPIE_CONSTRUCT_IRI) - { - $data = SimplePie_Misc::absolutize_url($data, $base); - } - - if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI)) - { - $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8'); - } - - if ($this->output_encoding !== 'UTF-8') - { - $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding); - } + $this->position++; + $this->skip_whitespace(); + $this->state = 'standalone_value'; + } + else + { + $this->state = false; } - return $data; } - function replace_urls($data, $tag, $attributes) + public function standalone_value() { - if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags)) + if ($standalone = $this->get_value()) { - $elements = SimplePie_Misc::get_element($tag, $data); - foreach ($elements as $element) + switch ($standalone) { - if (is_array($attributes)) - { - foreach ($attributes as $attribute) - { - if (isset($element['attribs'][$attribute]['data'])) - { - $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base); - $new_element = SimplePie_Misc::element_implode($element); - $data = str_replace($element['full'], $new_element, $data); - $element['full'] = $new_element; - } - } - } - elseif (isset($element['attribs'][$attributes]['data'])) - { - $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base); - $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data); - } + case 'yes': + $this->standalone = true; + break; + + case 'no': + $this->standalone = false; + break; + + default: + $this->state = false; + return; } - } - return $data; - } - function do_strip_htmltags($match) - { - if ($this->encode_instead_of_strip) - { - if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style'))) + $this->skip_whitespace(); + if ($this->has_data()) { - $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8'); - $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8'); - return "<$match[1]$match[2]>$match[3]</$match[1]>"; + $this->state = false; } else { - return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8'); + $this->state = 'emit'; } } - elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style'))) - { - return $match[4]; - } else { - return ''; + $this->state = false; } } } -?> -- cgit v1.2.3 From 192151b74b6b77cce79e36afd94200c50437085e Mon Sep 17 00:00:00 2001 From: Andreas Gohr <andi@splitbrain.org> Date: Sun, 3 Feb 2013 22:45:40 +0100 Subject: fixed revision JS for images --- lib/scripts/behaviour.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scripts/behaviour.js b/lib/scripts/behaviour.js index 6878b0b96..f1c46bf4c 100644 --- a/lib/scripts/behaviour.js +++ b/lib/scripts/behaviour.js @@ -51,7 +51,7 @@ var dw_behaviour = { dw_behaviour.subscription(); dw_behaviour.revisionBoxHandler(); - jQuery('#page__revisions input[type=checkbox]').on('click', + jQuery(document).on('click','#page__revisions input[type=checkbox]', dw_behaviour.revisionBoxHandler ); }, -- cgit v1.2.3