[PLUGINS] ~maj Crayons
authorLudovic CHEVALIER <ludovic.chevalier@heureux-cyclage.org>
Tue, 6 Sep 2016 14:23:54 +0000 (16:23 +0200)
committerLudovic CHEVALIER <ludovic.chevalier@heureux-cyclage.org>
Tue, 6 Sep 2016 14:23:54 +0000 (16:23 +0200)
76 files changed:
www/plugins/crayons/action/crayons.php
www/plugins/crayons/action/crayons_html.php
www/plugins/crayons/action/crayons_store.php
www/plugins/crayons/action/crayons_upload.php
www/plugins/crayons/controleurs/article_intro3.php
www/plugins/crayons/controleurs/article_introduction.html
www/plugins/crayons/controleurs/article_introduction.php
www/plugins/crayons/controleurs/auteur_qui.html
www/plugins/crayons/controleurs/extra_fonctions.php
www/plugins/crayons/controleurs/hyperlien.html
www/plugins/crayons/controleurs/logo.html
www/plugins/crayons/controleurs/portfolio.php
www/plugins/crayons/controleurs/rubrique_introduction.html [new file with mode: 0644]
www/plugins/crayons/controleurs/rubrique_introduction.php [new file with mode: 0644]
www/plugins/crayons/controleurs/vignette.html
www/plugins/crayons/crayons.js.html
www/plugins/crayons/crayons.js_fonctions.php
www/plugins/crayons/crayons_fonctions.php
www/plugins/crayons/inc/compat_crayons.php
www/plugins/crayons/inc/crayons-json.php
www/plugins/crayons/inc/crayons.php
www/plugins/crayons/js/crayons.js
www/plugins/crayons/js/jquery.form.js
www/plugins/crayons/js/jquery.html5uploader.js [new file with mode: 0644]
www/plugins/crayons/js/jquery.html5uploader.min.js [deleted file]
www/plugins/crayons/js/jquery.js
www/plugins/crayons/js/jquery.px.js [deleted file]
www/plugins/crayons/lang/crayons.xml
www/plugins/crayons/lang/crayons_ar.php
www/plugins/crayons/lang/crayons_ast.php
www/plugins/crayons/lang/crayons_br.php
www/plugins/crayons/lang/crayons_ca.php
www/plugins/crayons/lang/crayons_de.php
www/plugins/crayons/lang/crayons_en.php
www/plugins/crayons/lang/crayons_eo.php
www/plugins/crayons/lang/crayons_es.php
www/plugins/crayons/lang/crayons_eu.php
www/plugins/crayons/lang/crayons_fa.php
www/plugins/crayons/lang/crayons_fr.php
www/plugins/crayons/lang/crayons_fr_tu.php
www/plugins/crayons/lang/crayons_gl.php
www/plugins/crayons/lang/crayons_it.php
www/plugins/crayons/lang/crayons_it_fem.php
www/plugins/crayons/lang/crayons_km.php
www/plugins/crayons/lang/crayons_lb.php
www/plugins/crayons/lang/crayons_nl.php
www/plugins/crayons/lang/crayons_oc_lnc.php
www/plugins/crayons/lang/crayons_oc_ni_mis.php [new file with mode: 0644]
www/plugins/crayons/lang/crayons_pt_br.php
www/plugins/crayons/lang/crayons_ro.php
www/plugins/crayons/lang/crayons_ru.php
www/plugins/crayons/lang/crayons_sk.php
www/plugins/crayons/lang/crayons_sv.php
www/plugins/crayons/lang/crayons_tr.php
www/plugins/crayons/lang/crayons_tw.php
www/plugins/crayons/lang/crayons_zh.php
www/plugins/crayons/lang/crayons_zh_tw.php
www/plugins/crayons/lang/paquet-crayons.xml
www/plugins/crayons/lang/paquet-crayons_ar.php
www/plugins/crayons/lang/paquet-crayons_de.php
www/plugins/crayons/lang/paquet-crayons_en.php
www/plugins/crayons/lang/paquet-crayons_es.php
www/plugins/crayons/lang/paquet-crayons_fr.php
www/plugins/crayons/lang/paquet-crayons_fr_tu.php
www/plugins/crayons/lang/paquet-crayons_it.php
www/plugins/crayons/lang/paquet-crayons_nl.php
www/plugins/crayons/lang/paquet-crayons_oc_ni_mis.php [new file with mode: 0644]
www/plugins/crayons/lang/paquet-crayons_pt_br.php [new file with mode: 0644]
www/plugins/crayons/lang/paquet-crayons_ru.php
www/plugins/crayons/lang/paquet-crayons_sk.php
www/plugins/crayons/paquet.xml
www/plugins/crayons/plugin.xml
www/plugins/crayons/svn.revision
www/plugins/crayons/tetecrayons.php
www/plugins/crayons/vues/extra_fonctions.php
www/plugins/crayons/vues/rubrique_introduction.html [new file with mode: 0644]

index bd7a7c8..8bdc365 100644 (file)
@@ -1,12 +1,14 @@
 <?php
 /**
- * Crayons 
- * plugin for spip 
+ * Crayons
+ * plugin for spip
  * (c) Fil, toggg 2006-2013
  * licence GPL
  */
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 // On a ete appele par un formulaire normal (ajax est traite par crayons_store)
 function action_crayons_dist() {
@@ -21,13 +23,12 @@ function action_crayons_dist() {
        }
 
        // S'il n'y a pas de redirect, on est mal : eviter toutefois la page blanche
-       if (!_request('redirect'))
+       if (!_request('redirect')) {
                die('OK');
+       }
 
        // Invalider le cache parce que bon... a priori on est dans une
        // interface qui va avoir besoin de refresh
        include_spip('inc/invalideur');
        suivre_invalideur('1');
 }
-
-?>
\ No newline at end of file
index b9c6385..1af505b 100644 (file)
@@ -1,12 +1,14 @@
 <?php
 /**
- * Crayons 
- * plugin for spip 
+ * Crayons
+ * plugin for spip
  * (c) Fil, toggg 2006-2013
  * licence GPL
  */
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 /**
  * Affiche le controleur (formulaire) d'un crayon
@@ -15,13 +17,13 @@ if (!defined("_ECRIRE_INC_VERSION")) return;
  * @param string $class
  *   Class CSS décrivant le champ
  * @param null $c
- * 
+ *
  * @return array
  *   Tableau avec 2 entrées possibles :
  *   - '$erreur' : texte d'erreur éventuel
  *   - '$html' : code HTML du controleur
 **/
-function affiche_controleur($class, $c=null) {
+function affiche_controleur($class, $c = null) {
        $return = array('$erreur'=>'');
 
        if (preg_match(_PREG_CRAYON, $class, $regs)) {
@@ -29,27 +31,29 @@ function affiche_controleur($class, $c=null) {
                $regs[] = $class;
 
                // A-t-on le droit de crayonner ?
-               spip_log("autoriser('crayonner', $type, $id, NULL, array('modele'=>$champ)","crayons_distant");
-               if (!autoriser('crayonner',$type, $id, NULL, array('modele'=>$champ))) {
+               spip_log("autoriser('crayonner', $type, $id, NULL, array('modele'=>$champ)", 'crayons_distant');
+               if (!autoriser('crayonner', $type, $id, null, array('modele'=>$champ))) {
                        $return['$erreur'] = "$type $id: " . _U('crayons:non_autorise');
                } else {
                        $f = charger_fonction($type.'_'.$champ, 'controleurs', true)
-                       OR $f = charger_fonction($champ, 'controleurs', true)
-                       OR $f = charger_fonction($type, 'controleurs', true)
-                       OR $f = 'controleur_dist';
+                       or $f = charger_fonction($champ, 'controleurs', true)
+                       or $f = charger_fonction($type, 'controleurs', true)
+                       or $f = 'controleur_dist';
                        list($html,$status) = $f($regs, $c);
-                       if ($status)
+                       if ($status) {
                                $return['$erreur'] = $html;
-                       else
+                       } else {
                                $return['$html'] = $html;
+                       }
                }
-       } else
+       } else {
                $return['$erreur'] = _U('crayons:donnees_mal_formatees');
+       }
 
        return $return;
 }
 
-function controleur_dist($regs, $c=null) {
+function controleur_dist($regs, $c = null) {
        list( , $nomcrayon, $type, $champ, $id, $class) = $regs;
        $options = array(
                'class' => $class
@@ -61,25 +65,26 @@ function controleur_dist($regs, $c=null) {
        // Attention, un controleur multi-tables ne fonctionnera
        // que si les champs ont le meme nom dans toutes les tables
        // (par exemple: hyperlien est ok, mais pas nom)
-       if (($fichier = find_in_path(
-       ($controleur = 'controleurs/' . $type . '_' . $champ) . '.html'))
-       || ($fichier = find_in_path(
-       ($controleur = 'controleurs/' . $champ) .'.html'))) {
-               if (!lire_fichier($fichier, $controldata))
+       if (($fichier = find_in_path(($controleur = 'controleurs/' . $type . '_' . $champ) . '.html'))
+               || ($fichier = find_in_path(($controleur = 'controleurs/' . $champ) .'.html'))) {
+               if (!lire_fichier($fichier, $controldata)) {
                        die('erreur lecture controleur');
-               if (preg_match_all('/\bname=(["\'])#ENV\{name_(\w+)\}\1/',
-                       $controldata, $matches, PREG_PATTERN_ORDER))
+               }
+               if (preg_match_all('/\bname=(["\'])#ENV\{name_(\w+)\}\1/', $controldata, $matches, PREG_PATTERN_ORDER)) {
                        $champ = $matches[2];
-       } else
+               }
+       } else {
                $controleur = '';
+       }
 
        $valeur = valeur_colonne_table($type, $champ, $id);
 
        #spip_log("$valeur = valeur_colonne_table($type, $champ, $id);");
        #spip_log($champ);
 
-       if ($valeur === false)
+       if ($valeur === false) {
                return array("$type $id $champ: " . _U('crayons:pas_de_valeur'), 6);
+       }
 /*     if (is_scalar($valeur)) {
                $valeur = array($champ => $valeur);
        }*/
@@ -90,19 +95,17 @@ function controleur_dist($regs, $c=null) {
                $options['hauteurMini'] = 80; // base de hauteur mini
                $option['inmode'] = 'controleur';
                $options['controleur'] = $controleur;
-       } else
-       // si la valeur fait plusieurs lignes on doit mettre un textarea
-       // derogation specifique pour descriptif_site de spip_metas
-       if (
-               preg_match(",[\n\r],", $valeur[$champ])
-               OR (($champ == 'valeur') && ($id == 'descriptif_site'))
-               OR
+       } elseif (preg_match(",[\n\r],", $valeur[$champ])
+               or (($champ == 'valeur') && ($id == 'descriptif_site'))
+               or
        // on regarde le type tel que defini dans serial
        // (attention il y avait des blob dans les vieux spip)
                ($sqltype = colonne_table($type, $champ)) &&
-               (in_array($sqltype['type'] , array('mediumtext', 'longblob', 'longtext')) ||
-               (($sqltype['type'] == 'text' || $sqltype['type'] == 'blob') 
-               && in_array($champ, array('descriptif', 'bio'))))) {
+               (in_array($sqltype['type'], array('mediumtext', 'longblob', 'longtext')) ||
+               (($sqltype['type'] == 'text' || $sqltype['type'] == 'blob')
+               and in_array($champ, array('descriptif', 'bio'))))) {
+               // si la valeur fait plusieurs lignes on doit mettre un textarea
+               // derogation specifique pour descriptif_site de spip_metas
                $options['hauteurMini'] = 80; // hauteur mini d'un textarea
                $option['inmode'] = 'texte';
        } else { // ligne, hauteur naturelle
@@ -114,19 +117,18 @@ function controleur_dist($regs, $c=null) {
                        if (is_array($sqltype['long'])) {
                                if (count($sqltype['long']) == 2) {
                                        $inputAttrs['maxlength'] = $sqltype['long'][0] + 1 + $sqltype['long'][1];
-                               }
-                               // on ne sait pas ce que c'est !
-                               else {
+                               } else {
+                                       // on ne sait pas ce que c'est !
                                        $inputAttrs['maxlength'] = $sqltype['long'][0];
                                }
                        } else {
                                $inputAttrs['maxlength'] = $sqltype['long'];
-                       } 
+                       }
                }
        }
 
        $crayon = new Crayon($nomcrayon, $valeur, $options, $c);
-       $inputAttrs['style'] = implode('',$crayon->styles);
+       $inputAttrs['style'] = implode('', $crayon->styles);
 
        if (!$controleur) {
                $inputAttrs['style'] .= 'width:' . $crayon->largeur . 'px;' .
@@ -135,7 +137,7 @@ function controleur_dist($regs, $c=null) {
 
        $html = $controleur ? $crayon->formulaire(null, $inputAttrs) :
                                        $crayon->formulaire($option['inmode'], $inputAttrs);
-       $status = NULL;
+       $status = null;
 
        return array($html,$status);
 }
@@ -176,7 +178,7 @@ class Crayon {
        // $name : son nom
        // $texts : tableau associatif des valeurs ou valeur unique si crayon monochamp
        // $options : options directes du crayon (developpement)
-       function Crayon($name, $texts = array(), $options = array(), $c=null) {
+       function __construct($name, $texts = array(), $options = array(), $c = null) {
                $this->name = $name;
 
                list($this->type, $this->modele, $this->id) = array_pad(explode('-', $this->name, 3), 3, '');
@@ -187,7 +189,7 @@ class Crayon {
                $this->texts = $texts;
                $this->key = strtr(uniqid('wid', true), '.', '_');
                $this->md5 = $this->md5();
-               foreach ($options as $opt=>$val) {
+               foreach ($options as $opt => $val) {
                        $this->$opt = $val;
                }
                $this->dimension($c);
@@ -203,8 +205,7 @@ class Crayon {
        // dimensions indicatives
        function dimension($c) {
                // largeur du crayon
-               $this->largeur = min(max(intval(_request('w', $c)),
-                                       $this->largeurMini), $this->largeurMaxi);
+               $this->largeur = min(max(intval(_request('w', $c)), $this->largeurMini), $this->largeurMaxi);
                // hauteur maxi d'un textarea selon wh: window height
                $maxheight = min(max(intval(_request('wh', $c)) - 50, 400), $this->hauteurMaxi);
                $this->hauteur = min(max(intval(_request('h', $c)), $this->hauteurMini), $maxheight);
@@ -218,14 +219,15 @@ class Crayon {
 
        // recuperer les elements de style
        function css() {
-               foreach(array('color', 'font-size', 'font-family', 'font-weight', 'line-height', 'min-height', 'text-align') as $property) {
-                       if (null !== ($p = _request($property)))
+               foreach (array('color', 'font-size', 'font-family', 'font-weight', 'line-height', 'min-height', 'text-align') as $property) {
+                       if (null !== ($p = _request($property))) {
                                $this->styles[] = "$property:$p;";
+                       }
                }
 
                $property = 'background-color';
                if (!$p = _request($property)
-                       OR $p == 'transparent') {
+                       or $p == 'transparent') {
                        $p = 'white';
                }
                $this->styles[] = "$property:$p;";
@@ -250,14 +252,14 @@ class Crayon {
                . '<input type="hidden" name="md5_'.$this->key
                .'" value="'.$this->md5.'" />'."\n"
                . '<input type="hidden" name="fields_'.$this->key
-               .'" value="'.join(',',array_keys($this->texts)).'" />'
+               .'" value="'.join(',', array_keys($this->texts)).'" />'
                ."\n"
                ;
        }
 
 /**
  * Fabriquer les balises des champs d'apres un modele controleurs/(type_)modele.html
- * 
+ *
  * @param array $contexte
  *     tableau (nom=>valeur) qui sera enrichi puis passe à recuperer_fond
  * @return string
@@ -277,7 +279,7 @@ class Crayon {
                foreach ($this->texts as $champ => $val) {
                        $contexte['name_' . $champ] = 'content_' . $this->key . '_' . $champ;
                }
-               $contexte['style'] = join(' ',$this->styles);
+               $contexte['style'] = join(' ', $this->styles);
                include_spip('public/assembler');
                return recuperer_fond($this->controleur, $contexte);
        }
@@ -285,7 +287,7 @@ class Crayon {
 /**
  * Fabriquer les balises du ou des champs
  * $attrs est un tableau (attr=>val) d'attributs communs ou pour le champs unique
- * 
+ *
  * @param string|array $spec
  *  soit un scalaire 'ligne' ou 'texte' précisant le type de balise
  *  soit un array($champ=>array('type'=>'...', 'attrs'=>array(attributs specifique du champs)))
@@ -319,12 +321,12 @@ class Crayon {
                        }
 
                        if (is_array($spec) && isset($spec[$champ]['attrs'])) {
-                               foreach ($spec[$champ]['attrs'] as $attr=>$val) {
+                               foreach ($spec[$champ]['attrs'] as $attr => $val) {
                                        $input = inserer_attribut($input, $attr, $val);
                                }
                        }
 
-                       foreach ($attrs as $attr=>$val) {
+                       foreach ($attrs as $attr => $val) {
                                $input = inserer_attribut($input, $attr, $val);
                        }
 
@@ -332,14 +334,13 @@ class Crayon {
                        // pour faire propre il faudra reprogrammer la bt en jquery
                        $meta_crayon = isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']) : array();
                        if (isset($meta_crayon['barretypo'])
-                       AND $meta_crayon['barretypo']
-                       AND $type == 'texte') {
+                               and $meta_crayon['barretypo']
+                               and $type == 'texte') {
                                // Pas la peine de mettre cette barre si PortePlume est la
-                               if (
-                                       !(
+                               if (!(
                                                function_exists('chercher_filtre')
-                                               AND $f = chercher_filtre('info_plugin')
-                                               AND $f('PORTE_PLUME','est_actif')
+                                               and $f = chercher_filtre('info_plugin')
+                                               and $f('PORTE_PLUME', 'est_actif')
                                        )
                                ) {
                                        include_spip('inc/barre');
@@ -360,7 +361,7 @@ class Crayon {
 
 /**
  *     Fabriquer les boutons du formulaire
- * 
+ *
  *  @param array $boutons
  *      Le tableau des boutons
  *  @return string
@@ -371,30 +372,34 @@ function crayons_boutons($boutons = array()) {
        $boutons['cancel'] = array('cancel', texte_backend(_T('crayons:annuler')));
 
        $html = '';
-       foreach ($boutons as $bnam => $bdef) if ($bdef) {
-               $html .= '<button type="button" class="crayon-' . $bnam .
-                       '" title="' . $bdef[1] . '">' . $bdef[1] . '</button>';
+       foreach ($boutons as $bnam => $bdef) {
+               if ($bdef) {
+                       $html .= '<button type="button" class="crayon-' . $bnam .
+                               '" title="' . $bdef[1] . '">' . $bdef[1] . '</button>';
+               }
        }
 
-       if ($html)
+       if ($html) {
                return '<div class="crayon-boutons"><div>'.$html.'</div></div>';
+       }
 }
 
-function crayons_formulaire($html, $action='crayons_store') {
-       if (!$html)
+function crayons_formulaire($html, $action = 'crayons_store') {
+       if (!$html) {
                return '';
+       }
 
        // on est oblige de recreer un Crayon pour connaitre la largeur du form.
        // Pb conceptuel a revoir
-       $crayon = new Crayon("");
-       $class = ($crayon->largeur<250?" small":"");
+       $crayon = new Crayon('');
+       $class = ($crayon->largeur < 250 ? ' small' : '');
 
 
        include_spip('inc/filtres');
        return liens_absolus(
                '<div class="formulaire_spip">'
                . '<form class="formulaire_crayon'.$class.'" method="post" action="'
-               . url_absolue(parametre_url(self(),'action', $action))
+               . url_absolue(parametre_url(self(), 'action', $action))
                . '" enctype="multipart/form-data">'
                . $html
                . crayons_boutons()
@@ -408,8 +413,8 @@ function crayons_formulaire($html, $action='crayons_store') {
 //
 class SecureCrayon extends Crayon {
 
-       function SecureCrayon($name, $text='') {
-               parent::Crayon($name, $text);
+       function __construct($name, $text='') {
+               parent::__construct($name, $text);
        }
 
        function code() {
@@ -424,29 +429,29 @@ class SecureCrayon extends Crayon {
 
 /**
  * Action affichant le controleur html ou php adéquat
- * 
+ *
  * on affiche le formulaire demande (controleur associe au crayon)
  * Si le crayon n'est pas de type "crayon", c'est un crayon etendu, qui
  * integre le formulaire requis à son controleur (pour avoir les boutons
  * du formulaire dans un controleur Draggable, par exemple, mais il y a
  * d'autres usages possibles)
- * 
+ *
  */
 function action_crayons_html_dist() {
        include_spip('inc/crayons');
 
        // Utiliser la bonne langue d'environnement
-       if(!isset($GLOBALS['forcer_lang']) OR !$GLOBALS['forcer_lang'] OR ($GLOBALS['forcer_lang'] === 'non'))
+       if (!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang'] or ($GLOBALS['forcer_lang'] === 'non')) {
                lang_select($GLOBALS['auteur_session']['lang']);
+       }
 
        $return = affiche_controleur(_request('class'));
-       if (!_request('type') OR _request('type') == 'crayon')
+       if (!_request('type') or _request('type') == 'crayon') {
                $return['$html'] = crayons_formulaire($return['$html']);
+       }
 
        $json = trim(crayons_json_encode($return));
 
-       header("Content-Type: text/plain; charset=utf-8");
+       header('Content-Type: text/plain; charset=utf-8');
        die($json);
 }
-
-?>
index 85ac161..b440f7b 100644 (file)
@@ -1,17 +1,19 @@
 <?php
 /**
- * Crayons 
- * plugin for spip 
+ * Crayons
+ * plugin for spip
  * (c) Fil, toggg 2006-2013
  * licence GPL
  */
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 function verif_secu($w, $secu) {
        return (
                $secu == md5($GLOBALS['meta']['alea_ephemere'].'='.$w)
-       OR
+       or
                $secu == md5($GLOBALS['meta']['alea_ephemere_ancien'].'='.$w)
        );
 }
@@ -19,51 +21,52 @@ function verif_secu($w, $secu) {
 function post_crayons() {
        $results = array();
 
-       if (isset($_POST['crayons']) AND is_array($_POST['crayons']))
-       foreach ($_POST['crayons'] as $crayon) {
-               $name = $_POST['name_'.$crayon];
-               $content = array();
-               if ($_POST['fields_'.$crayon]) {
-                       foreach (explode(',', $_POST['fields_'.$crayon]) as $field) {
-                               // cas particulier d'un envoi de fichier
-                               if (isset($_FILES['content_'.$crayon.'_'.$field])) {
-                                       if ($_FILES['content_'.$crayon.'_'.$field]['size']>0)
-                                               $content[$field] = $_FILES['content_'.$crayon.'_'.$field];
-                                       else
-                                               $content[$field] = false;
-                                       // cf. valeur passee dans crayon->md5() : false ou filemtime() du logo
-                               } else {
-                                       /**
-                                        * le changement de charset n'est plus necessaire
-                                        * depuis jquery 1.5 (feature non documentee de jquery!)
-                                        */
-                                       if (isset($_POST['content_'.$crayon.'_'.$field])) {
-                                               $content[$field] = is_array($_POST['content_'.$crayon.'_'.$field])
-                                                       ?implode(',',$_POST['content_'.$crayon.'_'.$field])
-                                                       :$_POST['content_'.$crayon.'_'.$field];
+       if (isset($_POST['crayons']) and is_array($_POST['crayons'])) {
+               foreach ($_POST['crayons'] as $crayon) {
+                       $name = $_POST['name_'.$crayon];
+                       $content = array();
+                       if ($_POST['fields_'.$crayon]) {
+                               foreach (explode(',', $_POST['fields_'.$crayon]) as $field) {
+                                       // cas particulier d'un envoi de fichier
+                                       if (isset($_FILES['content_'.$crayon.'_'.$field])) {
+                                               if ($_FILES['content_'.$crayon.'_'.$field]['size'] > 0) {
+                                                       $content[$field] = $_FILES['content_'.$crayon.'_'.$field];
+                                               } else {
+                                                       $content[$field] = false;
+                                               }
+                                               // cf. valeur passee dans crayon->md5() : false ou filemtime() du logo
                                        } else {
-                                               $content[$field] = null;
+                                               /**
+                                                * le changement de charset n'est plus necessaire
+                                                * depuis jquery 1.5 (feature non documentee de jquery!)
+                                                */
+                                               if (isset($_POST['content_'.$crayon.'_'.$field])) {
+                                                       $content[$field] = is_array($_POST['content_'.$crayon.'_'.$field])
+                                                               ?implode(',', $_POST['content_'.$crayon.'_'.$field])
+                                                               :$_POST['content_'.$crayon.'_'.$field];
+                                               } else {
+                                                       $content[$field] = null;
+                                               }
                                        }
                                }
                        }
-               }
 
-               // Si les donnees POSTees ne correspondent pas a leur md5,
-               // il faut les traiter
-               if (isset($name)
-                       AND md5(serialize($content)) != $_POST['md5_'.$crayon]) {
-                       if (!isset($_POST['secu_'.$crayon])
-                               OR verif_secu($name, $_POST['secu_'.$crayon])) {
-                               $results[] = array($name, $content, $_POST['md5_'.$crayon], $crayon);
+                       // Si les donnees POSTees ne correspondent pas a leur md5,
+                       // il faut les traiter
+                       if (isset($name)
+                               and md5(serialize($content)) != $_POST['md5_'.$crayon]) {
+                               if (!isset($_POST['secu_'.$crayon])
+                                       or verif_secu($name, $_POST['secu_' . $crayon])) {
+                                       $results[] = array($name, $content, $_POST['md5_'.$crayon], $crayon);
+                               } else {
+                                       return false; // erreur secu
+                               }
+                       } else {
+                               // cas inchange
+                               $results[] = array($name, $content, false, $crayon);
                        }
-                       else
-                               return false; // erreur secu
                }
-               // cas inchange
-               else
-                       $results[] = array($name, $content, false, $crayon);
        }
-
        return $results;
 }
 
@@ -87,70 +90,70 @@ function crayons_store($options = array()) {
        if (!is_array($postees)) {
                $return['$erreur'] = _U('crayons:donnees_mal_formatees');
        } else {
-               foreach ($postees as $postee)
-               if ($postee[2] !== false) {
-                       $name = $postee[0];
-                       $content = $postee[1];
-
-                       if ($content && preg_match(_PREG_CRAYON, 'crayon '.$name, $regs)) {
-                               list(,$crayon,$type,$modele,$id) = $regs;
-                               $wid = $postee[3];
-
-                               spip_log("autoriser('crayonner', $type, $id, NULL, array('modele'=>$modele)","crayons_distant");
-                               if (!autoriser('crayonner', $type, $id, NULL, array('modele'=>$modele))) {
-                                       $return['$erreur'] =
-                                               "$type $id: " . _U('crayons:non_autorise');
-                               } else {
+               foreach ($postees as $postee) {
+                       if ($postee[2] !== false) {
+                               $name = $postee[0];
+                               $content = $postee[1];
+
+                               if ($content && preg_match(_PREG_CRAYON, 'crayon '.$name, $regs)) {
+                                       list(,$crayon,$type,$modele,$id) = $regs;
+                                       $wid = $postee[3];
+
+                                       spip_log("autoriser('crayonner', $type, $id, null, array('modele' => $modele)", 'crayons_distant');
+                                       if (!autoriser('crayonner', $type, $id, null, array('modele' => $modele))) {
+                                               $return['$erreur'] =
+                                                       "$type $id: " . _U('crayons:non_autorise');
+                                       } else {
+                                               // recuperer l'existant pour calculer son md5 et verifier
+                                               // qu'il n'a pas ete modifie entre-temps
+                                               $get_valeur = $options['f_get_valeur'];
+                                               $data = $get_valeur($content, $regs);
+
+                                               $md5 = md5(serialize($data));
+
+                                               // est-ce que le champ a ete modifie dans la base entre-temps ?
+                                               if ($md5 != $postee[2]) {
+                                                       // si oui, la modif demandee correspond peut-etre
+                                                       // a la nouvelle valeur ? dans ce cas on procede
+                                                       // comme si "pas de modification", sinon erreur
+                                                       if ($md5 != md5(serialize($content))) {
+                                                               $return['$erreur'] = "$type $id $modele: " .
+                                                                       _U('crayons:modifie_par_ailleurs');
+                                                       }
+                                               }
 
-                                       // recuperer l'existant pour calculer son md5 et verifier
-                                       // qu'il n'a pas ete modifie entre-temps
-                                       $get_valeur = $options['f_get_valeur'];
-                                       $data = $get_valeur($content, $regs);
-
-                                       $md5 = md5(serialize($data));
-
-                                       // est-ce que le champ a ete modifie dans la base entre-temps ?
-                                       if ($md5 != $postee[2]) {
-                                               // si oui, la modif demandee correspond peut-etre
-                                               // a la nouvelle valeur ? dans ce cas on procede
-                                               // comme si "pas de modification", sinon erreur
-                                               if ($md5 != md5(serialize($content))) {
-                                                       $return['$erreur'] = "$type $id $modele: " .
-                                                               _U('crayons:modifie_par_ailleurs');
+                                               $modifs[] = array($type, $modele, $id, $content, $wid);
+
+                                               /* aiguillage pour verification de la saisie
+                                               Pour traitement ulterieur les fonctions de verifications doivent renvoyer $invalides :
+                                                $invalides[wid_champ]['msg'] -> message de saisie invalide
+                                                $invalides[wid_champ]['retour'] -> caracteres invalides */
+                                               $f = 'verifier_'.$type.'_'.$modele;
+                                               if (function_exists($f)) {
+                                                       if (count($invalides = $f($modifs))) {
+                                                               $return['$invalides'] = $invalides;
+                                                       }
                                                }
                                        }
-
-                                       $modifs[] = array($type, $modele, $id, $content, $wid);
-                                       
-                                       /* aiguillage pour verification de la saisie
-                                       Pour traitement ulterieur les fonctions de verifications doivent renvoyer $invalides :
-                                        $invalides[wid_champ]['msg'] -> message de saisie invalide
-                                        $invalides[wid_champ]['retour'] -> caracteres invalides */
-                                       $f = 'verifier_'.$type.'_'.$modele;
-                                       if (function_exists($f)) {
-                                                if (count( $invalides = $f($modifs) )) {
-                                                       $return['$invalides'] = $invalides;
-                                                }
-                                                
-                                        }
                                }
                        }
                }
        }
 
-       if (!$modifs AND !$return['$erreur']) {
-               $return['$erreur'] = $wdgcfg['msgNoChange'] ?
-                  _U('crayons:pas_de_modification') : ' ';
+       if (!$modifs and !$return['$erreur']) {
+               $return['$erreur'] = $wdgcfg['msgNoChange'] ? _U('crayons:pas_de_modification') : ' ';
                $return['$annuler'] = true;
        }
-       
-       // un champ invalide ... ou rien ==> on ne fait rien ! 
-       if (isset($return['$invalides']) && $return['$invalides'])
+
+       // un champ invalide ... ou rien ==> on ne fait rien !
+       if (isset($return['$invalides']) and $return['$invalides']) {
                return $return;
+       }
 
        // une quelconque erreur ... ou rien ==> on ne fait rien !
-       if (isset($return['$erreur']) && $return['$erreur'])
+       if (isset($return['$erreur']) and $return['$erreur']) {
                return $return;
+       }
 
        // on traite toutes les modifications
        // en appelant la fonction adequate de traitement
@@ -158,17 +161,18 @@ function crayons_store($options = array()) {
        $return = $set_modifs($modifs, $return);
 
        // une quelconque erreur ... ou rien ==> on ne fait rien !
-       if ($return['$erreur'])
+       if ($return['$erreur']) {
                return $return;
+       }
 
        // et maintenant refaire l'affichage des crayons modifies
        include_spip('inc/texte');
        foreach ($modifs as $m) {
                list($type, $modele, $id, $content, $wid) = $m;
                        $f = charger_fonction($type.'_'.$modele, 'vues', true)
-                         OR $f = charger_fonction($modele, 'vues', true)
-                         OR $f = charger_fonction($type, 'vues', true)
-                         OR $f = 'vues_dist';
+                               or $f = charger_fonction($modele, 'vues', true)
+                               or $f = charger_fonction($type, 'vues', true)
+                               or $f = 'vues_dist';
                        $return[$wid] = $f($type, $modele, $id, $content, $wid);
        }
        return $return;
@@ -192,64 +196,62 @@ function crayons_store_set_modifs($modifs, $return) {
                $fun = '';
                // si le crayon est un MODELE avec une fonction xxx_revision associee
                // cas ou une fonction xxx_revision existe
-               if (function_exists($f = $type.'_'. $modele . "_revision")
-               OR function_exists($f = $modele . "_revision")
-               OR function_exists($f = $type . "_revision"))
+               if (function_exists($f = $type.'_'. $modele . '_revision')
+                       or function_exists($f = $modele . '_revision')
+                       or function_exists($f = $type . '_revision')) {
                        $fun = $f;
-
-               // si on est en SPIP 3+ et qu'on edite un objet editorial bien declare
-               // passer par l'API objet_modifier
-               elseif (function_exists('lister_tables_objets_sql')
-                 AND $tables_objet = lister_tables_objets_sql()
-                       AND isset($tables_objet[table_objet_sql($type)])) {
+               } elseif (function_exists('lister_tables_objets_sql')
+                       and $tables_objet = lister_tables_objets_sql()
+                       and isset($tables_objet[table_objet_sql($type)])) {
+                       // si on est en SPIP 3+ et qu'on edite un objet editorial bien declare
+                       // passer par l'API objet_modifier
                        $fun = 'crayons_objet_modifier';
-               }
-
-               // sinon spip < 3 (ou pas un objet edito)
-               // on teste les objets connus et on route sur les fonctions correspondantes
-               else switch($type) {
-                       case 'article':
-                               $fun = 'crayons_update_article';
-                               break;
-                       case 'breve':
-                               include_spip('action/editer_breve');
-                               $fun = 'revisions_breves';
-                               break;
-                       case 'forum':
-                               include_spip('inc/forum');
-                               $fun = 'enregistre_et_modifie_forum';
-                               break;
-                       case 'rubrique':
-                               include_spip('action/editer_rubrique');
-                               $fun = 'revisions_rubriques';
-                               break;
-                       case 'syndic':
-                       case 'site':
-                               include_spip('action/editer_site');
-                               $fun = 'revisions_sites';
-                               break;
-                       case 'document':
-                               include_spip('plugins/installer');
-                               include_spip('inc/plugin');
-                               if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) {
-                                       include_spip('action/editer_document');
-                                       $fun = 'document_modifier';
-                               } else {
+               } else {
+                       // sinon spip < 3 (ou pas un objet edito)
+                       // on teste les objets connus et on route sur les fonctions correspondantes
+                       switch ($type) {
+                               case 'article':
+                                       $fun = 'crayons_update_article';
+                                       break;
+                               case 'breve':
+                                       include_spip('action/editer_breve');
+                                       $fun = 'revisions_breves';
+                                       break;
+                               case 'forum':
+                                       include_spip('inc/forum');
+                                       $fun = 'enregistre_et_modifie_forum';
+                                       break;
+                               case 'rubrique':
+                                       include_spip('action/editer_rubrique');
+                                       $fun = 'revisions_rubriques';
+                                       break;
+                               case 'syndic':
+                               case 'site':
+                                       include_spip('action/editer_site');
+                                       $fun = 'revisions_sites';
+                                       break;
+                               case 'document':
+                                       include_spip('plugins/installer');
+                                       include_spip('inc/plugin');
+                                       if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) {
+                                               include_spip('action/editer_document');
+                                               $fun = 'document_modifier';
+                                       } else {
+                                               include_spip('inc/modifier');
+                                               $fun = 'revision_document';
+                                       }
+                                       break;
+                               // cas geres de la maniere la plus standard
+                               case 'auteur':
+                               case 'mot':
+                               case 'signature':
+                               case 'petition':
+                               default:
                                        include_spip('inc/modifier');
-                                       $fun = 'revision_document';
-                               }
-                               break;
-                       // cas geres de la maniere la plus standard
-                       case 'auteur':
-                       case 'mot':
-                       case 'signature':
-                       case 'petition':
-                       default:
-                               include_spip('inc/modifier');
-                               $fun = 'revision_'.$type;
-                               break;
+                                       $fun = 'revision_'.$type;
+                                       break;
+                       }
                }
-
                // si on a pas reussi on passe par crayons_update() qui fera un update sql brutal
                if (!$fun or !function_exists($fun)) {
                        $fun = 'crayons_update';
@@ -271,11 +273,12 @@ function crayons_store_set_modifs($modifs, $return) {
        }
 
        // il manque une fonction de mise a jour ==> on ne fait rien !
-       if ($return['$erreur'])
+       if ($return['$erreur']) {
                return $return;
+       }
 
        // hop ! mises a jour table par table et id par id
-       foreach ($updates as $type => $idschamps)
+       foreach ($updates as $type => $idschamps) {
                foreach ($idschamps as $fun => $ids) {
                        foreach ($ids as $id => $champsvaleurs) {
                                /* cas particulier du logo dans un crayon complexe :
@@ -289,21 +292,23 @@ function crayons_store_set_modifs($modifs, $return) {
                                        // -- revisions_articles($id_article, $c) --
                                        spip_log("$fun($id ...)", 'crayons');
                                        $updok = $fun($id, $champsvaleurs['chval'], $type, $champsvaleurs['wdg']);
-                                       // Renvoyer erreur si update base distante echoue, on ne regarde pas les updates base local car ils ne renvoient rien
+                                       // Renvoyer erreur si update base distante echoue,
+                                       // on ne regarde pas les updates base local car ils ne renvoient rien
                                        list($distant,$table) = distant_table($type);
-                                       if ($distant AND !$updok)
+                                       if ($distant and !$updok) {
                                                $return['$erreur'] = "$type: " . _U('crayons:update_impossible');
+                                       }
                                }
                        }
                }
-
+       }
        return $return;
 }
 
 //
 // VUE
 //
-function vues_dist($type, $modele, $id, $content, $wid){
+function vues_dist($type, $modele, $id, $content, $wid) {
        // pour ce qui a une {lang_select} par defaut dans la boucle,
        // la regler histoire d'avoir la bonne typo dans le propre()
        // NB: ceci n'a d'impact que sur le "par defaut" en bas
@@ -317,11 +322,12 @@ function vues_dist($type, $modele, $id, $content, $wid){
 
        // chercher vues/article_toto.html
        // sinon vues/toto.html
-       if (find_in_path( ($fond = 'vues/' . $type . '_' . $modele) . '.html')
-               OR find_in_path( ($fond = 'vues/' . $modele) .'.html')
-               OR find_in_path( ($fond = 'vues/' . $type) .'.html')) {
+       if (find_in_path(($fond = 'vues/' . $type . '_' . $modele) . '.html')
+               or find_in_path(($fond = 'vues/' . $modele) .'.html')
+               or find_in_path(($fond = 'vues/' . $type) .'.html')) {
+               $primary = (function_exists('id_table_objet')?id_table_objet($table):'id_' . $table);
                $contexte = array(
-                       'id_' . $table => $id,
+                       $primary => $id,
                        'crayon_type' => $type,
                        'crayon_modele' => $modele,
                        'champ' => $modele,
@@ -332,9 +338,8 @@ function vues_dist($type, $modele, $id, $content, $wid){
                $contexte = array_merge($contexte, $content);
                include_spip('public/assembler');
                return recuperer_fond($fond, $contexte);
-       }
-       // vue par defaut
-       else {
+       } else {
+               // vue par defaut
                // Par precaution on va rechercher la valeur
                // dans la base de donnees (meme si a priori la valeur est
                // ce qu'on vient d'envoyer, il y a nettoyage des caracteres et
@@ -355,13 +360,19 @@ function vues_dist($type, $modele, $id, $content, $wid){
                        }
                }
 
-               // seul spip core sait rendre les donnees
-               if (in_array($modele,
-                       array('chapo', 'texte', 'descriptif', 'ps', 'bio'))) {
-                       return propre($valeur);
-               } else {
-                       return typo($valeur);
+               if ($valeur) {
+                       // seul spip core sait rendre les donnees
+                       if (function_exists('appliquer_traitement_champ')) {
+                               $valeur = appliquer_traitement_champ($valeur, $modele, table_objet($table));
+                       } else {
+                               if (in_array($modele, array('chapo', 'texte', 'descriptif', 'ps', 'bio'))) {
+                                       $valeur = propre($valeur);
+                               } else {
+                                       $valeur = typo($valeur);
+                               }
+                       }
                }
+               return $valeur;
        }
 }
 
@@ -376,8 +387,8 @@ function vues_dist($type, $modele, $id, $content, $wid){
  */
 function crayons_objet_modifier($id, $data, $type, $ref) {
        if (include_spip('action/editer_objet')
-           AND function_exists('objet_modifier')) {
-               return objet_modifier(objet_type($type),$id,$data);
+               and function_exists('objet_modifier')) {
+               return objet_modifier(objet_type($type), $id, $data);
        }
        // fallback
        return crayons_update($id, $data, $type);
@@ -386,15 +397,17 @@ function crayons_objet_modifier($id, $data, $type, $ref) {
 //
 // Fonctions de mise a jour generique
 //
-function crayons_update($id, $colval = array(), $type = ''){
-       if (!$colval OR !count($colval))
+function crayons_update($id, $colval = array(), $type = '') {
+       if (!$colval or !count($colval)) {
                return false;
+       }
        list($distant,$table) = distant_table($type);
 
        if ($distant) {
                list($nom_table, $where) = table_where($type, $id);
-               if (!$nom_table)
+               if (!$nom_table) {
                        return false;
+               }
 
                $update = $sep = '';
                foreach ($colval as $col => $val) {
@@ -402,14 +415,12 @@ function crayons_update($id, $colval = array(), $type = ''){
                        $sep = ', ';
                }
 
-               $a = spip_query($q =
-                                       'UPDATE `' . $nom_table . '` SET ' . $update . ' WHERE ' . $where , $distant );
+               $a = spip_query($q = 'UPDATE `' . $nom_table . '` SET ' . $update . ' WHERE ' . $where, $distant);
 
                #spip_log($q);
                include_spip('inc/invalideur');
-               suivre_invalideur($cond, $modif=true);
-       }
-       else {
+               suivre_invalideur($cond, $modif = true);
+       } else {
                // cle primaire composee : 3-4-rubrique
                // calculer un where approprie
                // et modifier sans passer par la fonction destinee aux tables principales
@@ -423,7 +434,6 @@ function crayons_update($id, $colval = array(), $type = ''){
                        $a = modifier_contenu($type, $id, array(), $colval);
                }
        }
-
        return $a;
 }
 
@@ -440,7 +450,7 @@ function crayons_update_article($id_article, $c = false) {
        // NB: instituer_article veut id_parent, et pas id_rubrique !
        if (isset($c['id_rubrique'])) {
                $c['id_parent'] = $c['id_rubrique'];
-               unset ($c['id_rubrique']);
+               unset($c['id_rubrique']);
        }
        instituer_article($id_article, $c);
 }
@@ -452,7 +462,7 @@ function crayons_update_article($id_article, $c = false) {
  * La colonne est toujours 'valeur' pour ces données.
  * La donnée à enregistrer peut-être une sous partie de configuration.
  * Si c'est le cas, on gère l'enregistrement via ecrire_config.
- * 
+ *
  * @param string $a
  *   Nom ou clé de la meta (descriptif_site ou demo__truc pour demo/truc)
  * @param bool|array $c
@@ -493,7 +503,7 @@ function action_crayons_store_dist() {
 
 // permettre de passer une autre fonction de stockage des informations
 function action_crayons_store_args($store = 'crayons_store') {
-       header("Content-Type: text/plain; charset=".$GLOBALS['meta']['charset']);
+       header('Content-Type: text/plain; charset='.$GLOBALS['meta']['charset']);
        lang_select($GLOBALS['auteur_session']['lang']);
 
        $r = $store();
@@ -507,28 +517,25 @@ function action_crayons_store_args($store = 'crayons_store') {
        // En cas d'erreur il faudrait ajouter &err=... dans l'url ?
        if (_request('redirect')) {
                if (!$r['$erreur']
-               OR $r['$annuler']) {
+                       or $r['$annuler']) {
                        include_spip('inc/headers');
                        redirige_par_entete(_request('redirect'));
                } else {
                        echo "<h4 class='status'>".$r['$erreur']."</h4>\n";
 
                        foreach ($r as $wid => $v) {
-                               if ($wid !== '$erreur')
+                               if ($wid !== '$erreur') {
                                        echo "<div id='$wid'>$v</div><hr />\n";
+                               }
                        }
                        echo "<a href='".quote_amp(_request('redirect'))."'>"
                                .quote_amp(_request('redirect'))
                                ."</a>\n";
                }
-       }
-
-       // Cas normal : JSON
-       else {
+       } else {
+               // Cas normal : JSON
                echo crayons_json_export($r);
        }
 
        exit;
 }
-
-?>
index f09e7be..38b8099 100644 (file)
@@ -1,16 +1,18 @@
 <?php
 /**
- * Crayons 
- * plugin for spip 
+ * Crayons
+ * plugin for spip
  * (c) Fil, toggg 2006-2013
  * licence GPL
  */
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 /**
  * Upload de documents
- * 
+ *
  * Cette action recoit des fichiers ($_FILES)
  * et les affecte a l'objet courant ;
  * puis renvoie la liste des documents joints
@@ -22,40 +24,39 @@ function action_crayons_upload() {
 
        // check securite :-)
        include_spip('inc/autoriser');
-       if (!autoriser('joindredocument',$type,$id)) {
-               echo "Erreur: upload interdit";
+       if (!autoriser('joindredocument', $type, $id)) {
+               echo 'Erreur: upload interdit';
                return false;
        }
 
        // on n'accepte qu'un seul document à la fois, dans la variable 'upss'
        if ($file = $_FILES['upss']
-               AND $file['error'] == 0) {
-
+               and $file['error'] == 0) {
                $source = $file['tmp_name'];  # /tmp/php/phpxxx
-               $nom_envoye = $file['name'];  # mon-image.jpg   
-               
-               include_spip('plugins/installer'); // spip_version_compare dans SPIP 3.x 
-               include_spip('inc/plugin'); // spip_version_compare dans SPIP 2.x 
-               if (function_exists(spip_version_compare)) { // gerer son absence dans les branche precedente a SPIP 2.x
-                       if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) 
+               $nom_envoye = $file['name'];  # mon-image.jpg
+
+               include_spip('plugins/installer'); // spip_version_compare dans SPIP 3.x
+               include_spip('inc/plugin'); // spip_version_compare dans SPIP 2.x
+               if (function_exists('spip_version_compare')) { // gerer son absence dans les branche precedente a SPIP 2.x
+                       if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) {
                                define('_SPIP3', true);
-               } 
+                       }
+               }
                if (defined('_SPIP3')) {
                        include_spip('action/ajouter_documents');
-                       $ajouter_un_document = charger_fonction('ajouter_un_document','action');
-                       $id = $ajouter_un_document("new", $file, $type, $id, 'document');
+                       $ajouter_un_document = charger_fonction('ajouter_un_document', 'action');
+                       $id = $ajouter_un_document('new', $file, $type, $id, 'document');
                } else {
                        include_spip('inc/ajouter_documents');
-                       $id = ajouter_un_document($source, $nom_envoye, $type, $id, 'document', $id_document=0, $documents_actifs, $titrer=true);
+                       $id = ajouter_un_document($source, $nom_envoye, $type, $id, 'document', $id_document = 0, $documents_actifs, $titrer = true);
                }
        }
 
-       if (!$id)
-               $erreur = "erreur !";
+       if (!$id) {
+               $erreur = 'erreur !';
+       }
 
-       $a = recuperer_fond('modeles/uploader_item',array('id_document' => $id, 'erreur' => $erreur));
+       $a = recuperer_fond('modeles/uploader_item', array('id_document' => $id, 'erreur' => $erreur));
 
        echo $a;
 }
-
-?>
index 491cb70..557f676 100644 (file)
@@ -1,39 +1,38 @@
 <?php
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 // un controleur qui n'utilise que php et les inputs défauts
 function controleurs_article_intro3_dist($regs) {
-    list(,$crayon,$type,$champ,$id) = $regs;
-    $valeur = valeur_colonne_table($type, array('descriptif', 'chapo', 'texte'), $id);
-    if ($valeur === false) {
-           return array("$type $id $champ: " . _U('crayons:pas_de_valeur'), 6);
-    }
+       list(,$crayon,$type,$champ,$id) = $regs;
+       $valeur = valeur_colonne_table($type, array('descriptif', 'chapo', 'texte'), $id);
+       if ($valeur === false) {
+               return array("$type $id $champ: " . _U('crayons:pas_de_valeur'), 6);
+       }
+
+       $n = new Crayon('article-intro3-' . $id, $valeur, array('hauteurMini' => 234));
 
-       $n = new Crayon('article-intro3-' . $id, $valeur,
-                       array('hauteurMini' => 234));
-    
-    $return = array(
-       // html
-           $n->formulaire(
-               // champs et attributs propres
-               array(
-               'descriptif' => array('type' => 'texte', 'attrs' => array(
-                       'style' => 'height:' . ceil($n->hauteur*2/13) . 'px;' .
-                                               'width:' . $n->largeur . 'px;')),
+       $return = array(
+               // html
+               $n->formulaire(
+                       // champs et attributs propres
+                       array(
+                       'descriptif' => array('type' => 'texte', 'attrs' => array(
+                               'style' => 'height:' . ceil($n->hauteur*2/13) . 'px;' .
+                                                       'width:' . $n->largeur . 'px;')),
                        'chapo' =>  array('type' => 'texte', 'attrs' => array(
-                       'style' => 'height:' . ceil($n->hauteur*4/13) . 'px;' .
-                                               'width:' . $n->largeur . 'px;')),
+                               'style' => 'height:' . ceil($n->hauteur*4/13) . 'px;' .
+                                                       'width:' . $n->largeur . 'px;')),
                        'texte' =>  array('type' => 'texte', 'attrs' => array(
-                       'style' => 'height:' . ceil($n->hauteur*4/13) . 'px;' .
-                                               'width:' . $n->largeur . 'px;'))) //,
-                   // attributs communs :( marche pas pour style , pas 2 fois ?
-//             array('style' => 'width:' . $n->largeur . 'px;')
-       ),
-       // status
-       null);
+                               'style' => 'height:' . ceil($n->hauteur*4/13) . 'px;' .
+                                                       'width:' . $n->largeur . 'px;'))) //,
+                       // attributs communs :( marche pas pour style , pas 2 fois ?
+                       // array('style' => 'width:' . $n->largeur . 'px;')
+               ),
+               // status
+               null);
 
        return $return;
 }
-
-?>
index 75bb5bf..53d1694 100644 (file)
 ]
 #CACHE{0}
 <BOUCLE_a(ARTICLES){id_article}{statut==.}>
-<ul>
+<ul class="editer-groupe">
        <li class="fieldset" style="width:#ENV{largeur}px;#ENV{style}">
                <h3 class="legend"><:crayons:legend_introduction_article:></h3>
                <p class="explication"><:crayons:explication_introduction_article:></p>
-               <ul>
+               <ul class="editer-groupe">
                        <li class="editer_descriptif">
                                <label for="descriptif"><:texte_descriptif_rapide:></label>
                                <textarea class="crayon-active maxheight150" 
index 4768534..4c15293 100644 (file)
@@ -1,28 +1,26 @@
 <?php
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 // un controleur php + html
 // html == avec un modele, controleurs/article_introduction.html)
 function controleurs_article_introduction_dist($regs) {
-    list(,$crayon,$type,$champ,$id) = $regs;
-    $valeur = valeur_colonne_table($type, array('descriptif', 'chapo', 'texte'), $id);
-    if ($valeur === false) {
-           return array("$type $id $champ: " . _U('crayons:pas_de_valeur'), 6);
-    }
+       list(,$crayon,$type,$champ,$id) = $regs;
+       $valeur = valeur_colonne_table($type, array('descriptif', 'chapo', 'texte'), $id);
+       if ($valeur === false) {
+               return array("$type $id $champ: " . _U('crayons:pas_de_valeur'), 6);
+       }
+
+       $n = new Crayon('article-introduction-' . $id, $valeur, array('hauteurMini' => 234, 'controleur' => 'controleurs/article_introduction'));
 
-       $n = new Crayon('article-introduction-' . $id, $valeur,
-                       array('hauteurMini' => 234,
-                                 'controleur' => 'controleurs/article_introduction'));
-    
-    $contexte = array(
-       'h_descriptif' => (int)ceil($n->hauteur*2/13),
+       $contexte = array(
+               'h_descriptif' => (int)ceil($n->hauteur*2/13),
                'h_chapo' => (int)ceil($n->hauteur*4/13),
                'h_texte' => (int)ceil($n->hauteur*4/13));
-    $html = $n->formulaire($contexte);
-    $status = NULL;
+       $html = $n->formulaire($contexte);
+       $status = null;
 
        return array($html, $status);
 }
-
-?>
index b10d005..2ac3f63 100644 (file)
@@ -6,21 +6,19 @@
 #CACHE{0}
 
 <BOUCLE_a(AUTEURS){id_auteur}{tous}>
-<ul>
-       <li class="fieldset" style="#ENV{style}">
-               <h3 class="legend"><:crayons:legend_controleur_qui:></h3>
-               <ul>
-                       <li class="editer_nom">
-                               <label for="nom"><:ecrire:info_nom:> :</label>
-                               <input type="text" class="crayon-active text" name="#ENV{name_nom}" id="nom"
-                                       size="40" value="[(#NOM**|entites_html)]" />
-                       </li>
-                       <li class="editer_email">
-                               <label for="email"><:ecrire:email_2|ucfirst:></label>
-                               <input type="text" class="crayon-active text" name="#ENV{name_email}" id="email"
-                                       size="40" value="[(#EMAIL**|entites_html)]" />
-                       </li>
-               </ul>
-       </li>
-</ul>
+<fieldset style="#ENV{style}">
+       <h3 class="legend"><:crayons:legend_controleur_qui:></h3>
+       <ul class="editer-groupe">
+               <li class="editer_nom">
+                       <label for="nom"><:ecrire:info_nom:> :</label>
+                       <input type="text" class="crayon-active text" name="#ENV{name_nom}" id="nom"
+        size="40" value="[(#NOM**|entites_html)]" />
+    </li>
+               <li class="editer_email">
+      <label for="email"><:ecrire:email_2|ucfirst:></label>
+                       <input type="text" class="crayon-active text" name="#ENV{name_email}" id="email"
+        size="40" value="[(#EMAIL**|entites_html)]" />
+               </li>
+       </ul>
+</fieldset>
 </BOUCLE_a>
index 9dacf6e..cb208a0 100644 (file)
@@ -1,7 +1,8 @@
 <?php
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
-       include_spip('inc/extra');
-       include_spip('inc/presentation');
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
-?>
\ No newline at end of file
+include_spip('inc/extra');
+include_spip('inc/presentation');
index 1a4b65d..b271d83 100644 (file)
 #CACHE{0}
 
 <BOUCLE_a(AUTEURS){id_auteur}{tous}>
-<ul>
-       <li class="fieldset" style="#ENV{largeur}px;#ENV{style}">
-               <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
-               <ul>
-                       <li class="editer_nom_site">
-                               <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
-                                       size="40" value="[(#NOM_SITE**|entites_html)]" />
-                       </li>
-                       <li class="editer_url_site">
-                               <label for="url_site"><:form_prop_url_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
-                                       size="40" value="[(#URL_SITE**|entites_html)]" />
-                       </li>
-               </ul>
-       </li>
-</ul>
+<fieldset style="#ENV{largeur}px;#ENV{style}">
+       <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
+       <ul class="editer-groupe">
+               <li class="editer_nom_site">
+                       <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
+                   size="40" value="[(#NOM_SITE**|entites_html)]" />
+               </li>
+               <li class="editer_url_site">
+                       <label for="url_site"><:form_prop_url_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
+                   size="40" value="[(#URL_SITE**|entites_html)]" />
+               </li>
+  </ul>
+</fieldset>
 </BOUCLE_a>
 
 <BOUCLE_b(ARTICLES){id_article}{statut==.}>
-<ul>
-       <li class="fieldset" style="#ENV{largeur}px;#ENV{style}">
-               <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
-               <ul>
-                       <li class="editer_nom_site">
-                               <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
-                                       size="40" value="[(#NOM_SITE**|entites_html)]" />
-                       </li>
-                       <li class="editer_url_site">
-                               <label for="url_site"><:form_prop_url_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
-                                       size="40" value="[(#URL_SITE**|entites_html)]" />
-                       </li>
-               </ul>
-       </li>
-</ul>
+<fieldset style="#ENV{largeur}px;#ENV{style}">
+       <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
+       <ul class="editer-groupe">
+               <li class="editer_nom_site">
+                       <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
+                   size="40" value="[(#NOM_SITE**|entites_html)]" />
+               </li>
+               <li class="editer_url_site">
+                       <label for="url_site"><:form_prop_url_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
+                   size="40" value="[(#URL_SITE**|entites_html)]" />
+               </li>
+  </ul>
+</fieldset>
 </BOUCLE_b>
 
 <BOUCLE_c(SIGNATURES){id_signature}{statut==.}>
-<ul>
-       <li class="fieldset" style="#ENV{largeur}px;#ENV{style}">
-               <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
-               <ul>
-                       <li class="editer_nom_site">
-                               <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
-                                       size="40" value="[(#NOM_SITE**|entites_html)]" />
-                       </li>
-                       <li class="editer_url_site">
-                               <label for="url_site"><:form_prop_url_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
-                                       size="40" value="[(#URL_SITE**|entites_html)]" />
-                       </li>
-               </ul>
-       </li>
-</ul>
+<fieldset style="#ENV{largeur}px;#ENV{style}">
+       <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
+       <ul class="editer-groupe">
+               <li class="editer_nom_site">
+                       <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
+                   size="40" value="[(#NOM_SITE**|entites_html)]" />
+               </li>
+               <li class="editer_url_site">
+                       <label for="url_site"><:form_prop_url_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
+                   size="40" value="[(#URL_SITE**|entites_html)]" />
+               </li>
+  </ul>
+</fieldset>
 </BOUCLE_c>
 
 <BOUCLE_d(FORUMS){id_forum}{statut==.}>
-<ul>
-       <li class="fieldset" style="#ENV{largeur}px;#ENV{style}">
-               <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
-               <ul>
-                       <li class="editer_nom_site">
-                               <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
-                                       size="40" value="[(#NOM_SITE**|entites_html)]" />
-                       </li>
-                       <li class="editer_url_site">
-                               <label for="url_site"><:form_prop_url_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
-                                       size="40" value="[(#URL_SITE**|entites_html)]" />
-                       </li>
-               </ul>
-       </li>
-</ul>
+<fieldset style="#ENV{largeur}px;#ENV{style}">
+       <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
+       <ul class="editer-groupe">
+               <li class="editer_nom_site">
+                       <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
+                   size="40" value="[(#NOM_SITE**|entites_html)]" />
+               </li>
+               <li class="editer_url_site">
+                       <label for="url_site"><:form_prop_url_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
+                   size="40" value="[(#URL_SITE**|entites_html)]" />
+               </li>
+  </ul>
+</fieldset>
 </BOUCLE_d>
 
 <BOUCLE_e(SITES){id_syndic=#ENV{id_site}}{statut==.}>
-<ul>
-       <li class="fieldset" style="#ENV{largeur}px;#ENV{style}">
-               <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
-               <ul>
-                       <li class="editer_nom_site">
-                               <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
-                                       size="40" value="[(#NOM_SITE**|entites_html)]" />
-                       </li>
-                       <li class="editer_url_site">
-                               <label for="url_site"><:form_prop_url_site:></label>
-                               <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
-                                       size="40" value="[(#URL_SITE**|entites_html)]" />
-                       </li>
-               </ul>
-       </li>
-</ul>
+<fieldset style="#ENV{largeur}px;#ENV{style}">
+       <h3 class="legend"><:crayons:legend_controleur_hyperlien:></h3>
+       <ul class="editer-groupe">
+               <li class="editer_nom_site">
+                       <label for="nom_site"><:form_prop_indiquer_nom_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_nom_site}" id="nom_site"
+                   size="40" value="[(#NOM_SITE**|entites_html)]" />
+               </li>
+               <li class="editer_url_site">
+                       <label for="url_site"><:form_prop_url_site:></label>
+                       <input class="crayon-active text" name="#ENV{name_url_site}" id="url_site"
+                   size="40" value="[(#URL_SITE**|entites_html)]" />
+               </li>
+  </ul>
+</fieldset>
 </BOUCLE_e>
 
 <//B_d>
index 324ae9c..c8f120c 100644 (file)
        })]
 })]
 
-<ul>
-       <li class="fieldset" [ style="(#ENV{style}); border:none;"]>
-               <h3 class="legend">
-                       [(#GET{legend}|sinon{<:crayons:legend_controleur_logo:>})]
-                       [<div style="float:#LANG_RIGHT">(#GET{logo}|inserer_attribut{src,#GET{url}}
-                               |inserer_attribut{style,vertical-align:middle;})</div>]
-               </h3>
-               <ul>
-                       <li class="editer_logo">
-                               <div class="choix">
-                                       <input class="crayon-active file" name="#ENV{name_logo}" type="file"
-                                               onchange="if (this.value && !this.value.match(/\.(png|jpeg|jpg|gif)$/i)) { alert('<:crayons:message_image_obligatoire:>'); this.value=''; }; var q=cQuery('##ENV{name_logo}_supprimer').parent(); this.value ? q.hide() : q.show();" size="1" />
-                               </div>
-                               #GET{supprimer} 
-                       </li>
-               </ul>
-       </li>
-</ul>
\ No newline at end of file
+<fieldset [ style="(#ENV{style}); border:none;"]>
+       <h3 class="legend">
+               [(#GET{legend}|sinon{<:crayons:legend_controleur_logo:>})]
+               [<div style="float:#LANG_RIGHT">(#GET{logo}|inserer_attribut{src,#GET{url}}
+                       |inserer_attribut{style,vertical-align:middle;})</div>]
+       </h3>
+       <ul class="editer-groupe">
+               <li class="editer_logo">
+                       <div class="choix">
+                               <input class="crayon-active file" name="#ENV{name_logo}" type="file"
+                                       onchange="if (this.value && !this.value.match(/\.(png|jpeg|jpg|gif)$/i)) { alert('<:crayons:message_image_obligatoire:>'); this.value=''; }; var q=cQuery('##ENV{name_logo}_supprimer').parent(); this.value ? q.hide() : q.show();" size="1" />
+                       </div>
+                       #GET{supprimer}
+               </li>
+       </ul>
+</fieldset>
\ No newline at end of file
index 19e3c8f..362206a 100644 (file)
@@ -1,11 +1,13 @@
 <?php
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 // un controleur php (TODO -- NE FONCTIONNE PAS DU TOUT)
 
 function controleurs_portfolio_dist($regs) {
-    list(,$crayon,$type,$champ,$id) = $regs;
+       list(,$crayon,$type,$champ,$id) = $regs;
 
        include_spip('inc/minipres'); # pour aide()
        include_spip('inc/presentation'); # pour debut_cadre()
@@ -13,17 +15,12 @@ function controleurs_portfolio_dist($regs) {
        include_spip('inc/documents'); # pour aide()
 
        $html =
-               http_script("\nvar ajax_image_searching = \n'<div style=\"float: ".$GLOBALS['spip_lang_right'].";\"><img src=\"".url_absolue(_DIR_IMG_PACK."searching.gif")."\" alt=\"\" /></div>';")
+               http_script("\nvar ajax_image_searching = \n'<div style=\"float: " . $GLOBALS['spip_lang_right'] . ';\"><img src="' . url_absolue(_DIR_IMG_PACK . 'searching.gif')."\" alt=\"\" /></div>';")
                . http_script('', generer_url_public('jquery.js'))
-               . http_script('', _DIR_JAVASCRIPT . 'layer.js','')
+               . http_script('', _DIR_JAVASCRIPT . 'layer.js', '')
                . afficher_documents_colonne($id, $type, 'portfolio');
 
-    $status = NULL;
+       $status = null;
 
        return array($html, $status);
 }
-
-
-
-
-?>
diff --git a/www/plugins/crayons/controleurs/rubrique_introduction.html b/www/plugins/crayons/controleurs/rubrique_introduction.html
new file mode 100644 (file)
index 0000000..b1c98e0
--- /dev/null
@@ -0,0 +1,41 @@
+[(#REM)
+
+       Controleur pour le crayon 'rubrique_introduction' php+html
+       
+       (les balises écrites ci-dessous sont volontairement avec un espace pour ne pas être
+       compilée)
+       
+       Appelé via # EDIT{introduction} dans une boucle rubrique
+       
+       Affiche les deux champs :
+       - descriptif (si rempli, il sera le rendu de # INTRODUCTION)
+       - texte
+       
+       Si aucun descriptif, le rendu de # INTRODUCTION est par défaut les 600 premiers caractères de
+       # # TEXTE
+
+]
+#CACHE{0}
+<BOUCLE_a(RUBRIQUES){id_rubrique}{statut==.}>
+<fieldset style="width:#ENV{largeur}px;#ENV{style};background-color:inherit;">
+       <h3 class="legend"><:crayons:legend_introduction_rubrique:></h3>
+       <ul class="editer-groupe">
+               <li class="editer_descriptif">
+                       <label for="descriptif"><:texte_descriptif_rapide:></label>
+                       <textarea class="crayon-active maxheight150"
+                               name="#ENV{name_descriptif}"
+                               id="descriptif"
+                               style="width:100%;
+                               height:#ENV{h_descriptif}px;">[(#DESCRIPTIF**|entites_html)]</textarea>
+               </li>
+               <li class="editer_texte">
+                       <label for="text_area"><:info_texte:></label>
+                       <textarea class="crayon-active"
+                               name="#ENV{name_texte}"
+                               id="text_area"
+                               style="width:100%;
+                               height:#ENV{h_texte}px;">[(#TEXTE**|entites_html)]</textarea>
+               </li>
+       </ul>
+</fieldset>
+</BOUCLE_a>
diff --git a/www/plugins/crayons/controleurs/rubrique_introduction.php b/www/plugins/crayons/controleurs/rubrique_introduction.php
new file mode 100644 (file)
index 0000000..c1000af
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
+
+// un controleur php + html
+// html == avec un modele, controleurs/rubrique_introduction.html)
+function controleurs_rubrique_introduction_dist($regs) {
+       list(,$crayon,$type,$champ,$id) = $regs;
+       $valeur = valeur_colonne_table($type, array('descriptif', 'texte'), $id);
+       if ($valeur === false) {
+               return array("$type $id $champ: " . _U('crayons:pas_de_valeur'), 6);
+       }
+
+       $n = new Crayon(
+               'rubrique-introduction-' . $id,
+               $valeur,
+               array('hauteurMini' => 234, 'controleur' => 'controleurs/rubrique_introduction')
+       );
+
+       $contexte = array(
+       'h_descriptif' => (int)ceil($n->hauteur*5/13),
+               'h_texte' => (int)ceil($n->hauteur*7/13));
+       $html = $n->formulaire($contexte);
+       $status = null;
+
+       return array($html, $status);
+}
index db99f92..15bd12e 100644 (file)
        })]
 })]
 
-<ul>
-       <li class="fieldset" [ style="(#ENV{style}); border:none;"]>
-               <h3 class="legend">
-                       [(#GET{legend}|sinon{<:crayons:legend_controleur_vignette:>})]
-                       [<div style="float:#LANG_RIGHT">(#GET{vignette}|inserer_attribut{src,#GET{url}}
-                               |inserer_attribut{style,vertical-align:middle;})</div>]
-               </h3>
-               <ul>
-                       <li class="editer_vignette">
-                               <div class="choix">
-                                       <input class="crayon-active file" name="#ENV{name_vignette}" type="file"
-                                               onchange="if (this.value && !this.value.match(/\.(png|jpeg|jpg|gif)$/i)) { alert('<:crayons:message_image_obligatoire:>'); this.value=''; }; var q=cQuery('##ENV{name_vignette}_supprimer').parent(); this.value ? q.hide() : q.show();" size="10" />
-                               </div>
-                               #GET{supprimer} 
-                       </li>
-               </ul>
-       </li>
-</ul>
+<fieldset [ style="(#ENV{style}); border:none;"]>
+       <h3 class="legend">
+               [(#GET{legend}|sinon{<:crayons:legend_controleur_vignette:>})]
+               [<div style="float:#LANG_RIGHT">(#GET{vignette}|inserer_attribut{src,#GET{url}}
+                       |inserer_attribut{style,vertical-align:middle;})</div>]
+       </h3>
+       <ul class="editer-groupe">
+               <li class="editer_vignette">
+                       <div class="choix">
+                               <input class="crayon-active file" name="#ENV{name_vignette}" type="file"
+                                       onchange="if (this.value && !this.value.match(/\.(png|jpeg|jpg|gif)$/i)) { alert('<:crayons:message_image_obligatoire:>'); this.value=''; }; var q=cQuery('##ENV{name_vignette}_supprimer').parent(); this.value ? q.hide() : q.show();" size="10" />
+                       </div>
+                       #GET{supprimer}
+               </li>
+       </ul>
+</fieldset>
 </BOUCLE_document>
\ No newline at end of file
index 748b8e9..6448ca4 100644 (file)
@@ -19,17 +19,15 @@ cQuery.noConflict();
 
 [(#CHEMIN{js/jquery.form.js}|pack_cQuery)]
 
-[(#CHEMIN{js/jquery.px.js}|pack_cQuery)]
-
 [(#CHEMIN{js/crayons.js}|pack_cQuery)]
 
 [(#CHEMIN{js/resizehandle.js}|pack_cQuery)]
 
-[(#CHEMIN{js/jquery.html5uploader.min.js}|pack_cQuery)]
+[(#CHEMIN{js/jquery.html5uploader.js}|pack_cQuery)]
 
 [(#CONFIG{crayons}|match{s:11:"yellow_fade";s:2:"on";}|?{' ',''})
        [(#CHEMIN{js/crayons-fade.js}|pack_cQuery)]
 ]
 
 [(#REM) Appeler la callback si demandee ]
-[(#ENV{callback})();]
\ No newline at end of file
+[(#ENV{callback})();]
index e427f9e..17c8e3e 100644 (file)
@@ -1,46 +1,48 @@
 <?php
 /**
- * Crayons 
- * plugin for spip 
+ * Crayons
+ * plugin for spip
  * (c) Fil, toggg 2006-2013
  * licence GPL
  *
  */
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 //
 // Les crayons ont leur propre copie du pack de Dean Edwards
 // pour compatibilite avec SPIP < [9717]
 //
-
 function pack_cQuery($chemin) {
+       if (!$chemin) {
+               return;
+       }
+
        $flux = spip_file_get_contents($chemin);
        $flux = str_replace('jQuery', 'cQuery', $flux);
        $flux = str_replace('cQuery.spip', 'jQuery.spip', $flux);
 
        // On ne compacte PAS deux fois (c'est inutile et en plus ca bugge)
        if (!strlen($flux)
-       // mode debug des crayons
-       OR _request('debug_crayons')
-       // le vieil auto_compress_js
-       OR ($GLOBALS['meta']['auto_compress_js'] == 'oui'
-       AND @file_exists(_DIR_RESTREINT.'inc/compacte_js.php'))
-       // ou l'espace prive
-       OR !function_exists('test_espace_prive')
-       OR test_espace_prive())
+               or _request('debug_crayons') // mode debug des crayons
+               or ($GLOBALS['meta']['auto_compress_js'] == 'oui'       // le vieil auto_compress_js
+               and @file_exists(_DIR_RESTREINT.'inc/compacte_js.php'))
+               or !function_exists('test_espace_prive')// ou l'espace prive
+               or test_espace_prive()) {
                return $flux;
+       }
 
        include_spip('lib/JavaScriptPacker/class.JavaScriptPacker');
        $packer = new JavaScriptPacker($flux, 0, true, false);
 
        // en cas d'echec (?) renvoyer l'original
-       if (strlen($t = $packer->pack()))
+       if (strlen($t = $packer->pack())) {
                return $t;
+       }
 
        // erreur
        spip_log('erreur de pack_js');
        return $flux;
 }
-
-?>
index b271f55..fd0c89f 100644 (file)
-<?php\r
-/**\r
- * Crayons\r
- * plugin for spip\r
- * (c) Fil, toggg 2006-2014\r
- * licence GPL\r
- *\r
- * @package SPIP\Crayons\Fonctions\r
- */\r
-\r
-if (!defined("_ECRIRE_INC_VERSION")) return;\r
-\r
-if (!defined('_DEBUG_CRAYONS')) {\r
-       /**\r
-        * Débuguer les crayons\r
-        *\r
-        * Mettre a true dans mes_options pour avoir les crayons non compresses\r
-        */\r
-       define('_DEBUG_CRAYONS', false);\r
-}\r
-\r
-/**\r
- * Dire rapidement si ca vaut le coup de chercher des droits\r
- *\r
- * @return bool\r
-**/\r
-function analyse_droits_rapide_dist() {\r
-       return isset($GLOBALS['auteur_session']['statut']);\r
-}\r
-\r
-/**\r
- * Ajouter la gestion des crayons dans l'espace privé\r
- *\r
- * @pipeline header_prive\r
- * @uses Crayons_preparer_page()\r
- *\r
- * @param string $head\r
- *     Contenu du header\r
- * @return string\r
- *     Contenu du header\r
-**/\r
-function Crayons_insert_head($head) {\r
-       // verifie la presence d'une meta crayons, si c'est vide\r
-       // on ne cherche meme pas a traiter l'espace prive\r
-       $config_espace_prive = @unserialize($GLOBALS['meta']['crayons']);\r
-       if (empty($config_espace_prive)) {\r
-               return $head;\r
-       }\r
-\r
-       // verifie que l'edition de l'espace prive est autorisee\r
-       if (isset($config_espace_prive['espaceprive'])\r
-       and $config_espace_prive['espaceprive'] == 'on') {\r
-               // determine les pages (exec) crayonnables\r
-               if (($config_espace_prive['exec_autorise'] == '*') ||\r
-                       in_array(_request('exec'), explode(',', $config_espace_prive['exec_autorise']))) {\r
-                       // Calcul des droits\r
-                       include_spip('inc/crayons');\r
-                       $head = Crayons_preparer_page($head, '*', wdgcfg(), 'head');\r
-               }\r
-       }\r
-\r
-       // retourne l'entete modifiee\r
-       return $head;\r
-}\r
-\r
-/**\r
- * Ajouter la gestion des crayons dans l'espace public\r
- *\r
- * @pipeline affichage_final\r
- * @uses analyse_droits_rapide_dist()\r
- * @uses Crayons_preparer_page()\r
- * @note\r
- *     Le pipeline affichage_final est executé à chaque hit sur toute la page\r
- *\r
- * @param string $page\r
- *     Contenu de la page à envoyer au navigateur\r
- * @return string\r
- *     Contenu de la page à envoyer au navigateur\r
-**/\r
-function &Crayons_affichage_final(&$page) {\r
-\r
-       // ne pas se fatiguer si le visiteur n'a aucun droit\r
-       if (!(function_exists('analyse_droits_rapide')?analyse_droits_rapide():analyse_droits_rapide_dist())) {\r
-               return $page;\r
-       }\r
-\r
-       // sinon regarder rapidement si la page a des classes crayon\r
-       if (strpos($page, 'crayon')===false) {\r
-               return $page;\r
-       }\r
-\r
-       // voir un peu plus precisement lesquelles\r
-       include_spip('inc/crayons');\r
-       if (!preg_match_all(_PREG_CRAYON, $page, $regs, PREG_SET_ORDER)) {\r
-               return $page;\r
-       }\r
-\r
-       $wdgcfg = wdgcfg();\r
-\r
-       // calculer les droits sur ces crayons\r
-       include_spip('inc/autoriser');\r
-       $droits = array();\r
-       $droits_accordes = 0;\r
-       foreach ($regs as $reg) {\r
-               list(,$crayon,$type,$champ,$id) = $reg;\r
-               if (_DEBUG_CRAYONS) {\r
-                       spip_log("autoriser('modifier', $type, $id, NULL, array('champ'=>$champ))", "crayons_distant");\r
-               }\r
-               if (autoriser('modifier', $type, $id, null, array('champ'=>$champ))) {\r
-                       if (!isset($droits['.' . $crayon])) {\r
-                               $droits['.' . $crayon] = 0;\r
-                       }\r
-                       $droits['.' . $crayon]++;\r
-                       $droits_accordes ++;\r
-               }\r
-       }\r
-\r
-       // et les signaler dans la page\r
-       if ($droits_accordes == count($regs)) { // tous les droits\r
-               $page = Crayons_preparer_page($page, '*', $wdgcfg);\r
-       } elseif ($droits) { // seulement certains droits, preciser lesquels\r
-               $page = Crayons_preparer_page($page, join(',', array_keys($droits)), $wdgcfg);\r
-       }\r
-\r
-       return $page;\r
-}\r
-\r
-/**\r
- * Ajoute les scripts css et js nécessaires aux crayons dans le code HTML\r
- *\r
- * @uses crayons_var2js()\r
- *\r
- * @param string $page\r
- *     Code HTML de la page complète ou du header seulement\r
- * @param string $droits\r
- *     - Liste de css définissant les champs crayonnables\r
- *       (séparés par virgule) dont l'édition est autorisée\r
- *     - "*" si tous sont autorisés\r
- * @param array $wdgcfg\r
- *     Description de la configuration des crayons (attribut => valeur)\r
- * @param string $mode\r
- *     - page : toute la page est présente dans `$page`\r
- *     - head : seul le header est présent dans `$page`\r
- * @return\r
-**/\r
-function &Crayons_preparer_page(&$page, $droits, $wdgcfg = array(), $mode = 'page') {\r
-       /**\r
-        * Si pas forcer_lang, on charge le contrôleur dans la langue que l'utilisateur a dans le privé\r
-        */\r
-       if (!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang'] or ($GLOBALS['forcer_lang'] === 'non')) {\r
-               lang_select($GLOBALS['auteur_session']['lang']);\r
-       }\r
-\r
-       $jsFile = generer_url_public('crayons.js');\r
-       if (_DEBUG_CRAYONS) {\r
-               $jsFile = parametre_url($jsFile, 'debug_crayons', 1, '&');\r
-       }\r
-       include_spip('inc/filtres'); // rien que pour direction_css() :(\r
-       $cssFile = direction_css(find_in_path('crayons.css'));\r
-\r
-       $config = crayons_var2js(array(\r
-               'imgPath' => dirname(find_in_path('images/crayon.png')),\r
-               'droits' => $droits,\r
-               'dir_racine' => _DIR_RACINE,\r
-               'self' => self('&'),\r
-               'txt' => array(\r
-                       'error' => _U('crayons:svp_copier_coller'),\r
-                       'sauvegarder' => $wdgcfg['msgAbandon'] ? _U('crayons:sauvegarder') : ''\r
-               ),\r
-               'img' => array(\r
-                       'searching' => array(\r
-                               'txt' => _U('crayons:veuillez_patienter')\r
-                       ),\r
-                       'crayon' => array(\r
-                               'txt' => _U('crayons:editer')\r
-                       ),\r
-                       'edit' => array(\r
-                               'txt' => _U('crayons:editer_tout')\r
-                       ),\r
-                       'img-changed' => array(\r
-                               'txt' => _U('crayons:deja_modifie')\r
-                       )\r
-               ),\r
-               'cfg' => $wdgcfg\r
-       ));\r
-\r
-\r
-       // Est-ce que PortePlume est la ?\r
-       $meta_crayon = isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']): array();\r
-       $pp = '';\r
-       if (isset($meta_crayon['barretypo']) && $meta_crayon['barretypo']) {\r
-               if (function_exists('chercher_filtre')\r
-               and $f = chercher_filtre('info_plugin')\r
-               and $f('PORTE_PLUME','est_actif')) {\r
-\r
-                       $pp = <<<EOF\r
-cQuery(function() {\r
-       if (typeof onAjaxLoad == 'function') {\r
-               function barrebouilles_crayons() {\r
-                       $('.formulaire_crayon textarea.crayon-active')\r
-                       .barre_outils('edition');\r
-               }\r
-               onAjaxLoad(barrebouilles_crayons);\r
-       }\r
-});\r
-EOF;\r
-\r
-               }\r
-       }\r
-\r
-\r
-       $incCSS = "<link rel=\"stylesheet\" href=\"{$cssFile}\" type=\"text/css\" media=\"all\" />";\r
-       $incJS = <<<EOH\r
-<script type="text/javascript">/* <![CDATA[ */\r
-var configCrayons;\r
-function startCrayons() {\r
-       configCrayons = new cQuery.prototype.cfgCrayons({$config});\r
-       cQuery.fn.crayonsstart();\r
-{$pp}\r
-}\r
-var cr = document.createElement('script');\r
-cr.type = 'text/javascript'; cr.async = true;\r
-cr.src = '{$jsFile}\x26callback=startCrayons';\r
-var s = document.getElementsByTagName('script')[0];\r
-s.parentNode.insertBefore(cr, s);\r
-/* ]]> */</script>\r
-\r
-EOH;\r
-\r
-       if ($mode == 'head') {\r
-               return $page = $page . $incJS . $incCSS; //js inline avant les css, sinon ca bloque le chargement\r
-       }\r
-\r
-       $pos_head = strpos($page, '</head>');\r
-       if ($pos_head === false) {\r
-               return $page;\r
-       }\r
-\r
-       // js inline avant la premiere css, ou sinon avant la fin du head\r
-       $pos_link = strpos($page, '<link ');\r
-       if (!$pos_link) {\r
-               $pos_link = $pos_head;\r
-       }\r
-       $page = substr_replace($page, $incJS, $pos_link, 0);\r
-\r
-       // css avant la fin du head\r
-       $pos_head = strpos($page, '</head>');\r
-               $page = substr_replace($page, $incCSS, $pos_head, 0);\r
-\r
-       return $page;\r
-}\r
-\r
-/**\r
- * Balise indiquant un champ SQL crayonnable\r
- *\r
- * @note\r
- *   Si cette fonction est absente, `balise_EDIT_dist()` déclarée par SPIP\r
- *   ne retourne rien\r
- *\r
- * @example\r
- *     ```\r
- *     <div class="#EDIT{texte}">#TEXTE</div>\r
- *     <div class="#EDIT{ps}">#PS</div>\r
- *     ```\r
- *\r
- * @param Champ $p\r
- *   Pile au niveau de la balise\r
- * @return Champ\r
- *   Pile complétée par le code à générer\r
-**/\r
-function balise_EDIT($p) {\r
-\r
-       // le code compile de ce qui se trouve entre les {} de la balise\r
-       $label = interprete_argument_balise(1, $p);\r
-\r
-       // Verification si l'on est dans le cas d'une meta\r
-       // #EDIT{meta-descriptif_site} ou #EDIT{meta-demo/truc}\r
-       if (preg_match('/meta-(.*)\'/', $label, $meta)) {\r
-               $type = 'meta';\r
-               $label= 'valeur';\r
-               $primary = $meta[1];\r
-               $p->code = "classe_boucle_crayon('"\r
-                       . $type\r
-                       ."','"\r
-                       .$label\r
-                       ."',"\r
-                       . "str_replace('/', '__', '$primary')" # chaque / doit être remplacé pour CSS.\r
-                       .").' '";\r
-               $p->interdire_scripts = false;\r
-               return $p;\r
-       }\r
-\r
-       $i_boucle = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;\r
-       // #EDIT hors boucle? ne rien faire\r
-       if (!isset($p->boucles[$i_boucle]) or !$type = ($p->boucles[$i_boucle]->type_requete)) {\r
-               $p->code = "''";\r
-               $p->interdire_scripts = false;\r
-               return $p;\r
-       }\r
-\r
-       // crayon sur une base distante 'nua__article-intro-5'\r
-       if ($distant = $p->boucles[$i_boucle]->sql_serveur) {\r
-               $type = $distant.'__'.$type;\r
-       }\r
-\r
-       // le compilateur 1.9.2 ne calcule pas primary pour les tables secondaires\r
-       // il peut aussi arriver une table sans primary (par ex: une vue)\r
-       if (!($primary = $p->boucles[$i_boucle]->primary)) {\r
-               include_spip('inc/vieilles_defs'); # 1.9.2 pour trouver_def_table\r
-               if (function_exists('trouver_def_table')) {\r
-                       list($nom, $desc) = trouver_def_table(\r
-                               $p->boucles[$i_boucle]->type_requete,\r
-                               $p->boucles[$i_boucle]\r
-                       );\r
-                       $primary = $desc['key']['PRIMARY KEY'];\r
-               }\r
-       }\r
-       // On rajoute ici un debug dans le cas où aucune clé primaire n'est trouvée.\r
-       // Cela peut se présenter par exemple si on utilise #EDIT{monchamp} directement\r
-       // dans une boucle CONDITION sans faire référence au nom de la boucle d'au dessus.\r
-       if (!$primary) {\r
-               erreur_squelette(_T('crayons:absence_cle_primaire'), $p);\r
-       }\r
-\r
-       $primary = explode(',', $primary);\r
-       $id = array();\r
-       foreach ($primary as $key) {\r
-               $id[] = champ_sql(trim($key), $p);\r
-       }\r
-       $primary = implode(".'-'.", $id);\r
-\r
-       $p->code = "classe_boucle_crayon('"\r
-               . $type\r
-               ."',"\r
-               .sinon($label, "''")\r
-               .","\r
-               . $primary\r
-               .").' '";\r
-       $p->interdire_scripts = false;\r
-       return $p;\r
-}\r
-\r
-/**\r
- * Balise indiquant une configuration crayonnable\r
- *\r
- * @example\r
- *     ```\r
- *     <div class="#EDIT_CONFIG{descriptif_site}">#DESCRIPTIF_SITE_SPIP</div>\r
- *     <div class="#EDIT_CONFIG{demo/truc}">#CONFIG{demo/truc}</div>\r
- *     ```\r
- *\r
- * @param Champ $p\r
- *   Pile au niveau de la balise\r
- * @return Champ\r
- *   Pile complétée par le code à générer\r
-**/\r
-function balise_EDIT_CONFIG_dist($p) {\r
-\r
-       // le code compile de ce qui se trouve entre les {} de la balise\r
-       $config = interprete_argument_balise(1, $p);\r
-       if (!$config) {\r
-               return $p;\r
-       }\r
-\r
-       // chaque / du nom de config doit être transformé pour css.\r
-       // nous utiliserons '__' à la place.\r
-\r
-       $type = 'meta';\r
-       $label= 'valeur';\r
-\r
-       $p->code = "classe_boucle_crayon('"\r
-               . $type\r
-               . "','"\r
-               . $label\r
-               . "',"\r
-               . "str_replace('/', '__', $config)"\r
-               . ").' '";\r
-       $p->interdire_scripts = false;\r
-       return $p;\r
-}\r
-\r
-/**\r
- * Crée le controleur du crayon indiqué par la classe CSS\r
- *\r
- * @param string $class\r
- *   Class CSS de crayon tel que créé par #EDIT\r
- * @return string\r
- *   HTML du crayon, sinon texte d'erreur\r
-**/\r
-function creer_le_crayon($class) {\r
-       include_spip('inc/crayons');\r
-       include_spip('action/crayons_html');\r
-       $a = affiche_controleur($class, array('w' => 485, 'h' => 300, 'wh' => 500));\r
-       return $a['$erreur'] ? $a['$erreur'] : $a['$html'];\r
-}\r
-\r
-/**\r
- * Balise `#CRAYON` affichant un formulaire de crayon\r
- *\r
- * SI `?edit=1;`\r
- *\r
- * @example\r
- *    ```\r
- *    #CRAYON{ps}\r
- *    ```\r
- *\r
- * @param Champ $p\r
- *   Pile au niveau de la balise\r
- * @return Champ\r
- *   Pile complétée par le code à générer\r
-**/\r
-function balise_CRAYON($p) {\r
-       $p = balise_EDIT($p);\r
-       $p->code = 'creer_le_crayon('.$p->code.')';\r
-       return $p;\r
-}\r
-\r
-\r
-/**\r
- * Donne la classe CSS crayon\r
- *\r
- * En fonction :\r
- * - du type de la boucle\r
- *   (attention aux exceptions pour `#EDIT` dans les boucles HIERARCHIE et SITES)\r
- * - du champ demande (vide, + ou se terminant par + : (+)classe type--id)\r
- * - de l'id courant\r
- *\r
- * @param string $type\r
- *   Type d'objet, ou "meta" pour un champ de configuration\r
- * @param string $champ\r
- *   Champ SQL concerné\r
- * @param int|string $id\r
- *   Identifiant de la ligne sql\r
- * @return string\r
- *   Classes CSS (à ajouter dans le HTML à destination du javascript de Crayons)\r
-**/\r
-function classe_boucle_crayon($type, $champ, $id) {\r
-       // $type = objet_type($type);\r
-       $type = $type[strlen($type) - 1] == 's' ?\r
-               substr($type, 0, -1) :\r
-               str_replace(\r
-                       array('hierarchie','syndication'),\r
-                       array('rubrique','site'),\r
-                       $type\r
-               );\r
-\r
-       $plus = (substr($champ, -1) == '+' and $champ = substr($champ, 0, -1))\r
-               ? " $type--$id"\r
-               : '';\r
-\r
-       // test rapide pour verifier que l'id est valide (a-zA-Z0-9)\r
-       if (false !== strpos($id, ' ')) {\r
-               spip_log("L'identifiant ($id) ne pourra être géré ($type | $champ)", 'crayons');\r
-               return 'crayon_id_ingerable';\r
-       }\r
-\r
-       return 'crayon ' . $type . '-' . $champ . '-' . $id . $plus;\r
-}\r
-\r
-?>\r
+<?php
+/**
+ * Crayons
+ * plugin for spip
+ * (c) Fil, toggg 2006-2014
+ * licence GPL
+ *
+ * @package SPIP\Crayons\Fonctions
+ */
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
+
+if (!defined('_DEBUG_CRAYONS')) {
+       /**
+        * Débuguer les crayons
+        *
+        * Mettre a true dans mes_options pour avoir les crayons non compresses
+        */
+       define('_DEBUG_CRAYONS', false);
+}
+
+/**
+ * Dire rapidement si ca vaut le coup de chercher des droits
+ *
+ * @return bool
+**/
+function analyse_droits_rapide_dist() {
+       return isset($GLOBALS['auteur_session']['statut']);
+}
+
+/**
+ * Vérifier si un exec du privé est crayonnable
+ *
+ * @param string $exec
+ *
+ * @return bool
+ **/
+function test_exec_crayonnable($exec) {
+       if ($exec_autorise = lire_config('crayons/exec_autorise')) {
+               $execs = explode(',', $exec_autorise);
+               foreach ($execs as $key => $value) {
+                       $execs[$key] = trim($value);
+               }
+               if ($exec_autorise == '*' || in_array($exec, $execs)) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+/**
+ * Ajouter la gestion des crayons dans l'espace privé
+ *
+ * @pipeline header_prive
+ * @uses Crayons_preparer_page()
+ *
+ * @param string $head
+ *     Contenu du header
+ * @return string
+ *     Contenu du header
+**/
+function Crayons_insert_head($head) {
+       // verifie la presence d'une meta crayons, si c'est vide
+       // on ne cherche meme pas a traiter l'espace prive
+       $config_espace_prive = @unserialize($GLOBALS['meta']['crayons']);
+       if (empty($config_espace_prive)) {
+               return $head;
+       }
+
+       // verifie que l'edition de l'espace prive est autorisee
+       if (isset($config_espace_prive['espaceprive'])
+       and $config_espace_prive['espaceprive'] == 'on') {
+               // determine les pages (exec) crayonnables
+               if (test_exec_crayonnable(_request('exec'))) {
+                       // Calcul des droits
+                       include_spip('inc/crayons');
+                       $head = Crayons_preparer_page($head, '*', wdgcfg(), 'head');
+               }
+       }
+
+       // retourne l'entete modifiee
+       return $head;
+}
+
+/**
+ * Ajouter la gestion des crayons dans l'espace public
+ *
+ * @pipeline affichage_final
+ * @uses analyse_droits_rapide_dist()
+ * @uses Crayons_preparer_page()
+ * @note
+ *     Le pipeline affichage_final est executé à chaque hit sur toute la page
+ *
+ * @param string $page
+ *     Contenu de la page à envoyer au navigateur
+ * @return string
+ *     Contenu de la page à envoyer au navigateur
+**/
+function &Crayons_affichage_final(&$page) {
+
+       // ne pas se fatiguer si le visiteur n'a aucun droit
+       if (!(function_exists('analyse_droits_rapide')?analyse_droits_rapide():analyse_droits_rapide_dist())) {
+               return $page;
+       }
+
+       // sinon regarder rapidement si la page a des classes crayon
+       if (strpos($page, 'crayon')===false) {
+               return $page;
+       }
+
+       // voir un peu plus precisement lesquelles
+       include_spip('inc/crayons');
+       if (!preg_match_all(_PREG_CRAYON, $page, $regs, PREG_SET_ORDER)) {
+               return $page;
+       }
+
+       $wdgcfg = wdgcfg();
+
+       // calculer les droits sur ces crayons
+       include_spip('inc/autoriser');
+       $droits = array();
+       $droits_accordes = 0;
+       foreach ($regs as $reg) {
+               list(,$crayon,$type,$champ,$id) = $reg;
+               if (_DEBUG_CRAYONS) {
+                       spip_log("autoriser('modifier', $type, $id, NULL, array('champ'=>$champ))", 'crayons_distant');
+               }
+               if (autoriser('modifier', $type, $id, null, array('champ'=>$champ))) {
+                       if (!isset($droits['.' . $crayon])) {
+                               $droits['.' . $crayon] = 0;
+                       }
+                       $droits['.' . $crayon]++;
+                       $droits_accordes ++;
+               }
+       }
+
+       // et les signaler dans la page
+       if ($droits_accordes == count($regs)) { // tous les droits
+               $page = Crayons_preparer_page($page, '*', $wdgcfg);
+       } elseif ($droits) { // seulement certains droits, preciser lesquels
+               $page = Crayons_preparer_page($page, join(',', array_keys($droits)), $wdgcfg);
+       }
+
+       return $page;
+}
+
+/**
+ * Ajoute les scripts css et js nécessaires aux crayons dans le code HTML
+ *
+ * @uses crayons_var2js()
+ *
+ * @param string $page
+ *     Code HTML de la page complète ou du header seulement
+ * @param string $droits
+ *     - Liste de css définissant les champs crayonnables
+ *       (séparés par virgule) dont l'édition est autorisée
+ *     - "*" si tous sont autorisés
+ * @param array $wdgcfg
+ *     Description de la configuration des crayons (attribut => valeur)
+ * @param string $mode
+ *     - page : toute la page est présente dans `$page`
+ *     - head : seul le header est présent dans `$page`
+ * @return
+**/
+function &Crayons_preparer_page(&$page, $droits, $wdgcfg = array(), $mode = 'page') {
+       /**
+        * Si pas forcer_lang, on charge le contrôleur dans la langue que l'utilisateur a dans le privé
+        */
+       if (!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang'] or ($GLOBALS['forcer_lang'] === 'non')) {
+               lang_select($GLOBALS['auteur_session']['lang']);
+       }
+
+       $jsFile = generer_url_public('crayons.js');
+       if (_DEBUG_CRAYONS) {
+               $jsFile = parametre_url($jsFile, 'debug_crayons', 1, '&');
+       }
+       include_spip('inc/filtres'); // rien que pour direction_css() :(
+       $cssFile = direction_css(find_in_path('crayons.css'));
+
+       $config = crayons_var2js(array(
+               'imgPath' => dirname(find_in_path('images/crayon.png')),
+               'droits' => $droits,
+               'dir_racine' => _DIR_RACINE,
+               'self' => self('&'),
+               'txt' => array(
+                       'error' => _U('crayons:svp_copier_coller'),
+                       'sauvegarder' => $wdgcfg['msgAbandon'] ? _U('crayons:sauvegarder') : ''
+               ),
+               'img' => array(
+                       'searching' => array(
+                               'txt' => _U('crayons:veuillez_patienter')
+                       ),
+                       'crayon' => array(
+                               'txt' => _U('crayons:editer')
+                       ),
+                       'edit' => array(
+                               'txt' => _U('crayons:editer_tout')
+                       ),
+                       'img-changed' => array(
+                               'txt' => _U('crayons:deja_modifie')
+                       )
+               ),
+               'cfg' => $wdgcfg
+       ));
+
+
+       // Est-ce que PortePlume est la ?
+       $meta_crayon = isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']): array();
+       $pp = '';
+       if (isset($meta_crayon['barretypo']) && $meta_crayon['barretypo']) {
+               if (function_exists('chercher_filtre')
+               and $f = chercher_filtre('info_plugin')
+               and $f('PORTE_PLUME','est_actif')) {
+                       $pp = <<<EOF
+cQuery(function() {
+       if (typeof onAjaxLoad == 'function') {
+               function barrebouilles_crayons() {
+                       $('.formulaire_crayon textarea.crayon-active')
+                       .barre_outils('edition');
+               }
+               onAjaxLoad(barrebouilles_crayons);
+       }
+});
+EOF;
+               }
+       }
+
+
+       $incCSS = "<link rel=\"stylesheet\" href=\"{$cssFile}\" type=\"text/css\" media=\"all\" />";
+       $incJS = <<<EOH
+<script type="text/javascript">/* <![CDATA[ */
+var configCrayons;
+function startCrayons() {
+       configCrayons = new cQuery.prototype.cfgCrayons({$config});
+       cQuery.fn.crayonsstart();
+{$pp}
+}
+var cr = document.createElement('script');
+cr.type = 'text/javascript'; cr.async = true;
+cr.src = '{$jsFile}\x26callback=startCrayons';
+var s = document.getElementsByTagName('script')[0];
+s.parentNode.insertBefore(cr, s);
+/* ]]> */</script>
+
+EOH;
+
+       if ($mode == 'head') {
+               //js inline avant les css, sinon ca bloque le chargement
+               $page = $page . $incJS . $incCSS;
+               return $page;
+       }
+
+       $pos_head = strpos($page, '</head>');
+       if ($pos_head === false) {
+               return $page;
+       }
+
+       // js inline avant la premiere css, ou sinon avant la fin du head
+       $pos_link = strpos($page, '<link ');
+       if (!$pos_link) {
+               $pos_link = $pos_head;
+       }
+       $page = substr_replace($page, $incJS, $pos_link, 0);
+
+       // css avant la fin du head
+       $pos_head = strpos($page, '</head>');
+               $page = substr_replace($page, $incCSS, $pos_head, 0);
+
+       return $page;
+}
+
+/**
+ * Balise indiquant un champ SQL crayonnable
+ *
+ * @note
+ *   Si cette fonction est absente, `balise_EDIT_dist()` déclarée par SPIP
+ *   ne retourne rien
+ *
+ * @example
+ *     ```
+ *     <div class="#EDIT{texte}">#TEXTE</div>
+ *     <div class="#EDIT{ps}">#PS</div>
+ *     ```
+ *
+ * @param Champ $p
+ *   Pile au niveau de la balise
+ * @return Champ
+ *   Pile complétée par le code à générer
+**/
+function balise_EDIT($p) {
+
+       // le code compile de ce qui se trouve entre les {} de la balise
+       $label = interprete_argument_balise(1, $p);
+
+       // Verification si l'on est dans le cas d'une meta
+       // #EDIT{meta-descriptif_site} ou #EDIT{meta-demo/truc}
+       if (preg_match('/meta-(.*)\'/', $label, $meta)) {
+               $type = 'meta';
+               $label= 'valeur';
+               $primary = $meta[1];
+               $p->code = "classe_boucle_crayon('"
+                       . $type
+                       ."','"
+                       .$label
+                       ."',"
+                       . "str_replace('/', '__', '$primary')" # chaque / doit être remplacé pour CSS.
+                       .").' '";
+               $p->interdire_scripts = false;
+               return $p;
+       }
+
+       $i_boucle = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
+       // #EDIT hors boucle? ne rien faire
+       if (!isset($p->boucles[$i_boucle]) or !$type = ($p->boucles[$i_boucle]->type_requete)) {
+               $p->code = "''";
+               $p->interdire_scripts = false;
+               return $p;
+       }
+
+       // crayon sur une base distante 'nua__article-intro-5'
+       if ($distant = $p->boucles[$i_boucle]->sql_serveur) {
+               $type = $distant.'__'.$type;
+       }
+
+       // le compilateur 1.9.2 ne calcule pas primary pour les tables secondaires
+       // il peut aussi arriver une table sans primary (par ex: une vue)
+       if (!($primary = $p->boucles[$i_boucle]->primary)) {
+               include_spip('inc/vieilles_defs'); # 1.9.2 pour trouver_def_table
+               if (function_exists('trouver_def_table')) {
+                       list($nom, $desc) = trouver_def_table(
+                               $p->boucles[$i_boucle]->type_requete,
+                               $p->boucles[$i_boucle]
+                       );
+                       $primary = $desc['key']['PRIMARY KEY'];
+               }
+       }
+       // On rajoute ici un debug dans le cas où aucune clé primaire n'est trouvée.
+       // Cela peut se présenter par exemple si on utilise #EDIT{monchamp} directement
+       // dans une boucle CONDITION sans faire référence au nom de la boucle d'au dessus.
+       if (!$primary) {
+               erreur_squelette(_T('crayons:absence_cle_primaire'), $p);
+       }
+
+       $primary = explode(',', $primary);
+       $id = array();
+       foreach ($primary as $key) {
+               $id[] = champ_sql(trim($key), $p);
+       }
+       $primary = implode(".'-'.", $id);
+
+       $p->code = "classe_boucle_crayon('"
+               . $type
+               ."',"
+               .sinon($label, "''")
+               .','
+               . $primary
+               .").' '";
+       $p->interdire_scripts = false;
+       return $p;
+}
+
+/**
+ * Balise indiquant une configuration crayonnable
+ *
+ * @example
+ *     ```
+ *     <div class="#EDIT_CONFIG{descriptif_site}">#DESCRIPTIF_SITE_SPIP</div>
+ *     <div class="#EDIT_CONFIG{demo/truc}">#CONFIG{demo/truc}</div>
+ *     ```
+ *
+ * @param Champ $p
+ *   Pile au niveau de la balise
+ * @return Champ
+ *   Pile complétée par le code à générer
+**/
+function balise_EDIT_CONFIG_dist($p) {
+
+       // le code compile de ce qui se trouve entre les {} de la balise
+       $config = interprete_argument_balise(1, $p);
+       if (!$config) {
+               return $p;
+       }
+
+       // chaque / du nom de config doit être transformé pour css.
+       // nous utiliserons '__' à la place.
+
+       $type = 'meta';
+       $label= 'valeur';
+
+       $p->code = "classe_boucle_crayon('"
+               . $type
+               . "','"
+               . $label
+               . "',"
+               . "str_replace('/', '__', $config)"
+               . ").' '";
+       $p->interdire_scripts = false;
+       return $p;
+}
+
+/**
+ * Crée le controleur du crayon indiqué par la classe CSS
+ *
+ * @param string $class
+ *   Class CSS de crayon tel que créé par #EDIT
+ * @return string
+ *   HTML du crayon, sinon texte d'erreur
+**/
+function creer_le_crayon($class) {
+       include_spip('inc/crayons');
+       include_spip('action/crayons_html');
+       $a = affiche_controleur($class, array('w' => 485, 'h' => 300, 'wh' => 500));
+       return $a['$erreur'] ? $a['$erreur'] : $a['$html'];
+}
+
+/**
+ * Balise `#CRAYON` affichant un formulaire de crayon
+ *
+ * SI `?edit=1;`
+ *
+ * @example
+ *    ```
+ *    #CRAYON{ps}
+ *    ```
+ *
+ * @param Champ $p
+ *   Pile au niveau de la balise
+ * @return Champ
+ *   Pile complétée par le code à générer
+**/
+function balise_CRAYON($p) {
+       $p = balise_EDIT($p);
+       $p->code = 'creer_le_crayon('.$p->code.')';
+       return $p;
+}
+
+
+/**
+ * Donne la classe CSS crayon
+ *
+ * En fonction :
+ * - du type de la boucle
+ *   (attention aux exceptions pour `#EDIT` dans les boucles HIERARCHIE et SITES)
+ * - du champ demande (vide, + ou se terminant par + : (+)classe type--id)
+ * - de l'id courant
+ *
+ * @param string $type
+ *   Type d'objet, ou "meta" pour un champ de configuration
+ * @param string $champ
+ *   Champ SQL concerné
+ * @param int|string $id
+ *   Identifiant de la ligne sql
+ * @return string
+ *   Classes CSS (à ajouter dans le HTML à destination du javascript de Crayons)
+**/
+function classe_boucle_crayon($type, $champ, $id) {
+       // $type = objet_type($type);
+       $type = $type[strlen($type) - 1] == 's' ?
+               substr($type, 0, -1) :
+               str_replace(
+                       array('hierarchie','syndication'),
+                       array('rubrique','site'),
+                       $type
+               );
+
+       $plus = (substr($champ, -1) == '+' and $champ = substr($champ, 0, -1))
+               ? " $type--$id"
+               : '';
+
+       // test rapide pour verifier que l'id est valide (a-zA-Z0-9)
+       if (false !== strpos($id, ' ')) {
+               spip_log("L'identifiant ($id) ne pourra être géré ($type | $champ)", 'crayons');
+               return 'crayon_id_ingerable';
+       }
+
+       return 'crayon ' . $type . '-' . $champ . '-' . $id . $plus;
+}
index 5eba693..db6456c 100644 (file)
@@ -1,85 +1,90 @@
-<?php\r
-/**\r
- * Crayons \r
- * plugin for spip \r
- * (c) Fil, toggg 2006-2013\r
- * licence GPL\r
- */\r
-\r
-if (!defined("_ECRIRE_INC_VERSION")) return;\r
-\r
-## ceci n'est pas l'original mais la copie pour crayons\r
-\r
-// Module de compatibilite pour les plugins qui veulent passer en 1.9.3\r
-// tout en restant compatibles avec 1.9.2 voire 1.9.1 : il permet de faire\r
-// tourner sur ces versions du code prevu pour 1.9.3\r
-\r
-// C'est l'inverse de vieilles_defs (lequel vise a permettre a du code\r
-// fait pour 1.9.2 de tourner sur 1.9.3)\r
-\r
-// Ce module doit etre appele par le plugin ("nouveau code") de la\r
-// maniere suivante :\r
-/*\r
-\r
-// Si SPIP est vieux, charger les fonctions de compat\r
-if ($GLOBALS['spip_version_code'] < '1.93'\r
-AND $f = charger_fonction('compat', 'inc'))\r
-       $f();\r
-\r
-qui charge toutes les defs de compat connues\r
-\r
-ou plus precis :\r
-\r
-// Si SPIP est vieux, charger les fonctions de compat\r
-if ($GLOBALS['spip_version_code'] < '1.93'\r
-AND $f = charger_fonction('compat', 'inc'))\r
-       $f('sql_fetch');\r
-\r
-ou encore :\r
-\r
-// Si SPIP est vieux, charger les fonctions de compat\r
-if ($GLOBALS['spip_version_code'] < '1.93'\r
-AND $f = charger_fonction('compat', 'inc'))\r
-       $f(array('sql_fetch', '_q'));\r
-\r
-\r
-*/\r
-\r
-// En termes de distribution ce fichier PEUT etre recopie dans chaque plugin\r
-// qui desire en avoir une version autonome (voire forkee), A CONDITION DE\r
-// RENOMMER le fichier et ses deux fonctions ; c'est un peu lourd a maintenir\r
-// mais c'est le prix a payer pour l'independance des plugins entre eux :-(\r
-\r
-// la version commune a tous est developpee sur\r
-// svn://zone.spip.org/spip-zone/_dev_/compat/\r
-\r
-\r
-function inc_compat_crayons_dist($quoi = NULL) {\r
-       if (!function_exists($f = 'compat_crayons_defs')) $f .= '_dist';\r
-       $defs = $f();\r
-\r
-       if (is_string($quoi))\r
-               $quoi = array($quoi);\r
-       else if (is_null($quoi))\r
-               $quoi = array_keys($defs);\r
-\r
-       foreach ($quoi as $d) {\r
-               if (!function_exists($d)\r
-               AND isset($defs[$d])) {\r
-                       eval ("function $d".$defs[$d]);\r
-               }\r
-       }\r
-}\r
-\r
-function compat_crayons_defs_dist() {\r
-       $defs = array();\r
-\r
-       // http://trac.rezo.net/trac/spip/changeset/9919\r
-       if ($GLOBALS['spip_version_code'] < '1.9259')\r
-       $defs['sql_fetch'] = '($res, $serveur=\'\') {\r
-               return spip_fetch_array($res);\r
-       }';
-       
+<?php
+/**
+ * Crayons
+ * plugin for spip
+ * (c) Fil, toggg 2006-2013
+ * licence GPL
+ */
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
+
+## ceci n'est pas l'original mais la copie pour crayons
+
+// Module de compatibilite pour les plugins qui veulent passer en 1.9.3
+// tout en restant compatibles avec 1.9.2 voire 1.9.1 : il permet de faire
+// tourner sur ces versions du code prevu pour 1.9.3
+
+// C'est l'inverse de vieilles_defs (lequel vise a permettre a du code
+// fait pour 1.9.2 de tourner sur 1.9.3)
+
+// Ce module doit etre appele par le plugin ("nouveau code") de la
+// maniere suivante :
+/*
+
+// Si SPIP est vieux, charger les fonctions de compat
+if ($GLOBALS['spip_version_code'] < '1.93'
+AND $f = charger_fonction('compat', 'inc'))
+       $f();
+
+qui charge toutes les defs de compat connues
+
+ou plus precis :
+
+// Si SPIP est vieux, charger les fonctions de compat
+if ($GLOBALS['spip_version_code'] < '1.93'
+AND $f = charger_fonction('compat', 'inc'))
+       $f('sql_fetch');
+
+ou encore :
+
+// Si SPIP est vieux, charger les fonctions de compat
+if ($GLOBALS['spip_version_code'] < '1.93'
+AND $f = charger_fonction('compat', 'inc'))
+       $f(array('sql_fetch', '_q'));
+
+
+*/
+
+// En termes de distribution ce fichier PEUT etre recopie dans chaque plugin
+// qui desire en avoir une version autonome (voire forkee), A CONDITION DE
+// RENOMMER le fichier et ses deux fonctions ; c'est un peu lourd a maintenir
+// mais c'est le prix a payer pour l'independance des plugins entre eux :-(
+
+// la version commune a tous est developpee sur
+// svn://zone.spip.org/spip-zone/_dev_/compat/
+
+
+function inc_compat_crayons_dist($quoi = null) {
+       if (!function_exists($f = 'compat_crayons_defs')) {
+               $f .= '_dist';
+       }
+       $defs = $f();
+
+       if (is_string($quoi)) {
+               $quoi = array($quoi);
+       } elseif (is_null($quoi)) {
+               $quoi = array_keys($defs);
+       }
+
+       foreach ($quoi as $d) {
+               if (!function_exists($d) and isset($defs[$d])) {
+                       eval("function $d". $defs[$d]);
+               }
+       }
+}
+
+function compat_crayons_defs_dist() {
+       $defs = array();
+
+       // http://trac.rezo.net/trac/spip/changeset/9919
+       if ($GLOBALS['spip_version_code'] < '1.9259') {
+               $defs['sql_fetch'] = '($res, $serveur=\'\') {
+                       return spip_fetch_array($res);
+               }';
+       }
+
        $defs['table_objet_sql'] = '($type) {
                global $table_des_tables;
                $nom = table_objet($type);
@@ -89,12 +94,10 @@ function compat_crayons_defs_dist() {
                        $nom = \'spip_\' . $t;
                }
                return $nom ;
-       }';\r
-\r
-       // Contourner un bug du plugin CFG\r
-       include_spip('base/abstract_sql');\r
-\r
-       return $defs;\r
-}\r
-\r
-?>\r
+       }';
+
+       // Contourner un bug du plugin CFG
+       include_spip('base/abstract_sql');
+
+       return $defs;
+}
index 5311c5e..93a30b3 100644 (file)
@@ -1,18 +1,20 @@
 <?php
 /**
- * Crayons 
- * plugin for spip 
+ * Crayons
+ * plugin for spip
  * (c) Fil, toggg 2006-2013
  * licence GPL
  */
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 // Les fonctions de toggg pour faire du JSON
 
 /**
  * Transform a variable into its javascript equivalent (recursive)
- * 
+ *
  * @access private
  * @param mixed the variable
  * @return string|boolean
@@ -22,18 +24,18 @@ if (!defined("_ECRIRE_INC_VERSION")) return;
 function crayons_var2js($var) {
        $asso = false;
        switch (true) {
-               case is_null($var) :
+               case is_null($var):
                        return 'null';
-               case is_string($var) :
+               case is_string($var):
                        return '"' .addcslashes($var, "\"\\\n\r\t/") . '"';
-               case is_bool($var) :
+               case is_bool($var):
                        return $var ? 'true' : 'false';
-               case is_scalar($var) :
+               case is_scalar($var):
                        return (string)$var;
-               case is_object( $var) :
+               case is_object($var):
                        $var = get_object_vars($var);
                        $asso = true;
-               case is_array($var) :
+               case is_array($var):
                        $keys = array_keys($var);
                        $ikey = count($keys);
                        while (!$asso && $ikey--) {
@@ -46,14 +48,14 @@ function crayons_var2js($var) {
                                        $ret .= $sep . '"' . $key . '":' . crayons_var2js($elt);
                                        $sep = ',';
                                }
-                               return $ret ."}";
+                               return $ret .'}';
                        } else {
                                $ret = '[';
                                foreach ($var as $elt) {
                                        $ret .= $sep . crayons_var2js($elt);
                                        $sep = ',';
                                }
-                               return $ret ."]";
+                               return $ret .']';
                        }
        }
        return false;
@@ -61,9 +63,9 @@ function crayons_var2js($var) {
 
 // Un json_encode qui marche en iso (la spec JSON exige utf-8)
 function crayons_json_encode($v) {
-       if ($GLOBALS['meta']['charset'] == 'utf-8'
-       AND function_exists('json_encode'))
+       if ($GLOBALS['meta']['charset'] == 'utf-8' and function_exists('json_encode')) {
                return json_encode($v);
+       }
 
        $v = crayons_var2js($v);
 
@@ -89,5 +91,3 @@ function crayons_json_export($var) {
                return $var;
 */
 }
-
-?>
index ed40b6e..7bcf64d 100644 (file)
-<?php\r
-/**\r
- * Crayons \r
- * plugin for spip \r
- * (c) Fil, toggg 2006-2013\r
- * licence GPL\r
- */\r
-\r
-if (!defined("_ECRIRE_INC_VERSION")) return;\r
-\r
-define('_PREG_CRAYON', ',crayon\b[^<>\'"]+?\b((\w+)-(\w+)-(\w+(?:-\w+)*))\b,');\r
-\r
-// Compatibilite pour 1.92 : on a besoin de sql_fetch et table_objet_sql\r
-if ($GLOBALS['spip_version_code'] < '1.93' AND $f = charger_fonction('compat_crayons', 'inc'))\r
-       $f();\r
-\r
-// Autoriser les crayons sur les tables non SPIP ?\r
-// Par defaut : oui (pour les admins complets, si autoriser_defaut_dist()) ;\r
-// mettre a false en cas de mutualisation par prefixe de table,\r
-// sinon on ne peut pas garantir que les sites sont hermetiques\r
-if(!defined('_CRAYONS_TABLES_EXTERNES'))\r
-       define('_CRAYONS_TABLES_EXTERNES', true);\r
-\r
-// Autorisations non prevues par le core\r
-include_spip('inc/autoriser');\r
-\r
-include_spip('inc/crayons-json');\r
-\r
-if (!function_exists('autoriser_meta_modifier_dist')) {\r
-/**\r
- * Autorisation d'éditer les configurations dans spip_meta\r
- *\r
- * Les admins complets OK pour certains champs,\r
- * Sinon, il faut être webmestre\r
- *\r
- * @note\r
- *  Attention sur les SPIP < 11515 (avant 04/2008) inc/autoriser\r
- *  passe seulement intval($id) alors qu'ici la cle est une chaine...\r
- *\r
- * @param  string $faire Action demandée\r
- * @param  string $type  Type d'objet sur lequel appliquer l'action\r
- * @param  int    $id    Identifiant de l'objet\r
- * @param  array  $qui   Description de l'auteur demandant l'autorisation\r
- * @param  array  $opt   Options de cette autorisation\r
- * @return bool          true s'il a le droit, false sinon\r
-**/\r
-function autoriser_meta_modifier_dist($faire, $type, $id, $qui, $opt) {\r
-       // Certaines cles de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc})\r
-       // $id = str_replace('__', '/', $id);\r
-       if (in_array("$id", array(\r
-               'nom_site', 'slogan_site', 'descriptif_site', 'email_webmaster'\r
-       )))\r
-               return autoriser('configurer', null, null, $qui);\r
-       else\r
-               return autoriser('webmestre', null, null, $qui);\r
-}\r
-}\r
-\r
-// table spip_messages, la c'est tout simplement non (peut mieux faire,\r
-// mais c'est a voir dans le core/organiseur ou dans autorite)\r
-if (defined('_DIR_PLUGIN_ORGANISEUR'))\r
-       include_spip('organiseur_autoriser');\r
-if (!function_exists('autoriser_message_modifier_dist')) {\r
-       function autoriser_message_modifier_dist($faire, $type, $id, $qui, $opt) {\r
-               return false;\r
-       }\r
-}\r
-//compat 192 documents\r
-if ($GLOBALS['spip_version_code'] < '1.93'){\r
-       if (!function_exists('get_spip_doc')){\r
-               function get_spip_doc($fichier) {\r
-                       // fichier distant\r
-                       if (preg_match(',^\w+://,', $fichier))\r
-                                       return $fichier;\r
-\r
-                       // gestion d'erreurs, fichier=''\r
-                       if (!strlen($fichier))\r
-                                       return false;\r
-\r
-                       // fichier normal\r
-                       return (strpos($fichier, _DIR_IMG) === false)\r
-                       ? _DIR_IMG . $fichier\r
-                       : $fichier;\r
-               }\r
-       }\r
-}\r
-\r
-// Autoriser l'usage des crayons ?\r
-function autoriser_crayonner_dist($faire, $type, $id, $qui, $opt) {\r
-       // Le type pouvant etre une table, verifier les autoriser('modifier')\r
-       // correspondant ; ils demandent le nom de l'objet: spip_articles => article\r
-       // ex: spip_articles => 'article'\r
-       $type = preg_replace(',^spip_(.*?)s?$,', '\1', $type);\r
-       if (strlen($GLOBALS['table_prefix']))\r
-               $type = preg_replace(',^'.$GLOBALS['table_prefix'].'_(.*?)s?$,', '\1', $type);\r
-\r
-       // Tables non SPIP ? Si elles sont interdites il faut regarder\r
-       // quelle table on appelle, et verifier si elle est "interne"\r
-       if (!_CRAYONS_TABLES_EXTERNES) {\r
-               include_spip('base/serial');\r
-               include_spip('base/auxiliaires');\r
-               include_spip('public/parametrer');\r
-               if (!isset($GLOBALS['tables_principales']['spip_'.table_objet($type)])\r
-               AND !isset($GLOBALS['tables_auxiliaires']['spip_'.table_objet($type)]))\r
-                       return false;\r
-       }\r
-\r
-       // Traduire le modele en liste de champs\r
-       if (isset($opt['modele']))\r
-               $opt['champ'] = $opt['modele'];\r
-\r
-       // Pour un auteur, si le champ est statut ou email, signaler l'option\r
-       // ad hoc (cf. inc/autoriser)\r
-       if ($type == 'auteur'\r
-       AND in_array($opt['champ'], array('statut', 'email')))\r
-               $opt[$opt['champ']] = true;\r
-\r
-       return (\r
-                autoriser('modifier', $type, $id, $qui, $opt)\r
-       );\r
-}\r
-\r
-// Si un logo est demande, on renvoie la date dudit logo (permettra de gerer\r
-// un "modifie par ailleurs" si la date a change, rien de plus)\r
-function valeur_champ_logo($table, $id, $champ) {\r
-       $chercher_logo = charger_fonction('chercher_logo', 'inc');\r
-       $on = $chercher_logo($id, id_table_objet($table), 'on');\r
-       return $on ? filemtime($on[0]) : false;\r
-}\r
-\r
-// Idem : si un doc est demande, on renvoie la date du doc\r
-function valeur_champ_document($table, $id, $champ) {\r
-       $s = spip_query("SELECT date FROM spip_documents WHERE id_document="._q($id));\r
-       if ($t = sql_fetch($s))\r
-               return $t['date'];\r
-}\r
-\r
-function valeur_champ_vignette($table, $id, $champ) {\r
-       $vignette = sql_getfetsel('id_vignette','spip_documents','id_document='.intval($id));\r
-       if(is_numeric($vignette) && ($vignette > 0)){\r
-               $date = sql_getfetsel('date','spip_documents','id_document='.intval($vignette));\r
-       }\r
-       return $date ? $date : false;\r
-}\r
-// cette fonction de revision recoit le fichier upload a passer en logo\r
-// en reference : le nom du widget, pour aller chercher d'autres donnees\r
-// (ex: supprimer)\r
-function logo_revision($id, $file, $type, $ref) {\r
-       $chercher_logo = charger_fonction('chercher_logo', 'inc');\r
-       $_id_objet = id_table_objet($type);\r
-\r
-       // Chargement d'un nouveau logo ?\r
-       if ($file['logo']) {\r
-               define('FILE_UPLOAD', true); // message pour crayons_json_export :(\r
-\r
-               // supprimer l'ancien logo\r
-               $on = $chercher_logo($id, $_id_objet, 'on');\r
-               if ($on) @unlink($on[0]);\r
-\r
-               // ajouter le nouveau\r
-               include_spip('action/iconifier');\r
-               action_spip_image_ajouter_dist(\r
-                       type_du_logo($_id_objet).'on'.$id, false, false\r
-               ); // beurk\r
-       }\r
-\r
-       else\r
-\r
-       // Suppression du logo ?\r
-       if ($wid = array_pop($ref)\r
-       AND $_POST['content_'.$wid.'_logo_supprimer'] == 'on') {\r
-               if ($on = $chercher_logo($id, $_id_objet, 'on'))\r
-                       @unlink($on[0]);\r
-       }\r
-\r
-       // Reduire le logo ?\r
-       if (is_array($cfg = @unserialize($GLOBALS['meta']['crayons']))\r
-       AND $max = intval($cfg['reduire_logo'])) {\r
-               $on = $chercher_logo($id, $_id_objet, 'on');\r
-               include_spip('inc/filtres');\r
-               @copy($on[0], $temp = _DIR_VAR.'tmp'.rand(0,999).'.'.$on[3]);\r
-               $img1 = filtrer('image_reduire', $temp, $max);\r
-               $img2 = preg_replace(',[?].*,', '', extraire_attribut($img1, 'src'));\r
-               if (@file_exists($img2)\r
-               AND $img2 !=  $temp) {\r
-                       @unlink($on[0]);\r
-                       $dest = $on[1].$on[2].'.'\r
-                               .preg_replace(',^.*\.(gif|jpg|png)$,', '\1', $img2);\r
-                       @rename($img2,$dest);\r
-               }\r
-               @unlink($temp);\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-\r
-// cette fonction de revision recoit le fichier upload a passer en document\r
-function document_fichier_revision($id, $data, $type, $ref) {\r
-\r
-       $s = spip_query("SELECT * FROM spip_documents WHERE id_document=".intval($id));\r
-       if (!$t = sql_fetch($s))\r
-               return false;\r
-\r
-       /*\r
-       // Envoi d'une URL de document distant ?\r
-       // TODO: verifier l'extension distante, sinon tout explose\r
-       if ($data['fichier']\r
-       AND preg_match(',^(https?|ftp)://.+,', $data['fichier'])) {\r
-               include_spip('inc/modifier');\r
-               modifier_contenu('document', $id,\r
-                       array('champs' => array('fichier', 'distant')),\r
-                       array('fichier' => $data['fichier'], 'distant' => 'oui')\r
-               );\r
-               return true;\r
-       }\r
-       else\r
-       */\r
-\r
-       // Chargement d'un nouveau doc ?\r
-       if ($data['document']) {\r
-\r
-               $arg = $data['document'];\r
-               \r
-               /** \r
-                * Méthode >= SPIP 3.0 \r
-                * ou SPIP 2.x + Mediathèque\r
-                */ \r
-               if($ajouter_documents = charger_fonction('ajouter_documents','action',true)){ \r
-                       $actifs = $ajouter_documents($id,array($arg),'', 0,$t['mode']);\r
-                       $x = reset($actifs);\r
-                       if(is_numeric($x))\r
-                               return true;\r
-                       else\r
-                               return false;\r
-               }\r
-               /**\r
-                * Méthode SPIP < 3.0\r
-                */\r
-               else if($ajouter_documents = charger_fonction('ajouter_documents','inc',true)){ \r
-                       check_upload_error($arg['error']);\r
-                       $x = $ajouter_documents($arg['tmp_name'], $arg['name'],\r
-                                       'article', 0, 'document', null, $actifs);\r
-                       // $actifs contient l'id_document nouvellement cree\r
-                       // on recopie les donnees interessantes dans l'ancien\r
-                       $extension=", extension ";\r
-                       //compat 192\r
-                       if ($GLOBALS['spip_version_code'] < '1.93')\r
-                               $extension="";\r
-\r
-                       if ($id_new = array_pop($actifs)\r
-                       AND $s = spip_query("SELECT fichier, taille, largeur, hauteur $extension, distant FROM spip_documents\r
-                               WHERE id_document="._q($id_new))\r
-                       AND $new = sql_fetch($s)) {\r
-                               define('FILE_UPLOAD', true); // message pour crayons_json_export :(\r
-\r
-                               // Une vignette doit rester une image\r
-                               if ($t['mode'] == 'vignette'\r
-                               AND !in_array($new['extension'], array('jpg', 'gif', 'png')))\r
-                                       return false;\r
-\r
-                               // Maintenant on est bon, on recopie les nouvelles donnees\r
-                               // dans l'ancienne ligne spip_documents\r
-                               include_spip('inc/modifier');\r
-                               modifier_contenu('document', $id,\r
-                                       # 'champs' inutile a partir de SPIP 11348\r
-                                       array('champs' => array_keys($new)),\r
-                                       $new);\r
-\r
-                               // supprimer l'ancien document (sauf s'il etait distant)\r
-                               if ($t['distant'] != 'oui'\r
-                               AND file_exists(get_spip_doc($t['fichier'])))\r
-                                       supprimer_fichier(get_spip_doc($t['fichier']));\r
-\r
-                               // Effacer la ligne temporaire de spip_document\r
-                               spip_query("DELETE FROM spip_documents WHERE id_document="._q($id_new));\r
-\r
-                               // oublier id_document temporaire (ca marche chez moi, sinon bof)\r
-                               spip_query("ALTER TABLE spip_documents AUTO_INCREMENT="._q($id_new));\r
-\r
-                               return true;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-// cette fonction de revision soit supprime la vignette d'un document,\r
-// soit recoit le fichier upload a passer ou remplacer la vignette du document\r
-function vignette_revision($id, $data, $type, $ref) {\r
-       $s = sql_fetsel("id_document,id_vignette","spip_documents","id_document=".intval($id));\r
-       if (!is_array($s))\r
-               return false;\r
-\r
-       include_spip('inc/modifier');\r
-       include_spip('inc/documents');\r
-       include_spip('action/editer_document');//pour revision_document\r
-       // Chargement d'un nouveau doc ?\r
-       if ($data['vignette']) {\r
-               define('FILE_UPLOAD', true);\r
-               if(is_numeric($s['id_vignette']) && ($s['id_vignette']>0)){\r
-                       spip_log('suppression de la vignette');\r
-                       // Suppression du document\r
-                       $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette']));\r
-                       if (@file_exists($f = get_spip_doc($vignette))) { \r
-                               spip_log("efface $f"); \r
-                               supprimer_fichier($f); \r
-                       }\r
-                       sql_delete('spip_documents', 'id_document='.intval($s['id_vignette']));\r
-                       sql_delete('spip_documents_liens', 'id_document='.intval($s['id_vignette']));\r
-\r
-                       pipeline('post_edition',\r
-                               array(\r
-                                       'args' => array(\r
-                                               'operation' => 'supprimer_document',\r
-                                               'table' => 'spip_documents',\r
-                                               'id_objet' => $s['id_vignette']\r
-                                       ),\r
-                                       'data' => null\r
-                               )\r
-                       );\r
-                       $id_vignette = 0;\r
-               }\r
-\r
-               $arg = $data['vignette'];\r
-               check_upload_error($arg['error']);\r
-               // Ajout du document comme vignette\r
-\r
-               /**\r
-                * Méthode >= SPIP 3.0 \r
-                * ou SPIP 2.x + Mediatheque\r
-                */\r
-               if($ajouter_documents = charger_fonction('ajouter_documents','action',true)){\r
-                       $x = $ajouter_documents(null,array($arg),'', 0, 'vignette');\r
-                       $vignette = reset($x);\r
-                       if(intval($vignette))\r
-                               document_modifier($id, array('id_vignette'=>$vignette));\r
-                       else if($id_vignette)\r
-                               document_modifier($id, array('id_vignette'=>$id_vignette));\r
-               }\r
-               /**\r
-                * Méthode < SPIP 3.0\r
-                */\r
-               else if($ajouter_documents = charger_fonction('ajouter_documents','inc',true)){\r
-                       // On remet l'id_vignette a 0 si on l'a supprimé\r
-                       if($id_vignette) revision_document($s['id_document'], array('id_vignette'=>0));\r
-                       $x = $ajouter_documents($arg['tmp_name'], $arg['name'],'','', 'vignette', $id, $actifs);\r
-               }\r
-               \r
-       }else\r
-               // Suppression de la vignette ?\r
-               if ($wid = array_pop($ref)\r
-                       AND $_POST['content_'.$wid.'_vignette_supprimer'] == 'on') {\r
-                       if(is_numeric($s['id_vignette']) && ($s['id_vignette']>0)){\r
-                               // Suppression du document\r
-                               $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette']));\r
-                               if (@file_exists($f = get_spip_doc($vignette))) { \r
-                                       spip_log("efface $f"); \r
-                                       supprimer_fichier($f); \r
-                               }\r
-                               sql_delete('spip_documents', 'id_document='.intval($s['id_vignette']));\r
-                               sql_delete('spip_documents_liens',  'id_document='.intval($s['id_vignette']));\r
-\r
-                               pipeline('post_edition',\r
-                                       array(\r
-                                               'args' => array(\r
-                                                       'operation' => 'supprimer_document',\r
-                                                       'table' => 'spip_documents',\r
-                                                       'id_objet' => $s['id_vignette']\r
-                                               ),\r
-                                               'data' => null\r
-                                       )\r
-                               );\r
-\r
-                               // On remet l'id_vignette a 0\r
-                               revision_document($s['id_document'], array('id_vignette'=>0));\r
-                       }\r
-               }\r
-       return true;\r
-}\r
-\r
-\r
-function colonne_table($type, $col) {\r
-       list($distant,$table) = distant_table($type);\r
-       $nom_table = '';\r
-       if (!(($tabref = &crayons_get_table($table, $nom_table))\r
-               && isset($tabref['field'][$col])\r
-               && ($brut = $tabref['field'][$col]))) {\r
-                       return false;\r
-       }\r
-       $ana = explode(' ', $brut);\r
-       $sta = 0;\r
-       $sep = '';\r
-       $ret = array('brut' => $brut,\r
-               'type' => '', 'notnull' => false, 'long' => 0, 'def' => '');\r
-       foreach ($ana as $mot) {\r
-               switch ($sta) {\r
-                       case 0: $ret['type'] = ($mot = strtolower($mot));\r
-                       case 1: if ($mot[strlen($mot) - 1] == ')') {\r
-                                       $pos = strpos($mot, '(');\r
-                                       $ret['type'] = strtolower(substr($mot, 0, $pos++));\r
-                                       $vir = explode(',', substr($mot, $pos, -1));\r
-                                       if ($ret['type'] == 'enum') {\r
-                                               $ret['enum'] = $vir;\r
-                                       } elseif (count($vir) > 1) {\r
-                                               $ret['long'] = $vir;\r
-                                       } else {\r
-                                               $ret['long'] = $vir[0];\r
-                                       }\r
-                                       $sta = 1;\r
-                                       continue;\r
-                               }\r
-                               if (!$sta) {\r
-                                       $sta = 1;\r
-                                       continue;\r
-                               }\r
-                       case 2: switch (strtolower($mot)) {\r
-                               case 'not':\r
-                                       $sta = 3;\r
-                                       continue;\r
-                               case 'default':\r
-                                       $sta = 4;\r
-                                       continue;\r
-                               }\r
-                               continue;\r
-                       case 3:         $ret['notnull'] = strtolower($mot) == 'null';\r
-                               $sta = 2;\r
-                               continue;\r
-                       case 4: $df1 = strpos('"\'', $mot[0]) !== false? $mot[0] : '';\r
-                               $sta = 5;\r
-                       case 5: $ret['def'] .= $sep . $mot;\r
-                               if (!$df1) {\r
-                                       $sta = 2;\r
-                                       continue;\r
-                               }\r
-                               if ($df1 == $mot[strlen($mot) - 1]) {\r
-                                       $ret['def'] = substr($ret['def'], 1, -1);\r
-                                       $sta = 2;\r
-                               }\r
-                               $sep = ' ';\r
-                               continue;\r
-               }\r
-       }\r
-       return $ret;\r
-}\r
-\r
-\r
-/**\r
- * Obtient le nom de la table ainsi que sa ou ses clés primaires\r
- *\r
- * @param string $type\r
- *     Table sur laquelle s'applique le crayon.\r
- *     Ce type peut contenir le nom d'un connecteur distant tel que `{connect}__{table}`\r
- *\r
- * @return array|bool\r
- *     - false si on ne trouve pas de table ou de table ayant de clé primaire\r
- *     - liste :\r
- *     - - nom de la table sql\r
- *     - - tableau des noms de clés primaires\r
-**/\r
-function crayons_get_table_name_and_primary($type) {\r
-       static $types = array();\r
-       if (isset($types[$type])) {\r
-               return $types[$type];\r
-       }\r
-\r
-       $nom_table = '';\r
-       if ($tabref = &crayons_get_table($type, $nom_table)\r
-         and ($tabid = explode(',', $tabref['key']['PRIMARY KEY'])))\r
-       {\r
-               return $types[$type] = array($nom_table, $tabid);\r
-       }\r
-       spip_log('crayons: table ' . $type . ' inconnue');\r
-       return $types[$type] = false;\r
-}\r
-\r
-\r
-function table_where($type, $id, $where_en_tableau = false) {\r
-\r
-\r
-       if (!$infos = crayons_get_table_name_and_primary($type)) {\r
-               return array(false, false);\r
-       }\r
-\r
-       list($nom_table, $tabid) = $infos;\r
-\r
-\r
-       if (is_scalar($id))\r
-               $id = explode('-', $id);\r
-       // sortie tableau pour sql_updateq\r
-       if ($where_en_tableau) {\r
-               $where = array();\r
-               foreach ($id as $idcol => $idval) {\r
-                       $where[] = '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . sql_quote($idval);\r
-               }\r
-       // sinon sortie texte pour sql_query\r
-       } else {\r
-\r
-               $where = $and = '';\r
-               foreach ($id as $idcol => $idval) {\r
-                       $where .= $and . '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . _q($idval);\r
-                       $and = ' AND ';\r
-               }\r
-       }\r
-       return array($nom_table, $where);\r
-}\r
-//     var_dump(colonne_table('forum', 'id_syndic')); die();\r
-\r
-function valeur_colonne_table_dist($type, $col, $id) {\r
-\r
-       // Table introuvable ou sans clé primaire\r
-       if (!$infos = crayons_get_table_name_and_primary($type)) {\r
-               return false;\r
-       }\r
-       $table = reset($infos);\r
-\r
-       $r = array();\r
-\r
-       // valeurs non SQL\r
-       foreach ($col as $champ) {\r
-               if (function_exists($f = 'valeur_champ_'.$table.'_'.$champ) OR function_exists($f = 'valeur_champ_'.$champ)) {\r
-                       $r[$champ] = $f($table, $id, $champ);\r
-                       $col = array_diff($col, array($champ));\r
-               }\r
-       }\r
-\r
-       // valeurs SQL\r
-       if (count($col)) {\r
-               list($distant, $table)   = distant_table($type);\r
-               list($nom_table, $where) = table_where($type, $id);\r
-\r
-               if ($s = spip_query(\r
-                               'SELECT `' . implode($col, '`, `') .\r
-                               '` FROM ' . $nom_table . ' WHERE ' . $where, $distant)\r
-                       AND $t = sql_fetch($s)){\r
-                               $r = array_merge($r, $t);\r
-               }\r
-       }\r
-\r
-       return $r;\r
-}\r
-\r
-/**\r
- * Extrait la valeur d'une ou plusieurs colonnes d'une table\r
- *\r
- * @param string $table\r
- *   Type d'objet de la table (article)\r
- * @param string|array $col\r
- *   Nom de la ou des colonnes (ps)\r
- * @param string $id\r
- *   Identifiant de l'objet\r
- * @return array\r
- *   Couples Nom de la colonne => Contenu de la colonne\r
-**/\r
-function valeur_colonne_table($table, $col, $id) {\r
-       if (!is_array($col))\r
-               $col = array($col);\r
-\r
-       if (function_exists($f = $table.'_valeur_colonne_table_dist')\r
-       OR function_exists($f = $table.'_valeur_colonne_table')\r
-       OR $f = 'valeur_colonne_table_dist')\r
-               return $f($table, $col, $id);\r
-}\r
-\r
-/**\r
- * Extrait la valeur d'une configuration en meta\r
- *\r
- * Pour ces données, il n'y a toujours qu'une colonne (valeur),\r
- * mais on gère l'enregistrement et la lecture via lire_config ou ecrire_config\r
- * dès que l'on demande des sous parties d'une configuration.\r
- *\r
- * On ne retourne alors ici dans 'valeur' que la sous-partie demandée si\r
- * c'est le cas.\r
- *\r
- * @param string $table\r
- *   Nom de la table (meta)\r
- * @param array $col\r
- *   Nom des colonnes (valeur)\r
- * @param string $id\r
- *   Nom ou clé de configuration (descriptif_site ou demo__truc pour demo/truc)\r
- * @return array\r
- *   Couple valeur => Contenu de la configuration\r
-**/\r
-function meta_valeur_colonne_table_dist($table, $col, $id) {\r
-       // Certaines clés de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc})\r
-       $id = str_replace('__', '/', $id);\r
-\r
-       // Éviter de planter les vieux SPIP\r
-       if (false === strpos($id, '/')) {\r
-               $config = isset($GLOBALS['meta'][$id]) ? $GLOBALS['meta'][$id] : '';\r
-       // SPIP 3 ou Bonux 2 ou CFG\r
-       } else {\r
-               include_spip('inc/config');\r
-               $config =  lire_config($id, '');\r
-       }\r
-       return array('valeur' => $config);\r
-}\r
-\r
-\r
-function return_log($var) {\r
-       die(crayons_json_export(array('$erreur'=> var_export($var,true))));\r
-}\r
-\r
-function _U($texte, $params=array()) {\r
-       include_spip('inc/charsets');\r
-       return unicode2charset(html2unicode(_T($texte, $params)));\r
-}\r
-\r
-/**\r
- * Obtenir la configuration des crayons\r
- *\r
- * @note wdgcfg = widget config :-)\r
- * \r
- * @return array\r
- *     Couples : attribut => valeur\r
-**/\r
-function wdgcfg() {\r
-       $php = function_exists('crayons_config') ? crayons_config() : array();\r
-       include_spip('inc/meta');\r
-       lire_metas();\r
-       global $meta;\r
-       $metacrayons = empty($meta['crayons']) ? array() : unserialize($meta['crayons']);\r
-       $wdgcfg = array();\r
-       foreach (array(\r
-               'msgNoChange' => false,\r
-               'msgAbandon' => false,  /* etait: true */\r
-               'filet' => false,\r
-               'yellow_fade' => false,\r
-               'clickhide' => false /* etait: true */\r
-       )\r
-       as $cfgi => $def) {\r
-               $wdgcfg[$cfgi] = isset($php[$cfgi]) ? $php[$cfgi] :\r
-                       isset($metacrayons[$cfgi]) ? $metacrayons[$cfgi] : $def;\r
-       }\r
-       return $wdgcfg;\r
-}\r
-\r
-function &crayons_get_table($type, &$nom_table) {\r
-       list($distant,$table) = distant_table($type);\r
-       static $return = array();\r
-       static $noms = array();\r
-       if (!isset($return[$table])) {\r
-               $try = array(table_objet_sql($table), 'spip_'.table_objet($table), 'spip_' . $table . 's', $table . 's', 'spip_' . $table, $table);\r
-\r
-               // premiere possibilite (à partir de 1.9.3) : regarder directement la base\r
-               if (function_exists('sql_showtable')) {\r
-                       foreach ($try as $nom) {\r
-                               if ($q = sql_showtable($nom , !$distant , $distant)) {\r
-                                       $noms[$table] = $nom;\r
-                                       $return[$table] = $q;\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               // seconde, une heuristique 1.9.2\r
-               if (!isset($return[$table])) {\r
-                       include_spip('base/serial');\r
-                       include_spip('base/auxiliaires');\r
-                       include_spip('public/parametrer');\r
-                       foreach(array('tables_principales', 'tables_auxiliaires') as $categ) {\r
-                               foreach ($try as $nom) {\r
-                                       if (isset($GLOBALS[$categ][$nom])) {\r
-                                               $noms[$table] = $nom;\r
-                                               $return[$table] = & $GLOBALS[$categ][$nom];\r
-                                               break 2;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       $nom_table = $noms[$table];\r
-       return $return[$table];\r
-}\r
-\r
-function distant_table($type) {\r
-       //separation $type en $distant $table\r
-       //separateur double underscore "__"\r
-       strstr($type,'__')? list($distant,$table) = explode('__',$type) : list($distant,$table) = array(False,$type);\r
-       return array($distant,$table);\r
-}\r
-?>\r
+<?php
+/**
+ * Crayons
+ * plugin for spip
+ * (c) Fil, toggg 2006-2013
+ * licence GPL
+ */
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
+
+define('_PREG_CRAYON', ',crayon\b[^<>\'"]+?\b((\w+)-(\w+)-(\w+(?:-\w+)*))\b,');
+
+// Compatibilite pour 1.92 : on a besoin de sql_fetch et table_objet_sql
+if ($GLOBALS['spip_version_code'] < '1.93' and $f = charger_fonction('compat_crayons', 'inc')) {
+       $f();
+}
+
+// Autoriser les crayons sur les tables non SPIP ?
+// Par defaut : oui (pour les admins complets, si autoriser_defaut_dist()) ;
+// mettre a false en cas de mutualisation par prefixe de table,
+// sinon on ne peut pas garantir que les sites sont hermetiques
+if (!defined('_CRAYONS_TABLES_EXTERNES')) {
+       define('_CRAYONS_TABLES_EXTERNES', true);
+}
+
+// Autorisations non prevues par le core
+include_spip('inc/autoriser');
+
+include_spip('inc/crayons-json');
+
+if (!function_exists('autoriser_meta_modifier_dist')) {
+/**
+ * Autorisation d'éditer les configurations dans spip_meta
+ *
+ * Les admins complets OK pour certains champs,
+ * Sinon, il faut être webmestre
+ *
+ * @note
+ *  Attention sur les SPIP < 11515 (avant 04/2008) inc/autoriser
+ *  passe seulement intval($id) alors qu'ici la cle est une chaine...
+ *
+ * @param  string $faire Action demandée
+ * @param  string $type  Type d'objet sur lequel appliquer l'action
+ * @param  int    $id    Identifiant de l'objet
+ * @param  array  $qui   Description de l'auteur demandant l'autorisation
+ * @param  array  $opt   Options de cette autorisation
+ * @return bool          true s'il a le droit, false sinon
+**/
+function autoriser_meta_modifier_dist($faire, $type, $id, $qui, $opt) {
+       // Certaines cles de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc})
+       // $id = str_replace('__', '/', $id);
+       if (in_array($id, array('nom_site', 'slogan_site', 'descriptif_site', 'email_webmaster'))) {
+               return autoriser('configurer', null, null, $qui);
+       } else {
+               return autoriser('webmestre', null, null, $qui);
+       }
+}
+}
+
+// table spip_messages, la c'est tout simplement non (peut mieux faire,
+// mais c'est a voir dans le core/organiseur ou dans autorite)
+if (defined('_DIR_PLUGIN_ORGANISEUR')) {
+       include_spip('organiseur_autoriser');
+}
+
+if (!function_exists('autoriser_message_modifier_dist')) {
+       function autoriser_message_modifier_dist($faire, $type, $id, $qui, $opt) {
+               return false;
+       }
+}
+//compat 192 documents
+if ($GLOBALS['spip_version_code'] < '1.93') {
+       if (!function_exists('get_spip_doc')) {
+               function get_spip_doc($fichier) {
+                       // fichier distant
+                       if (preg_match(',^\w+://,', $fichier)) {
+                               return $fichier;
+                       }
+                       // gestion d'erreurs, fichier=''
+                       if (!strlen($fichier)) {
+                               return false;
+                       }
+
+                       // fichier normal
+                       return (strpos($fichier, _DIR_IMG) === false) ? _DIR_IMG . $fichier : $fichier;
+               }
+       }
+}
+
+// Autoriser l'usage des crayons ?
+function autoriser_crayonner_dist($faire, $type, $id, $qui, $opt) {
+       // Le type pouvant etre une table, verifier les autoriser('modifier')
+       // correspondant ; ils demandent le nom de l'objet: spip_articles => article
+       // ex: spip_articles => 'article'
+       $type = preg_replace(',^spip_(.*?)s?$,', '\1', $type);
+       if (strlen($GLOBALS['table_prefix'])) {
+               $type = preg_replace(',^'.$GLOBALS['table_prefix'].'_(.*?)s?$,', '\1', $type);
+       }
+
+       // Tables non SPIP ? Si elles sont interdites il faut regarder
+       // quelle table on appelle, et verifier si elle est "interne"
+       if (!_CRAYONS_TABLES_EXTERNES) {
+               include_spip('base/serial');
+               include_spip('base/auxiliaires');
+               include_spip('public/parametrer');
+               if (!isset($GLOBALS['tables_principales']['spip_'.table_objet($type)])
+                       and !isset($GLOBALS['tables_auxiliaires']['spip_'.table_objet($type)])) {
+                       return false;
+               }
+       }
+
+       // Traduire le modele en liste de champs
+       if (isset($opt['modele'])) {
+               $opt['champ'] = $opt['modele'];
+       }
+
+       // Pour un auteur, si le champ est statut ou email, signaler l'option
+       // ad hoc (cf. inc/autoriser)
+       if ($type == 'auteur'
+               and in_array($opt['champ'], array('statut', 'email'))) {
+               $opt[$opt['champ']] = true;
+       }
+
+       return (
+                autoriser('modifier', $type, $id, $qui, $opt)
+       );
+}
+
+// Si un logo est demande, on renvoie la date dudit logo (permettra de gerer
+// un "modifie par ailleurs" si la date a change, rien de plus)
+function valeur_champ_logo($table, $id, $champ) {
+       $chercher_logo = charger_fonction('chercher_logo', 'inc');
+       $on = $chercher_logo($id, id_table_objet($table), 'on');
+       return $on ? filemtime($on[0]) : false;
+}
+
+// Idem : si un doc est demande, on renvoie la date du doc
+function valeur_champ_document($table, $id, $champ) {
+       $s = spip_query('SELECT date FROM spip_documents WHERE id_document=' . _q($id));
+       if ($t = sql_fetch($s)) {
+               return $t['date'];
+       }
+}
+
+function valeur_champ_vignette($table, $id, $champ) {
+       $vignette = sql_getfetsel('id_vignette', 'spip_documents', 'id_document=' . intval($id));
+       if (is_numeric($vignette) && ($vignette > 0)) {
+               $date = sql_getfetsel('date', 'spip_documents', 'id_document=' . intval($vignette));
+       }
+       return $date ? $date : false;
+}
+// cette fonction de revision recoit le fichier upload a passer en logo
+// en reference : le nom du widget, pour aller chercher d'autres donnees
+// (ex: supprimer)
+function logo_revision($id, $file, $type, $ref) {
+       $chercher_logo = charger_fonction('chercher_logo', 'inc');
+       $_id_objet = id_table_objet($type);
+
+       // Chargement d'un nouveau logo ?
+       if ($file['logo']) {
+               define('FILE_UPLOAD', true); // message pour crayons_json_export :(
+
+               if (include_spip('action/editer_logo')
+                       and function_exists('logo_modifier')) {
+                       logo_modifier($type, $id, 'on', $file['logo']);
+               } else {
+                       // compat SPIP < 3.1
+                       // supprimer l'ancien logo
+                       $on = $chercher_logo($id, $_id_objet, 'on');
+                       if ($on) {
+                               @unlink($on[0]);
+                       }
+
+                       // ajouter le nouveau
+                       include_spip('action/iconifier');
+                       action_spip_image_ajouter_dist(type_du_logo($_id_objet) . 'on' . $id, false, false); // beurk
+               }
+       } else {
+               // Suppression du logo ?
+               if ($wid = array_pop($ref)
+                       and $_POST['content_'.$wid.'_logo_supprimer'] == 'on') {
+                       if (include_spip('action/editer_logo')
+                               and function_exists('logo_supprimer')) {
+                               logo_supprimer($type, $id, 'on');
+                       } else {
+                               if ($on = $chercher_logo($id, $_id_objet, 'on')) {
+                                       @unlink($on[0]);
+                               }
+                       }
+               }
+       }
+
+       // Reduire le logo ?
+       if (is_array($cfg = @unserialize($GLOBALS['meta']['crayons']))
+               and $max = intval($cfg['reduire_logo'])) {
+               $on = $chercher_logo($id, $_id_objet, 'on');
+               include_spip('inc/filtres');
+               @copy($on[0], $temp = _DIR_VAR . 'tmp' . rand(0, 999) . '.' . $on[3]);
+               $img1 = filtrer('image_reduire', $temp, $max);
+               $img2 = preg_replace(',[?].*,', '', extraire_attribut($img1, 'src'));
+               if (@file_exists($img2)
+                       and $img2 !=  $temp) {
+                       if (include_spip('action/editer_logo')
+                               and function_exists('logo_modifier')) {
+                               logo_modifier($type, $id, 'on', $img2);
+                       } else {
+                               @unlink($on[0]);
+                               $dest = $on[1].$on[2].'.'
+                                       .preg_replace(',^.*\.(gif|jpg|png)$,', '\1', $img2);
+                               @rename($img2, $dest);
+                       }
+               }
+               @unlink($temp);
+       }
+
+       return true;
+}
+
+
+// cette fonction de revision recoit le fichier upload a passer en document
+function document_fichier_revision($id, $data, $type, $ref) {
+
+       $s = spip_query('SELECT * FROM spip_documents WHERE id_document=' . intval($id));
+       if (!$t = sql_fetch($s)) {
+               return false;
+       }
+
+       /*
+       // Envoi d'une URL de document distant ?
+       // TODO: verifier l'extension distante, sinon tout explose
+       if ($data['fichier']
+       AND preg_match(',^(https?|ftp)://.+,', $data['fichier'])) {
+               include_spip('inc/modifier');
+               modifier_contenu('document', $id,
+                       array('champs' => array('fichier', 'distant')),
+                       array('fichier' => $data['fichier'], 'distant' => 'oui')
+               );
+               return true;
+       }
+       else
+       */
+
+       // Chargement d'un nouveau doc ?
+       if ($data['document']) {
+               $arg = $data['document'];
+               /**
+                * Méthode >= SPIP 3.0
+                * ou SPIP 2.x + Mediathèque
+                */
+               if ($ajouter_documents = charger_fonction('ajouter_documents', 'action', true)) {
+                       $actifs = $ajouter_documents($id, array($arg), '', 0, $t['mode']);
+                       $x = reset($actifs);
+                       if (is_numeric($x)) {
+                               return true;
+                       } else {
+                               return false;
+                       }
+               } elseif ($ajouter_documents = charger_fonction('ajouter_documents', 'inc', true)) {
+                       /**
+                        * Méthode SPIP < 3.0
+                        */
+                       check_upload_error($arg['error']);
+                       $x = $ajouter_documents($arg['tmp_name'], $arg['name'],
+                                       'article', 0, 'document', null, $actifs);
+                       // $actifs contient l'id_document nouvellement cree
+                       // on recopie les donnees interessantes dans l'ancien
+                        $extension = ', extension ';
+                       //compat 192
+                       if ($GLOBALS['spip_version_code'] < '1.93') {
+                               $extension = '';
+                       }
+
+                       if ($id_new = array_pop($actifs)
+                               and $s = spip_query("SELECT fichier, taille, largeur, hauteur $extension, distant FROM spip_documents
+                               WHERE id_document="._q($id_new))
+                               and $new = sql_fetch($s)) {
+                               define('FILE_UPLOAD', true); // message pour crayons_json_export :(
+
+                               // Une vignette doit rester une image
+                               if ($t['mode'] == 'vignette'
+                                       and !in_array($new['extension'], array('jpg', 'gif', 'png'))) {
+                                       return false;
+                               }
+
+                               // Maintenant on est bon, on recopie les nouvelles donnees
+                               // dans l'ancienne ligne spip_documents
+                               include_spip('inc/modifier');
+                               modifier_contenu(
+                                       'document',
+                                       $id,
+                                       # 'champs' inutile a partir de SPIP 11348
+                                       array('champs' => array_keys($new)),
+                                       $new
+                               );
+
+                               // supprimer l'ancien document (sauf s'il etait distant)
+                               if ($t['distant'] != 'oui'
+                                       and file_exists(get_spip_doc($t['fichier']))) {
+                                       supprimer_fichier(get_spip_doc($t['fichier']));
+                               }
+
+                               // Effacer la ligne temporaire de spip_document
+                               spip_query('DELETE FROM spip_documents WHERE id_document='.intval($id_new));
+
+                               // oublier id_document temporaire (ca marche chez moi, sinon bof)
+                               spip_query('ALTER TABLE spip_documents AUTO_INCREMENT='.intval($id_new));
+
+                               return true;
+                       }
+               }
+       }
+}
+
+// cette fonction de revision soit supprime la vignette d'un document,
+// soit recoit le fichier upload a passer ou remplacer la vignette du document
+function vignette_revision($id, $data, $type, $ref) {
+       $s = sql_fetsel('id_document,id_vignette', 'spip_documents', 'id_document = '.intval($id));
+       if (!is_array($s)) {
+               return false;
+       }
+
+       include_spip('inc/modifier');
+       include_spip('inc/documents');
+       include_spip('action/editer_document');//pour revision_document
+       // Chargement d'un nouveau doc ?
+       if ($data['vignette']) {
+               define('FILE_UPLOAD', true);
+               if (is_numeric($s['id_vignette']) and ($s['id_vignette'] > 0)) {
+                       spip_log('suppression de la vignette');
+                       // Suppression du document
+                       $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette']));
+                       if (@file_exists($f = get_spip_doc($vignette))) {
+                               spip_log("efface $f");
+                               supprimer_fichier($f);
+                       }
+                       sql_delete('spip_documents', 'id_document='.intval($s['id_vignette']));
+                       sql_delete('spip_documents_liens', 'id_document='.intval($s['id_vignette']));
+
+                       pipeline(
+                               'post_edition',
+                               array(
+                                       'args' => array(
+                                               'operation' => 'supprimer_document',
+                                               'table' => 'spip_documents',
+                                               'id_objet' => $s['id_vignette']
+                                       ),
+                                       'data' => null
+                               )
+                       );
+                       $id_vignette = 0;
+               }
+
+               $arg = $data['vignette'];
+               check_upload_error($arg['error']);
+               // Ajout du document comme vignette
+
+               /**
+                * Méthode >= SPIP 3.0
+                * ou SPIP 2.x + Mediatheque
+                */
+               if ($ajouter_documents = charger_fonction('ajouter_documents', 'action', true)) {
+                       $x = $ajouter_documents(null,array($arg),'', 0, 'vignette');
+                       $vignette = reset($x);
+                       if (intval($vignette)) {
+                               document_modifier($id, array('id_vignette'=>$vignette));
+                       } elseif ($id_vignette) {
+                               document_modifier($id, array('id_vignette'=>$id_vignette));
+                       }
+               } elseif ($ajouter_documents = charger_fonction('ajouter_documents', 'inc', true)) {
+                       /**
+                        * Méthode < SPIP 3.0
+                        */
+                       // On remet l'id_vignette a 0 si on l'a supprimé
+                       if ($id_vignette) {
+                               revision_document($s['id_document'], array('id_vignette' => 0));
+                       }
+                       $x = $ajouter_documents($arg['tmp_name'], $arg['name'],'','', 'vignette', $id, $actifs);
+               }
+       } elseif ($wid = array_pop($ref)
+               and $_POST['content_'.$wid.'_vignette_supprimer'] == 'on') {
+               if (is_numeric($s['id_vignette']) and ($s['id_vignette']>0)) {
+                       // Suppression du document
+                       $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette']));
+                       if (@file_exists($f = get_spip_doc($vignette))) {
+                               spip_log("efface $f");
+                               supprimer_fichier($f);
+                       }
+                       sql_delete('spip_documents', 'id_document='.intval($s['id_vignette']));
+                       sql_delete('spip_documents_liens', 'id_document = ' . intval($s['id_vignette']));
+
+                       pipeline(
+                               'post_edition',
+                               array(
+                                       'args' => array(
+                                               'operation' => 'supprimer_document',
+                                               'table' => 'spip_documents',
+                                               'id_objet' => $s['id_vignette']
+                                       ),
+                                       'data' => null
+                               )
+                       );
+
+                       // On remet l'id_vignette a 0
+                       revision_document($s['id_document'], array('id_vignette'=>0));
+               }
+       }
+       return true;
+}
+
+
+function colonne_table($type, $col) {
+       list($distant,$table) = distant_table($type);
+       $nom_table = '';
+       if (!(($tabref = &crayons_get_table($table, $nom_table))
+               && isset($tabref['field'][$col])
+               && ($brut = $tabref['field'][$col]))) {
+                       return false;
+       }
+       $ana = explode(' ', $brut);
+       $sta = 0;
+       $sep = '';
+       $ret = array('brut' => $brut,
+               'type' => '', 'notnull' => false, 'long' => 0, 'def' => '');
+       foreach ($ana as $mot) {
+               switch ($sta) {
+                       case 0:
+                               $ret['type'] = ($mot = strtolower($mot));
+                               continue;
+                       case 1:
+                               if ($mot[strlen($mot) - 1] == ')') {
+                                       $pos = strpos($mot, '(');
+                                       $ret['type'] = strtolower(substr($mot, 0, $pos++));
+                                       $vir = explode(',', substr($mot, $pos, -1));
+                                       if ($ret['type'] == 'enum') {
+                                               $ret['enum'] = $vir;
+                                       } elseif (count($vir) > 1) {
+                                               $ret['long'] = $vir;
+                                       } else {
+                                               $ret['long'] = $vir[0];
+                                       }
+                                       $sta = 1;
+                                       continue;
+                               }
+                               if (!$sta) {
+                                       $sta = 1;
+                                       continue;
+                               }
+                               continue;
+                       case 2:
+                               switch (strtolower($mot)) {
+                                       case 'not':
+                                               $sta = 3;
+                                               continue;
+                                       case 'default':
+                                               $sta = 4;
+                                               continue;
+                               }
+                               continue;
+                       case 3:
+                               $ret['notnull'] = strtolower($mot) == 'null';
+                               $sta = 2;
+                               continue;
+                       case 4:
+                               $df1 = strpos('"\'', $mot[0]) !== false? $mot[0] : '';
+                               $sta = 5;
+                               continue;
+                       case 5:
+                               $ret['def'] .= $sep . $mot;
+                               if (!$df1) {
+                                       $sta = 2;
+                                       continue;
+                               }
+                               if ($df1 == $mot[strlen($mot) - 1]) {
+                                       $ret['def'] = substr($ret['def'], 1, -1);
+                                       $sta = 2;
+                               }
+                               $sep = ' ';
+                               continue;
+               }
+       }
+       return $ret;
+}
+
+
+/**
+ * Obtient le nom de la table ainsi que sa ou ses clés primaires
+ *
+ * @param string $type
+ *     Table sur laquelle s'applique le crayon.
+ *     Ce type peut contenir le nom d'un connecteur distant tel que `{connect}__{table}`
+ *
+ * @return array|bool
+ *     - false si on ne trouve pas de table ou de table ayant de clé primaire
+ *     - liste :
+ *     - - nom de la table sql
+ *     - - tableau des noms de clés primaires
+**/
+function crayons_get_table_name_and_primary($type) {
+       static $types = array();
+       if (isset($types[$type])) {
+               return $types[$type];
+       }
+
+       $nom_table = '';
+       if ($tabref = &crayons_get_table($type, $nom_table)
+               and ($tabid = explode(',', $tabref['key']['PRIMARY KEY']))) {
+               return $types[$type] = array($nom_table, $tabid);
+       }
+       spip_log('crayons: table ' . $type . ' inconnue');
+       return $types[$type] = false;
+}
+
+
+function table_where($type, $id, $where_en_tableau = false) {
+       if (!$infos = crayons_get_table_name_and_primary($type)) {
+               return array(false, false);
+       }
+
+       list($nom_table, $tabid) = $infos;
+
+       if (is_scalar($id)) {
+               $id = explode('-', $id);
+       }
+       // sortie tableau pour sql_updateq
+       if ($where_en_tableau) {
+               $where = array();
+               foreach ($id as $idcol => $idval) {
+                       $where[] = '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . sql_quote($idval);
+               }
+       // sinon sortie texte pour sql_query
+       } else {
+               $where = $and = '';
+               foreach ($id as $idcol => $idval) {
+                       $where .= $and . '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . _q($idval);
+                       $and = ' AND ';
+               }
+       }
+       return array($nom_table, $where);
+}
+//     var_dump(colonne_table('forum', 'id_syndic')); die();
+
+function valeur_colonne_table_dist($type, $col, $id) {
+
+       // Table introuvable ou sans clé primaire
+       if (!$infos = crayons_get_table_name_and_primary($type)) {
+               return false;
+       }
+       $table = reset($infos);
+
+       $r = array();
+
+       // valeurs non SQL
+       foreach ($col as $champ) {
+               if (function_exists($f = 'valeur_champ_'.$table.'_'.$champ)
+                       or function_exists($f = 'valeur_champ_'.$champ)) {
+                       $r[$champ] = $f($table, $id, $champ);
+                       $col = array_diff($col, array($champ));
+               }
+       }
+
+       // valeurs SQL
+       if (count($col)) {
+               list($distant, $table)   = distant_table($type);
+               list($nom_table, $where) = table_where($type, $id);
+
+               if ($s = spip_query(
+                       'SELECT `' . implode($col, '`, `') .
+                       '` FROM ' . $nom_table . ' WHERE ' . $where,
+                       $distant
+               ) and $t = sql_fetch($s)) {
+                               $r = array_merge($r, $t);
+               }
+       }
+
+       return $r;
+}
+
+/**
+ * Extrait la valeur d'une ou plusieurs colonnes d'une table
+ *
+ * @param string $table
+ *   Type d'objet de la table (article)
+ * @param string|array $col
+ *   Nom de la ou des colonnes (ps)
+ * @param string $id
+ *   Identifiant de l'objet
+ * @return array
+ *   Couples Nom de la colonne => Contenu de la colonne
+**/
+function valeur_colonne_table($table, $col, $id) {
+       if (!is_array($col)) {
+               $col = array($col);
+       }
+
+       if (function_exists($f = $table . '_valeur_colonne_table_dist')
+               or function_exists($f = $table.'_valeur_colonne_table')
+               or $f = 'valeur_colonne_table_dist') {
+               return $f($table, $col, $id);
+       }
+}
+
+/**
+ * Extrait la valeur d'une configuration en meta
+ *
+ * Pour ces données, il n'y a toujours qu'une colonne (valeur),
+ * mais on gère l'enregistrement et la lecture via lire_config ou ecrire_config
+ * dès que l'on demande des sous parties d'une configuration.
+ *
+ * On ne retourne alors ici dans 'valeur' que la sous-partie demandée si
+ * c'est le cas.
+ *
+ * @param string $table
+ *   Nom de la table (meta)
+ * @param array $col
+ *   Nom des colonnes (valeur)
+ * @param string $id
+ *   Nom ou clé de configuration (descriptif_site ou demo__truc pour demo/truc)
+ * @return array
+ *   Couple valeur => Contenu de la configuration
+**/
+function meta_valeur_colonne_table_dist($table, $col, $id) {
+       // Certaines clés de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc})
+       $id = str_replace('__', '/', $id);
+
+       // Éviter de planter les vieux SPIP
+       if (false === strpos($id, '/')) {
+               $config = isset($GLOBALS['meta'][$id]) ? $GLOBALS['meta'][$id] : '';
+       // SPIP 3 ou Bonux 2 ou CFG
+       } else {
+               include_spip('inc/config');
+               $config =  lire_config($id, '');
+       }
+       return array('valeur' => $config);
+}
+
+
+function return_log($var) {
+       die(crayons_json_export(array('$erreur'=> var_export($var, true))));
+}
+
+function _U($texte, $params = array()) {
+       include_spip('inc/charsets');
+       return unicode2charset(html2unicode(_T($texte, $params)));
+}
+
+/**
+ * Obtenir la configuration des crayons
+ *
+ * @note wdgcfg = widget config :-)
+ *
+ * @return array
+ *     Couples : attribut => valeur
+**/
+function wdgcfg() {
+       $php = function_exists('crayons_config') ? crayons_config() : array();
+       include_spip('inc/meta');
+       lire_metas();
+       global $meta;
+       $metacrayons = empty($meta['crayons']) ? array() : unserialize($meta['crayons']);
+       $wdgcfg = array();
+       foreach (array(
+               'msgNoChange' => false,
+               'msgAbandon' => false,  /* etait: true */
+               'filet' => false,
+               'yellow_fade' => false,
+               'clickhide' => false /* etait: true */
+       ) as $cfgi => $def) {
+               $wdgcfg[$cfgi] = isset($php[$cfgi]) ? $php[$cfgi] :
+                       isset($metacrayons[$cfgi]) ? $metacrayons[$cfgi] : $def;
+       }
+       return $wdgcfg;
+}
+
+function &crayons_get_table($type, &$nom_table) {
+       list($distant,$table) = distant_table($type);
+       static $return = array();
+       static $noms = array();
+       if (!isset($return[$table])) {
+               $try = array(table_objet_sql($table), 'spip_'.table_objet($table), 'spip_' . $table . 's', $table . 's', 'spip_' . $table, $table);
+
+               // premiere possibilite (à partir de 1.9.3) : regarder directement la base
+               if (function_exists('sql_showtable')) {
+                       foreach ($try as $nom) {
+                               if ($q = sql_showtable($nom, !$distant, $distant)) {
+                                       $noms[$table] = $nom;
+                                       $return[$table] = $q;
+                                       break;
+                               }
+                       }
+               }
+
+               // seconde, une heuristique 1.9.2
+               if (!isset($return[$table])) {
+                       include_spip('base/serial');
+                       include_spip('base/auxiliaires');
+                       include_spip('public/parametrer');
+                       foreach (array('tables_principales', 'tables_auxiliaires') as $categ) {
+                               foreach ($try as $nom) {
+                                       if (isset($GLOBALS[$categ][$nom])) {
+                                               $noms[$table] = $nom;
+                                               $return[$table] = & $GLOBALS[$categ][$nom];
+                                               break 2;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       $nom_table = $noms[$table];
+       return $return[$table];
+}
+
+function distant_table($type) {
+       //separation $type en $distant $table
+       //separateur double underscore "__"
+       strstr($type, '__') ? list($distant,$table) = explode('__', $type) : list($distant, $table) = array(false, $type);
+       return array($distant,$table);
+}
index 00300b5..713b8ac 100644 (file)
@@ -114,10 +114,10 @@ $.fn.opencrayon = function(evt, percent) {
                                'h': $(this).height(),
                                'ww': (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth)),
                                'wh': (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight)),
-                               'em': $(this).px('fontSize'), // eviter un bug MSIE sur fontSize
+                               'em': $(this).css('fontSize'), // Bug de jquery resolu : http://bugs.jquery.com/ticket/760
                                'class': me.className,
                                'color': $(this).css('color'),
-                               'font-size': $(this).px('fontSize'),
+                               'font-size': $(this).css('fontSize'),
                                'font-family': $(this).css('fontFamily'),
                                'font-weight': $(this).css('fontWeight'),
                                'line-height': $(this).css('lineHeight'),
@@ -166,7 +166,11 @@ $.fn.opencrayon = function(evt, percent) {
                                        .addClass('crayon-has')
                                        .find('>.crayon-icones')
                                                .attr('rel','crayon_'+id_crayon);
-                                       if ($.browser.msie) $(me).css({'zoom':1});
+                                       // Detection IE sur sa capacite a gerer zoom :
+                                       // http://www.sitepoint.com/detect-css3-property-browser-support/
+                                       if (document.createElement("detect").style.zoom === "") {
+                                               $(me).css({'zoom':1});
+                                       }
                                        var pos = $(me).offset();
                                        $('<div class="crayon-html" id="crayon_'+id_crayon+'"></div>')
                                        .css({
@@ -329,6 +333,12 @@ $.fn.activatecrayon = function(percent) {
                                        d[$('input.crayon-id', crayon).val()]
                                )
                                .iconecrayon();
+
+                               // Invalider des préchargements ajax
+                               if (typeof jQuery.spip == 'object' && typeof jQuery.spip.preloaded_urls == 'object') {
+                                       jQuery.spip.preloaded_urls = {};
+                               }
+
                                // Declencher le onAjaxLoad normal de SPIP
                                if (typeof jQuery.spip == 'object' && typeof jQuery.spip.triggerAjaxLoad == 'function') {
                                        jQuery.spip.triggerAjaxLoad(tous.get());
index c0fba53..591ad6f 100644 (file)
 /*!
  * jQuery Form Plugin
- * version: 2.73 (03-MAY-2011)
- * @requires jQuery v1.3.2 or later
- *
+ * version: 3.51.0-2014.06.20
+ * Requires jQuery v1.5 or later
+ * Copyright (c) 2014 M. Alsup
  * Examples and documentation at: http://malsup.com/jquery/form/
- * Dual licensed under the MIT and GPL licenses:
- *   http://www.opensource.org/licenses/mit-license.php
- *   http://www.gnu.org/licenses/gpl.html
+ * Project repository: https://github.com/malsup/form
+ * Dual licensed under the MIT and GPL licenses.
+ * https://github.com/malsup/form#copyright-and-license
  */
-;(function($) {
+/*global ActiveXObject */
+
+// AMD support
+(function (factory) {
+    "use strict";
+    if (typeof define === 'function' && define.amd) {
+        // using AMD; register as anon module
+        define(['jquery'], factory);
+    } else {
+        // no AMD; invoke directly
+        factory( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto );
+    }
+}
+
+(function($) {
+"use strict";
 
 /*
-       Usage Note:
-       -----------
-       Do not use both ajaxSubmit and ajaxForm on the same form.  These
-       functions are intended to be exclusive.  Use ajaxSubmit if you want
-       to bind your own submit handler to the form.  For example,
-
-       $(document).ready(function() {
-               $('#myForm').bind('submit', function(e) {
-                       e.preventDefault(); // <-- important
-                       $(this).ajaxSubmit({
-                               target: '#output'
-                       });
-               });
-       });
-
-       Use ajaxForm when you want the plugin to manage all the event binding
-       for you.  For example,
-
-       $(document).ready(function() {
-               $('#myForm').ajaxForm({
-                       target: '#output'
-               });
-       });
-
-       When using ajaxForm, the ajaxSubmit function will be invoked for you
-       at the appropriate time.
+    Usage Note:
+    -----------
+    Do not use both ajaxSubmit and ajaxForm on the same form.  These
+    functions are mutually exclusive.  Use ajaxSubmit if you want
+    to bind your own submit handler to the form.  For example,
+
+    $(document).ready(function() {
+        $('#myForm').on('submit', function(e) {
+            e.preventDefault(); // <-- important
+            $(this).ajaxSubmit({
+                target: '#output'
+            });
+        });
+    });
+
+    Use ajaxForm when you want the plugin to manage all the event binding
+    for you.  For example,
+
+    $(document).ready(function() {
+        $('#myForm').ajaxForm({
+            target: '#output'
+        });
+    });
+
+    You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
+    form does not have to exist when you invoke ajaxForm:
+
+    $('#myForm').ajaxForm({
+        delegation: true,
+        target: '#output'
+    });
+
+    When using ajaxForm, the ajaxSubmit function will be invoked for you
+    at the appropriate time.
 */
 
+/**
+ * Feature detection
+ */
+var feature = {};
+feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
+feature.formdata = window.FormData !== undefined;
+
+var hasProp = !!$.fn.prop;
+
+// attr2 uses prop when it can but checks the return type for
+// an expected string.  this accounts for the case where a form 
+// contains inputs with names like "action" or "method"; in those
+// cases "prop" returns the element
+$.fn.attr2 = function() {
+    if ( ! hasProp ) {
+        return this.attr.apply(this, arguments);
+    }
+    var val = this.prop.apply(this, arguments);
+    if ( ( val && val.jquery ) || typeof val === 'string' ) {
+        return val;
+    }
+    return this.attr.apply(this, arguments);
+};
+
 /**
  * ajaxSubmit() provides a mechanism for immediately submitting
  * an HTML form using AJAX.
  */
 $.fn.ajaxSubmit = function(options) {
-       // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
-       if (!this.length) {
-               log('ajaxSubmit: skipping submit process - no element selected');
-               return this;
-       }
-
-       if (typeof options == 'function') {
-               options = { success: options };
-       }
-
-       var action = this.attr('action');
-       var url = (typeof action === 'string') ? $.trim(action) : '';
-       if (url) {
-               // clean url (don't include hash vaue)
-               url = (url.match(/^([^#]+)/)||[])[1];
-       }
-       url = url || window.location.href || '';
-
-       options = $.extend(true, {
-               url:  url,
-               success: $.ajaxSettings.success,
-               type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57)
-               iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
-       }, options);
-
-       // hook for manipulating the form data before it is extracted;
-       // convenient for use with rich editors like tinyMCE or FCKEditor
-       var veto = {};
-       this.trigger('form-pre-serialize', [this, options, veto]);
-       if (veto.veto) {
-               log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
-               return this;
-       }
-
-       // provide opportunity to alter form data before it is serialized
-       if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
-               log('ajaxSubmit: submit aborted via beforeSerialize callback');
-               return this;
-       }
-
-       var n,v,a = this.formToArray(options.semantic);
-       if (options.data) {
-               options.extraData = options.data;
-               for (n in options.data) {
-                       if(options.data[n] instanceof Array) {
-                               for (var k in options.data[n]) {
-                                       a.push( { name: n, value: options.data[n][k] } );
-                               }
-                       }
-                       else {
-                               v = options.data[n];
-                               v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
-                               a.push( { name: n, value: v } );
-                       }
-               }
-       }
-
-       // give pre-submit callback an opportunity to abort the submit
-       if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
-               log('ajaxSubmit: submit aborted via beforeSubmit callback');
-               return this;
-       }
-
-       // fire vetoable 'validate' event
-       this.trigger('form-submit-validate', [a, this, options, veto]);
-       if (veto.veto) {
-               log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
-               return this;
-       }
-
-       var q = $.param(a);
-
-       if (options.type.toUpperCase() == 'GET') {
-               options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
-               options.data = null;  // data is null for 'get'
-       }
-       else {
-               options.data = q; // data is the query string for 'post'
-       }
-
-       var $form = this, callbacks = [];
-       if (options.resetForm) {
-               callbacks.push(function() { $form.resetForm(); });
-       }
-       if (options.clearForm) {
-               callbacks.push(function() { $form.clearForm(); });
-       }
-
-       // perform a load on the target only if dataType is not provided
-       if (!options.dataType && options.target) {
-               var oldSuccess = options.success || function(){};
-               callbacks.push(function(data) {
-                       var fn = options.replaceTarget ? 'replaceWith' : 'html';
-                       $(options.target)[fn](data).each(oldSuccess, arguments);
-               });
-       }
-       else if (options.success) {
-               callbacks.push(options.success);
-       }
-
-       options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
-               var context = options.context || options;   // jQuery 1.4+ supports scope context 
-               for (var i=0, max=callbacks.length; i < max; i++) {
-                       callbacks[i].apply(context, [data, status, xhr || $form, $form]);
-               }
-       };
-
-       // are there files to upload?
-       var fileInputs = $('input:file', this).length > 0;
-       var mp = 'multipart/form-data';
-       var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
-
-       // options.iframe allows user to force iframe mode
-       // 06-NOV-09: now defaulting to iframe mode if file input is detected
-   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
-          // hack to fix Safari hang (thanks to Tim Molendijk for this)
-          // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
-          if (options.closeKeepAlive) {
-                  $.get(options.closeKeepAlive, fileUpload);
-               }
-          else {
-                  fileUpload();
-               }
-   }
-   else {
-               $.ajax(options);
-   }
-
-       // fire 'notify' event
-       this.trigger('form-submit-notify', [this, options]);
-       return this;
-
-
-       // private function for handling file uploads (hat tip to YAHOO!)
-       function fileUpload() {
-               var form = $form[0];
-
-               if ($(':input[name=submit],:input[id=submit]', form).length) {
-                       // if there is an input with a name or id of 'submit' then we won't be
-                       // able to invoke the submit fn on the form (at least not x-browser)
-                       alert('Error: Form elements must not have name or id of "submit".');
-                       return;
-               }
-               
-               var s = $.extend(true, {}, $.ajaxSettings, options);
-               s.context = s.context || s;
-               var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
-               var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />');
-               var io = $io[0];
-
-               $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
-
-               var xhr = { // mock object
-                       aborted: 0,
-                       responseText: null,
-                       responseXML: null,
-                       status: 0,
-                       statusText: 'n/a',
-                       getAllResponseHeaders: function() {},
-                       getResponseHeader: function() {},
-                       setRequestHeader: function() {},
-                       abort: function(status) {
-                               var e = (status === 'timeout' ? 'timeout' : 'aborted');
-                               log('aborting upload... ' + e);
-                               this.aborted = 1;
-                               $io.attr('src', s.iframeSrc); // abort op in progress
-                               xhr.error = e;
-                               s.error && s.error.call(s.context, xhr, e, e);
-                               g && $.event.trigger("ajaxError", [xhr, s, e]);
-                               s.complete && s.complete.call(s.context, xhr, e);
-                       }
-               };
-
-               var g = s.global;
-               // trigger ajax global events so that activity/block indicators work like normal
-               if (g && ! $.active++) {
-                       $.event.trigger("ajaxStart");
-               }
-               if (g) {
-                       $.event.trigger("ajaxSend", [xhr, s]);
-               }
-
-               if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
-                       if (s.global) { 
-                               $.active--;
-                       }
-                       return;
-               }
-               if (xhr.aborted) {
-                       return;
-               }
-
-               var timedOut = 0, timeoutHandle;
-
-               // add submitting element to data if we know it
-               var sub = form.clk;
-               if (sub) {
-                       var n = sub.name;
-                       if (n && !sub.disabled) {
-                               s.extraData = s.extraData || {};
-                               s.extraData[n] = sub.value;
-                               if (sub.type == "image") {
-                                       s.extraData[n+'.x'] = form.clk_x;
-                                       s.extraData[n+'.y'] = form.clk_y;
-                               }
-                       }
-               }
-
-               // take a breath so that pending repaints get some cpu time before the upload starts
-               function doSubmit() {
-                       // make sure form attrs are set
-                       var t = $form.attr('target'), a = $form.attr('action');
-
-                       // update form attrs in IE friendly way
-                       form.setAttribute('target',id);
-                       if (form.getAttribute('method') != 'POST') {
-                               form.setAttribute('method', 'POST');
-                       }
-                       if (form.getAttribute('action') != s.url) {
-                               form.setAttribute('action', s.url);
-                       }
-
-                       // ie borks in some cases when setting encoding
-                       if (! s.skipEncodingOverride) {
-                               $form.attr({
-                                       encoding: 'multipart/form-data',
-                                       enctype:  'multipart/form-data'
-                               });
-                       }
-
-                       // support timout
-                       if (s.timeout) {
-                               timeoutHandle = setTimeout(function() { timedOut = true; cb(true); }, s.timeout);
-                       }
-
-                       // add "extra" data to form if provided in options
-                       var extraInputs = [];
-                       try {
-                               if (s.extraData) {
-                                       for (var n in s.extraData) {
-                                               extraInputs.push(
-                                                       $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
-                                                               .appendTo(form)[0]);
-                                       }
-                               }
-
-                               // add iframe to doc and submit the form
-                               $io.appendTo('body');
-                io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
-                               form.submit();
-                       }
-                       finally {
-                               // reset attrs and remove "extra" input elements
-                               form.setAttribute('action',a);
-                               if(t) {
-                                       form.setAttribute('target', t);
-                               } else {
-                                       $form.removeAttr('target');
-                               }
-                               $(extraInputs).remove();
-                       }
-               }
-
-               if (s.forceSync) {
-                       doSubmit();
-               }
-               else {
-                       setTimeout(doSubmit, 10); // this lets dom updates render
-               }
-       
-               var data, doc, domCheckCount = 50, callbackProcessed;
-
-               function cb(e) {
-                       if (xhr.aborted || callbackProcessed) {
-                               return;
-                       }
-                       if (e === true && xhr) {
-                               xhr.abort('timeout');
-                               return;
-                       }
-                       
-                       var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
-                       if (!doc || doc.location.href == s.iframeSrc) {
-                               // response not received yet
-                               if (!timedOut)
-                                       return;
-                       }
-            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
-
-                       var ok = true;
-                       try {
-                               if (timedOut) {
-                                       throw 'timeout';
-                               }
-
-                               var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
-                               log('isXml='+isXml);
-                               if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
-                                       if (--domCheckCount) {
-                                               // in some browsers (Opera) the iframe DOM is not always traversable when
-                                               // the onload callback fires, so we loop a bit to accommodate
-                                               log('requeing onLoad callback, DOM not available');
-                                               setTimeout(cb, 250);
-                                               return;
-                                       }
-                                       // let this fall through because server response could be an empty document
-                                       //log('Could not access iframe DOM after mutiple tries.');
-                                       //throw 'DOMException: not available';
-                               }
-
-                               //log('response detected');
-                               xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null; 
-                               xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
-                               if (isXml)
-                                       s.dataType = 'xml';
-                               xhr.getResponseHeader = function(header){
-                                       var headers = {'content-type': s.dataType};
-                                       return headers[header];
-                               };
-
-                               var scr = /(json|script|text)/.test(s.dataType);
-                               if (scr || s.textarea) {
-                                       // see if user embedded response in textarea
-                                       var ta = doc.getElementsByTagName('textarea')[0];
-                                       if (ta) {
-                                               xhr.responseText = ta.value;
-                                       }
-                                       else if (scr) {
-                                               // account for browsers injecting pre around json response
-                                               var pre = doc.getElementsByTagName('pre')[0];
-                                               var b = doc.getElementsByTagName('body')[0];
-                                               if (pre) {
-                                                       xhr.responseText = pre.textContent;
-                                               }
-                                               else if (b) {
-                                                       xhr.responseText = b.innerHTML;
-                                               }
-                                       }                         
-                               }
-                               else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
-                                       xhr.responseXML = toXml(xhr.responseText);
-                               }
-                               
-                               data = httpData(xhr, s.dataType, s);
-                       }
-                       catch(e){
-                               log('error caught:',e);
-                               ok = false;
-                               xhr.error = e;
-                               s.error && s.error.call(s.context, xhr, 'error', e);
-                               g && $.event.trigger("ajaxError", [xhr, s, e]);
-                       }
-                       
-                       if (xhr.aborted) {
-                               log('upload aborted');
-                               ok = false;
-                       }
-
-                       // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
-                       if (ok) {
-                               s.success && s.success.call(s.context, data, 'success', xhr);
-                               g && $.event.trigger("ajaxSuccess", [xhr, s]);
-                       }
-                       
-                       g && $.event.trigger("ajaxComplete", [xhr, s]);
-
-                       if (g && ! --$.active) {
-                               $.event.trigger("ajaxStop");
-                       }
-                       
-                       s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error');
-
-                       callbackProcessed = true;
-                       if (s.timeout)
-                               clearTimeout(timeoutHandle);
-
-                       // clean up
-                       setTimeout(function() {
-                               $io.removeData('form-plugin-onload');
-                               $io.remove();
-                               xhr.responseXML = null;
-                       }, 100);
-               }
-
-               var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
-                       if (window.ActiveXObject) {
-                               doc = new ActiveXObject('Microsoft.XMLDOM');
-                               doc.async = 'false';
-                               doc.loadXML(s);
-                       }
-                       else {
-                               doc = (new DOMParser()).parseFromString(s, 'text/xml');
-                       }
-                       return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
-               };
-               var parseJSON = $.parseJSON || function(s) {
-                       return window['eval']('(' + s + ')');
-               };
-               
-               var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
-                       var ct = xhr.getResponseHeader('content-type') || '',
-                               xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
-                               data = xml ? xhr.responseXML : xhr.responseText;
-
-                       if (xml && data.documentElement.nodeName === 'parsererror') {
-                               $.error && $.error('parsererror');
-                       }
-                       if (s && s.dataFilter) {
-                               data = s.dataFilter(data, type);
-                       }
-                       if (typeof data === 'string') {
-                               if (type === 'json' || !type && ct.indexOf('json') >= 0) {
-                                       data = parseJSON(data);
-                               } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
-                                       $.globalEval(data);
-                               }
-                       }
-                       return data;
-               };
-       }
+    /*jshint scripturl:true */
+
+    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
+    if (!this.length) {
+        log('ajaxSubmit: skipping submit process - no element selected');
+        return this;
+    }
+
+    var method, action, url, $form = this;
+
+    if (typeof options == 'function') {
+        options = { success: options };
+    }
+    else if ( options === undefined ) {
+        options = {};
+    }
+
+    method = options.type || this.attr2('method');
+    action = options.url  || this.attr2('action');
+
+    url = (typeof action === 'string') ? $.trim(action) : '';
+    url = url || window.location.href || '';
+    if (url) {
+        // clean url (don't include hash vaue)
+        url = (url.match(/^([^#]+)/)||[])[1];
+    }
+
+    options = $.extend(true, {
+        url:  url,
+        success: $.ajaxSettings.success,
+        type: method || $.ajaxSettings.type,
+        iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
+    }, options);
+
+    // hook for manipulating the form data before it is extracted;
+    // convenient for use with rich editors like tinyMCE or FCKEditor
+    var veto = {};
+    this.trigger('form-pre-serialize', [this, options, veto]);
+    if (veto.veto) {
+        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+        return this;
+    }
+
+    // provide opportunity to alter form data before it is serialized
+    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
+        log('ajaxSubmit: submit aborted via beforeSerialize callback');
+        return this;
+    }
+
+    var traditional = options.traditional;
+    if ( traditional === undefined ) {
+        traditional = $.ajaxSettings.traditional;
+    }
+
+    var elements = [];
+    var qx, a = this.formToArray(options.semantic, elements);
+    if (options.data) {
+        options.extraData = options.data;
+        qx = $.param(options.data, traditional);
+    }
+
+    // give pre-submit callback an opportunity to abort the submit
+    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
+        log('ajaxSubmit: submit aborted via beforeSubmit callback');
+        return this;
+    }
+
+    // fire vetoable 'validate' event
+    this.trigger('form-submit-validate', [a, this, options, veto]);
+    if (veto.veto) {
+        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+        return this;
+    }
+
+    var q = $.param(a, traditional);
+    if (qx) {
+        q = ( q ? (q + '&' + qx) : qx );
+    }
+    if (options.type.toUpperCase() == 'GET') {
+        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+        options.data = null;  // data is null for 'get'
+    }
+    else {
+        options.data = q; // data is the query string for 'post'
+    }
+
+    var callbacks = [];
+    if (options.resetForm) {
+        callbacks.push(function() { $form.resetForm(); });
+    }
+    if (options.clearForm) {
+        callbacks.push(function() { $form.clearForm(options.includeHidden); });
+    }
+
+    // perform a load on the target only if dataType is not provided
+    if (!options.dataType && options.target) {
+        var oldSuccess = options.success || function(){};
+        callbacks.push(function(data) {
+            var fn = options.replaceTarget ? 'replaceWith' : 'html';
+            $(options.target)[fn](data).each(oldSuccess, arguments);
+        });
+    }
+    else if (options.success) {
+        callbacks.push(options.success);
+    }
+
+    options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
+        var context = options.context || this ;    // jQuery 1.4+ supports scope context
+        for (var i=0, max=callbacks.length; i < max; i++) {
+            callbacks[i].apply(context, [data, status, xhr || $form, $form]);
+        }
+    };
+
+    if (options.error) {
+        var oldError = options.error;
+        options.error = function(xhr, status, error) {
+            var context = options.context || this;
+            oldError.apply(context, [xhr, status, error, $form]);
+        };
+    }
+
+     if (options.complete) {
+        var oldComplete = options.complete;
+        options.complete = function(xhr, status) {
+            var context = options.context || this;
+            oldComplete.apply(context, [xhr, status, $form]);
+        };
+    }
+
+    // are there files to upload?
+
+    // [value] (issue #113), also see comment:
+    // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
+    var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() !== ''; });
+
+    var hasFileInputs = fileInputs.length > 0;
+    var mp = 'multipart/form-data';
+    var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
+
+    var fileAPI = feature.fileapi && feature.formdata;
+    log("fileAPI :" + fileAPI);
+    var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
+
+    var jqxhr;
+
+    // options.iframe allows user to force iframe mode
+    // 06-NOV-09: now defaulting to iframe mode if file input is detected
+    if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
+        // hack to fix Safari hang (thanks to Tim Molendijk for this)
+        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+        if (options.closeKeepAlive) {
+            $.get(options.closeKeepAlive, function() {
+                jqxhr = fileUploadIframe(a);
+            });
+        }
+        else {
+            jqxhr = fileUploadIframe(a);
+        }
+    }
+    else if ((hasFileInputs || multipart) && fileAPI) {
+        jqxhr = fileUploadXhr(a);
+    }
+    else {
+        jqxhr = $.ajax(options);
+    }
+
+    $form.removeData('jqxhr').data('jqxhr', jqxhr);
+
+    // clear element array
+    for (var k=0; k < elements.length; k++) {
+        elements[k] = null;
+    }
+
+    // fire 'notify' event
+    this.trigger('form-submit-notify', [this, options]);
+    return this;
+
+    // utility fn for deep serialization
+    function deepSerialize(extraData){
+        var serialized = $.param(extraData, options.traditional).split('&');
+        var len = serialized.length;
+        var result = [];
+        var i, part;
+        for (i=0; i < len; i++) {
+            // #252; undo param space replacement
+            serialized[i] = serialized[i].replace(/\+/g,' ');
+            part = serialized[i].split('=');
+            // #278; use array instead of object storage, favoring array serializations
+            result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
+        }
+        return result;
+    }
+
+     // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
+    function fileUploadXhr(a) {
+        var formdata = new FormData();
+
+        for (var i=0; i < a.length; i++) {
+            formdata.append(a[i].name, a[i].value);
+        }
+
+        if (options.extraData) {
+            var serializedData = deepSerialize(options.extraData);
+            for (i=0; i < serializedData.length; i++) {
+                if (serializedData[i]) {
+                    formdata.append(serializedData[i][0], serializedData[i][1]);
+                }
+            }
+        }
+
+        options.data = null;
+
+        var s = $.extend(true, {}, $.ajaxSettings, options, {
+            contentType: false,
+            processData: false,
+            cache: false,
+            type: method || 'POST'
+        });
+
+        if (options.uploadProgress) {
+            // workaround because jqXHR does not expose upload property
+            s.xhr = function() {
+                var xhr = $.ajaxSettings.xhr();
+                if (xhr.upload) {
+                    xhr.upload.addEventListener('progress', function(event) {
+                        var percent = 0;
+                        var position = event.loaded || event.position; /*event.position is deprecated*/
+                        var total = event.total;
+                        if (event.lengthComputable) {
+                            percent = Math.ceil(position / total * 100);
+                        }
+                        options.uploadProgress(event, position, total, percent);
+                    }, false);
+                }
+                return xhr;
+            };
+        }
+
+        s.data = null;
+        var beforeSend = s.beforeSend;
+        s.beforeSend = function(xhr, o) {
+            //Send FormData() provided by user
+            if (options.formData) {
+                o.data = options.formData;
+            }
+            else {
+                o.data = formdata;
+            }
+            if(beforeSend) {
+                beforeSend.call(this, xhr, o);
+            }
+        };
+        return $.ajax(s);
+    }
+
+    // private function for handling file uploads (hat tip to YAHOO!)
+    function fileUploadIframe(a) {
+        var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
+        var deferred = $.Deferred();
+
+        // #341
+        deferred.abort = function(status) {
+            xhr.abort(status);
+        };
+
+        if (a) {
+            // ensure that every serialized input is still enabled
+            for (i=0; i < elements.length; i++) {
+                el = $(elements[i]);
+                if ( hasProp ) {
+                    el.prop('disabled', false);
+                }
+                else {
+                    el.removeAttr('disabled');
+                }
+            }
+        }
+
+        s = $.extend(true, {}, $.ajaxSettings, options);
+        s.context = s.context || s;
+        id = 'jqFormIO' + (new Date().getTime());
+        if (s.iframeTarget) {
+            $io = $(s.iframeTarget);
+            n = $io.attr2('name');
+            if (!n) {
+                $io.attr2('name', id);
+            }
+            else {
+                id = n;
+            }
+        }
+        else {
+            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
+            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+        }
+        io = $io[0];
+
+
+        xhr = { // mock object
+            aborted: 0,
+            responseText: null,
+            responseXML: null,
+            status: 0,
+            statusText: 'n/a',
+            getAllResponseHeaders: function() {},
+            getResponseHeader: function() {},
+            setRequestHeader: function() {},
+            abort: function(status) {
+                var e = (status === 'timeout' ? 'timeout' : 'aborted');
+                log('aborting upload... ' + e);
+                this.aborted = 1;
+
+                try { // #214, #257
+                    if (io.contentWindow.document.execCommand) {
+                        io.contentWindow.document.execCommand('Stop');
+                    }
+                }
+                catch(ignore) {}
+
+                $io.attr('src', s.iframeSrc); // abort op in progress
+                xhr.error = e;
+                if (s.error) {
+                    s.error.call(s.context, xhr, e, status);
+                }
+                if (g) {
+                    $.event.trigger("ajaxError", [xhr, s, e]);
+                }
+                if (s.complete) {
+                    s.complete.call(s.context, xhr, e);
+                }
+            }
+        };
+
+        g = s.global;
+        // trigger ajax global events so that activity/block indicators work like normal
+        if (g && 0 === $.active++) {
+            $.event.trigger("ajaxStart");
+        }
+        if (g) {
+            $.event.trigger("ajaxSend", [xhr, s]);
+        }
+
+        if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
+            if (s.global) {
+                $.active--;
+            }
+            deferred.reject();
+            return deferred;
+        }
+        if (xhr.aborted) {
+            deferred.reject();
+            return deferred;
+        }
+
+        // add submitting element to data if we know it
+        sub = form.clk;
+        if (sub) {
+            n = sub.name;
+            if (n && !sub.disabled) {
+                s.extraData = s.extraData || {};
+                s.extraData[n] = sub.value;
+                if (sub.type == "image") {
+                    s.extraData[n+'.x'] = form.clk_x;
+                    s.extraData[n+'.y'] = form.clk_y;
+                }
+            }
+        }
+
+        var CLIENT_TIMEOUT_ABORT = 1;
+        var SERVER_ABORT = 2;
+                
+        function getDoc(frame) {
+            /* it looks like contentWindow or contentDocument do not
+             * carry the protocol property in ie8, when running under ssl
+             * frame.document is the only valid response document, since
+             * the protocol is know but not on the other two objects. strange?
+             * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
+             */
+            
+            var doc = null;
+            
+            // IE8 cascading access check
+            try {
+                if (frame.contentWindow) {
+                    doc = frame.contentWindow.document;
+                }
+            } catch(err) {
+                // IE8 access denied under ssl & missing protocol
+                log('cannot get iframe.contentWindow document: ' + err);
+            }
+
+            if (doc) { // successful getting content
+                return doc;
+            }
+
+            try { // simply checking may throw in ie8 under ssl or mismatched protocol
+                doc = frame.contentDocument ? frame.contentDocument : frame.document;
+            } catch(err) {
+                // last attempt
+                log('cannot get iframe.contentDocument: ' + err);
+                doc = frame.document;
+            }
+            return doc;
+        }
+
+        // Rails CSRF hack (thanks to Yvan Barthelemy)
+        var csrf_token = $('meta[name=csrf-token]').attr('content');
+        var csrf_param = $('meta[name=csrf-param]').attr('content');
+        if (csrf_param && csrf_token) {
+            s.extraData = s.extraData || {};
+            s.extraData[csrf_param] = csrf_token;
+        }
+
+        // take a breath so that pending repaints get some cpu time before the upload starts
+        function doSubmit() {
+            // make sure form attrs are set
+            var t = $form.attr2('target'), 
+                a = $form.attr2('action'), 
+                mp = 'multipart/form-data',
+                et = $form.attr('enctype') || $form.attr('encoding') || mp;
+
+            // update form attrs in IE friendly way
+            form.setAttribute('target',id);
+            if (!method || /post/i.test(method) ) {
+                form.setAttribute('method', 'POST');
+            }
+            if (a != s.url) {
+                form.setAttribute('action', s.url);
+            }
+
+            // ie borks in some cases when setting encoding
+            if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
+                $form.attr({
+                    encoding: 'multipart/form-data',
+                    enctype:  'multipart/form-data'
+                });
+            }
+
+            // support timout
+            if (s.timeout) {
+                timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
+            }
+
+            // look for server aborts
+            function checkState() {
+                try {
+                    var state = getDoc(io).readyState;
+                    log('state = ' + state);
+                    if (state && state.toLowerCase() == 'uninitialized') {
+                        setTimeout(checkState,50);
+                    }
+                }
+                catch(e) {
+                    log('Server abort: ' , e, ' (', e.name, ')');
+                    cb(SERVER_ABORT);
+                    if (timeoutHandle) {
+                        clearTimeout(timeoutHandle);
+                    }
+                    timeoutHandle = undefined;
+                }
+            }
+
+            // add "extra" data to form if provided in options
+            var extraInputs = [];
+            try {
+                if (s.extraData) {
+                    for (var n in s.extraData) {
+                        if (s.extraData.hasOwnProperty(n)) {
+                           // if using the $.param format that allows for multiple values with the same name
+                           if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
+                               extraInputs.push(
+                               $('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
+                                   .appendTo(form)[0]);
+                           } else {
+                               extraInputs.push(
+                               $('<input type="hidden" name="'+n+'">').val(s.extraData[n])
+                                   .appendTo(form)[0]);
+                           }
+                        }
+                    }
+                }
+
+                if (!s.iframeTarget) {
+                    // add iframe to doc and submit the form
+                    $io.appendTo('body');
+                }
+                if (io.attachEvent) {
+                    io.attachEvent('onload', cb);
+                }
+                else {
+                    io.addEventListener('load', cb, false);
+                }
+                setTimeout(checkState,15);
+
+                try {
+                    form.submit();
+                } catch(err) {
+                    // just in case form has element with name/id of 'submit'
+                    var submitFn = document.createElement('form').submit;
+                    submitFn.apply(form);
+                }
+            }
+            finally {
+                // reset attrs and remove "extra" input elements
+                form.setAttribute('action',a);
+                form.setAttribute('enctype', et); // #380
+                if(t) {
+                    form.setAttribute('target', t);
+                } else {
+                    $form.removeAttr('target');
+                }
+                $(extraInputs).remove();
+            }
+        }
+
+        if (s.forceSync) {
+            doSubmit();
+        }
+        else {
+            setTimeout(doSubmit, 10); // this lets dom updates render
+        }
+
+        var data, doc, domCheckCount = 50, callbackProcessed;
+
+        function cb(e) {
+            if (xhr.aborted || callbackProcessed) {
+                return;
+            }
+            
+            doc = getDoc(io);
+            if(!doc) {
+                log('cannot access response document');
+                e = SERVER_ABORT;
+            }
+            if (e === CLIENT_TIMEOUT_ABORT && xhr) {
+                xhr.abort('timeout');
+                deferred.reject(xhr, 'timeout');
+                return;
+            }
+            else if (e == SERVER_ABORT && xhr) {
+                xhr.abort('server abort');
+                deferred.reject(xhr, 'error', 'server abort');
+                return;
+            }
+
+            if (!doc || doc.location.href == s.iframeSrc) {
+                // response not received yet
+                if (!timedOut) {
+                    return;
+                }
+            }
+            if (io.detachEvent) {
+                io.detachEvent('onload', cb);
+            }
+            else {
+                io.removeEventListener('load', cb, false);
+            }
+
+            var status = 'success', errMsg;
+            try {
+                if (timedOut) {
+                    throw 'timeout';
+                }
+
+                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
+                log('isXml='+isXml);
+                if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
+                    if (--domCheckCount) {
+                        // in some browsers (Opera) the iframe DOM is not always traversable when
+                        // the onload callback fires, so we loop a bit to accommodate
+                        log('requeing onLoad callback, DOM not available');
+                        setTimeout(cb, 250);
+                        return;
+                    }
+                    // let this fall through because server response could be an empty document
+                    //log('Could not access iframe DOM after mutiple tries.');
+                    //throw 'DOMException: not available';
+                }
+
+                //log('response detected');
+                var docRoot = doc.body ? doc.body : doc.documentElement;
+                xhr.responseText = docRoot ? docRoot.innerHTML : null;
+                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+                if (isXml) {
+                    s.dataType = 'xml';
+                }
+                xhr.getResponseHeader = function(header){
+                    var headers = {'content-type': s.dataType};
+                    return headers[header.toLowerCase()];
+                };
+                // support for XHR 'status' & 'statusText' emulation :
+                if (docRoot) {
+                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
+                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
+                }
+
+                var dt = (s.dataType || '').toLowerCase();
+                var scr = /(json|script|text)/.test(dt);
+                if (scr || s.textarea) {
+                    // see if user embedded response in textarea
+                    var ta = doc.getElementsByTagName('textarea')[0];
+                    if (ta) {
+                        xhr.responseText = ta.value;
+                        // support for XHR 'status' & 'statusText' emulation :
+                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
+                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
+                    }
+                    else if (scr) {
+                        // account for browsers injecting pre around json response
+                        var pre = doc.getElementsByTagName('pre')[0];
+                        var b = doc.getElementsByTagName('body')[0];
+                        if (pre) {
+                            xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
+                        }
+                        else if (b) {
+                            xhr.responseText = b.textContent ? b.textContent : b.innerText;
+                        }
+                    }
+                }
+                else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
+                    xhr.responseXML = toXml(xhr.responseText);
+                }
+
+                try {
+                    data = httpData(xhr, dt, s);
+                }
+                catch (err) {
+                    status = 'parsererror';
+                    xhr.error = errMsg = (err || status);
+                }
+            }
+            catch (err) {
+                log('error caught: ',err);
+                status = 'error';
+                xhr.error = errMsg = (err || status);
+            }
+
+            if (xhr.aborted) {
+                log('upload aborted');
+                status = null;
+            }
+
+            if (xhr.status) { // we've set xhr.status
+                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
+            }
+
+            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
+            if (status === 'success') {
+                if (s.success) {
+                    s.success.call(s.context, data, 'success', xhr);
+                }
+                deferred.resolve(xhr.responseText, 'success', xhr);
+                if (g) {
+                    $.event.trigger("ajaxSuccess", [xhr, s]);
+                }
+            }
+            else if (status) {
+                if (errMsg === undefined) {
+                    errMsg = xhr.statusText;
+                }
+                if (s.error) {
+                    s.error.call(s.context, xhr, status, errMsg);
+                }
+                deferred.reject(xhr, 'error', errMsg);
+                if (g) {
+                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
+                }
+            }
+
+            if (g) {
+                $.event.trigger("ajaxComplete", [xhr, s]);
+            }
+
+            if (g && ! --$.active) {
+                $.event.trigger("ajaxStop");
+            }
+
+            if (s.complete) {
+                s.complete.call(s.context, xhr, status);
+            }
+
+            callbackProcessed = true;
+            if (s.timeout) {
+                clearTimeout(timeoutHandle);
+            }
+
+            // clean up
+            setTimeout(function() {
+                if (!s.iframeTarget) {
+                    $io.remove();
+                }
+                else { //adding else to clean up existing iframe response.
+                    $io.attr('src', s.iframeSrc);
+                }
+                xhr.responseXML = null;
+            }, 100);
+        }
+
+        var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
+            if (window.ActiveXObject) {
+                doc = new ActiveXObject('Microsoft.XMLDOM');
+                doc.async = 'false';
+                doc.loadXML(s);
+            }
+            else {
+                doc = (new DOMParser()).parseFromString(s, 'text/xml');
+            }
+            return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
+        };
+        var parseJSON = $.parseJSON || function(s) {
+            /*jslint evil:true */
+            return window['eval']('(' + s + ')');
+        };
+
+        var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
+
+            var ct = xhr.getResponseHeader('content-type') || '',
+                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
+                data = xml ? xhr.responseXML : xhr.responseText;
+
+            if (xml && data.documentElement.nodeName === 'parsererror') {
+                if ($.error) {
+                    $.error('parsererror');
+                }
+            }
+            if (s && s.dataFilter) {
+                data = s.dataFilter(data, type);
+            }
+            if (typeof data === 'string') {
+                if (type === 'json' || !type && ct.indexOf('json') >= 0) {
+                    data = parseJSON(data);
+                } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
+                    $.globalEval(data);
+                }
+            }
+            return data;
+        };
+
+        return deferred;
+    }
 };
 
 /**
@@ -472,9 +839,9 @@ $.fn.ajaxSubmit = function(options) {
  * The advantages of using this method instead of ajaxSubmit() are:
  *
  * 1: This method will include coordinates for <input type="image" /> elements (if the element
- *     is used to submit the form).
+ *    is used to submit the form).
  * 2. This method will include the submit element's name/value data (for the element that was
- *     used to submit the form).
+ *    used to submit the form).
  * 3. This method binds the submit() method to the form for you.
  *
  * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
@@ -482,60 +849,83 @@ $.fn.ajaxSubmit = function(options) {
  * the form itself.
  */
 $.fn.ajaxForm = function(options) {
-       // in jQuery 1.3+ we can fix mistakes with the ready state
-       if (this.length === 0) {
-               var o = { s: this.selector, c: this.context };
-               if (!$.isReady && o.s) {
-                       log('DOM not ready, queuing ajaxForm');
-                       $(function() {
-                               $(o.s,o.c).ajaxForm(options);
-                       });
-                       return this;
-               }
-               // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
-               log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
-               return this;
-       }
-       
-       return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
-               if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
-                       e.preventDefault();
-                       $(this).ajaxSubmit(options);
-               }
-       }).bind('click.form-plugin', function(e) {
-               var target = e.target;
-               var $el = $(target);
-               if (!($el.is(":submit,input:image"))) {
-                       // is this a child element of the submit el?  (ex: a span within a button)
-                       var t = $el.closest(':submit');
-                       if (t.length == 0) {
-                               return;
-                       }
-                       target = t[0];
-               }
-               var form = this;
-               form.clk = target;
-               if (target.type == 'image') {
-                       if (e.offsetX != undefined) {
-                               form.clk_x = e.offsetX;
-                               form.clk_y = e.offsetY;
-                       } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
-                               var offset = $el.offset();
-                               form.clk_x = e.pageX - offset.left;
-                               form.clk_y = e.pageY - offset.top;
-                       } else {
-                               form.clk_x = e.pageX - target.offsetLeft;
-                               form.clk_y = e.pageY - target.offsetTop;
-                       }
-               }
-               // clear form vars
-               setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
-       });
+    options = options || {};
+    options.delegation = options.delegation && $.isFunction($.fn.on);
+
+    // in jQuery 1.3+ we can fix mistakes with the ready state
+    if (!options.delegation && this.length === 0) {
+        var o = { s: this.selector, c: this.context };
+        if (!$.isReady && o.s) {
+            log('DOM not ready, queuing ajaxForm');
+            $(function() {
+                $(o.s,o.c).ajaxForm(options);
+            });
+            return this;
+        }
+        // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+        log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+        return this;
+    }
+
+    if ( options.delegation ) {
+        $(document)
+            .off('submit.form-plugin', this.selector, doAjaxSubmit)
+            .off('click.form-plugin', this.selector, captureSubmittingElement)
+            .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
+            .on('click.form-plugin', this.selector, options, captureSubmittingElement);
+        return this;
+    }
+
+    return this.ajaxFormUnbind()
+        .bind('submit.form-plugin', options, doAjaxSubmit)
+        .bind('click.form-plugin', options, captureSubmittingElement);
 };
 
+// private event handlers
+function doAjaxSubmit(e) {
+    /*jshint validthis:true */
+    var options = e.data;
+    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
+        e.preventDefault();
+        $(e.target).ajaxSubmit(options); // #365
+    }
+}
+
+function captureSubmittingElement(e) {
+    /*jshint validthis:true */
+    var target = e.target;
+    var $el = $(target);
+    if (!($el.is("[type=submit],[type=image]"))) {
+        // is this a child element of the submit el?  (ex: a span within a button)
+        var t = $el.closest('[type=submit]');
+        if (t.length === 0) {
+            return;
+        }
+        target = t[0];
+    }
+    var form = this;
+    form.clk = target;
+    if (target.type == 'image') {
+        if (e.offsetX !== undefined) {
+            form.clk_x = e.offsetX;
+            form.clk_y = e.offsetY;
+        } else if (typeof $.fn.offset == 'function') {
+            var offset = $el.offset();
+            form.clk_x = e.pageX - offset.left;
+            form.clk_y = e.pageY - offset.top;
+        } else {
+            form.clk_x = e.pageX - target.offsetLeft;
+            form.clk_y = e.pageY - target.offsetTop;
+        }
+    }
+    // clear form vars
+    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
+}
+
+
 // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
 $.fn.ajaxFormUnbind = function() {
-       return this.unbind('submit.form-plugin click.form-plugin');
+    return this.unbind('submit.form-plugin click.form-plugin');
 };
 
 /**
@@ -549,56 +939,92 @@ $.fn.ajaxFormUnbind = function() {
  * It is this array that is passed to pre-submit callback functions provided to the
  * ajaxSubmit() and ajaxForm() methods.
  */
-$.fn.formToArray = function(semantic) {
-       var a = [];
-       if (this.length === 0) {
-               return a;
-       }
-
-       var form = this[0];
-       var els = semantic ? form.getElementsByTagName('*') : form.elements;
-       if (!els) {
-               return a;
-       }
-       
-       var i,j,n,v,el,max,jmax;
-       for(i=0, max=els.length; i < max; i++) {
-               el = els[i];
-               n = el.name;
-               if (!n) {
-                       continue;
-               }
-
-               if (semantic && form.clk && el.type == "image") {
-                       // handle image inputs on the fly when semantic == true
-                       if(!el.disabled && form.clk == el) {
-                               a.push({name: n, value: $(el).val()});
-                               a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
-                       }
-                       continue;
-               }
-
-               v = $.fieldValue(el, true);
-               if (v && v.constructor == Array) {
-                       for(j=0, jmax=v.length; j < jmax; j++) {
-                               a.push({name: n, value: v[j]});
-                       }
-               }
-               else if (v !== null && typeof v != 'undefined') {
-                       a.push({name: n, value: v});
-               }
-       }
-
-       if (!semantic && form.clk) {
-               // input type=='image' are not found in elements array! handle it here
-               var $input = $(form.clk), input = $input[0];
-               n = input.name;
-               if (n && !input.disabled && input.type == 'image') {
-                       a.push({name: n, value: $input.val()});
-                       a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
-               }
-       }
-       return a;
+$.fn.formToArray = function(semantic, elements) {
+    var a = [];
+    if (this.length === 0) {
+        return a;
+    }
+
+    var form = this[0];
+    var formId = this.attr('id');
+    var els = semantic ? form.getElementsByTagName('*') : form.elements;
+    var els2;
+
+    if (els && !/MSIE [678]/.test(navigator.userAgent)) { // #390
+        els = $(els).get();  // convert to standard array
+    }
+
+    // #386; account for inputs outside the form which use the 'form' attribute
+    if ( formId ) {
+        els2 = $(':input[form="' + formId + '"]').get(); // hat tip @thet
+        if ( els2.length ) {
+            els = (els || []).concat(els2);
+        }
+    }
+
+    if (!els || !els.length) {
+        return a;
+    }
+
+    var i,j,n,v,el,max,jmax;
+    for(i=0, max=els.length; i < max; i++) {
+        el = els[i];
+        n = el.name;
+        if (!n || el.disabled) {
+            continue;
+        }
+
+        if (semantic && form.clk && el.type == "image") {
+            // handle image inputs on the fly when semantic == true
+            if(form.clk == el) {
+                a.push({name: n, value: $(el).val(), type: el.type });
+                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+            }
+            continue;
+        }
+
+        v = $.fieldValue(el, true);
+        if (v && v.constructor == Array) {
+            if (elements) {
+                elements.push(el);
+            }
+            for(j=0, jmax=v.length; j < jmax; j++) {
+                a.push({name: n, value: v[j]});
+            }
+        }
+        else if (feature.fileapi && el.type == 'file') {
+            if (elements) {
+                elements.push(el);
+            }
+            var files = el.files;
+            if (files.length) {
+                for (j=0; j < files.length; j++) {
+                    a.push({name: n, value: files[j], type: el.type});
+                }
+            }
+            else {
+                // #180
+                a.push({ name: n, value: '', type: el.type });
+            }
+        }
+        else if (v !== null && typeof v != 'undefined') {
+            if (elements) {
+                elements.push(el);
+            }
+            a.push({name: n, value: v, type: el.type, required: el.required});
+        }
+    }
+
+    if (!semantic && form.clk) {
+        // input type=='image' are not found in elements array! handle it here
+        var $input = $(form.clk), input = $input[0];
+        n = input.name;
+        if (n && !input.disabled && input.type == 'image') {
+            a.push({name: n, value: $input.val()});
+            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+        }
+    }
+    return a;
 };
 
 /**
@@ -606,8 +1032,8 @@ $.fn.formToArray = function(semantic) {
  * in the format: name1=value1&amp;name2=value2
  */
 $.fn.formSerialize = function(semantic) {
-       //hand off to jQuery.param for proper encoding
-       return $.param(this.formToArray(semantic));
+    //hand off to jQuery.param for proper encoding
+    return $.param(this.formToArray(semantic));
 };
 
 /**
@@ -615,51 +1041,51 @@ $.fn.formSerialize = function(semantic) {
  * This method will return a string in the format: name1=value1&amp;name2=value2
  */
 $.fn.fieldSerialize = function(successful) {
-       var a = [];
-       this.each(function() {
-               var n = this.name;
-               if (!n) {
-                       return;
-               }
-               var v = $.fieldValue(this, successful);
-               if (v && v.constructor == Array) {
-                       for (var i=0,max=v.length; i < max; i++) {
-                               a.push({name: n, value: v[i]});
-                       }
-               }
-               else if (v !== null && typeof v != 'undefined') {
-                       a.push({name: this.name, value: v});
-               }
-       });
-       //hand off to jQuery.param for proper encoding
-       return $.param(a);
+    var a = [];
+    this.each(function() {
+        var n = this.name;
+        if (!n) {
+            return;
+        }
+        var v = $.fieldValue(this, successful);
+        if (v && v.constructor == Array) {
+            for (var i=0,max=v.length; i < max; i++) {
+                a.push({name: n, value: v[i]});
+            }
+        }
+        else if (v !== null && typeof v != 'undefined') {
+            a.push({name: this.name, value: v});
+        }
+    });
+    //hand off to jQuery.param for proper encoding
+    return $.param(a);
 };
 
 /**
  * Returns the value(s) of the element in the matched set.  For example, consider the following form:
  *
  *  <form><fieldset>
- *       <input name="A" type="text" />
- *       <input name="A" type="text" />
- *       <input name="B" type="checkbox" value="B1" />
- *       <input name="B" type="checkbox" value="B2"/>
- *       <input name="C" type="radio" value="C1" />
- *       <input name="C" type="radio" value="C2" />
+ *      <input name="A" type="text" />
+ *      <input name="A" type="text" />
+ *      <input name="B" type="checkbox" value="B1" />
+ *      <input name="B" type="checkbox" value="B2"/>
+ *      <input name="C" type="radio" value="C1" />
+ *      <input name="C" type="radio" value="C2" />
  *  </fieldset></form>
  *
- *  var v = $(':text').fieldValue();
+ *  var v = $('input[type=text]').fieldValue();
  *  // if no values are entered into the text inputs
  *  v == ['','']
  *  // if values entered into the text inputs are 'foo' and 'bar'
  *  v == ['foo','bar']
  *
- *  var v = $(':checkbox').fieldValue();
+ *  var v = $('input[type=checkbox]').fieldValue();
  *  // if neither checkbox is checked
  *  v === undefined
  *  // if both checkboxes are checked
  *  v == ['B1', 'B2']
  *
- *  var v = $(':radio').fieldValue();
+ *  var v = $('input[type=radio]').fieldValue();
  *  // if neither radio is checked
  *  v === undefined
  *  // if first radio is checked
@@ -671,60 +1097,65 @@ $.fn.fieldSerialize = function(successful) {
  * for each element is returned.
  *
  * Note: This method *always* returns an array.  If no valid value can be determined the
- *        array will be empty, otherwise it will contain one or more values.
+ *    array will be empty, otherwise it will contain one or more values.
  */
 $.fn.fieldValue = function(successful) {
-       for (var val=[], i=0, max=this.length; i < max; i++) {
-               var el = this[i];
-               var v = $.fieldValue(el, successful);
-               if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
-                       continue;
-               }
-               v.constructor == Array ? $.merge(val, v) : val.push(v);
-       }
-       return val;
+    for (var val=[], i=0, max=this.length; i < max; i++) {
+        var el = this[i];
+        var v = $.fieldValue(el, successful);
+        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
+            continue;
+        }
+        if (v.constructor == Array) {
+            $.merge(val, v);
+        }
+        else {
+            val.push(v);
+        }
+    }
+    return val;
 };
 
 /**
  * Returns the value of the field element.
  */
 $.fieldValue = function(el, successful) {
-       var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
-       if (successful === undefined) {
-               successful = true;
-       }
-
-       if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
-               (t == 'checkbox' || t == 'radio') && !el.checked ||
-               (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
-               tag == 'select' && el.selectedIndex == -1)) {
-                       return null;
-       }
-
-       if (tag == 'select') {
-               var index = el.selectedIndex;
-               if (index < 0) {
-                       return null;
-               }
-               var a = [], ops = el.options;
-               var one = (t == 'select-one');
-               var max = (one ? index+1 : ops.length);
-               for(var i=(one ? index : 0); i < max; i++) {
-                       var op = ops[i];
-                       if (op.selected) {
-                               var v = op.value;
-                               if (!v) { // extra pain for IE...
-                                       v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
-                               }
-                               if (one) {
-                                       return v;
-                               }
-                               a.push(v);
-                       }
-               }
-               return a;
-       }
-       return $(el).val();
+    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
+    if (successful === undefined) {
+        successful = true;
+    }
+
+    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
+        (t == 'checkbox' || t == 'radio') && !el.checked ||
+        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
+        tag == 'select' && el.selectedIndex == -1)) {
+            return null;
+    }
+
+    if (tag == 'select') {
+        var index = el.selectedIndex;
+        if (index < 0) {
+            return null;
+        }
+        var a = [], ops = el.options;
+        var one = (t == 'select-one');
+        var max = (one ? index+1 : ops.length);
+        for(var i=(one ? index : 0); i < max; i++) {
+            var op = ops[i];
+            if (op.selected) {
+                var v = op.value;
+                if (!v) { // extra pain for IE...
+                    v = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text : op.value;
+                }
+                if (one) {
+                    return v;
+                }
+                a.push(v);
+            }
+        }
+        return a;
+    }
+    return $(el).val();
 };
 
 /**
@@ -735,53 +1166,71 @@ $.fieldValue = function(el, successful) {
  *  - inputs of type submit, button, reset, and hidden will *not* be effected
  *  - button elements will *not* be effected
  */
-$.fn.clearForm = function() {
-       return this.each(function() {
-               $('input,select,textarea', this).clearFields();
-       });
+$.fn.clearForm = function(includeHidden) {
+    return this.each(function() {
+        $('input,select,textarea', this).clearFields(includeHidden);
+    });
 };
 
 /**
  * Clears the selected form elements.
  */
-$.fn.clearFields = $.fn.clearInputs = function() {
-       return this.each(function() {
-               var t = this.type, tag = this.tagName.toLowerCase();
-               if (t == 'text' || t == 'password' || tag == 'textarea') {
-                       this.value = '';
-               }
-               else if (t == 'checkbox' || t == 'radio') {
-                       this.checked = false;
-               }
-               else if (tag == 'select') {
-                       this.selectedIndex = -1;
-               }
-       });
+$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
+    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
+    return this.each(function() {
+        var t = this.type, tag = this.tagName.toLowerCase();
+        if (re.test(t) || tag == 'textarea') {
+            this.value = '';
+        }
+        else if (t == 'checkbox' || t == 'radio') {
+            this.checked = false;
+        }
+        else if (tag == 'select') {
+            this.selectedIndex = -1;
+        }
+        else if (t == "file") {
+            if (/MSIE/.test(navigator.userAgent)) {
+                $(this).replaceWith($(this).clone(true));
+            } else {
+                $(this).val('');
+            }
+        }
+        else if (includeHidden) {
+            // includeHidden can be the value true, or it can be a selector string
+            // indicating a special test; for example:
+            //  $('#myForm').clearForm('.special:hidden')
+            // the above would clean hidden inputs that have the class of 'special'
+            if ( (includeHidden === true && /hidden/.test(t)) ||
+                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) {
+                this.value = '';
+            }
+        }
+    });
 };
 
 /**
  * Resets the form data.  Causes all form elements to be reset to their original value.
  */
 $.fn.resetForm = function() {
-       return this.each(function() {
-               // guard against an input with the name of 'reset'
-               // note that IE reports the reset function as an 'object'
-               if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
-                       this.reset();
-               }
-       });
+    return this.each(function() {
+        // guard against an input with the name of 'reset'
+        // note that IE reports the reset function as an 'object'
+        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
+            this.reset();
+        }
+    });
 };
 
 /**
  * Enables or disables any matching elements.
  */
 $.fn.enable = function(b) {
-       if (b === undefined) {
-               b = true;
-       }
-       return this.each(function() {
-               this.disabled = !b;
-       });
+    if (b === undefined) {
+        b = true;
+    }
+    return this.each(function() {
+        this.disabled = !b;
+    });
 };
 
 /**
@@ -789,37 +1238,40 @@ $.fn.enable = function(b) {
  * selects/deselects and matching option elements.
  */
 $.fn.selected = function(select) {
-       if (select === undefined) {
-               select = true;
-       }
-       return this.each(function() {
-               var t = this.type;
-               if (t == 'checkbox' || t == 'radio') {
-                       this.checked = select;
-               }
-               else if (this.tagName.toLowerCase() == 'option') {
-                       var $sel = $(this).parent('select');
-                       if (select && $sel[0] && $sel[0].type == 'select-one') {
-                               // deselect all other options
-                               $sel.find('option').selected(false);
-                       }
-                       this.selected = select;
-               }
-       });
+    if (select === undefined) {
+        select = true;
+    }
+    return this.each(function() {
+        var t = this.type;
+        if (t == 'checkbox' || t == 'radio') {
+            this.checked = select;
+        }
+        else if (this.tagName.toLowerCase() == 'option') {
+            var $sel = $(this).parent('select');
+            if (select && $sel[0] && $sel[0].type == 'select-one') {
+                // deselect all other options
+                $sel.find('option').selected(false);
+            }
+            this.selected = select;
+        }
+    });
 };
 
+// expose debug var
+$.fn.ajaxSubmit.debug = false;
+
 // helper fn for console logging
-// set $.fn.ajaxSubmit.debug to true to enable debug logging
 function log() {
-       if ($.fn.ajaxSubmit.debug) {
-               var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
-               if (window.console && window.console.log) {
-                       window.console.log(msg);
-               }
-               else if (window.opera && window.opera.postError) {
-                       window.opera.postError(msg);
-               }
-       }
-};
-
-})(jQuery);
+    if (!$.fn.ajaxSubmit.debug) {
+        return;
+    }
+    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
+    if (window.console && window.console.log) {
+        window.console.log(msg);
+    }
+    else if (window.opera && window.opera.postError) {
+        window.opera.postError(msg);
+    }
+}
+
+}));
diff --git a/www/plugins/crayons/js/jquery.html5uploader.js b/www/plugins/crayons/js/jquery.html5uploader.js
new file mode 100644 (file)
index 0000000..ac1fad8
--- /dev/null
@@ -0,0 +1,157 @@
+(function ($) {\r
+\r
+    $.fn.html5Uploader = function (options) {\r
+\r
+        var crlf = '\r\n';\r
+        var boundary = "iloveigloo";\r
+        var dashes = "--";\r
+\r
+        var settings = {\r
+            "name": "uploadedFile",\r
+            "postUrl": "Upload.aspx",\r
+            "onClientAbort": null,\r
+            "onClientError": null,\r
+            "onClientLoad": null,\r
+            "onClientLoadEnd": null,\r
+            "onClientLoadStart": null,\r
+            "onClientProgress": null,\r
+            "onServerAbort": null,\r
+            "onServerError": null,\r
+            "onServerLoad": null,\r
+            "onServerLoadStart": null,\r
+            "onServerProgress": null,\r
+            "onServerReadyStateChange": null,\r
+            "onSuccess": null\r
+        };\r
+\r
+        if (options) {\r
+            $.extend(settings, options);\r
+        }\r
+\r
+        return this.each(function (options) {\r
+            var $this = $(this);\r
+            if ($this.is("[type='file']")) {\r
+                $this\r
+                .bind("change", function () {\r
+                    var files = this.files;\r
+                    for (var i = 0; i < files.length; i++) {\r
+                        fileHandler(files[i]);\r
+                    }\r
+                });\r
+            } else {\r
+                $this\r
+                .bind("dragenter dragover", function () {\r
+                    $(this).addClass("hover");\r
+                    return false;\r
+                })\r
+                .bind("dragleave", function () {\r
+                    $(this).removeClass("hover");\r
+                    return false;\r
+                })\r
+                .bind("drop", function (e) {\r
+                    $(this).removeClass("hover");\r
+                    var files = e.originalEvent.dataTransfer.files;\r
+                    for (var i = 0; i < files.length; i++) {\r
+                        fileHandler(files[i]);\r
+                    }\r
+                    return false;\r
+                });\r
+            }\r
+        });\r
+\r
+        function fileHandler(file) {\r
+            var fileReader = new FileReader();\r
+            fileReader.onabort = function (e) {\r
+                if (settings.onClientAbort) {\r
+                    settings.onClientAbort(e, file);\r
+                }\r
+            };\r
+            fileReader.onerror = function (e) {\r
+                if (settings.onClientError) {\r
+                    settings.onClientError(e, file);\r
+                }\r
+            };\r
+            fileReader.onload = function (e) {\r
+                if (settings.onClientLoad) {\r
+                    settings.onClientLoad(e, file);\r
+                }\r
+            };\r
+            fileReader.onloadend = function (e) {\r
+                if (settings.onClientLoadEnd) {\r
+                    settings.onClientLoadEnd(e, file);\r
+                }\r
+            };\r
+            fileReader.onloadstart = function (e) {\r
+                if (settings.onClientLoadStart) {\r
+                    settings.onClientLoadStart(e, file);\r
+                }\r
+            };\r
+            fileReader.onprogress = function (e) {\r
+                if (settings.onClientProgress) {\r
+                    settings.onClientProgress(e, file);\r
+                }\r
+            };\r
+            fileReader.readAsDataURL(file);\r
+\r
+            var xmlHttpRequest = new XMLHttpRequest();\r
+            xmlHttpRequest.upload.onabort = function (e) {\r
+                if (settings.onServerAbort) {\r
+                    settings.onServerAbort(e, file);\r
+                }\r
+            };\r
+            xmlHttpRequest.upload.onerror = function (e) {\r
+                if (settings.onServerError) {\r
+                    settings.onServerError(e, file);\r
+                }\r
+            };\r
+            xmlHttpRequest.upload.onload = function (e) {\r
+                if (settings.onServerLoad) {\r
+                    settings.onServerLoad(e, file);\r
+                }\r
+            };\r
+            xmlHttpRequest.upload.onloadstart = function (e) {\r
+                if (settings.onServerLoadStart) {\r
+                    settings.onServerLoadStart(e, file);\r
+                }\r
+            };\r
+            xmlHttpRequest.upload.onprogress = function (e) {\r
+                if (settings.onServerProgress) {\r
+                    settings.onServerProgress(e, file);\r
+                }\r
+            };\r
+            xmlHttpRequest.onreadystatechange = function (e) {\r
+                if (settings.onServerReadyStateChange) {\r
+                    settings.onServerReadyStateChange(e, file, xmlHttpRequest.readyState);\r
+                }\r
+                if (settings.onSuccess && xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200) {\r
+                    settings.onSuccess(e, file, xmlHttpRequest.responseText);\r
+                }\r
+            };\r
+            xmlHttpRequest.open("POST", settings.postUrl, true);\r
+\r
+            if (file.getAsBinary) { // Firefox\r
+\r
+                var data = dashes + boundary + crlf +\r
+                    "Content-Disposition: form-data;" +\r
+                    "name=\"" + settings.name + "\";" +\r
+                    "filename=\"" + unescape(encodeURIComponent(file.name)) + "\"" + crlf +\r
+                    "Content-Type: application/octet-stream" + crlf + crlf +\r
+                    file.getAsBinary() + crlf +\r
+                    dashes + boundary + dashes;\r
+\r
+                xmlHttpRequest.setRequestHeader("Content-Type", "multipart/form-data;boundary=" + boundary);\r
+                xmlHttpRequest.sendAsBinary(data);\r
+\r
+            } else if (window.FormData) { // Chrome\r
+\r
+                var formData = new FormData();\r
+                formData.append(settings.name, file);\r
+\r
+                xmlHttpRequest.send(formData);\r
+\r
+            }\r
+        }\r
+\r
+    };\r
+\r
+})(jQuery);
\ No newline at end of file
diff --git a/www/plugins/crayons/js/jquery.html5uploader.min.js b/www/plugins/crayons/js/jquery.html5uploader.min.js
deleted file mode 100644 (file)
index 3e18698..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*!
-* jQuery HTML5 Uploader 1.0b
-*
-* http://www.igloolab.com/jquery-html5-uploader
-*/
-(function($){$.fn.html5Uploader=function(options){var crlf='\r\n';var boundary="iloveigloo";var dashes="--";var settings={"name":"uploadedFile","postUrl":"Upload.aspx","onClientAbort":null,"onClientError":null,"onClientLoad":null,"onClientLoadEnd":null,"onClientLoadStart":null,"onClientProgress":null,"onServerAbort":null,"onServerError":null,"onServerLoad":null,"onServerLoadStart":null,"onServerProgress":null,"onServerReadyStateChange":null};if(options){$.extend(settings,options);}
-return this.each(function(options){var $this=$(this);if($this.is("[type='file']")){$this
-.bind("change",function(){var files=this.files;for(var i=0;i<files.length;i++){fileHandler(files[i]);}});}else{$this
-.bind("dragenter dragover",function(){return false;})
-.bind("drop",function(e){var files=e.originalEvent.dataTransfer.files;for(var i=0;i<files.length;i++){fileHandler(files[i]);}
-return false;});}});function fileHandler(file){var fileReader=new FileReader();fileReader.onabort=function(e){if(settings.onClientAbort){settings.onClientAbort(e,file);}};fileReader.onerror=function(e){if(settings.onClientError){settings.onClientError(e,file);}};fileReader.onload=function(e){if(settings.onClientLoad){settings.onClientLoad(e,file);}};fileReader.onloadend=function(e){if(settings.onClientLoadEnd){settings.onClientLoadEnd(e,file);}};fileReader.onloadstart=function(e){if(settings.onClientLoadStart){settings.onClientLoadStart(e,file);}};fileReader.onprogress=function(e){if(settings.onClientProgress){settings.onClientProgress(e,file);}};fileReader.readAsDataURL(file);var xmlHttpRequest=new XMLHttpRequest();xmlHttpRequest.upload.onabort=function(e){if(settings.onServerAbort){settings.onServerAbort(e,file);}};xmlHttpRequest.upload.onerror=function(e){if(settings.onServerError){settings.onServerError(e,file);}};xmlHttpRequest.upload.onload=function(e){if(settings.onServerLoad){settings.onServerLoad(e,file);}};xmlHttpRequest.upload.onloadstart=function(e){if(settings.onServerLoadStart){settings.onServerLoadStart(e,file);}};xmlHttpRequest.upload.onprogress=function(e){if(settings.onServerProgress){settings.onServerProgress(e,file);}};xmlHttpRequest.onreadystatechange=function(e){if(settings.onServerReadyStateChange){settings.onServerReadyStateChange(e,file);}};xmlHttpRequest.open("POST",settings.postUrl,true);if(file.getAsBinary){var data=dashes+boundary+crlf+
-"Content-Disposition: form-data;"+
-"name=\""+settings.name+"\";"+
-"filename=\""+unescape(encodeURIComponent(file.name))+"\""+crlf+
-"Content-Type: application/octet-stream"+crlf+crlf+
-file.getAsBinary()+crlf+
-dashes+boundary+dashes;xmlHttpRequest.setRequestHeader("Content-Type","multipart/form-data;boundary="+boundary);xmlHttpRequest.sendAsBinary(data);}else if(window.FormData){var formData=new FormData();formData.append(settings.name,file);xmlHttpRequest.send(formData);}}};})(jQuery);
index 9a13ab9..6feb110 100644 (file)
 /*!
- * jQuery JavaScript Library v1.6
+ * jQuery JavaScript Library v1.11.3
  * 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 May 2 13:50:00 2011 -0400
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-04-28T16:19Z
  */
-(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
-       // (both of which we optimize for)
-       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.]+))?/,
-
-       // 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;
-               }
+(function( global, factory ) {
+
+       if ( typeof module === "object" && typeof module.exports === "object" ) {
+               // For CommonJS and CommonJS-like environments where a proper window is present,
+               // execute the factory and get jQuery
+               // For environments that do not inherently posses a window with a document
+               // (such as Node.js), expose a jQuery-making factory as module.exports
+               // This accentuates the need for the creation of a real window
+               // e.g. var jQuery = require("jquery")(window);
+               // See ticket #14549 for more info
+               module.exports = global.document ?
+                       factory( global, true ) :
+                       function( w ) {
+                               if ( !w.document ) {
+                                       throw new Error( "jQuery requires a window with a document" );
+                               }
+                               return factory( w );
+                       };
+       } else {
+               factory( global );
+       }
 
-               // Handle $(DOMElement)
-               if ( selector.nodeType ) {
-                       this.context = this[0] = selector;
-                       this.length = 1;
-                       return this;
-               }
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
 
-               // 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;
-               }
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//
 
-               // 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 ];
+var deletedIds = [];
 
-                       } else {
-                               match = quickExpr.exec( selector );
-                       }
+var slice = deletedIds.slice;
 
-                       // Verify a match, and that no context was specified for #id
-                       if ( match && (match[1] || !context) ) {
+var concat = deletedIds.concat;
 
-                               // HANDLE: $(html) -> $(array)
-                               if ( match[1] ) {
-                                       context = context instanceof jQuery ? context[0] : context;
-                                       doc = (context ? context.ownerDocument || context : document);
+var push = deletedIds.push;
 
-                                       // 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 );
+var indexOf = deletedIds.indexOf;
 
-                                       if ( ret ) {
-                                               if ( jQuery.isPlainObject( context ) ) {
-                                                       selector = [ document.createElement( ret[1] ) ];
-                                                       jQuery.fn.attr.call( selector, context, true );
+var class2type = {};
 
-                                               } else {
-                                                       selector = [ doc.createElement( ret[1] ) ];
-                                               }
+var toString = class2type.toString;
 
-                                       } else {
-                                               ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
-                                               selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
-                                       }
+var hasOwn = class2type.hasOwnProperty;
 
-                                       return jQuery.merge( this, selector );
+var support = {};
 
-                               // 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;
-                                       }
+var
+       version = "1.11.3",
 
-                                       this.context = document;
-                                       this.selector = selector;
-                                       return this;
-                               }
+       // Define a local copy of jQuery
+       jQuery = function( selector, context ) {
+               // The jQuery object is actually just the init constructor 'enhanced'
+               // Need init if jQuery is called (just allow error to be thrown if not included)
+               return new jQuery.fn.init( selector, context );
+       },
 
-                       // HANDLE: $(expr, $(...))
-                       } else if ( !context || context.jquery ) {
-                               return (context || rootjQuery).find( selector );
+       // Support: Android<4.1, IE<9
+       // Make sure we trim BOM and NBSP
+       rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
 
-                       // HANDLE: $(expr, context)
-                       // (which is just equivalent to: $(context).find(expr)
-                       } else {
-                               return this.constructor( context ).find( selector );
-                       }
+       // Matches dashed string for camelizing
+       rmsPrefix = /^-ms-/,
+       rdashAlpha = /-([\da-z])/gi,
 
-               // HANDLE: $(function)
-               // Shortcut for document ready
-               } else if ( jQuery.isFunction( selector ) ) {
-                       return rootjQuery.ready( selector );
-               }
+       // Used by jQuery.camelCase as callback to replace()
+       fcamelCase = function( all, letter ) {
+               return letter.toUpperCase();
+       };
 
-               if (selector.selector !== undefined) {
-                       this.selector = selector.selector;
-                       this.context = selector.context;
-               }
+jQuery.fn = jQuery.prototype = {
+       // The current version of jQuery being used
+       jquery: version,
 
-               return jQuery.makeArray( selector, this );
-       },
+       constructor: jQuery,
 
        // Start with an empty selector
        selector: "",
 
-       // The current version of jQuery being used
-       jquery: "1.6",
-
        // 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 );
+               return slice.call( this );
        },
 
        // Get the Nth element in the matched element set OR
        // Get the whole matched element set as a clean array
        get: function( num ) {
-               return num == null ?
+               return num != null ?
 
-                       // Return a 'clean' array
-                       this.toArray() :
+                       // Return just the one element from the set
+                       ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
 
-                       // Return just the object
-                       ( num < 0 ? this[ this.length + num ] : this[ num ] );
+                       // Return all the elements in a clean array
+                       slice.call( this );
        },
 
        // Take an array of elements and push it onto the stack
        // (returning the new matched element set)
-       pushStack: function( elems, name, selector ) {
-               // Build a new jQuery matched element set
-               var ret = this.constructor();
-
-               if ( jQuery.isArray( elems ) ) {
-                       push.apply( ret, elems );
+       pushStack: function( elems ) {
 
-               } else {
-                       jQuery.merge( ret, elems );
-               }
+               // Build a new jQuery matched element set
+               var ret = jQuery.merge( this.constructor(), elems );
 
                // Add the old object onto the stack (as a reference)
                ret.prevObject = this;
-
                ret.context = this.context;
 
-               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;
        },
@@ -265,20 +136,14 @@ jQuery.fn = jQuery.prototype = {
                return jQuery.each( this, callback, args );
        },
 
-       ready: function( fn ) {
-               // Attach the listeners
-               jQuery.bindReady();
-
-               // Add the callback
-               readyList.done( fn );
-
-               return this;
+       map: function( callback ) {
+               return this.pushStack( jQuery.map(this, function( elem, i ) {
+                       return callback.call( elem, i, elem );
+               }));
        },
 
-       eq: function( i ) {
-               return i === -1 ?
-                       this.slice( i ) :
-                       this.slice( i, +i + 1 );
+       slice: function() {
+               return this.pushStack( slice.apply( this, arguments ) );
        },
 
        first: function() {
@@ -289,15 +154,10 @@ jQuery.fn = jQuery.prototype = {
                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 );
-               }));
+       eq: function( i ) {
+               var len = this.length,
+                       j = +i + ( i < 0 ? len : 0 );
+               return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
        },
 
        end: function() {
@@ -307,15 +167,12 @@ jQuery.fn = jQuery.prototype = {
        // For internal use only.
        // Behaves like an Array's method, not like a jQuery method.
        push: push,
-       sort: [].sort,
-       splice: [].splice
+       sort: deletedIds.sort,
+       splice: deletedIds.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,
+       var src, copyIsArray, copy, name, options, clone,
                target = arguments[0] || {},
                i = 1,
                length = arguments.length,
@@ -324,9 +181,10 @@ jQuery.extend = jQuery.fn.extend = function() {
        // Handle a deep copy situation
        if ( typeof target === "boolean" ) {
                deep = target;
-               target = arguments[1] || {};
+
                // skip the boolean and the target
-               i = 2;
+               target = arguments[ i ] || {};
+               i++;
        }
 
        // Handle case when target is a string or something (possible in deep copy)
@@ -335,9 +193,9 @@ jQuery.extend = jQuery.fn.extend = function() {
        }
 
        // extend jQuery itself if only one argument is passed
-       if ( length === i ) {
+       if ( i === length ) {
                target = this;
-               --i;
+               i--;
        }
 
        for ( ; i < length; i++ ) {
@@ -379,105 +237,17 @@ jQuery.extend = jQuery.fn.extend = function() {
 };
 
 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;
-                       }
+       // Unique for each copy of jQuery on the page
+       expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
 
-                       // If there are functions bound, to execute
-                       readyList.resolveWith( document, [ jQuery ] );
+       // Assume jQuery is ready without the ready module
+       isReady: true,
 
-                       // Trigger any bound ready events
-                       if ( jQuery.fn.trigger ) {
-                               jQuery( document ).trigger( "ready" ).unbind( "ready" );
-                       }
-               }
+       error: function( msg ) {
+               throw new Error( msg );
        },
 
-       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();
-                       }
-               }
-       },
+       noop: function() {},
 
        // See test/unit/core.js for details concerning isFunction.
        // Since version 1.3, DOM methods and functions like alert
@@ -490,22 +260,30 @@ jQuery.extend({
                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;
+               /* jshint eqeqeq: false */
+               return obj != null && obj == obj.window;
        },
 
-       isNaN: function( obj ) {
-               return obj == null || !rdigit.test( obj ) || isNaN( obj );
+       isNumeric: function( obj ) {
+               // parseFloat NaNs numeric-cast false positives (null|true|false|"")
+               // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+               // subtraction forces infinities to NaN
+               // adding 1 corrects loss of precision from parseFloat (#15100)
+               return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
        },
 
-       type: function( obj ) {
-               return obj == null ?
-                       String( obj ) :
-                       class2type[ toString.call(obj) ] || "object";
+       isEmptyObject: function( obj ) {
+               var name;
+               for ( name in obj ) {
+                       return false;
+               }
+               return true;
        },
 
        isPlainObject: function( obj ) {
+               var key;
+
                // Must be an Object.
                // Because of IE, we also have to check the presence of the constructor property.
                // Make sure that DOM nodes and window objects don't pass through, as well
@@ -513,87 +291,47 @@ jQuery.extend({
                        return false;
                }
 
-               // Not own constructor property must be Object
-               if ( obj.constructor &&
-                       !hasOwn.call(obj, "constructor") &&
-                       !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+               try {
+                       // Not own constructor property must be Object
+                       if ( obj.constructor &&
+                               !hasOwn.call(obj, "constructor") &&
+                               !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+                               return false;
+                       }
+               } catch ( e ) {
+                       // IE8,9 Will throw exceptions on certain host objects #9897
                        return false;
                }
 
+               // Support: IE<9
+               // Handle iteration over inherited properties before own properties.
+               if ( support.ownLast ) {
+                       for ( key in obj ) {
+                               return hasOwn.call( obj, key );
+                       }
+               }
+
                // Own properties are enumerated firstly, so to speed up,
                // if last one is own, then all properties are own.
-
-               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
-       // (xml & tmp used internally)
-       parseXML: function( data , xml , tmp ) {
-
-               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 );
-               }
-
-               tmp = xml.documentElement;
-
-               if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
-                       jQuery.error( "Invalid XML: " + data );
+       type: function( obj ) {
+               if ( obj == null ) {
+                       return obj + "";
                }
-
-               return xml;
+               return typeof obj === "object" || typeof obj === "function" ?
+                       class2type[ toString.call(obj) ] || "object" :
+                       typeof obj;
        },
 
-       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 ) ) {
+               if ( data && jQuery.trim( data ) ) {
                        // We use execScript on Internet Explorer
                        // We use an anonymous function so that context is window
                        // rather than jQuery in Firefox
@@ -603,26 +341,37 @@ jQuery.extend({
                }
        },
 
+       // 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();
+               return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
        },
 
        // args is for internal usage only
-       each: function( object, callback, args ) {
-               var name, i = 0,
-                       length = object.length,
-                       isObj = length === undefined || jQuery.isFunction( object );
+       each: function( obj, callback, args ) {
+               var value,
+                       i = 0,
+                       length = obj.length,
+                       isArray = isArraylike( obj );
 
                if ( args ) {
-                       if ( isObj ) {
-                               for ( name in object ) {
-                                       if ( callback.apply( object[ name ], args ) === false ) {
+                       if ( isArray ) {
+                               for ( ; i < length; i++ ) {
+                                       value = callback.apply( obj[ i ], args );
+
+                                       if ( value === false ) {
                                                break;
                                        }
                                }
                        } else {
-                               for ( ; i < length; ) {
-                                       if ( callback.apply( object[ i++ ], args ) === false ) {
+                               for ( i in obj ) {
+                                       value = callback.apply( obj[ i ], args );
+
+                                       if ( value === false ) {
                                                break;
                                        }
                                }
@@ -630,69 +379,69 @@ jQuery.extend({
 
                // 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 ) {
+                       if ( isArray ) {
+                               for ( ; i < length; i++ ) {
+                                       value = callback.call( obj[ i ], i, obj[ i ] );
+
+                                       if ( value === false ) {
                                                break;
                                        }
                                }
                        } else {
-                               for ( ; i < length; ) {
-                                       if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+                               for ( i in obj ) {
+                                       value = callback.call( obj[ i ], i, obj[ i ] );
+
+                                       if ( value === false ) {
                                                break;
                                        }
                                }
                        }
                }
 
-               return object;
+               return obj;
        },
 
-       // 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, "" );
-               },
+       // Support: Android<4.1, IE<9
+       trim: function( text ) {
+               return text == null ?
+                       "" :
+                       ( text + "" ).replace( rtrim, "" );
+       },
 
        // results is for internal usage only
-       makeArray: function( array, results ) {
+       makeArray: function( arr, 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 );
+               if ( arr != null ) {
+                       if ( isArraylike( Object(arr) ) ) {
+                               jQuery.merge( ret,
+                                       typeof arr === "string" ?
+                                       [ arr ] : arr
+                               );
                        } else {
-                               jQuery.merge( ret, array );
+                               push.call( ret, arr );
                        }
                }
 
                return ret;
        },
 
-       inArray: function( elem, array ) {
+       inArray: function( elem, arr, i ) {
+               var len;
 
-               if ( indexOf ) {
-                       return indexOf.call( array, elem );
-               }
+               if ( arr ) {
+                       if ( indexOf ) {
+                               return indexOf.call( arr, elem, i );
+                       }
 
-               for ( var i = 0, length = array.length; i < length; i++ ) {
-                       if ( array[ i ] === elem ) {
-                               return i;
+                       len = arr.length;
+                       i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+                       for ( ; i < len; i++ ) {
+                               // Skip accessing in sparse arrays
+                               if ( i in arr && arr[ i ] === elem ) {
+                                       return i;
+                               }
                        }
                }
 
@@ -700,15 +449,17 @@ jQuery.extend({
        },
 
        merge: function( first, second ) {
-               var i = first.length,
-                       j = 0;
+               var len = +second.length,
+                       j = 0,
+                       i = first.length;
 
-               if ( typeof second.length === "number" ) {
-                       for ( var l = second.length; j < l; j++ ) {
-                               first[ i++ ] = second[ j ];
-                       }
+               while ( j < len ) {
+                       first[ i++ ] = second[ j++ ];
+               }
 
-               } else {
+               // Support: IE<9
+               // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
+               if ( len !== len ) {
                        while ( second[j] !== undefined ) {
                                first[ i++ ] = second[ j++ ];
                        }
@@ -719,53 +470,56 @@ jQuery.extend({
                return first;
        },
 
-       grep: function( elems, callback, inv ) {
-               var ret = [], retVal;
-               inv = !!inv;
+       grep: function( elems, callback, invert ) {
+               var callbackInverse,
+                       matches = [],
+                       i = 0,
+                       length = elems.length,
+                       callbackExpect = !invert;
 
                // Go through the array, only saving the items
                // that pass the validator function
-               for ( var i = 0, length = elems.length; i < length; i++ ) {
-                       retVal = !!callback( elems[ i ], i );
-                       if ( inv !== retVal ) {
-                               ret.push( elems[ i ] );
+               for ( ; i < length; i++ ) {
+                       callbackInverse = !callback( elems[ i ], i );
+                       if ( callbackInverse !== callbackExpect ) {
+                               matches.push( elems[ i ] );
                        }
                }
 
-               return ret;
+               return matches;
        },
 
        // arg is for internal usage only
        map: function( elems, callback, arg ) {
-               var value, key, ret = [],
+               var value,
                        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 ) ) ;
+                       isArray = isArraylike( elems ),
+                       ret = [];
 
-               // Go through the array, translating each of the items to their
+               // Go through the array, translating each of the items to their new values
                if ( isArray ) {
                        for ( ; i < length; i++ ) {
                                value = callback( elems[ i ], i, arg );
 
                                if ( value != null ) {
-                                       ret[ ret.length ] = value;
+                                       ret.push( value );
                                }
                        }
 
                // Go through every key on the object,
                } else {
-                       for ( key in elems ) {
-                               value = callback( elems[ key ], key, arg );
+                       for ( i in elems ) {
+                               value = callback( elems[ i ], i, arg );
 
                                if ( value != null ) {
-                                       ret[ ret.length ] = value;
+                                       ret.push( value );
                                }
                        }
                }
 
                // Flatten any nested arrays
-               return ret.concat.apply( [], ret );
+               return concat.apply( [], ret );
        },
 
        // A global GUID counter for objects
@@ -774,8 +528,10 @@ jQuery.extend({
        // Bind a function to a context, optionally partially applying any
        // arguments.
        proxy: function( fn, context ) {
+               var args, proxy, tmp;
+
                if ( typeof context === "string" ) {
-                       var tmp = fn[ context ];
+                       tmp = fn[ context ];
                        context = fn;
                        fn = tmp;
                }
@@ -787,5071 +543,5459 @@ jQuery.extend({
                }
 
                // Simulated bind
-               var args = slice.call( arguments, 2 ),
-                       proxy = function() {
-                               return fn.apply( context, args.concat( slice.call( arguments ) ) );
-                       };
+               args = slice.call( arguments, 2 );
+               proxy = function() {
+                       return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+               };
 
                // Set the guid of unique handler to the same of original handler, so it can be removed
-               proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+               proxy.guid = fn.guid = fn.guid || jQuery.guid++;
 
                return proxy;
        },
 
-       // Mutifunctional method to get and set values to a collection
-       // The value/s can be optionally by executed if its 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;
+               return +( new Date() );
        },
 
-       browser: {}
+       // jQuery.support is not used in Core but other projects attach their
+       // properties to it so it needs to exist.
+       support: support
 });
 
 // Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".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;
-}
+function isArraylike( obj ) {
 
-// Deprecated, use jQuery.browser.webkit instead
-if ( jQuery.browser.webkit ) {
-       jQuery.browser.safari = true;
-}
+       // Support: iOS 8.2 (not reproducible in simulator)
+       // `in` check used to prevent JIT error (gh-2145)
+       // hasOwn isn't used here due to false negatives
+       // regarding Nodelist length in IE
+       var length = "length" in obj && obj.length,
+               type = jQuery.type( obj );
+
+       if ( type === "function" || jQuery.isWindow( obj ) ) {
+               return false;
+       }
 
-// IE doesn't match non-breaking spaces with \s
-if ( rnotwhite.test( "\xA0" ) ) {
-       trimLeft = /^[\s\xA0]+/;
-       trimRight = /[\s\xA0]+$/;
+       if ( obj.nodeType === 1 && length ) {
+               return true;
+       }
+
+       return type === "array" || length === 0 ||
+               typeof length === "number" && length > 0 && ( length - 1 ) in obj;
 }
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.0-pre
+ * http://sizzlejs.com/
+ *
+ * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-12-16
+ */
+(function( window ) {
+
+var i,
+       support,
+       Expr,
+       getText,
+       isXML,
+       tokenize,
+       compile,
+       select,
+       outermostContext,
+       sortInput,
+       hasDuplicate,
+
+       // Local document vars
+       setDocument,
+       document,
+       docElem,
+       documentIsHTML,
+       rbuggyQSA,
+       rbuggyMatches,
+       matches,
+       contains,
+
+       // Instance-specific data
+       expando = "sizzle" + 1 * new Date(),
+       preferredDoc = window.document,
+       dirruns = 0,
+       done = 0,
+       classCache = createCache(),
+       tokenCache = createCache(),
+       compilerCache = createCache(),
+       sortOrder = function( a, b ) {
+               if ( a === b ) {
+                       hasDuplicate = true;
+               }
+               return 0;
+       },
 
-// All jQuery objects should point back to these
-rootjQuery = jQuery(document);
+       // General-purpose constants
+       MAX_NEGATIVE = 1 << 31,
 
-// Cleanup functions for the document ready method
-if ( document.addEventListener ) {
-       DOMContentLoaded = function() {
-               document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
-               jQuery.ready();
+       // Instance methods
+       hasOwn = ({}).hasOwnProperty,
+       arr = [],
+       pop = arr.pop,
+       push_native = arr.push,
+       push = arr.push,
+       slice = arr.slice,
+       // Use a stripped-down indexOf as it's faster than native
+       // http://jsperf.com/thor-indexof-vs-for/5
+       indexOf = function( list, elem ) {
+               var i = 0,
+                       len = list.length;
+               for ( ; i < len; i++ ) {
+                       if ( list[i] === elem ) {
+                               return i;
+                       }
+               }
+               return -1;
+       },
+
+       booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+       // Regular expressions
+
+       // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+       whitespace = "[\\x20\\t\\r\\n\\f]",
+       // http://www.w3.org/TR/css3-syntax/#characters
+       characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+       // Loosely modeled on CSS identifier characters
+       // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+       // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+       identifier = characterEncoding.replace( "w", "w#" ),
+
+       // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+       attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+               // Operator (capture 2)
+               "*([*^$|!~]?=)" + whitespace +
+               // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+               "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+               "*\\]",
+
+       pseudos = ":(" + characterEncoding + ")(?:\\((" +
+               // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+               // 1. quoted (capture 3; capture 4 or capture 5)
+               "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+               // 2. simple (capture 6)
+               "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+               // 3. anything else (capture 2)
+               ".*" +
+               ")\\)|)",
+
+       // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+       rwhitespace = new RegExp( whitespace + "+", "g" ),
+       rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+       rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+       rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+       rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+       rpseudo = new RegExp( pseudos ),
+       ridentifier = new RegExp( "^" + identifier + "$" ),
+
+       matchExpr = {
+               "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+               "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+               "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+               "ATTR": new RegExp( "^" + attributes ),
+               "PSEUDO": new RegExp( "^" + pseudos ),
+               "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+                       "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+                       "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+               "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+               // For use in libraries implementing .is()
+               // We use this for POS matching in `select`
+               "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+                       whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+       },
+
+       rinputs = /^(?:input|select|textarea|button)$/i,
+       rheader = /^h\d$/i,
+
+       rnative = /^[^{]+\{\s*\[native \w/,
+
+       // Easily-parseable/retrievable ID or TAG or CLASS selectors
+       rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+       rsibling = /[+~]/,
+       rescape = /'|\\/g,
+
+       // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+       runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+       funescape = function( _, escaped, escapedWhitespace ) {
+               var high = "0x" + escaped - 0x10000;
+               // NaN means non-codepoint
+               // Support: Firefox<24
+               // Workaround erroneous numeric interpretation of +"0x"
+               return high !== high || escapedWhitespace ?
+                       escaped :
+                       high < 0 ?
+                               // BMP codepoint
+                               String.fromCharCode( high + 0x10000 ) :
+                               // Supplemental Plane codepoint (surrogate pair)
+                               String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+       },
+
+       // Used for iframes
+       // See setDocument()
+       // Removing the function wrapper causes a "Permission Denied"
+       // error in IE
+       unloadHandler = function() {
+               setDocument();
        };
 
-} 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();
+// Optimize for push.apply( _, NodeList )
+try {
+       push.apply(
+               (arr = slice.call( preferredDoc.childNodes )),
+               preferredDoc.childNodes
+       );
+       // Support: Android<4.0
+       // Detect silently failing push.apply
+       arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+       push = { apply: arr.length ?
+
+               // Leverage slice if possible
+               function( target, els ) {
+                       push_native.apply( target, slice.call(els) );
+               } :
+
+               // Support: IE<9
+               // Otherwise append directly
+               function( target, els ) {
+                       var j = target.length,
+                               i = 0;
+                       // Can't trust NodeList.length
+                       while ( (target[j++] = els[i++]) ) {}
+                       target.length = j - 1;
                }
        };
 }
 
-// The DOM ready check for Internet Explorer
-function doScrollCheck() {
-       if ( jQuery.isReady ) {
-               return;
-       }
+function Sizzle( selector, context, results, seed ) {
+       var match, elem, m, nodeType,
+               // QSA vars
+               i, groups, old, nid, newContext, newSelector;
 
-       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;
+       if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+               setDocument( context );
        }
 
-       // and execute any waiting functions
-       jQuery.ready();
-}
-
-// Expose jQuery to the global object
-return jQuery;
+       context = context || document;
+       results = results || [];
+       nodeType = context.nodeType;
 
-})();
+       if ( typeof selector !== "string" || !selector ||
+               nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
 
+               return results;
+       }
 
-var // Promise methods
-       promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ),
-       // Static reference to slice
-       sliceDeferred = [].slice;
+       if ( !seed && documentIsHTML ) {
 
-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 ] );
+               // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
+               if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+                       // Speed-up: Sizzle("#ID")
+                       if ( (m = match[1]) ) {
+                               if ( nodeType === 9 ) {
+                                       elem = context.getElementById( m );
+                                       // Check parentNode to catch when Blackberry 4.6 returns
+                                       // nodes that are no longer in the document (jQuery #6963)
+                                       if ( elem && elem.parentNode ) {
+                                               // Handle the case where IE, Opera, and Webkit return items
+                                               // by name instead of ID
+                                               if ( elem.id === m ) {
+                                                       results.push( elem );
+                                                       return results;
                                                }
+                                       } else {
+                                               return results;
                                        }
-                                       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;
-                                               }
+                               } else {
+                                       // Context is not a document
+                                       if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+                                               contains( context, elem ) && elem.id === m ) {
+                                               results.push( elem );
+                                               return results;
                                        }
-                                       return this;
-                               },
+                               }
 
-                               // resolve with this as context and given arguments
-                               resolve: function() {
-                                       deferred.resolveWith( this, arguments );
-                                       return this;
-                               },
+                       // Speed-up: Sizzle("TAG")
+                       } else if ( match[2] ) {
+                               push.apply( results, context.getElementsByTagName( selector ) );
+                               return results;
 
-                               // Has this deferred been resolved?
-                               isResolved: function() {
-                                       return !!( firing || fired );
-                               },
+                       // Speed-up: Sizzle(".CLASS")
+                       } else if ( (m = match[3]) && support.getElementsByClassName ) {
+                               push.apply( results, context.getElementsByClassName( m ) );
+                               return results;
+                       }
+               }
 
-                               // Cancel
-                               cancel: function() {
-                                       cancelled = 1;
-                                       callbacks = [];
-                                       return this;
-                               }
-                       };
+               // QSA path
+               if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+                       nid = old = expando;
+                       newContext = context;
+                       newSelector = nodeType !== 1 && selector;
 
-               return deferred;
-       },
+                       // qSA works strangely on Element-rooted queries
+                       // We can work around this by specifying an extra ID on the root
+                       // and working up from there (Thanks to Andrew Dupont for the technique)
+                       // IE 8 doesn't work on object elements
+                       if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+                               groups = tokenize( selector );
 
-       // 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 ( jQuery.isFunction( returned.promise ) ) {
-                                                                       returned.promise().then( newDefer.resolve, newDefer.reject );
-                                                               } else {
-                                                                       newDefer[ action ]( 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 = {};
+                               if ( (old = context.getAttribute("id")) ) {
+                                       nid = old.replace( rescape, "\\$&" );
+                               } else {
+                                       context.setAttribute( "id", nid );
                                }
-                               var i = promiseMethods.length;
-                               while( i-- ) {
-                                       obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
+                               nid = "[id='" + nid + "'] ";
+
+                               i = groups.length;
+                               while ( i-- ) {
+                                       groups[i] = nid + toSelector( groups[i] );
                                }
-                               return obj;
+                               newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+                               newSelector = groups.join(",");
                        }
-               });
-               // 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 ( newSelector ) {
+                               try {
+                                       push.apply( results,
+                                               newContext.querySelectorAll( newSelector )
+                                       );
+                                       return results;
+                               } catch(qsaError) {
+                               } finally {
+                                       if ( !old ) {
+                                               context.removeAttribute("id");
+                                       }
                                }
                        }
-                       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" ),
-               all,
-               a,
-               select,
-               opt,
-               input,
-               marginDiv,
-               support,
-               fragment,
-               body,
-               bodyStyle,
-               tds,
-               events,
-               eventName,
-               i,
-               isSupported;
-
-       // Preliminary tests
-       div.setAttribute("className", "t");
-       div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+       // All others
+       return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
 
-       all = div.getElementsByTagName( "*" );
-       a = div.getElementsByTagName( "a" )[ 0 ];
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ *     property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ *     deleting the oldest entry
+ */
+function createCache() {
+       var keys = [];
 
-       // Can't get basic test support
-       if ( !all || !all.length || !a ) {
-               return {};
+       function cache( key, value ) {
+               // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+               if ( keys.push( key + " " ) > Expr.cacheLength ) {
+                       // Only keep the most recent entries
+                       delete cache[ keys.shift() ];
+               }
+               return (cache[ key + " " ] = value);
        }
+       return cache;
+}
 
-       // 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;
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+       fn[ expando ] = true;
+       return fn;
+}
 
-       // 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;
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+       var div = document.createElement("div");
 
-       // 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 click() {
-                       // Cloning a node shouldn't copy over any
-                       // bound event handlers (IE does this)
-                       support.noCloneEvent = false;
-                       div.detachEvent( "onclick", click );
-               });
-               div.cloneNode( true ).fireEvent( "onclick" );
+               return !!fn( div );
+       } catch (e) {
+               return false;
+       } finally {
+               // Remove from its parent by default
+               if ( div.parentNode ) {
+                       div.parentNode.removeChild( div );
+               }
+               // release memory in IE
+               div = null;
        }
+}
 
-       // 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";
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+       var arr = attrs.split("|"),
+               i = attrs.length;
 
-       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";
-
-       // We use our own, invisible, body
-       body = document.createElement( "body" );
-       bodyStyle = {
-               visibility: "hidden",
-               width: 0,
-               height: 0,
-               border: 0,
-               margin: 0,
-               // Set background to avoid IE crashes when removing (#9028)
-               background: "none"
-       };
-       for ( i in bodyStyle ) {
-               body.style[ i ] = bodyStyle[ i ];
+       while ( i-- ) {
+               Expr.attrHandle[ arr[i] ] = handler;
        }
-       body.appendChild( div );
-       document.documentElement.appendChild( body );
-
-       // 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 );
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+       var cur = b && a,
+               diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+                       ( ~b.sourceIndex || MAX_NEGATIVE ) -
+                       ( ~a.sourceIndex || MAX_NEGATIVE );
+
+       // Use IE sourceIndex if available on both nodes
+       if ( diff ) {
+               return diff;
+       }
 
-               // Check if elements with layout shrink-wrap their children
-               // (IE 6 does this)
-               div.style.display = "";
-               div.innerHTML = "<div style='width:4px;'></div>";
-               support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
-       }
-
-       div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
-       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, 10 ) || 0 ) === 0;
-       }
-
-       // Remove the body element we added
-       body.innerHTML = "";
-       document.documentElement.removeChild( body );
-
-       // 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" );
+       // Check if b follows a
+       if ( cur ) {
+               while ( (cur = cur.nextSibling) ) {
+                       if ( cur === b ) {
+                               return -1;
                        }
-                       support[ i + "Bubbles" ] = isSupported;
                }
        }
 
-       return support;
-})();
-
-// Keep track of boxModel
-jQuery.boxModel = jQuery.support.boxModel;
+       return a ? 1 : -1;
+}
 
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+       return function( elem ) {
+               var name = elem.nodeName.toLowerCase();
+               return name === "input" && elem.type === type;
+       };
+}
 
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+       return function( elem ) {
+               var name = elem.nodeName.toLowerCase();
+               return (name === "input" || name === "button") && elem.type === type;
+       };
+}
 
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+       return markFunction(function( argument ) {
+               argument = +argument;
+               return markFunction(function( seed, matches ) {
+                       var j,
+                               matchIndexes = fn( [], seed.length, argument ),
+                               i = matchIndexes.length;
+
+                       // Match elements found at the specified indexes
+                       while ( i-- ) {
+                               if ( seed[ (j = matchIndexes[i]) ] ) {
+                                       seed[j] = !(matches[j] = seed[j]);
+                               }
+                       }
+               });
+       });
+}
 
-var rbrace = /^(?:\{.*\}|\[.*\])$/,
-       rmultiDash = /([a-z])([A-Z])/g;
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+       return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
 
-jQuery.extend({
-       cache: {},
+// Expose support vars for convenience
+support = Sizzle.support = {};
 
-       // Please use with caution
-       uuid: 0,
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+       // documentElement is verified for cases where it doesn't yet exist
+       // (such as loading iframes in IE - #4833)
+       var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+       return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
 
-       // 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, "" ),
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+       var hasCompare, parent,
+               doc = node ? node.ownerDocument || node : preferredDoc;
 
-       // 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
-       },
+       // If no document and documentElement is available, return
+       if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+               return document;
+       }
 
-       hasData: function( elem ) {
-               elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+       // Set our document
+       document = doc;
+       docElem = doc.documentElement;
+       parent = doc.defaultView;
+
+       // Support: IE>8
+       // If iframe document is assigned to "document" variable and if iframe has been reloaded,
+       // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+       // IE6-8 do not support the defaultView property so parent will be undefined
+       if ( parent && parent !== parent.top ) {
+               // IE11 does not have attachEvent, so all must suffer
+               if ( parent.addEventListener ) {
+                       parent.addEventListener( "unload", unloadHandler, false );
+               } else if ( parent.attachEvent ) {
+                       parent.attachEvent( "onunload", unloadHandler );
+               }
+       }
 
-               return !!elem && !isEmptyDataObject( elem );
-       },
+       /* Support tests
+       ---------------------------------------------------------------------- */
+       documentIsHTML = !isXML( doc );
 
-       data: function( elem, name, data, pvt /* Internal Use Only */ ) {
-               if ( !jQuery.acceptData( elem ) ) {
-                       return;
-               }
+       /* Attributes
+       ---------------------------------------------------------------------- */
 
-               var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
+       // Support: IE<8
+       // Verify that getAttribute really returns attributes and not properties
+       // (excepting IE8 booleans)
+       support.attributes = assert(function( div ) {
+               div.className = "i";
+               return !div.getAttribute("className");
+       });
 
-                       // 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,
+       /* getElement(s)By*
+       ---------------------------------------------------------------------- */
 
-                       // 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,
+       // Check if getElementsByTagName("*") returns only elements
+       support.getElementsByTagName = assert(function( div ) {
+               div.appendChild( doc.createComment("") );
+               return !div.getElementsByTagName("*").length;
+       });
 
-                       // 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;
+       // Support: IE<9
+       support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
 
-               // 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 ][ internalKey ])) && getByName && data === undefined ) {
-                       return;
-               }
+       // Support: IE<10
+       // Check if getElementById returns elements by name
+       // The broken getElementById methods don't pick up programatically-set names,
+       // so use a roundabout getElementsByName test
+       support.getById = assert(function( div ) {
+               docElem.appendChild( div ).id = expando;
+               return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+       });
 
-               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;
+       // ID find and filter
+       if ( support.getById ) {
+               Expr.find["ID"] = function( id, context ) {
+                       if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+                               var m = context.getElementById( id );
+                               // Check parentNode to catch when Blackberry 4.6 returns
+                               // nodes that are no longer in the document #6963
+                               return m && m.parentNode ? [ m ] : [];
                        }
-               }
+               };
+               Expr.filter["ID"] = function( id ) {
+                       var attrId = id.replace( runescape, funescape );
+                       return function( elem ) {
+                               return elem.getAttribute("id") === attrId;
+                       };
+               };
+       } else {
+               // Support: IE6/7
+               // getElementById is not reliable as a find shortcut
+               delete Expr.find["ID"];
+
+               Expr.filter["ID"] =  function( id ) {
+                       var attrId = id.replace( runescape, funescape );
+                       return function( elem ) {
+                               var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+                               return node && node.value === attrId;
+                       };
+               };
+       }
 
-               if ( !cache[ id ] ) {
-                       cache[ id ] = {};
+       // Tag
+       Expr.find["TAG"] = support.getElementsByTagName ?
+               function( tag, context ) {
+                       if ( typeof context.getElementsByTagName !== "undefined" ) {
+                               return context.getElementsByTagName( tag );
 
-                       // 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;
+                       // DocumentFragment nodes don't have gEBTN
+                       } else if ( support.qsa ) {
+                               return context.querySelectorAll( tag );
                        }
-               }
+               } :
 
-               // 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);
-                       }
-               }
+               function( tag, context ) {
+                       var elem,
+                               tmp = [],
+                               i = 0,
+                               // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+                               results = context.getElementsByTagName( tag );
 
-               thisCache = cache[ id ];
+                       // Filter out possible comments
+                       if ( tag === "*" ) {
+                               while ( (elem = results[i++]) ) {
+                                       if ( elem.nodeType === 1 ) {
+                                               tmp.push( elem );
+                                       }
+                               }
 
-               // 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 ] = {};
+                               return tmp;
                        }
+                       return results;
+               };
 
-                       thisCache = thisCache[ internalKey ];
-               }
-
-               if ( data !== undefined ) {
-                       thisCache[ 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;
-               }
-
-               return getByName ? thisCache[ name ] : thisCache;
-       },
-
-       removeData: function( elem, name, pvt /* Internal Use Only */ ) {
-               if ( !jQuery.acceptData( elem ) ) {
-                       return;
+       // Class
+       Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+               if ( documentIsHTML ) {
+                       return context.getElementsByClassName( className );
                }
+       };
 
-               var internalKey = jQuery.expando, isNode = elem.nodeType,
-
-                       // See jQuery.data for more information
-                       cache = isNode ? jQuery.cache : elem,
+       /* QSA/matchesSelector
+       ---------------------------------------------------------------------- */
 
-                       // See jQuery.data for more information
-                       id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+       // QSA and matchesSelector support
 
-               // If there is already no cache entry for this object, there is no
-               // purpose in continuing
-               if ( !cache[ id ] ) {
-                       return;
-               }
+       // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+       rbuggyMatches = [];
 
-               if ( name ) {
-                       var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
+       // qSa(:focus) reports false when true (Chrome 21)
+       // We allow this because of a bug in IE8/9 that throws an error
+       // whenever `document.activeElement` is accessed on an iframe
+       // So, we allow :focus to pass through QSA all the time to avoid the IE error
+       // See http://bugs.jquery.com/ticket/13378
+       rbuggyQSA = [];
 
-                       if ( thisCache ) {
-                               delete thisCache[ name ];
+       if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+               // Build QSA regex
+               // Regex strategy adopted from Diego Perini
+               assert(function( div ) {
+                       // Select is set to empty string on purpose
+                       // This is to test IE's treatment of not explicitly
+                       // setting a boolean content attribute,
+                       // since its presence should be enough
+                       // http://bugs.jquery.com/ticket/12359
+                       docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
+                               "<select id='" + expando + "-\f]' msallowcapture=''>" +
+                               "<option selected=''></option></select>";
 
-                               // 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;
-                               }
+                       // Support: IE8, Opera 11-12.16
+                       // Nothing should be selected when empty strings follow ^= or $= or *=
+                       // The test attribute must be unknown in Opera but "safe" for WinRT
+                       // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+                       if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+                               rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
                        }
-               }
 
-               // See jQuery.data for more information
-               if ( pvt ) {
-                       delete cache[ id ][ internalKey ];
+                       // Support: IE8
+                       // Boolean attributes and "value" are not treated correctly
+                       if ( !div.querySelectorAll("[selected]").length ) {
+                               rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+                       }
 
-                       // Don't destroy the parent cache unless the internal data object
-                       // had been the only thing left in it
-                       if ( !isEmptyDataObject(cache[ id ]) ) {
-                               return;
+                       // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
+                       if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+                               rbuggyQSA.push("~=");
                        }
-               }
 
-               var internalCache = cache[ id ][ internalKey ];
+                       // Webkit/Opera - :checked should return selected option elements
+                       // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+                       // IE8 throws error here and will not see later tests
+                       if ( !div.querySelectorAll(":checked").length ) {
+                               rbuggyQSA.push(":checked");
+                       }
 
-               // 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
-               if ( jQuery.support.deleteExpando || cache != window ) {
-                       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;
+                       // Support: Safari 8+, iOS 8+
+                       // https://bugs.webkit.org/show_bug.cgi?id=136851
+                       // In-page `selector#id sibing-combinator selector` fails
+                       if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+                               rbuggyQSA.push(".#.+[+~]");
                        }
-               }
-       },
+               });
 
-       // For internal use only.
-       _data: function( elem, name, data ) {
-               return jQuery.data( elem, name, data, true );
-       },
+               assert(function( div ) {
+                       // Support: Windows 8 Native Apps
+                       // The type and name attributes are restricted during .innerHTML assignment
+                       var input = doc.createElement("input");
+                       input.setAttribute( "type", "hidden" );
+                       div.appendChild( input ).setAttribute( "name", "D" );
 
-       // 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() ];
+                       // Support: IE8
+                       // Enforce case-sensitivity of name attribute
+                       if ( div.querySelectorAll("[name=d]").length ) {
+                               rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+                       }
 
-                       if ( match ) {
-                               return !(match === true || elem.getAttribute("classid") !== match);
+                       // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+                       // IE8 throws error here and will not see later tests
+                       if ( !div.querySelectorAll(":enabled").length ) {
+                               rbuggyQSA.push( ":enabled", ":disabled" );
                        }
-               }
 
-               return true;
+                       // Opera 10-11 does not throw on post-comma invalid pseudos
+                       div.querySelectorAll("*,:x");
+                       rbuggyQSA.push(",.*:");
+               });
        }
-});
-
-jQuery.fn.extend({
-       data: function( key, value ) {
-               var data = null;
 
-               if ( typeof key === "undefined" ) {
-                       if ( this.length ) {
-                               data = jQuery.data( this[0] );
+       if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+               docElem.webkitMatchesSelector ||
+               docElem.mozMatchesSelector ||
+               docElem.oMatchesSelector ||
+               docElem.msMatchesSelector) )) ) {
 
-                               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;
+               assert(function( div ) {
+                       // Check to see if it's possible to do matchesSelector
+                       // on a disconnected node (IE 9)
+                       support.disconnectedMatch = matches.call( div, "div" );
 
-                                               if ( name.indexOf( "data-" ) === 0 ) {
-                                                       name = jQuery.camelCase( name.substring(5) );
+                       // This should fail with an exception
+                       // Gecko does not error, returns false instead
+                       matches.call( div, "[s!='']:x" );
+                       rbuggyMatches.push( "!=", pseudos );
+               });
+       }
 
-                                                       dataAttr( this[0], name, data[ name ] );
-                                               }
+       rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+       rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+       /* Contains
+       ---------------------------------------------------------------------- */
+       hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+       // Element contains another
+       // Purposefully does not implement inclusive descendent
+       // As in, an element does not contain itself
+       contains = hasCompare || rnative.test( docElem.contains ) ?
+               function( a, b ) {
+                       var adown = a.nodeType === 9 ? a.documentElement : a,
+                               bup = b && b.parentNode;
+                       return a === bup || !!( bup && bup.nodeType === 1 && (
+                               adown.contains ?
+                                       adown.contains( bup ) :
+                                       a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+                       ));
+               } :
+               function( a, b ) {
+                       if ( b ) {
+                               while ( (b = b.parentNode) ) {
+                                       if ( b === a ) {
+                                               return true;
                                        }
                                }
                        }
+                       return false;
+               };
 
-                       return data;
+       /* Sorting
+       ---------------------------------------------------------------------- */
 
-               } else if ( typeof key === "object" ) {
-                       return this.each(function() {
-                               jQuery.data( this, key );
-                       });
+       // Document order sorting
+       sortOrder = hasCompare ?
+       function( a, b ) {
+
+               // Flag for duplicate removal
+               if ( a === b ) {
+                       hasDuplicate = true;
+                       return 0;
                }
 
-               var parts = key.split(".");
-               parts[1] = parts[1] ? "." + parts[1] : "";
+               // Sort on method existence if only one input has compareDocumentPosition
+               var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+               if ( compare ) {
+                       return compare;
+               }
 
-               if ( value === undefined ) {
-                       data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+               // Calculate position if both inputs belong to the same document
+               compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+                       a.compareDocumentPosition( b ) :
 
-                       // 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 );
-                       }
+                       // Otherwise we know they are disconnected
+                       1;
 
-                       return data === undefined && parts[1] ?
-                               this.data( parts[0] ) :
-                               data;
+               // Disconnected nodes
+               if ( compare & 1 ||
+                       (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
 
-               } else {
-                       return this.each(function() {
-                               var $this = jQuery( this ),
-                                       args = [ parts[0], value ];
+                       // Choose the first element that is related to our preferred document
+                       if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+                               return -1;
+                       }
+                       if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+                               return 1;
+                       }
 
-                               $this.triggerHandler( "setData" + parts[1] + "!", args );
-                               jQuery.data( this, key, value );
-                               $this.triggerHandler( "changeData" + parts[1] + "!", args );
-                       });
+                       // Maintain original order
+                       return sortInput ?
+                               ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+                               0;
                }
-       },
-
-       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 ) {
-               name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
+               return compare & 4 ? -1 : 1;
+       } :
+       function( a, b ) {
+               // Exit early if the nodes are identical
+               if ( a === b ) {
+                       hasDuplicate = true;
+                       return 0;
+               }
 
-               data = elem.getAttribute( name );
+               var cur,
+                       i = 0,
+                       aup = a.parentNode,
+                       bup = b.parentNode,
+                       ap = [ a ],
+                       bp = [ b ];
+
+               // Parentless nodes are either documents or disconnected
+               if ( !aup || !bup ) {
+                       return a === doc ? -1 :
+                               b === doc ? 1 :
+                               aup ? -1 :
+                               bup ? 1 :
+                               sortInput ?
+                               ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+                               0;
 
-               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 ) {}
+               // If the nodes are siblings, we can do a quick check
+               } else if ( aup === bup ) {
+                       return siblingCheck( a, b );
+               }
 
-                       // Make sure we set the data so it isn't changed later
-                       jQuery.data( elem, key, data );
+               // Otherwise we need full lists of their ancestors for comparison
+               cur = a;
+               while ( (cur = cur.parentNode) ) {
+                       ap.unshift( cur );
+               }
+               cur = b;
+               while ( (cur = cur.parentNode) ) {
+                       bp.unshift( cur );
+               }
 
-               } else {
-                       data = undefined;
+               // Walk down the tree looking for a discrepancy
+               while ( ap[i] === bp[i] ) {
+                       i++;
                }
-       }
 
-       return data;
-}
+               return i ?
+                       // Do a sibling check if the nodes have a common ancestor
+                       siblingCheck( ap[i], bp[i] ) :
 
-// 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;
-               }
-       }
+                       // Otherwise nodes in our document sort first
+                       ap[i] === preferredDoc ? -1 :
+                       bp[i] === preferredDoc ? 1 :
+                       0;
+       };
 
-       return true;
-}
+       return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+       return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+       // Set document vars if needed
+       if ( ( elem.ownerDocument || elem ) !== document ) {
+               setDocument( elem );
+       }
 
+       // Make sure that attribute selectors are quoted
+       expr = expr.replace( rattributeQuotes, "='$1']" );
 
+       if ( support.matchesSelector && documentIsHTML &&
+               ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+               ( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
 
+               try {
+                       var ret = matches.call( elem, expr );
 
-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();
+                       // IE 9's matchesSelector returns false on disconnected nodes
+                       if ( ret || support.disconnectedMatch ||
+                                       // As well, disconnected nodes are said to be in a document
+                                       // fragment in IE 9
+                                       elem.document && elem.document.nodeType !== 11 ) {
+                               return ret;
                        }
-               }, 0 );
+               } catch (e) {}
        }
-}
 
-jQuery.extend({
+       return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
 
-       _mark: function( elem, type ) {
-               if ( elem ) {
-                       type = (type || "fx") + "mark";
-                       jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );
-               }
-       },
+Sizzle.contains = function( context, elem ) {
+       // Set document vars if needed
+       if ( ( context.ownerDocument || context ) !== document ) {
+               setDocument( context );
+       }
+       return contains( context, elem );
+};
 
-       _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" );
-                       }
-               }
-       },
+Sizzle.attr = function( elem, name ) {
+       // Set document vars if needed
+       if ( ( elem.ownerDocument || elem ) !== document ) {
+               setDocument( elem );
+       }
 
-       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 || [];
-               }
-       },
+       var fn = Expr.attrHandle[ name.toLowerCase() ],
+               // Don't get fooled by Object.prototype properties (jQuery #13807)
+               val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+                       fn( elem, name, !documentIsHTML ) :
+                       undefined;
+
+       return val !== undefined ?
+               val :
+               support.attributes || !documentIsHTML ?
+                       elem.getAttribute( name ) :
+                       (val = elem.getAttributeNode(name)) && val.specified ?
+                               val.value :
+                               null;
+};
 
-       dequeue: function( elem, type ) {
-               type = type || "fx";
+Sizzle.error = function( msg ) {
+       throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
 
-               var queue = jQuery.queue( elem, type ),
-                       fn = queue.shift(),
-                       defer;
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+       var elem,
+               duplicates = [],
+               j = 0,
+               i = 0;
 
-               // If the fx queue is dequeued, always remove the progress sentinel
-               if ( fn === "inprogress" ) {
-                       fn = queue.shift();
-               }
+       // Unless we *know* we can detect duplicates, assume their presence
+       hasDuplicate = !support.detectDuplicates;
+       sortInput = !support.sortStable && results.slice( 0 );
+       results.sort( sortOrder );
 
-               if ( fn ) {
-                       // Add a progress sentinel to prevent the fx queue from being
-                       // automatically dequeued
-                       if ( type === "fx" ) {
-                               queue.unshift("inprogress");
+       if ( hasDuplicate ) {
+               while ( (elem = results[i++]) ) {
+                       if ( elem === results[ i ] ) {
+                               j = duplicates.push( i );
                        }
-
-                       fn.call(elem, function() {
-                               jQuery.dequeue(elem, type);
-                       });
                }
-
-               if ( !queue.length ) {
-                       jQuery.removeData( elem, type + "queue", true );
-                       handleQueueMarkDefer( elem, type, "queue" );
+               while ( j-- ) {
+                       results.splice( duplicates[ j ], 1 );
                }
        }
-});
-
-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 );
+       // Clear input after sorting to release objects
+       // See https://github.com/jquery/sizzle/pull/225
+       sortInput = null;
 
-                       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 results;
+};
 
-               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";
-               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 );
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+       var node,
+               ret = "",
+               i = 0,
+               nodeType = elem.nodeType;
+
+       if ( !nodeType ) {
+               // If no nodeType, this is expected to be an array
+               while ( (node = elem[i++]) ) {
+                       // Do not traverse comment nodes
+                       ret += getText( node );
+               }
+       } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+               // Use textContent for elements
+               // innerText usage removed for consistency of new lines (jQuery #11153)
+               if ( typeof elem.textContent === "string" ) {
+                       return elem.textContent;
+               } else {
+                       // Traverse its children
+                       for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+                               ret += getText( elem );
                        }
                }
-               resolve();
-               return defer.promise();
+       } else if ( nodeType === 3 || nodeType === 4 ) {
+               return elem.nodeValue;
        }
-});
+       // Do not include comment or processing instruction nodes
 
+       return ret;
+};
 
+Expr = Sizzle.selectors = {
 
+       // Can be adjusted by the user
+       cacheLength: 50,
 
-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,
-       rspecial = /^(?:data-|aria-)/,
-       rinvalidChar = /\:/,
-       formHook;
+       createPseudo: markFunction,
 
-jQuery.fn.extend({
-       attr: function( name, value ) {
-               return jQuery.access( this, name, value, true, jQuery.attr );
-       },
+       match: matchExpr,
 
-       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 ) {
-               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 ) {}
-               });
-       },
+       attrHandle: {},
 
-       addClass: function( value ) {
-               if ( jQuery.isFunction( value ) ) {
-                       return this.each(function(i) {
-                               var self = jQuery(this);
-                               self.addClass( value.call(this, i, self.attr("class") || "") );
-                       });
-               }
+       find: {},
 
-               if ( value && typeof value === "string" ) {
-                       var classNames = (value || "").split( rspace );
+       relative: {
+               ">": { dir: "parentNode", first: true },
+               " ": { dir: "parentNode" },
+               "+": { dir: "previousSibling", first: true },
+               "~": { dir: "previousSibling" }
+       },
 
-                       for ( var i = 0, l = this.length; i < l; i++ ) {
-                               var elem = this[i];
+       preFilter: {
+               "ATTR": function( match ) {
+                       match[1] = match[1].replace( runescape, funescape );
 
-                               if ( elem.nodeType === 1 ) {
-                                       if ( !elem.className ) {
-                                               elem.className = value;
+                       // Move the given value to match[3] whether quoted or unquoted
+                       match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
 
-                                       } else {
-                                               var className = " " + elem.className + " ",
-                                                       setClass = elem.className;
+                       if ( match[2] === "~=" ) {
+                               match[3] = " " + match[3] + " ";
+                       }
 
-                                               for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
-                                                       if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
-                                                               setClass += " " + classNames[c];
-                                                       }
-                                               }
-                                               elem.className = jQuery.trim( setClass );
-                                       }
+                       return match.slice( 0, 4 );
+               },
+
+               "CHILD": function( match ) {
+                       /* matches from matchExpr["CHILD"]
+                               1 type (only|nth|...)
+                               2 what (child|of-type)
+                               3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+                               4 xn-component of xn+y argument ([+-]?\d*n|)
+                               5 sign of xn-component
+                               6 x of xn-component
+                               7 sign of y-component
+                               8 y of y-component
+                       */
+                       match[1] = match[1].toLowerCase();
+
+                       if ( match[1].slice( 0, 3 ) === "nth" ) {
+                               // nth-* requires argument
+                               if ( !match[3] ) {
+                                       Sizzle.error( match[0] );
                                }
+
+                               // numeric x and y parameters for Expr.filter.CHILD
+                               // remember that false/true cast respectively to 0/1
+                               match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+                               match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+                       // other types prohibit arguments
+                       } else if ( match[3] ) {
+                               Sizzle.error( match[0] );
                        }
-               }
 
-               return this;
-       },
+                       return match;
+               },
 
-       removeClass: function( value ) {
-               if ( jQuery.isFunction(value) ) {
-                       return this.each(function(i) {
-                               var self = jQuery(this);
-                               self.removeClass( value.call(this, i, self.attr("class")) );
-                       });
-               }
+               "PSEUDO": function( match ) {
+                       var excess,
+                               unquoted = !match[6] && match[2];
 
-               if ( (value && typeof value === "string") || value === undefined ) {
-                       var classNames = (value || "").split( rspace );
+                       if ( matchExpr["CHILD"].test( match[0] ) ) {
+                               return null;
+                       }
 
-                       for ( var i = 0, l = this.length; i < l; i++ ) {
-                               var elem = this[i];
+                       // Accept quoted arguments as-is
+                       if ( match[3] ) {
+                               match[2] = match[4] || match[5] || "";
 
-                               if ( elem.nodeType === 1 && elem.className ) {
-                                       if ( value ) {
-                                               var className = (" " + elem.className + " ").replace(rclass, " ");
-                                               for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
-                                                       className = className.replace(" " + classNames[c] + " ", " ");
-                                               }
-                                               elem.className = jQuery.trim( className );
+                       // Strip excess characters from unquoted arguments
+                       } else if ( unquoted && rpseudo.test( unquoted ) &&
+                               // Get excess from tokenize (recursively)
+                               (excess = tokenize( unquoted, true )) &&
+                               // advance to the next closing parenthesis
+                               (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
 
-                                       } else {
-                                               elem.className = "";
-                                       }
-                               }
+                               // excess is a negative index
+                               match[0] = match[0].slice( 0, excess );
+                               match[2] = unquoted.slice( 0, excess );
                        }
-               }
 
-               return this;
+                       // Return only captures needed by the pseudo filter method (type and argument)
+                       return match.slice( 0, 3 );
+               }
        },
 
-       toggleClass: function( value, stateVal ) {
-               var type = typeof value,
-                       isBool = typeof stateVal === "boolean";
+       filter: {
 
-               if ( jQuery.isFunction( value ) ) {
-                       return this.each(function(i) {
-                               var self = jQuery(this);
-                               self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
-                       });
-               }
+               "TAG": function( nodeNameSelector ) {
+                       var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+                       return nodeNameSelector === "*" ?
+                               function() { return true; } :
+                               function( elem ) {
+                                       return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+                               };
+               },
 
-               return this.each(function() {
-                       if ( type === "string" ) {
-                               // toggle individual class names
-                               var className,
-                                       i = 0,
-                                       self = jQuery( this ),
-                                       state = stateVal,
-                                       classNames = value.split( rspace );
+               "CLASS": function( className ) {
+                       var pattern = classCache[ className + " " ];
 
-                               while ( (className = classNames[ i++ ]) ) {
-                                       // check each className given, space seperated list
-                                       state = isBool ? state : !self.hasClass( className );
-                                       self[ state ? "addClass" : "removeClass" ]( className );
-                               }
+                       return pattern ||
+                               (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+                               classCache( className, function( elem ) {
+                                       return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+                               });
+               },
 
-                       } else if ( type === "undefined" || type === "boolean" ) {
-                               if ( this.className ) {
-                                       // store className if set
-                                       jQuery._data( this, "__className__", this.className );
+               "ATTR": function( name, operator, check ) {
+                       return function( elem ) {
+                               var result = Sizzle.attr( elem, name );
+
+                               if ( result == null ) {
+                                       return operator === "!=";
+                               }
+                               if ( !operator ) {
+                                       return true;
                                }
 
-                               // toggle whole className
-                               this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
-                       }
-               });
-       },
+                               result += "";
 
-       hasClass: function( selector ) {
-               var className = " " + selector + " ";
-               for ( var i = 0, l = this.length; i < l; i++ ) {
-                       if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
-                               return true;
-                       }
-               }
+                               return operator === "=" ? result === check :
+                                       operator === "!=" ? result !== check :
+                                       operator === "^=" ? check && result.indexOf( check ) === 0 :
+                                       operator === "*=" ? check && result.indexOf( check ) > -1 :
+                                       operator === "$=" ? check && result.slice( -check.length ) === check :
+                                       operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+                                       operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+                                       false;
+                       };
+               },
 
-               return false;
-       },
+               "CHILD": function( type, what, argument, first, last ) {
+                       var simple = type.slice( 0, 3 ) !== "nth",
+                               forward = type.slice( -4 ) !== "last",
+                               ofType = what === "of-type";
+
+                       return first === 1 && last === 0 ?
+
+                               // Shortcut for :nth-*(n)
+                               function( elem ) {
+                                       return !!elem.parentNode;
+                               } :
+
+                               function( elem, context, xml ) {
+                                       var cache, outerCache, node, diff, nodeIndex, start,
+                                               dir = simple !== forward ? "nextSibling" : "previousSibling",
+                                               parent = elem.parentNode,
+                                               name = ofType && elem.nodeName.toLowerCase(),
+                                               useCache = !xml && !ofType;
+
+                                       if ( parent ) {
+
+                                               // :(first|last|only)-(child|of-type)
+                                               if ( simple ) {
+                                                       while ( dir ) {
+                                                               node = elem;
+                                                               while ( (node = node[ dir ]) ) {
+                                                                       if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+                                                                               return false;
+                                                                       }
+                                                               }
+                                                               // Reverse direction for :only-* (if we haven't yet done so)
+                                                               start = dir = type === "only" && !start && "nextSibling";
+                                                       }
+                                                       return true;
+                                               }
 
-       val: function( value ) {
-               var hooks, ret,
-                       elem = this[0];
-               
-               if ( !arguments.length ) {
-                       if ( elem ) {
-                               hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
+                                               start = [ forward ? parent.firstChild : parent.lastChild ];
 
-                               if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
-                                       return ret;
-                               }
+                                               // non-xml :nth-child(...) stores cache data on `parent`
+                                               if ( forward && useCache ) {
+                                                       // Seek `elem` from a previously-cached index
+                                                       outerCache = parent[ expando ] || (parent[ expando ] = {});
+                                                       cache = outerCache[ type ] || [];
+                                                       nodeIndex = cache[0] === dirruns && cache[1];
+                                                       diff = cache[0] === dirruns && cache[2];
+                                                       node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+                                                       while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+                                                               // Fallback to seeking `elem` from the start
+                                                               (diff = nodeIndex = 0) || start.pop()) ) {
+
+                                                               // When found, cache indexes on `parent` and break
+                                                               if ( node.nodeType === 1 && ++diff && node === elem ) {
+                                                                       outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+                                                                       break;
+                                                               }
+                                                       }
 
-                               return (elem.value || "").replace(rreturn, "");
+                                               // Use previously-cached element index if available
+                                               } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+                                                       diff = cache[1];
+
+                                               // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+                                               } else {
+                                                       // Use the same loop as above to seek `elem` from the start
+                                                       while ( (node = ++nodeIndex && node && node[ dir ] ||
+                                                               (diff = nodeIndex = 0) || start.pop()) ) {
+
+                                                               if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+                                                                       // Cache the index of each encountered element
+                                                                       if ( useCache ) {
+                                                                               (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+                                                                       }
+
+                                                                       if ( node === elem ) {
+                                                                               break;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+
+                                               // Incorporate the offset, then check against cycle size
+                                               diff -= last;
+                                               return diff === first || ( diff % first === 0 && diff / first >= 0 );
+                                       }
+                               };
+               },
+
+               "PSEUDO": function( pseudo, argument ) {
+                       // pseudo-class names are case-insensitive
+                       // http://www.w3.org/TR/selectors/#pseudo-classes
+                       // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+                       // Remember that setFilters inherits from pseudos
+                       var args,
+                               fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+                                       Sizzle.error( "unsupported pseudo: " + pseudo );
+
+                       // The user may use createPseudo to indicate that
+                       // arguments are needed to create the filter function
+                       // just as Sizzle does
+                       if ( fn[ expando ] ) {
+                               return fn( argument );
+                       }
+
+                       // But maintain support for old signatures
+                       if ( fn.length > 1 ) {
+                               args = [ pseudo, pseudo, "", argument ];
+                               return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+                                       markFunction(function( seed, matches ) {
+                                               var idx,
+                                                       matched = fn( seed, argument ),
+                                                       i = matched.length;
+                                               while ( i-- ) {
+                                                       idx = indexOf( seed, matched[i] );
+                                                       seed[ idx ] = !( matches[ idx ] = matched[i] );
+                                               }
+                                       }) :
+                                       function( elem ) {
+                                               return fn( elem, 0, args );
+                                       };
                        }
 
-                       return undefined;
+                       return fn;
                }
+       },
 
-               var isFunction = jQuery.isFunction( value );
+       pseudos: {
+               // Potentially complex pseudos
+               "not": markFunction(function( selector ) {
+                       // Trim the selector passed to compile
+                       // to avoid treating leading and trailing
+                       // spaces as combinators
+                       var input = [],
+                               results = [],
+                               matcher = compile( selector.replace( rtrim, "$1" ) );
 
-               return this.each(function( i ) {
-                       var self = jQuery(this), val;
+                       return matcher[ expando ] ?
+                               markFunction(function( seed, matches, context, xml ) {
+                                       var elem,
+                                               unmatched = matcher( seed, null, xml, [] ),
+                                               i = seed.length;
 
-                       if ( this.nodeType !== 1 ) {
-                               return;
-                       }
+                                       // Match elements unmatched by `matcher`
+                                       while ( i-- ) {
+                                               if ( (elem = unmatched[i]) ) {
+                                                       seed[i] = !(matches[i] = elem);
+                                               }
+                                       }
+                               }) :
+                               function( elem, context, xml ) {
+                                       input[0] = elem;
+                                       matcher( input, null, xml, results );
+                                       // Don't keep the element (issue #299)
+                                       input[0] = null;
+                                       return !results.pop();
+                               };
+               }),
 
-                       if ( isFunction ) {
-                               val = value.call( this, i, self.val() );
-                       } else {
-                               val = value;
-                       }
+               "has": markFunction(function( selector ) {
+                       return function( elem ) {
+                               return Sizzle( selector, elem ).length > 0;
+                       };
+               }),
 
-                       // 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 + "";
-                               });
-                       }
+               "contains": markFunction(function( text ) {
+                       text = text.replace( runescape, funescape );
+                       return function( elem ) {
+                               return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+                       };
+               }),
+
+               // "Whether an element is represented by a :lang() selector
+               // is based solely on the element's language value
+               // being equal to the identifier C,
+               // or beginning with the identifier C immediately followed by "-".
+               // The matching of C against the element's language value is performed case-insensitively.
+               // The identifier C does not have to be a valid language name."
+               // http://www.w3.org/TR/selectors/#lang-pseudo
+               "lang": markFunction( function( lang ) {
+                       // lang value must be a valid identifier
+                       if ( !ridentifier.test(lang || "") ) {
+                               Sizzle.error( "unsupported lang: " + lang );
+                       }
+                       lang = lang.replace( runescape, funescape ).toLowerCase();
+                       return function( elem ) {
+                               var elemLang;
+                               do {
+                                       if ( (elemLang = documentIsHTML ?
+                                               elem.lang :
+                                               elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+                                               elemLang = elemLang.toLowerCase();
+                                               return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+                                       }
+                               } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+                               return false;
+                       };
+               }),
 
-                       hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
+               // Miscellaneous
+               "target": function( elem ) {
+                       var hash = window.location && window.location.hash;
+                       return hash && hash.slice( 1 ) === elem.id;
+               },
 
-                       // If set returns undefined, fall back to normal setting
-                       if ( !hooks || ("set" in hooks && hooks.set( this, val, "value" ) === undefined) ) {
-                               this.value = val;
-                       }
-               });
-       }
-});
+               "root": function( elem ) {
+                       return elem === docElem;
+               },
 
-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;
+               "focus": function( elem ) {
+                       return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+               },
+
+               // Boolean properties
+               "enabled": function( elem ) {
+                       return elem.disabled === false;
+               },
+
+               "disabled": function( elem ) {
+                       return elem.disabled === true;
+               },
+
+               "checked": function( elem ) {
+                       // In CSS3, :checked should return both checked and selected elements
+                       // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+                       var nodeName = elem.nodeName.toLowerCase();
+                       return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+               },
+
+               "selected": function( elem ) {
+                       // Accessing this property makes selected-by-default
+                       // options in Safari work properly
+                       if ( elem.parentNode ) {
+                               elem.parentNode.selectedIndex;
                        }
+
+                       return elem.selected === true;
                },
-               select: {
-                       get: function( elem ) {
-                               var index = elem.selectedIndex,
-                                       values = [],
-                                       options = elem.options,
-                                       one = elem.type === "select-one";
 
-                               // Nothing was selected
-                               if ( index < 0 ) {
-                                       return null;
+               // Contents
+               "empty": function( elem ) {
+                       // http://www.w3.org/TR/selectors/#empty-pseudo
+                       // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+                       //   but not by others (comment: 8; processing instruction: 7; etc.)
+                       // nodeType < 6 works because attributes (2) do not appear as children
+                       for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+                               if ( elem.nodeType < 6 ) {
+                                       return false;
                                }
+                       }
+                       return true;
+               },
 
-                               // 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 ];
+               "parent": function( elem ) {
+                       return !Expr.pseudos["empty"]( elem );
+               },
 
-                                       // 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" )) ) {
+               // Element/input types
+               "header": function( elem ) {
+                       return rheader.test( elem.nodeName );
+               },
 
-                                               // Get the specific value for the option
-                                               value = jQuery( option ).val();
+               "input": function( elem ) {
+                       return rinputs.test( elem.nodeName );
+               },
 
-                                               // We don't need an array for one selects
-                                               if ( one ) {
-                                                       return value;
-                                               }
+               "button": function( elem ) {
+                       var name = elem.nodeName.toLowerCase();
+                       return name === "input" && elem.type === "button" || name === "button";
+               },
 
-                                               // Multi-Selects return an array
-                                               values.push( value );
-                                       }
-                               }
+               "text": function( elem ) {
+                       var attr;
+                       return elem.nodeName.toLowerCase() === "input" &&
+                               elem.type === "text" &&
 
-                               // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
-                               if ( one && !values.length && options.length ) {
-                                       return jQuery( options[ index ] ).val();
-                               }
+                               // Support: IE<8
+                               // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+                               ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+               },
 
-                               return values;
-                       },
+               // Position-in-collection
+               "first": createPositionalPseudo(function() {
+                       return [ 0 ];
+               }),
 
-                       set: function( elem, value ) {
-                               var values = jQuery.makeArray( value );
+               "last": createPositionalPseudo(function( matchIndexes, length ) {
+                       return [ length - 1 ];
+               }),
 
-                               jQuery(elem).find("option").each(function() {
-                                       this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
-                               });
+               "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+                       return [ argument < 0 ? argument + length : argument ];
+               }),
 
-                               if ( !values.length ) {
-                                       elem.selectedIndex = -1;
-                               }
-                               return values;
+               "even": createPositionalPseudo(function( matchIndexes, length ) {
+                       var i = 0;
+                       for ( ; i < length; i += 2 ) {
+                               matchIndexes.push( i );
                        }
-               }
-       },
+                       return matchIndexes;
+               }),
 
-       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",
-               readonly: "readOnly"
-       },
-       
-       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;
-               }
+               "odd": createPositionalPseudo(function( matchIndexes, length ) {
+                       var i = 1;
+                       for ( ; i < length; i += 2 ) {
+                               matchIndexes.push( i );
+                       }
+                       return matchIndexes;
+               }),
 
-               if ( pass && name in jQuery.attrFn ) {
-                       return jQuery( elem )[ name ]( value );
-               }
-               
-               var ret, hooks,
-                       notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-               
-               // Normalize the name if needed
-               name = notxml && jQuery.attrFix[ name ] || name;
+               "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+                       var i = argument < 0 ? argument + length : argument;
+                       for ( ; --i >= 0; ) {
+                               matchIndexes.push( i );
+                       }
+                       return matchIndexes;
+               }),
 
-               // Get the appropriate hook, or the formHook
-               // if getSetAttribute is not supported and we have form objects in IE6/7
-               hooks = jQuery.attrHooks[ name ] ||
-                       ( formHook && (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ?
-                               formHook :
-                               undefined );
+               "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+                       var i = argument < 0 ? argument + length : argument;
+                       for ( ; ++i < length; ) {
+                               matchIndexes.push( i );
+                       }
+                       return matchIndexes;
+               })
+       }
+};
 
-               if ( value !== undefined ) {
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
 
-                       if ( value === null || (value === false && !rspecial.test( name )) ) {
-                               jQuery.removeAttr( elem, name );
-                               return undefined;
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+       Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+       Expr.pseudos[ i ] = createButtonPseudo( i );
+}
 
-                       } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
-                               return ret;
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
 
-                       } else {
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+       var matched, match, tokens, type,
+               soFar, groups, preFilters,
+               cached = tokenCache[ selector + " " ];
 
-                               // Set boolean attributes to the same name
-                               if ( value === true && !rspecial.test( name ) ) {
-                                       value = name;
-                               }
+       if ( cached ) {
+               return parseOnly ? 0 : cached.slice( 0 );
+       }
 
-                               elem.setAttribute( name, "" + value );
-                               return value;
+       soFar = selector;
+       groups = [];
+       preFilters = Expr.preFilter;
+
+       while ( soFar ) {
+
+               // Comma and first run
+               if ( !matched || (match = rcomma.exec( soFar )) ) {
+                       if ( match ) {
+                               // Don't consume trailing commas as valid
+                               soFar = soFar.slice( match[0].length ) || soFar;
                        }
+                       groups.push( (tokens = []) );
+               }
 
-               } else {
+               matched = false;
 
-                       if ( hooks && "get" in hooks && notxml ) {
-                               return hooks.get( elem, name );
+               // Combinators
+               if ( (match = rcombinators.exec( soFar )) ) {
+                       matched = match.shift();
+                       tokens.push({
+                               value: matched,
+                               // Cast descendant combinators to space
+                               type: match[0].replace( rtrim, " " )
+                       });
+                       soFar = soFar.slice( matched.length );
+               }
+
+               // Filters
+               for ( type in Expr.filter ) {
+                       if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+                               (match = preFilters[ type ]( match ))) ) {
+                               matched = match.shift();
+                               tokens.push({
+                                       value: matched,
+                                       type: type,
+                                       matches: match
+                               });
+                               soFar = soFar.slice( matched.length );
+                       }
+               }
 
-                       } else {
+               if ( !matched ) {
+                       break;
+               }
+       }
+
+       // Return the length of the invalid excess
+       // if we're just parsing
+       // Otherwise, throw an error or return tokens
+       return parseOnly ?
+               soFar.length :
+               soFar ?
+                       Sizzle.error( selector ) :
+                       // Cache the tokens
+                       tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+       var i = 0,
+               len = tokens.length,
+               selector = "";
+       for ( ; i < len; i++ ) {
+               selector += tokens[i].value;
+       }
+       return selector;
+}
 
-                               ret = elem.getAttribute( name );
+function addCombinator( matcher, combinator, base ) {
+       var dir = combinator.dir,
+               checkNonElements = base && dir === "parentNode",
+               doneName = done++;
 
-                               // Non-existent attributes return null, we normalize to undefined
-                               return ret === null ?
-                                       undefined :
-                                       ret;
+       return combinator.first ?
+               // Check against closest ancestor/preceding element
+               function( elem, context, xml ) {
+                       while ( (elem = elem[ dir ]) ) {
+                               if ( elem.nodeType === 1 || checkNonElements ) {
+                                       return matcher( elem, context, xml );
+                               }
                        }
-               }
-       },
-       
-       removeAttr: function( elem, name ) {
-               if ( elem.nodeType === 1 ) {
-                       name = jQuery.attrFix[ name ] || name;
-               
-                       if ( jQuery.support.getSetAttribute ) {
-                               // Use removeAttribute in browsers that support it
-                               elem.removeAttribute( name );
+               } :
+
+               // Check against all ancestor/preceding elements
+               function( elem, context, xml ) {
+                       var oldCache, outerCache,
+                               newCache = [ dirruns, doneName ];
+
+                       // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+                       if ( xml ) {
+                               while ( (elem = elem[ dir ]) ) {
+                                       if ( elem.nodeType === 1 || checkNonElements ) {
+                                               if ( matcher( elem, context, xml ) ) {
+                                                       return true;
+                                               }
+                                       }
+                               }
                        } else {
-                               jQuery.attr( elem, name, "" );
-                               elem.removeAttributeNode( elem.getAttributeNode( name ) );
-                       }
-               }
-       },
+                               while ( (elem = elem[ dir ]) ) {
+                                       if ( elem.nodeType === 1 || checkNonElements ) {
+                                               outerCache = elem[ expando ] || (elem[ expando ] = {});
+                                               if ( (oldCache = outerCache[ dir ]) &&
+                                                       oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+                                                       // Assign to newCache so results back-propagate to previous elements
+                                                       return (newCache[ 2 ] = oldCache[ 2 ]);
+                                               } else {
+                                                       // Reuse newcache so results back-propagate to previous elements
+                                                       outerCache[ dir ] = newCache;
 
-       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.getAttribute("value");
-                                       elem.setAttribute( "type", value );
-                                       if ( val ) {
-                                               elem.value = val;
+                                                       // A match means we're done; a fail means we have to keep checking
+                                                       if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+                                                               return true;
+                                                       }
+                                               }
                                        }
-                                       return value;
                                }
                        }
-               },
-               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;
-                       }
-               }
-       },
-       
-       propFix: {},
-       
-       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 );
-               
-               // Try to normalize/fix the name
-               name = notxml && 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 )) !== undefined ) {
-                               return ret;
-                               
-                       } else {
-                               return elem[ name ];
+function elementMatcher( matchers ) {
+       return matchers.length > 1 ?
+               function( elem, context, xml ) {
+                       var i = matchers.length;
+                       while ( i-- ) {
+                               if ( !matchers[i]( elem, context, xml ) ) {
+                                       return false;
+                               }
                        }
-               }
-       },
-       
-       propHooks: {}
-});
+                       return true;
+               } :
+               matchers[0];
+}
 
-// IE6/7 do not support getting/setting some attributes with get/setAttribute
-if ( !jQuery.support.getSetAttribute ) {
-       jQuery.attrFix = jQuery.extend( jQuery.attrFix, {
-               "for": "htmlFor",
-               "class": "className",
-               maxlength: "maxLength",
-               cellspacing: "cellSpacing",
-               cellpadding: "cellPadding",
-               rowspan: "rowSpan",
-               colspan: "colSpan",
-               usemap: "useMap",
-               frameborder: "frameBorder"
-       });
-       
-       // Use this for any attribute on a form in IE6/7
-       formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = {
-               get: function( elem, name ) {
-                       var ret;
-                       if ( name === "value" && !jQuery.nodeName( elem, "button" ) ) {
-                               return elem.getAttribute( name );
-                       }
-                       ret = elem.getAttributeNode( name );
-                       // Return undefined if not specified instead of empty string
-                       return ret && ret.specified ?
-                               ret.nodeValue :
-                               undefined;
-               },
-               set: function( elem, value, name ) {
-                       // Check form objects in IE (multiple bugs related)
-                       // Only use nodeValue if the attribute node exists on the form
-                       var ret = elem.getAttributeNode( name );
-                       if ( ret ) {
-                               ret.nodeValue = value;
-                               return value;
-                       }
-               }
-       };
+function multipleContexts( selector, contexts, results ) {
+       var i = 0,
+               len = contexts.length;
+       for ( ; i < len; i++ ) {
+               Sizzle( selector, contexts[i], results );
+       }
+       return results;
+}
 
-       // 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;
+function condense( unmatched, map, filter, context, xml ) {
+       var elem,
+               newUnmatched = [],
+               i = 0,
+               len = unmatched.length,
+               mapped = map != null;
+
+       for ( ; i < len; i++ ) {
+               if ( (elem = unmatched[i]) ) {
+                       if ( !filter || filter( elem, context, xml ) ) {
+                               newUnmatched.push( elem );
+                               if ( mapped ) {
+                                       map.push( i );
                                }
                        }
-               });
-       });
+               }
+       }
+
+       return newUnmatched;
 }
 
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+       if ( postFilter && !postFilter[ expando ] ) {
+               postFilter = setMatcher( postFilter );
+       }
+       if ( postFinder && !postFinder[ expando ] ) {
+               postFinder = setMatcher( postFinder, postSelector );
+       }
+       return markFunction(function( seed, results, context, xml ) {
+               var temp, i, elem,
+                       preMap = [],
+                       postMap = [],
+                       preexisting = results.length,
 
-// 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;
-                       }
-               });
-       });
-}
+                       // Get initial elements from seed or context
+                       elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
 
-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);
-               }
-       };
-}
+                       // Prefilter to get matcher input, preserving a map for seed-results synchronization
+                       matcherIn = preFilter && ( seed || !selector ) ?
+                               condense( elems, preMap, preFilter, context, xml ) :
+                               elems,
 
-// 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;
+                       matcherOut = matcher ?
+                               // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+                               postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
 
-                       if ( parent ) {
-                               parent.selectedIndex;
+                                       // ...intermediate processing is necessary
+                                       [] :
 
-                               // Make sure that it also works with optgroups, see #5701
-                               if ( parent.parentNode ) {
-                                       parent.parentNode.selectedIndex;
+                                       // ...otherwise use results directly
+                                       results :
+                               matcherIn;
+
+               // Find primary matches
+               if ( matcher ) {
+                       matcher( matcherIn, matcherOut, context, xml );
+               }
+
+               // Apply postFilter
+               if ( postFilter ) {
+                       temp = condense( matcherOut, postMap );
+                       postFilter( temp, [], context, xml );
+
+                       // Un-match failing elements by moving them back to matcherIn
+                       i = temp.length;
+                       while ( i-- ) {
+                               if ( (elem = temp[i]) ) {
+                                       matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
                                }
                        }
                }
-       });
-}
 
-// 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;
+               if ( seed ) {
+                       if ( postFinder || preFilter ) {
+                               if ( postFinder ) {
+                                       // Get the final matcherOut by condensing this intermediate into postFinder contexts
+                                       temp = [];
+                                       i = matcherOut.length;
+                                       while ( i-- ) {
+                                               if ( (elem = matcherOut[i]) ) {
+                                                       // Restore matcherIn since elem is not yet a final match
+                                                       temp.push( (matcherIn[i] = elem) );
+                                               }
+                                       }
+                                       postFinder( null, (matcherOut = []), temp, xml );
+                               }
+
+                               // Move matched elements from seed to results to keep them synchronized
+                               i = matcherOut.length;
+                               while ( i-- ) {
+                                       if ( (elem = matcherOut[i]) &&
+                                               (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+                                               seed[temp] = !(results[temp] = elem);
+                                       }
+                               }
                        }
-               };
+
+               // Add elements to results, through postFinder if defined
+               } else {
+                       matcherOut = condense(
+                               matcherOut === results ?
+                                       matcherOut.splice( preexisting, matcherOut.length ) :
+                                       matcherOut
+                       );
+                       if ( postFinder ) {
+                               postFinder( null, results, matcherOut, xml );
+                       } else {
+                               push.apply( results, matcherOut );
+                       }
+               }
        });
 }
-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);
+
+function matcherFromTokens( tokens ) {
+       var checkContext, matcher, j,
+               len = tokens.length,
+               leadingRelative = Expr.relative[ tokens[0].type ],
+               implicitRelative = leadingRelative || Expr.relative[" "],
+               i = leadingRelative ? 1 : 0,
+
+               // The foundational matcher ensures that elements are reachable from top-level context(s)
+               matchContext = addCombinator( function( elem ) {
+                       return elem === checkContext;
+               }, implicitRelative, true ),
+               matchAnyContext = addCombinator( function( elem ) {
+                       return indexOf( checkContext, elem ) > -1;
+               }, implicitRelative, true ),
+               matchers = [ function( elem, context, xml ) {
+                       var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+                               (checkContext = context).nodeType ?
+                                       matchContext( elem, context, xml ) :
+                                       matchAnyContext( elem, context, xml ) );
+                       // Avoid hanging onto element (issue #299)
+                       checkContext = null;
+                       return ret;
+               } ];
+
+       for ( ; i < len; i++ ) {
+               if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+                       matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+               } else {
+                       matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+                       // Return special upon seeing a positional matcher
+                       if ( matcher[ expando ] ) {
+                               // Find the next relative operator (if any) for proper handling
+                               j = ++i;
+                               for ( ; j < len; j++ ) {
+                                       if ( Expr.relative[ tokens[j].type ] ) {
+                                               break;
+                                       }
+                               }
+                               return setMatcher(
+                                       i > 1 && elementMatcher( matchers ),
+                                       i > 1 && toSelector(
+                                               // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+                                               tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+                                       ).replace( rtrim, "$1" ),
+                                       matcher,
+                                       i < j && matcherFromTokens( tokens.slice( i, j ) ),
+                                       j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+                                       j < len && toSelector( tokens )
+                               );
                        }
+                       matchers.push( matcher );
                }
-       });
-});
+       }
 
+       return elementMatcher( matchers );
+}
 
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+       var bySet = setMatchers.length > 0,
+               byElement = elementMatchers.length > 0,
+               superMatcher = function( seed, context, xml, results, outermost ) {
+                       var elem, j, matcher,
+                               matchedCount = 0,
+                               i = "0",
+                               unmatched = seed && [],
+                               setMatched = [],
+                               contextBackup = outermostContext,
+                               // We must always have either seed elements or outermost context
+                               elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+                               // Use integer dirruns iff this is the outermost matcher
+                               dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+                               len = elems.length;
+
+                       if ( outermost ) {
+                               outermostContext = context !== document && context;
+                       }
+
+                       // Add elements passing elementMatchers directly to results
+                       // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+                       // Support: IE<9, Safari
+                       // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+                       for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+                               if ( byElement && elem ) {
+                                       j = 0;
+                                       while ( (matcher = elementMatchers[j++]) ) {
+                                               if ( matcher( elem, context, xml ) ) {
+                                                       results.push( elem );
+                                                       break;
+                                               }
+                                       }
+                                       if ( outermost ) {
+                                               dirruns = dirrunsUnique;
+                                       }
+                               }
 
+                               // Track unmatched elements for set filters
+                               if ( bySet ) {
+                                       // They will have gone through all possible matchers
+                                       if ( (elem = !matcher && elem) ) {
+                                               matchedCount--;
+                                       }
 
-var hasOwn = Object.prototype.hasOwnProperty,
-       rnamespaces = /\.(.*)$/,
-       rformElems = /^(?:textarea|input|select)$/i,
-       rperiod = /\./g,
-       rspaces = / /g,
-       rescape = /[^\w\s.|`]/g,
-       fcleanup = function( nm ) {
-               return nm.replace(rescape, "\\$&");
-       };
+                                       // Lengthen the array for every element, matched or not
+                                       if ( seed ) {
+                                               unmatched.push( elem );
+                                       }
+                               }
+                       }
 
-/*
- * A number of helper functions used for managing events.
- * Many of the ideas behind this code originated from
- * Dean Edwards' addEvent library.
- */
-jQuery.event = {
+                       // Apply set filters to unmatched elements
+                       matchedCount += i;
+                       if ( bySet && i !== matchedCount ) {
+                               j = 0;
+                               while ( (matcher = setMatchers[j++]) ) {
+                                       matcher( unmatched, setMatched, context, xml );
+                               }
 
-       // 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 ( seed ) {
+                                       // Reintegrate element matches to eliminate the need for sorting
+                                       if ( matchedCount > 0 ) {
+                                               while ( i-- ) {
+                                                       if ( !(unmatched[i] || setMatched[i]) ) {
+                                                               setMatched[i] = pop.call( results );
+                                                       }
+                                               }
+                                       }
 
-               if ( handler === false ) {
-                       handler = returnFalse;
-               } else if ( !handler ) {
-                       // Fixes bug #7229. Fix recommended by jdalton
-                       return;
-               }
+                                       // Discard index placeholder values to get only actual matches
+                                       setMatched = condense( setMatched );
+                               }
 
-               var handleObjIn, handleObj;
+                               // Add matches to results
+                               push.apply( results, setMatched );
 
-               if ( handler.handler ) {
-                       handleObjIn = handler;
-                       handler = handleObjIn.handler;
-               }
+                               // Seedless set matches succeeding multiple successful matchers stipulate sorting
+                               if ( outermost && !seed && setMatched.length > 0 &&
+                                       ( matchedCount + setMatchers.length ) > 1 ) {
 
-               // Make sure that the function being executed has a unique ID
-               if ( !handler.guid ) {
-                       handler.guid = jQuery.guid++;
-               }
+                                       Sizzle.uniqueSort( results );
+                               }
+                       }
 
-               // Init the element's event structure
-               var elemData = jQuery._data( elem );
+                       // Override manipulation of globals by nested matchers
+                       if ( outermost ) {
+                               dirruns = dirrunsUnique;
+                               outermostContext = contextBackup;
+                       }
 
-               // If no elemData is found then we must be trying to bind to one of the
-               // banned noData elements
-               if ( !elemData ) {
-                       return;
-               }
+                       return unmatched;
+               };
+
+       return bySet ?
+               markFunction( superMatcher ) :
+               superMatcher;
+}
 
-               var events = elemData.events,
-                       eventHandle = elemData.handle;
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+       var i,
+               setMatchers = [],
+               elementMatchers = [],
+               cached = compilerCache[ selector + " " ];
 
-               if ( !events ) {
-                       elemData.events = events = {};
+       if ( !cached ) {
+               // Generate a function of recursive functions that can be used to check each element
+               if ( !match ) {
+                       match = tokenize( selector );
                }
-
-               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;
-                       };
+               i = match.length;
+               while ( i-- ) {
+                       cached = matcherFromTokens( match[i] );
+                       if ( cached[ expando ] ) {
+                               setMatchers.push( cached );
+                       } else {
+                               elementMatchers.push( cached );
+                       }
                }
 
-               // 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;
+               // Cache the compiled function
+               cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
 
-               // Handle multiple events separated by a space
-               // jQuery(...).bind("mouseover mouseout", fn);
-               types = types.split(" ");
+               // Save selector and tokenization
+               cached.selector = selector;
+       }
+       return cached;
+};
 
-               var type, i = 0, namespaces;
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ *  selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ *  selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+       var i, tokens, token, type, find,
+               compiled = typeof selector === "function" && selector,
+               match = !seed && tokenize( (selector = compiled.selector || selector) );
 
-               while ( (type = types[ i++ ]) ) {
-                       handleObj = handleObjIn ?
-                               jQuery.extend({}, handleObjIn) :
-                               { handler: handler, data: data };
+       results = results || [];
 
-                       // Namespaced event handlers
-                       if ( type.indexOf(".") > -1 ) {
-                               namespaces = type.split(".");
-                               type = namespaces.shift();
-                               handleObj.namespace = namespaces.slice(0).sort().join(".");
+       // Try to minimize operations if there is no seed and only one group
+       if ( match.length === 1 ) {
 
-                       } else {
-                               namespaces = [];
-                               handleObj.namespace = "";
-                       }
+               // Take a shortcut and set the context if the root selector is an ID
+               tokens = match[0] = match[0].slice( 0 );
+               if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+                               support.getById && context.nodeType === 9 && documentIsHTML &&
+                               Expr.relative[ tokens[1].type ] ) {
 
-                       handleObj.type = type;
-                       if ( !handleObj.guid ) {
-                               handleObj.guid = handler.guid;
-                       }
+                       context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+                       if ( !context ) {
+                               return results;
 
-                       // Get the current list of functions bound to this event
-                       var handlers = events[ type ],
-                               special = jQuery.event.special[ type ] || {};
+                       // Precompiled matchers will still verify ancestry, so step up a level
+                       } else if ( compiled ) {
+                               context = context.parentNode;
+                       }
 
-                       // Init the event handler queue
-                       if ( !handlers ) {
-                               handlers = events[ type ] = [];
+                       selector = selector.slice( tokens.shift().value.length );
+               }
 
-                               // 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 );
+               // Fetch a seed set for right-to-left matching
+               i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+               while ( i-- ) {
+                       token = tokens[i];
 
-                                       } else if ( elem.attachEvent ) {
-                                               elem.attachEvent( "on" + type, eventHandle );
+                       // Abort if we hit a combinator
+                       if ( Expr.relative[ (type = token.type) ] ) {
+                               break;
+                       }
+                       if ( (find = Expr.find[ type ]) ) {
+                               // Search, expanding context for leading sibling combinators
+                               if ( (seed = find(
+                                       token.matches[0].replace( runescape, funescape ),
+                                       rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+                               )) ) {
+
+                                       // If seed is empty or no tokens remain, we can return early
+                                       tokens.splice( i, 1 );
+                                       selector = seed.length && toSelector( tokens );
+                                       if ( !selector ) {
+                                               push.apply( results, seed );
+                                               return results;
                                        }
+
+                                       break;
                                }
                        }
+               }
+       }
 
-                       if ( special.add ) {
-                               special.add.call( elem, handleObj );
+       // Compile and execute a filtering function if one is not provided
+       // Provide `match` to avoid retokenization if we modified the selector above
+       ( compiled || compile( selector, match ) )(
+               seed,
+               context,
+               !documentIsHTML,
+               results,
+               rsibling.test( selector ) && testContext( context.parentNode ) || context
+       );
+       return results;
+};
 
-                               if ( !handleObj.handler.guid ) {
-                                       handleObj.handler.guid = handler.guid;
-                               }
-                       }
+// One-time assignments
 
-                       // Add the function to the element's handler list
-                       handlers.push( handleObj );
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
 
-                       // Keep track of which events have been used, for event optimization
-                       jQuery.event.global[ type ] = true;
-               }
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
 
-               // Nullify elem to prevent memory leaks in IE
-               elem = null;
-       },
+// Initialize against the default document
+setDocument();
 
-       global: {},
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+       // Should return 1, but returns 4 (following)
+       return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
 
-       // 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;
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+       div.innerHTML = "<a href='#'></a>";
+       return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+       addHandle( "type|href|height|width", function( elem, name, isXML ) {
+               if ( !isXML ) {
+                       return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
                }
+       });
+}
 
-               if ( handler === false ) {
-                       handler = returnFalse;
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+       div.innerHTML = "<input/>";
+       div.firstChild.setAttribute( "value", "" );
+       return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+       addHandle( "value", function( elem, name, isXML ) {
+               if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+                       return elem.defaultValue;
                }
+       });
+}
 
-               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;
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+       return div.getAttribute("disabled") == null;
+}) ) {
+       addHandle( booleans, function( elem, name, isXML ) {
+               var val;
+               if ( !isXML ) {
+                       return elem[ name ] === true ? name.toLowerCase() :
+                                       (val = elem.getAttributeNode( name )) && val.specified ?
+                                       val.value :
+                               null;
                }
+       });
+}
 
-               // types is actually an event object here
-               if ( types && types.type ) {
-                       handler = types.handler;
-                       types = types.type;
-               }
+return Sizzle;
 
-               // Unbind all events for the element
-               if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
-                       types = types || "";
+})( window );
 
-                       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(" ");
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
 
-               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("\\.(?:.*\\.)?") + "(\\.|$)");
-                       }
+var rneedsContext = jQuery.expr.match.needsContext;
 
-                       eventType = events[ type ];
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
 
-                       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 );
-                                       }
-                               }
+var risSimple = /^.[^:#\[\.,]*$/;
 
-                               continue;
-                       }
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+       if ( jQuery.isFunction( qualifier ) ) {
+               return jQuery.grep( elements, function( elem, i ) {
+                       /* jshint -W018 */
+                       return !!qualifier.call( elem, i, elem ) !== not;
+               });
 
-                       special = jQuery.event.special[ type ] || {};
+       }
 
-                       for ( j = pos || 0; j < eventType.length; j++ ) {
-                               handleObj = eventType[ j ];
+       if ( qualifier.nodeType ) {
+               return jQuery.grep( elements, function( elem ) {
+                       return ( elem === qualifier ) !== not;
+               });
 
-                               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 ( typeof qualifier === "string" ) {
+               if ( risSimple.test( qualifier ) ) {
+                       return jQuery.filter( qualifier, elements, not );
+               }
 
-                                       if ( pos != null ) {
-                                               break;
-                                       }
-                               }
-                       }
+               qualifier = jQuery.filter( qualifier, elements );
+       }
 
-                       // 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 );
-                               }
+       return jQuery.grep( elements, function( elem ) {
+               return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
+       });
+}
 
-                               ret = null;
-                               delete events[ type ];
-                       }
-               }
+jQuery.filter = function( expr, elems, not ) {
+       var elem = elems[ 0 ];
 
-               // 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 ( not ) {
+               expr = ":not(" + expr + ")";
+       }
 
-                       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
-       },
+       return elems.length === 1 && elem.nodeType === 1 ?
+               jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+               jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+                       return elem.nodeType === 1;
+               }));
+};
 
-       trigger: function( event, data, elem, onlyHandlers ) {
-               // Event object or event type
-               var type = event.type || event,
-                       namespaces = [],
-                       exclusive;
+jQuery.fn.extend({
+       find: function( selector ) {
+               var i,
+                       ret = [],
+                       self = this,
+                       len = self.length;
 
-               if ( type.indexOf("!") >= 0 ) {
-                       // Exclusive events trigger only for the exact event (no namespaces)
-                       type = type.slice(0, -1);
-                       exclusive = true;
+               if ( typeof selector !== "string" ) {
+                       return this.pushStack( jQuery( selector ).filter(function() {
+                               for ( i = 0; i < len; i++ ) {
+                                       if ( jQuery.contains( self[ i ], this ) ) {
+                                               return true;
+                                       }
+                               }
+                       }) );
                }
 
-               if ( type.indexOf(".") >= 0 ) {
-                       // Namespaced trigger; create a regexp to match event type in handle()
-                       namespaces = type.split(".");
-                       type = namespaces.shift();
-                       namespaces.sort();
+               for ( i = 0; i < len; i++ ) {
+                       jQuery.find( selector, self[ i ], ret );
                }
 
-               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;
-               }
+               // Needed because $( selector, context ) becomes $( context ).find( selector )
+               ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+               ret.selector = this.selector ? this.selector + " " + selector : selector;
+               return ret;
+       },
+       filter: function( selector ) {
+               return this.pushStack( winnow(this, selector || [], false) );
+       },
+       not: function( selector ) {
+               return this.pushStack( winnow(this, selector || [], true) );
+       },
+       is: function( selector ) {
+               return !!winnow(
+                       this,
+
+                       // If this is a positional/relative selector, check membership in the returned set
+                       // so $("p:first").is("p:last") won't return true for a doc with two "p".
+                       typeof selector === "string" && rneedsContext.test( selector ) ?
+                               jQuery( selector ) :
+                               selector || [],
+                       false
+               ).length;
+       }
+});
 
-               // 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();
-               }
+// Initialize a jQuery object
 
-               // 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;
-               }
+// A central reference to the root jQuery(document)
+var rootjQuery,
 
-               // Clean up the event in case it is being reused
-               event.result = undefined;
-               event.target = elem;
+       // Use the correct document accordingly with window argument (sandbox)
+       document = window.document,
 
-               // Clone any incoming data and prepend the event, creating the handler arg list
-               data = data ? jQuery.makeArray( data ) : [];
-               data.unshift( event );
+       // A simple way to check for HTML strings
+       // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+       // Strict HTML recognition (#11290: must start with <)
+       rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
 
-               var cur = elem,
-                       // IE doesn't like method names with a colon (#3533, #8272)
-                       ontype = type.indexOf(":") < 0 ? "on" + type : "";
+       init = jQuery.fn.init = function( selector, context ) {
+               var match, elem;
 
-               // Fire event on the current element, then bubble up the DOM tree
-               do {
-                       var handle = jQuery._data( cur, "handle" );
+               // HANDLE: $(""), $(null), $(undefined), $(false)
+               if ( !selector ) {
+                       return this;
+               }
 
-                       event.currentTarget = cur;
-                       if ( handle ) {
-                               handle.apply( cur, data );
-                       }
+               // Handle HTML strings
+               if ( typeof selector === "string" ) {
+                       if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+                               // Assume that strings that start and end with <> are HTML and skip the regex check
+                               match = [ null, selector, null ];
 
-                       // Trigger an inline bound script
-                       if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {
-                               event.result = false;
-                               event.preventDefault();
+                       } else {
+                               match = rquickExpr.exec( selector );
                        }
 
-                       // 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 ) ) {
+                       // Match html or make sure no context is specified for #id
+                       if ( match && (match[1] || !context) ) {
 
-                               // 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 ];
+                               // HANDLE: $(html) -> $(array)
+                               if ( match[1] ) {
+                                       context = context instanceof jQuery ? context[0] : context;
 
-                                               if ( old ) {
-                                                       elem[ ontype ] = null;
+                                       // scripts is true for back-compat
+                                       // Intentionally let the error be thrown if parseHTML is not present
+                                       jQuery.merge( this, jQuery.parseHTML(
+                                               match[1],
+                                               context && context.nodeType ? context.ownerDocument || context : document,
+                                               true
+                                       ) );
+
+                                       // HANDLE: $(html, props)
+                                       if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+                                               for ( match in context ) {
+                                                       // Properties of context are called as methods if possible
+                                                       if ( jQuery.isFunction( this[ match ] ) ) {
+                                                               this[ match ]( context[ match ] );
+
+                                                       // ...and otherwise set as attributes
+                                                       } else {
+                                                               this.attr( match, context[ match ] );
+                                                       }
                                                }
-
-                                               jQuery.event.triggered = type;
-                                               elem[ type ]();
                                        }
-                               } catch ( ieError ) {}
 
-                               if ( old ) {
-                                       elem[ ontype ] = old;
-                               }
+                                       return this;
 
-                               jQuery.event.triggered = undefined;
-                       }
-               }
-               
-               return event.result;
-       },
+                               // HANDLE: $(#id)
+                               } else {
+                                       elem = document.getElementById( match[2] );
 
-       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 );
+                                       // 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 );
+                                               }
 
-               // 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();
+                                               // Otherwise, we inject the element directly into the jQuery object
+                                               this.length = 1;
+                                               this[0] = elem;
                                        }
-                               }
 
-                               if ( event.isImmediatePropagationStopped() ) {
-                                       break;
+                                       this.context = document;
+                                       this.selector = selector;
+                                       return this;
                                }
-                       }
-               }
-               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(" "),
+                       // HANDLE: $(expr, $(...))
+                       } else if ( !context || context.jquery ) {
+                               return ( context || rootjQuery ).find( selector );
 
-       fix: function( event ) {
-               if ( event[ jQuery.expando ] ) {
-                       return event;
-               }
+                       // HANDLE: $(expr, context)
+                       // (which is just equivalent to: $(context).find(expr)
+                       } else {
+                               return this.constructor( context ).find( selector );
+                       }
 
-               // store a copy of the original event object
-               // and "clone" to set read-only properties
-               var originalEvent = event;
-               event = jQuery.Event( originalEvent );
+               // HANDLE: $(DOMElement)
+               } else if ( selector.nodeType ) {
+                       this.context = this[0] = selector;
+                       this.length = 1;
+                       return this;
 
-               for ( var i = this.props.length, prop; i; ) {
-                       prop = this.props[ --i ];
-                       event[ prop ] = originalEvent[ prop ];
+               // HANDLE: $(function)
+               // Shortcut for document ready
+               } else if ( jQuery.isFunction( selector ) ) {
+                       return typeof rootjQuery.ready !== "undefined" ?
+                               rootjQuery.ready( selector ) :
+                               // Execute immediately if ready is not present
+                               selector( jQuery );
                }
 
-               // Fix target property, if necessary
-               if ( !event.target ) {
-                       // Fixes #1925 where srcElement might not be defined either
-                       event.target = event.srcElement || document;
+               if ( selector.selector !== undefined ) {
+                       this.selector = selector.selector;
+                       this.context = selector.context;
                }
 
-               // check if target is a textnode (safari)
-               if ( event.target.nodeType === 3 ) {
-                       event.target = event.target.parentNode;
-               }
+               return jQuery.makeArray( selector, this );
+       };
 
-               // Add relatedTarget, if necessary
-               if ( !event.relatedTarget && event.fromElement ) {
-                       event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
-               }
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
 
-               // 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;
+// Initialize central reference
+rootjQuery = jQuery( document );
 
-                       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;
-               }
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+       // methods guaranteed to produce a unique set when starting from a unique set
+       guaranteedUnique = {
+               children: true,
+               contents: true,
+               next: true,
+               prev: true
+       };
 
-               // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
-               if ( !event.metaKey && event.ctrlKey ) {
-                       event.metaKey = event.ctrlKey;
-               }
+jQuery.extend({
+       dir: function( elem, dir, until ) {
+               var matched = [],
+                       cur = elem[ dir ];
 
-               // 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 ) ));
+               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 event;
+               return matched;
        },
 
-       // Deprecated, use jQuery.guid instead
-       guid: 1E8,
+       sibling: function( n, elem ) {
+               var r = [];
 
-       // Deprecated, use jQuery.proxy instead
-       proxy: jQuery.proxy,
+               for ( ; n; n = n.nextSibling ) {
+                       if ( n.nodeType === 1 && n !== elem ) {
+                               r.push( n );
+                       }
+               }
 
-       special: {
-               ready: {
-                       // Make sure the ready event is setup
-                       setup: jQuery.bindReady,
-                       teardown: jQuery.noop
-               },
+               return r;
+       }
+});
 
-               live: {
-                       add: function( handleObj ) {
-                               jQuery.event.add( this,
-                                       liveConvert( handleObj.origType, handleObj.selector ),
-                                       jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
-                       },
+jQuery.fn.extend({
+       has: function( target ) {
+               var i,
+                       targets = jQuery( target, this ),
+                       len = targets.length;
 
-                       remove: function( handleObj ) {
-                               jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
+               return this.filter(function() {
+                       for ( i = 0; i < len; i++ ) {
+                               if ( jQuery.contains( this, targets[i] ) ) {
+                                       return true;
+                               }
                        }
-               },
+               });
+       },
 
-               beforeunload: {
-                       setup: function( data, namespaces, eventHandle ) {
-                               // We only want to do this special case on windows
-                               if ( jQuery.isWindow( this ) ) {
-                                       this.onbeforeunload = eventHandle;
-                               }
-                       },
+       closest: function( selectors, context ) {
+               var cur,
+                       i = 0,
+                       l = this.length,
+                       matched = [],
+                       pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+                               jQuery( selectors, context || this.context ) :
+                               0;
+
+               for ( ; i < l; i++ ) {
+                       for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+                               // Always skip document fragments
+                               if ( cur.nodeType < 11 && (pos ?
+                                       pos.index(cur) > -1 :
 
-                       teardown: function( namespaces, eventHandle ) {
-                               if ( this.onbeforeunload === eventHandle ) {
-                                       this.onbeforeunload = null;
+                                       // Don't pass non-elements to Sizzle
+                                       cur.nodeType === 1 &&
+                                               jQuery.find.matchesSelector(cur, selectors)) ) {
+
+                                       matched.push( cur );
+                                       break;
                                }
                        }
                }
-       }
-};
 
-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 );
-               }
-       };
+               return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+       },
 
-jQuery.Event = function( src, props ) {
-       // Allow instantiation without the 'new' keyword
-       if ( !this.preventDefault ) {
-               return new jQuery.Event( src, props );
-       }
+       // Determine the position of an element within
+       // the matched set of elements
+       index: function( elem ) {
 
-       // Event object
-       if ( src && src.type ) {
-               this.originalEvent = src;
-               this.type = src.type;
+               // No argument, return index in parent
+               if ( !elem ) {
+                       return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+               }
 
-               // 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;
+               // index in selector
+               if ( typeof elem === "string" ) {
+                       return jQuery.inArray( this[0], jQuery( elem ) );
+               }
 
-       // Event type
-       } else {
-               this.type = src;
-       }
+               // 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 );
+       },
 
-       // Put explicitly provided properties onto the event object
-       if ( props ) {
-               jQuery.extend( this, props );
-       }
+       add: function( selector, context ) {
+               return this.pushStack(
+                       jQuery.unique(
+                               jQuery.merge( this.get(), jQuery( selector, context ) )
+                       )
+               );
+       },
 
-       // timeStamp is buggy for some events on Firefox(#3843)
-       // So we won't rely on the native value
-       this.timeStamp = jQuery.now();
+       addBack: function( selector ) {
+               return this.add( selector == null ?
+                       this.prevObject : this.prevObject.filter(selector)
+               );
+       }
+});
 
-       // Mark it as fixed
-       this[ jQuery.expando ] = true;
-};
+function sibling( cur, dir ) {
+       do {
+               cur = cur[ dir ];
+       } while ( cur && cur.nodeType !== 1 );
 
-function returnFalse() {
-       return false;
-}
-function returnTrue() {
-       return true;
+       return cur;
 }
 
-// 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;
-               }
+jQuery.each({
+       parent: function( elem ) {
+               var parent = elem.parentNode;
+               return parent && parent.nodeType !== 11 ? parent : null;
        },
-       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;
+       parents: function( elem ) {
+               return jQuery.dir( elem, "parentNode" );
        },
-       stopImmediatePropagation: function() {
-               this.isImmediatePropagationStopped = returnTrue;
-               this.stopPropagation();
+       parentsUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "parentNode", until );
        },
-       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 parent = event.relatedTarget;
-
-       // Firefox sometimes assigns relatedTarget a XUL element
-       // which we cannot access the parentNode property of
-       try {
+       next: function( elem ) {
+               return sibling( elem, "nextSibling" );
+       },
+       prev: function( elem ) {
+               return sibling( elem, "previousSibling" );
+       },
+       nextAll: function( elem ) {
+               return jQuery.dir( elem, "nextSibling" );
+       },
+       prevAll: function( elem ) {
+               return jQuery.dir( elem, "previousSibling" );
+       },
+       nextUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "nextSibling", until );
+       },
+       prevUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "previousSibling", until );
+       },
+       siblings: function( elem ) {
+               return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+       },
+       children: function( elem ) {
+               return jQuery.sibling( elem.firstChild );
+       },
+       contents: function( elem ) {
+               return jQuery.nodeName( elem, "iframe" ) ?
+                       elem.contentDocument || elem.contentWindow.document :
+                       jQuery.merge( [], elem.childNodes );
+       }
+}, function( name, fn ) {
+       jQuery.fn[ name ] = function( until, selector ) {
+               var ret = jQuery.map( this, fn, until );
 
-               // Chrome does something similar, the parentNode property
-               // can be accessed but is null.
-               if ( parent && parent !== document && !parent.parentNode ) {
-                       return;
-               }
-               // Traverse up the tree
-               while ( parent && parent !== this ) {
-                       parent = parent.parentNode;
+               if ( name.slice( -5 ) !== "Until" ) {
+                       selector = until;
                }
 
-               if ( parent !== this ) {
-                       // set the correct event type
-                       event.type = event.data;
-
-                       // handle event if we actually just moused on to a non sub-element
-                       jQuery.event.handle.apply( this, arguments );
+               if ( selector && typeof selector === "string" ) {
+                       ret = jQuery.filter( selector, ret );
                }
 
-       // assuming we've left the element since we most likely mousedover a xul element
-       } catch(e) { }
-},
-
-// 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 );
-};
+               if ( this.length > 1 ) {
+                       // Remove duplicates
+                       if ( !guaranteedUnique[ name ] ) {
+                               ret = jQuery.unique( ret );
+                       }
 
-// 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 );
+                       // Reverse order for parents* and prev-derivatives
+                       if ( rparentsprev.test( name ) ) {
+                               ret = ret.reverse();
+                       }
                }
+
+               return this.pushStack( ret );
        };
 });
+var rnotwhite = (/\S+/g);
 
-// 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 ) {
-                                       var elem = e.target,
-                                               type = 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 = elem.type;
+// String to Object options format cache
+var optionsCache = {};
 
-                                       if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
-                                               trigger( "submit", this, arguments );
-                                       }
-                               });
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+       var object = optionsCache[ options ] = {};
+       jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+               object[ flag ] = true;
+       });
+       return object;
+}
 
-                       } else {
-                               return false;
+/*
+ * Create a callback list using the following parameters:
+ *
+ *     options: an optional list of space-separated options that will change how
+ *                     the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *     once:                   will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *     memory:                 will keep track of previous values and will call any callback added
+ *                                     after the list has been fired right away with the latest "memorized"
+ *                                     values (like a Deferred)
+ *
+ *     unique:                 will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *     stopOnFalse:    interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+       // Convert options from String-formatted to Object-formatted if needed
+       // (we check in cache first)
+       options = typeof options === "string" ?
+               ( optionsCache[ options ] || createOptions( options ) ) :
+               jQuery.extend( {}, options );
+
+       var // Flag to know if list is currently firing
+               firing,
+               // Last fire value (for non-forgettable lists)
+               memory,
+               // Flag to know if list was already fired
+               fired,
+               // End of the loop when firing
+               firingLength,
+               // Index of currently firing callback (modified by remove if needed)
+               firingIndex,
+               // First callback to fire (used internally by add and fireWith)
+               firingStart,
+               // Actual callback list
+               list = [],
+               // Stack of fire calls for repeatable lists
+               stack = !options.once && [],
+               // Fire callbacks
+               fire = function( data ) {
+                       memory = options.memory && data;
+                       fired = true;
+                       firingIndex = firingStart || 0;
+                       firingStart = 0;
+                       firingLength = list.length;
+                       firing = true;
+                       for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+                               if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+                                       memory = false; // To prevent further calls using add
+                                       break;
+                               }
+                       }
+                       firing = false;
+                       if ( list ) {
+                               if ( stack ) {
+                                       if ( stack.length ) {
+                                               fire( stack.shift() );
+                                       }
+                               } else if ( memory ) {
+                                       list = [];
+                               } else {
+                                       self.disable();
+                               }
                        }
                },
+               // Actual Callbacks object
+               self = {
+                       // Add a callback or a collection of callbacks to the list
+                       add: function() {
+                               if ( list ) {
+                                       // First, we save the current length
+                                       var start = list.length;
+                                       (function add( args ) {
+                                               jQuery.each( args, function( _, arg ) {
+                                                       var type = jQuery.type( arg );
+                                                       if ( type === "function" ) {
+                                                               if ( !options.unique || !self.has( arg ) ) {
+                                                                       list.push( arg );
+                                                               }
+                                                       } else if ( arg && arg.length && type !== "string" ) {
+                                                               // Inspect recursively
+                                                               add( arg );
+                                                       }
+                                               });
+                                       })( arguments );
+                                       // Do we need to add the callbacks to the
+                                       // current firing batch?
+                                       if ( firing ) {
+                                               firingLength = list.length;
+                                       // With memory, if we're not firing then
+                                       // we should call right away
+                                       } else if ( memory ) {
+                                               firingStart = start;
+                                               fire( memory );
+                                       }
+                               }
+                               return this;
+                       },
+                       // Remove a callback from the list
+                       remove: function() {
+                               if ( list ) {
+                                       jQuery.each( arguments, function( _, arg ) {
+                                               var index;
+                                               while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+                                                       list.splice( index, 1 );
+                                                       // Handle firing indexes
+                                                       if ( firing ) {
+                                                               if ( index <= firingLength ) {
+                                                                       firingLength--;
+                                                               }
+                                                               if ( index <= firingIndex ) {
+                                                                       firingIndex--;
+                                                               }
+                                                       }
+                                               }
+                                       });
+                               }
+                               return this;
+                       },
+                       // Check if a given callback is in the list.
+                       // If no argument is given, return whether or not list has callbacks attached.
+                       has: function( fn ) {
+                               return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+                       },
+                       // Remove all callbacks from the list
+                       empty: function() {
+                               list = [];
+                               firingLength = 0;
+                               return this;
+                       },
+                       // Have the list do nothing anymore
+                       disable: function() {
+                               list = stack = memory = undefined;
+                               return this;
+                       },
+                       // Is it disabled?
+                       disabled: function() {
+                               return !list;
+                       },
+                       // Lock the list in its current state
+                       lock: function() {
+                               stack = undefined;
+                               if ( !memory ) {
+                                       self.disable();
+                               }
+                               return this;
+                       },
+                       // Is it locked?
+                       locked: function() {
+                               return !stack;
+                       },
+                       // Call all callbacks with the given context and arguments
+                       fireWith: function( context, args ) {
+                               if ( list && ( !fired || stack ) ) {
+                                       args = args || [];
+                                       args = [ context, args.slice ? args.slice() : args ];
+                                       if ( firing ) {
+                                               stack.push( args );
+                                       } else {
+                                               fire( args );
+                                       }
+                               }
+                               return this;
+                       },
+                       // Call all the callbacks with the given arguments
+                       fire: function() {
+                               self.fireWith( this, arguments );
+                               return this;
+                       },
+                       // To know if the callbacks have already been called at least once
+                       fired: function() {
+                               return !!fired;
+                       }
+               };
 
-               teardown: function( namespaces ) {
-                       jQuery.event.remove( this, ".specialSubmit" );
-               }
-       };
-
-}
+       return self;
+};
 
-// change delegation, happens here so we have bind.
-if ( !jQuery.support.changeBubbles ) {
 
-       var changeFilters,
+jQuery.extend({
 
-       getVal = function( elem ) {
-               var type = elem.type, val = elem.value;
+       Deferred: function( func ) {
+               var tuples = [
+                               // action, add listener, listener list, final state
+                               [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+                               [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+                               [ "notify", "progress", jQuery.Callbacks("memory") ]
+                       ],
+                       state = "pending",
+                       promise = {
+                               state: function() {
+                                       return state;
+                               },
+                               always: function() {
+                                       deferred.done( arguments ).fail( arguments );
+                                       return this;
+                               },
+                               then: function( /* fnDone, fnFail, fnProgress */ ) {
+                                       var fns = arguments;
+                                       return jQuery.Deferred(function( newDefer ) {
+                                               jQuery.each( tuples, function( i, tuple ) {
+                                                       var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+                                                       // deferred[ done | fail | progress ] for forwarding actions to newDefer
+                                                       deferred[ tuple[1] ](function() {
+                                                               var returned = fn && fn.apply( this, arguments );
+                                                               if ( returned && jQuery.isFunction( returned.promise ) ) {
+                                                                       returned.promise()
+                                                                               .done( newDefer.resolve )
+                                                                               .fail( newDefer.reject )
+                                                                               .progress( newDefer.notify );
+                                                               } else {
+                                                                       newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+                                                               }
+                                                       });
+                                               });
+                                               fns = null;
+                                       }).promise();
+                               },
+                               // Get a promise for this deferred
+                               // If obj is provided, the promise aspect is added to the object
+                               promise: function( obj ) {
+                                       return obj != null ? jQuery.extend( obj, promise ) : promise;
+                               }
+                       },
+                       deferred = {};
 
-               if ( type === "radio" || type === "checkbox" ) {
-                       val = elem.checked;
+               // Keep pipe for back-compat
+               promise.pipe = promise.then;
 
-               } else if ( type === "select-multiple" ) {
-                       val = elem.selectedIndex > -1 ?
-                               jQuery.map( elem.options, function( elem ) {
-                                       return elem.selected;
-                               }).join("-") :
-                               "";
+               // Add list-specific methods
+               jQuery.each( tuples, function( i, tuple ) {
+                       var list = tuple[ 2 ],
+                               stateString = tuple[ 3 ];
 
-               } else if ( jQuery.nodeName( elem, "select" ) ) {
-                       val = elem.selectedIndex;
-               }
+                       // promise[ done | fail | progress ] = list.add
+                       promise[ tuple[1] ] = list.add;
 
-               return val;
-       },
+                       // Handle state
+                       if ( stateString ) {
+                               list.add(function() {
+                                       // state = [ resolved | rejected ]
+                                       state = stateString;
 
-       testChange = function testChange( e ) {
-               var elem = e.target, data, val;
+                               // [ reject_list | resolve_list ].disable; progress_list.lock
+                               }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+                       }
 
-               if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
-                       return;
-               }
+                       // deferred[ resolve | reject | notify ]
+                       deferred[ tuple[0] ] = function() {
+                               deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+                               return this;
+                       };
+                       deferred[ tuple[0] + "With" ] = list.fireWith;
+               });
 
-               data = jQuery._data( elem, "_change_data" );
-               val = getVal(elem);
+               // Make the deferred a promise
+               promise.promise( deferred );
 
-               // the current data will be also retrieved by beforeactivate
-               if ( e.type !== "focusout" || elem.type !== "radio" ) {
-                       jQuery._data( elem, "_change_data", val );
+               // Call given func if any
+               if ( func ) {
+                       func.call( deferred, deferred );
                }
 
-               if ( data === undefined || val === data ) {
-                       return;
-               }
+               // All done!
+               return deferred;
+       },
 
-               if ( data != null || val ) {
-                       e.type = "change";
-                       e.liveFired = undefined;
-                       jQuery.event.trigger( e, arguments[1], elem );
-               }
-       };
+       // Deferred helper
+       when: function( subordinate /* , ..., subordinateN */ ) {
+               var i = 0,
+                       resolveValues = slice.call( arguments ),
+                       length = resolveValues.length,
 
-       jQuery.event.special.change = {
-               filters: {
-                       focusout: testChange,
+                       // the count of uncompleted subordinates
+                       remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
 
-                       beforedeactivate: testChange,
+                       // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+                       deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
 
-                       click: function( e ) {
-                               var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
+                       // Update function for both resolve and progress values
+                       updateFunc = function( i, contexts, values ) {
+                               return function( value ) {
+                                       contexts[ i ] = this;
+                                       values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+                                       if ( values === progressValues ) {
+                                               deferred.notifyWith( contexts, values );
 
-                               if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) {
-                                       testChange.call( this, e );
-                               }
+                                       } else if ( !(--remaining) ) {
+                                               deferred.resolveWith( contexts, values );
+                                       }
+                               };
                        },
 
-                       // 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 : "";
+                       progressValues, progressContexts, resolveContexts;
 
-                               if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) ||
-                                       (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
-                                       type === "select-multiple" ) {
-                                       testChange.call( this, e );
+               // add listeners to Deferred subordinates; treat others as resolved
+               if ( length > 1 ) {
+                       progressValues = new Array( length );
+                       progressContexts = new Array( length );
+                       resolveContexts = new Array( length );
+                       for ( ; i < length; i++ ) {
+                               if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+                                       resolveValues[ i ].promise()
+                                               .done( updateFunc( i, resolveContexts, resolveValues ) )
+                                               .fail( deferred.reject )
+                                               .progress( updateFunc( i, progressContexts, progressValues ) );
+                               } else {
+                                       --remaining;
                                }
-                       },
-
-                       // 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;
-}
+               // if we're not waiting on anything, resolve the master
+               if ( !remaining ) {
+                       deferred.resolveWith( resolveContexts, resolveValues );
+               }
 
-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();
+               return deferred.promise();
        }
-}
-
-// 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 );
-                               }
-                       }
-               };
+// The deferred used on DOM ready
+var readyList;
 
-               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.fn.ready = function( fn ) {
+       // Add the callback
+       jQuery.ready.promise().done( fn );
 
-jQuery.each(["bind", "one"], function( i, name ) {
-       jQuery.fn[ name ] = function( type, data, fn ) {
-               var handler;
+       return this;
+};
 
-               // Handle object literals
-               if ( typeof type === "object" ) {
-                       for ( var key in type ) {
-                               this[ name ](key, data, type[key], fn);
-                       }
-                       return this;
-               }
+jQuery.extend({
+       // Is the DOM ready to be used? Set to true once it occurs.
+       isReady: false,
 
-               if ( arguments.length === 2 || data === false ) {
-                       fn = data;
-                       data = undefined;
-               }
+       // A counter to track how many items to wait for before
+       // the ready event fires. See #6781
+       readyWait: 1,
 
-               if ( name === "one" ) {
-                       handler = function( event ) {
-                               jQuery( this ).unbind( event, handler );
-                               return fn.apply( this, arguments );
-                       };
-                       handler.guid = fn.guid || jQuery.guid++;
+       // Hold (or release) the ready event
+       holdReady: function( hold ) {
+               if ( hold ) {
+                       jQuery.readyWait++;
                } else {
-                       handler = fn;
+                       jQuery.ready( true );
                }
+       },
 
-               if ( type === "unload" && name !== "one" ) {
-                       this.one( type, data, fn );
+       // Handle when the DOM is ready
+       ready: function( wait ) {
 
-               } else {
-                       for ( var i = 0, l = this.length; i < l; i++ ) {
-                               jQuery.event.add( this[i], type, handler, data );
-                       }
+               // Abort if there are pending holds or we're already ready
+               if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+                       return;
                }
 
-               return this;
-       };
-});
+               // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+               if ( !document.body ) {
+                       return setTimeout( jQuery.ready );
+               }
 
-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]);
-                       }
+               // Remember that the DOM is ready
+               jQuery.isReady = true;
 
-               } else {
-                       for ( var i = 0, l = this.length; i < l; i++ ) {
-                               jQuery.event.remove( this[i], type, fn );
-                       }
+               // If a normal DOM Ready event fired, decrement, and wait if need be
+               if ( wait !== true && --jQuery.readyWait > 0 ) {
+                       return;
                }
 
-               return this;
-       },
+               // If there are functions bound, to execute
+               readyList.resolveWith( document, [ jQuery ] );
 
-       delegate: function( selector, types, data, fn ) {
-               return this.live( types, data, fn, selector );
-       },
+               // Trigger any bound ready events
+               if ( jQuery.fn.triggerHandler ) {
+                       jQuery( document ).triggerHandler( "ready" );
+                       jQuery( document ).off( "ready" );
+               }
+       }
+});
 
-       undelegate: function( selector, types, fn ) {
-               if ( arguments.length === 0 ) {
-                       return this.unbind( "live" );
+/**
+ * Clean-up method for dom ready events
+ */
+function detach() {
+       if ( document.addEventListener ) {
+               document.removeEventListener( "DOMContentLoaded", completed, false );
+               window.removeEventListener( "load", completed, false );
 
-               } 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 );
-               }
-       },
+       } else {
+               document.detachEvent( "onreadystatechange", completed );
+               window.detachEvent( "onload", completed );
+       }
+}
 
-       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 );
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+       // readyState === "complete" is good enough for us to call the dom ready in oldIE
+       if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+               detach();
+               jQuery.ready();
+       }
+}
 
-                               // Make sure that clicks stop
-                               event.preventDefault();
+jQuery.ready.promise = function( obj ) {
+       if ( !readyList ) {
 
-                               // and execute the function
-                               return args[ lastToggle ].apply( this, arguments ) || false;
-                       };
+               readyList = jQuery.Deferred();
 
-               // link all the functions, so any of them can unbind this click handler
-               toggler.guid = guid;
-               while ( i < args.length ) {
-                       args[ i++ ].guid = guid;
-               }
+               // Catch cases where $(document).ready() is called after the browser event has already occurred.
+               // we once tried to use readyState "interactive" here, but it caused issues like the one
+               // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+               if ( document.readyState === "complete" ) {
+                       // Handle it asynchronously to allow scripts the opportunity to delay ready
+                       setTimeout( jQuery.ready );
 
-               return this.click( toggler );
-       },
+               // Standards-based browsers support DOMContentLoaded
+               } else if ( document.addEventListener ) {
+                       // Use the handy event callback
+                       document.addEventListener( "DOMContentLoaded", completed, false );
 
-       hover: function( fnOver, fnOut ) {
-               return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
-       }
-});
+                       // A fallback to window.onload, that will always work
+                       window.addEventListener( "load", completed, false );
 
-var liveMap = {
-       focus: "focusin",
-       blur: "focusout",
-       mouseenter: "mouseover",
-       mouseleave: "mouseout"
-};
+               // If IE event model is used
+               } else {
+                       // Ensure firing before onload, maybe late but safe also for iframes
+                       document.attachEvent( "onreadystatechange", completed );
 
-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 );
+                       // A fallback to window.onload, that will always work
+                       window.attachEvent( "onload", completed );
 
-               if ( typeof types === "object" && !types.preventDefault ) {
-                       for ( var key in types ) {
-                               context[ name ]( key, data, types[key], selector );
-                       }
+                       // If IE and not a frame
+                       // continually check to see if the document is ready
+                       var top = false;
 
-                       return this;
-               }
+                       try {
+                               top = window.frameElement == null && document.documentElement;
+                       } catch(e) {}
 
-               if ( name === "die" && !types &&
-                                       origSelector && origSelector.charAt(0) === "." ) {
+                       if ( top && top.doScroll ) {
+                               (function doScrollCheck() {
+                                       if ( !jQuery.isReady ) {
 
-                       context.unbind( origSelector );
+                                               try {
+                                                       // Use the trick by Diego Perini
+                                                       // http://javascript.nwbox.com/IEContentLoaded/
+                                                       top.doScroll("left");
+                                               } catch(e) {
+                                                       return setTimeout( doScrollCheck, 50 );
+                                               }
 
-                       return this;
-               }
+                                               // detach all dom ready events
+                                               detach();
 
-               if ( data === false || jQuery.isFunction( data ) ) {
-                       fn = data || returnFalse;
-                       data = undefined;
+                                               // and execute any waiting functions
+                                               jQuery.ready();
+                                       }
+                               })();
+                       }
                }
+       }
+       return readyList.promise( obj );
+};
 
-               types = (types || "").split(" ");
-
-               while ( (type = types[ i++ ]) != null ) {
-                       match = rnamespaces.exec( type );
-                       namespaces = "";
 
-                       if ( match )  {
-                               namespaces = match[0];
-                               type = type.replace( rnamespaces, "" );
-                       }
+var strundefined = typeof undefined;
 
-                       if ( type === "hover" ) {
-                               types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
-                               continue;
-                       }
 
-                       preType = type;
 
-                       if ( liveMap[ type ] ) {
-                               types.push( liveMap[ type ] + namespaces );
-                               type = type + namespaces;
+// Support: IE<9
+// Iteration over object's inherited properties before its own
+var i;
+for ( i in jQuery( support ) ) {
+       break;
+}
+support.ownLast = i !== "0";
 
-                       } else {
-                               type = (liveMap[ type ] || type) + namespaces;
-                       }
+// Note: most support tests are defined in their respective modules.
+// false until the test is run
+support.inlineBlockNeedsLayout = false;
 
-                       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 } );
-                               }
+// Execute ASAP in case we need to set body.style.zoom
+jQuery(function() {
+       // Minified: var a,b,c,d
+       var val, div, body, container;
 
-                       } else {
-                               // unbind live handler
-                               context.unbind( "live." + liveConvert( type, selector ), fn );
-                       }
-               }
+       body = document.getElementsByTagName( "body" )[ 0 ];
+       if ( !body || !body.style ) {
+               // Return for frameset docs that don't have a body
+               return;
+       }
 
-               return this;
-       };
-});
+       // Setup
+       div = document.createElement( "div" );
+       container = document.createElement( "div" );
+       container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+       body.appendChild( container ).appendChild( div );
 
-function liveHandler( event ) {
-       var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
-               elems = [],
-               selectors = [],
-               events = jQuery._data( this, "events" );
+       if ( typeof div.style.zoom !== strundefined ) {
+               // Support: IE<8
+               // Check if natively block-level elements act like inline-block
+               // elements when setting their display to 'inline' and giving
+               // them layout
+               div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
 
-       // 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;
+               support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
+               if ( val ) {
+                       // Prevent IE 6 from affecting layout for positioned elements #11048
+                       // Prevent IE from shrinking the body in IE 7 mode #12869
+                       // Support: IE<8
+                       body.style.zoom = 1;
+               }
        }
 
-       if ( event.namespace ) {
-               namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
-       }
+       body.removeChild( container );
+});
 
-       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 );
+(function() {
+       var div = document.createElement( "div" );
 
-               } else {
-                       live.splice( j--, 1 );
+       // Execute the test only if not already executed in another module.
+       if (support.deleteExpando == null) {
+               // Support: IE<9
+               support.deleteExpando = true;
+               try {
+                       delete div.test;
+               } catch( e ) {
+                       support.deleteExpando = false;
                }
        }
 
-       match = jQuery( event.target ).closest( selectors, event.currentTarget );
+       // Null elements to avoid leaks in IE.
+       div = null;
+})();
 
-       for ( i = 0, l = match.length; i < l; i++ ) {
-               close = match[i];
 
-               for ( j = 0; j < live.length; j++ ) {
-                       handleObj = live[j];
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( elem ) {
+       var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
+               nodeType = +elem.nodeType || 1;
 
-                       if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
-                               elem = close.elem;
-                               related = null;
+       // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
+       return nodeType !== 1 && nodeType !== 9 ?
+               false :
 
-                               // 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];
+               // Nodes accept data unless otherwise specified; rejection can be conditional
+               !noData || noData !== true && elem.getAttribute("classid") === noData;
+};
 
-                                       // 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 });
-                               }
-                       }
-               }
-       }
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+       rmultiDash = /([A-Z])/g;
 
-       for ( i = 0, l = elems.length; i < l; i++ ) {
-               match = elems[i];
+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 ) {
 
-               if ( maxLevel && match.level > maxLevel ) {
-                       break;
-               }
+               var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
 
-               event.currentTarget = match.elem;
-               event.data = match.handleObj.data;
-               event.handleObj = match.handleObj;
+               data = elem.getAttribute( name );
 
-               ret = match.handleObj.origHandler.apply( match.elem, arguments );
+               if ( typeof data === "string" ) {
+                       try {
+                               data = data === "true" ? true :
+                                       data === "false" ? false :
+                                       data === "null" ? null :
+                                       // Only convert to a number if it doesn't change the string
+                                       +data + "" === data ? +data :
+                                       rbrace.test( data ) ? jQuery.parseJSON( data ) :
+                                       data;
+                       } catch( e ) {}
 
-               if ( ret === false || event.isPropagationStopped() ) {
-                       maxLevel = match.level;
+                       // Make sure we set the data so it isn't changed later
+                       jQuery.data( elem, key, data );
 
-                       if ( ret === false ) {
-                               stop = false;
-                       }
-                       if ( event.isImmediatePropagationStopped() ) {
-                               break;
-                       }
+               } else {
+                       data = undefined;
                }
        }
 
-       return stop;
-}
-
-function liveConvert( type, selector ) {
-       return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&");
+       return data;
 }
 
-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 ) {
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+       var name;
+       for ( name in obj ) {
 
-       // Handle event binding
-       jQuery.fn[ name ] = function( data, fn ) {
-               if ( fn == null ) {
-                       fn = data;
-                       data = null;
+               // if the public data object is empty, the private is still empty
+               if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+                       continue;
+               }
+               if ( name !== "toJSON" ) {
+                       return false;
                }
-
-               return arguments.length > 0 ?
-                       this.bind( name, data, fn ) :
-                       this.trigger( name );
-       };
-
-       if ( jQuery.attrFn ) {
-               jQuery.attrFn[ name ] = true;
        }
-});
 
+       return true;
+}
 
+function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
+       if ( !jQuery.acceptData( elem ) ) {
+               return;
+       }
 
-/*!
- * Sizzle CSS Selector Engine
- *  Copyright 2011, The Dojo Foundation
- *  Released under the MIT, BSD, and GPL Licenses.
- *  More information: http://sizzlejs.com/
- */
-(function(){
+       var ret, thisCache,
+               internalKey = jQuery.expando,
 
-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;
-});
+               // 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,
 
-var Sizzle = function( selector, context, results, seed ) {
-       results = results || [];
-       context = context || document;
+               // 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,
 
-       var origContext = context;
+               // Only defining an ID for JS objects if its cache already exists allows
+               // the code to shortcut on the same path as a DOM node with no cache
+               id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
 
-       if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
-               return [];
-       }
-       
-       if ( !selector || typeof selector !== "string" ) {
-               return results;
+       // Avoid doing any more work than we need to when trying to get data on an
+       // object that has no data at all
+       if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
+               return;
        }
 
-       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;
-                       }
+       if ( !id ) {
+               // Only DOM nodes need a new unique ID for each element since their data
+               // ends up in the global cache
+               if ( isNode ) {
+                       id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
+               } else {
+                       id = internalKey;
                }
-       } while ( m );
-
-       if ( parts.length > 1 && origPOS.exec( selector ) ) {
+       }
 
-               if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
-                       set = posProcess( parts[0] + parts[1], context );
+       if ( !cache[ id ] ) {
+               // Avoid exposing jQuery metadata on plain JS objects when the object
+               // is serialized using JSON.stringify
+               cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
+       }
 
+       // An object can be passed to jQuery.data instead of a key/value pair; this gets
+       // shallow copied over onto the existing cache
+       if ( typeof name === "object" || typeof name === "function" ) {
+               if ( pvt ) {
+                       cache[ id ] = jQuery.extend( cache[ id ], name );
                } else {
-                       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 );
-                       }
+                       cache[ id ].data = jQuery.extend( cache[ id ].data, name );
                }
+       }
 
-       } 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]) ) {
+       thisCache = cache[ id ];
 
-                       ret = Sizzle.find( parts.shift(), context, contextXML );
-                       context = ret.expr ?
-                               Sizzle.filter( ret.expr, ret.set )[0] :
-                               ret.set[0];
+       // jQuery data() is stored in a separate object inside the object's internal data
+       // cache in order to avoid key collisions between internal data and user-defined
+       // data.
+       if ( !pvt ) {
+               if ( !thisCache.data ) {
+                       thisCache.data = {};
                }
 
-               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 = [];
-               }
+               thisCache = thisCache.data;
        }
 
-       if ( !checkSet ) {
-               checkSet = set;
+       if ( data !== undefined ) {
+               thisCache[ jQuery.camelCase( name ) ] = data;
        }
 
-       if ( !checkSet ) {
-               Sizzle.error( cur || selector );
-       }
+       // Check for both converted-to-camel and non-converted data property names
+       // If a data property was specified
+       if ( typeof name === "string" ) {
 
-       if ( toString.call(checkSet) === "[object Array]" ) {
-               if ( !prune ) {
-                       results.push.apply( results, checkSet );
+               // First Try to find as-is property data
+               ret = thisCache[ name ];
 
-               } 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] );
-                               }
-                       }
+               // Test for null|undefined property data
+               if ( ret == null ) {
 
-               } else {
-                       for ( i = 0; checkSet[i] != null; i++ ) {
-                               if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
-                                       results.push( set[i] );
-                               }
-                       }
+                       // Try to find the camelCased property
+                       ret = thisCache[ jQuery.camelCase( name ) ];
                }
-
        } else {
-               makeArray( checkSet, results );
+               ret = thisCache;
        }
 
-       if ( extra ) {
-               Sizzle( extra, origContext, results, seed );
-               Sizzle.uniqueSort( results );
+       return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+       if ( !jQuery.acceptData( elem ) ) {
+               return;
        }
 
-       return results;
-};
+       var thisCache, i,
+               isNode = elem.nodeType,
 
-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 );
-                               }
-                       }
-               }
+               // See jQuery.data for more information
+               cache = isNode ? jQuery.cache : elem,
+               id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+       // If there is already no cache entry for this object, there is no
+       // purpose in continuing
+       if ( !cache[ id ] ) {
+               return;
        }
 
-       return results;
-};
+       if ( name ) {
 
-Sizzle.matches = function( expr, set ) {
-       return Sizzle( expr, null, null, set );
-};
+               thisCache = pvt ? cache[ id ] : cache[ id ].data;
 
-Sizzle.matchesSelector = function( node, expr ) {
-       return Sizzle( expr, null, null, [node] ).length > 0;
-};
+               if ( thisCache ) {
 
-Sizzle.find = function( expr, context, isXML ) {
-       var set;
+                       // Support array or space separated string names for data keys
+                       if ( !jQuery.isArray( name ) ) {
 
-       if ( !expr ) {
-               return [];
-       }
+                               // try the string as a key before any manipulation
+                               if ( name in thisCache ) {
+                                       name = [ name ];
+                               } else {
 
-       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 );
+                                       // split the camel cased version by spaces unless a key with the spaces exists
+                                       name = jQuery.camelCase( name );
+                                       if ( name in thisCache ) {
+                                               name = [ name ];
+                                       } else {
+                                               name = name.split(" ");
+                                       }
+                               }
+                       } else {
+                               // If "name" is an array of keys...
+                               // When data is initially created, via ("key", "val") signature,
+                               // keys will be converted to camelCase.
+                               // Since there is no way to tell _how_ a key was added, remove
+                               // both plain key and camelCase key. #12786
+                               // This will only penalize the array argument path.
+                               name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+                       }
 
-                       if ( left.substr( left.length - 1 ) !== "\\" ) {
-                               match[1] = (match[1] || "").replace( rBackslash, "" );
-                               set = Expr.find[ type ]( match, context, isXML );
+                       i = name.length;
+                       while ( i-- ) {
+                               delete thisCache[ name[i] ];
+                       }
 
-                               if ( set != null ) {
-                                       expr = expr.replace( Expr.match[ type ], "" );
-                                       break;
-                               }
+                       // If there is no data left in the cache, we want to continue
+                       // and let the cache object itself get destroyed
+                       if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
+                               return;
                        }
                }
        }
 
-       if ( !set ) {
-               set = typeof context.getElementsByTagName !== "undefined" ?
-                       context.getElementsByTagName( "*" ) :
-                       [];
-       }
+       // See jQuery.data for more information
+       if ( !pvt ) {
+               delete cache[ id ].data;
 
-       return { set: set, expr: expr };
-};
+               // Don't destroy the parent cache unless the internal data object
+               // had been the only thing left in it
+               if ( !isEmptyDataObject( cache[ id ] ) ) {
+                       return;
+               }
+       }
 
-Sizzle.filter = function( expr, set, inplace, not ) {
-       var match, anyFound,
-               old = expr,
-               result = [],
-               curLoop = set,
-               isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+       // Destroy the cache
+       if ( isNode ) {
+               jQuery.cleanData( [ elem ], true );
 
-       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];
+       // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+       /* jshint eqeqeq: false */
+       } else if ( support.deleteExpando || cache != cache.window ) {
+               /* jshint eqeqeq: true */
+               delete cache[ id ];
 
-                               anyFound = false;
+       // When all else fails, null
+       } else {
+               cache[ id ] = null;
+       }
+}
 
-                               match.splice(1,1);
+jQuery.extend({
+       cache: {},
 
-                               if ( left.substr( left.length - 1 ) === "\\" ) {
-                                       continue;
-                               }
+       // The following elements (space-suffixed to avoid Object.prototype collisions)
+       // throw uncatchable exceptions if you attempt to set expando properties
+       noData: {
+               "applet ": true,
+               "embed ": true,
+               // ...but Flash objects (which have this classid) *can* handle expandos
+               "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+       },
 
-                               if ( curLoop === result ) {
-                                       result = [];
-                               }
+       hasData: function( elem ) {
+               elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+               return !!elem && !isEmptyDataObject( elem );
+       },
 
-                               if ( Expr.preFilter[ type ] ) {
-                                       match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+       data: function( elem, name, data ) {
+               return internalData( elem, name, data );
+       },
 
-                                       if ( !match ) {
-                                               anyFound = found = true;
+       removeData: function( elem, name ) {
+               return internalRemoveData( elem, name );
+       },
 
-                                       } else if ( match === true ) {
-                                               continue;
-                                       }
-                               }
+       // For internal use only.
+       _data: function( elem, name, data ) {
+               return internalData( elem, name, data, true );
+       },
 
-                               if ( match ) {
-                                       for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
-                                               if ( item ) {
-                                                       found = filter( item, match, i, curLoop );
-                                                       var pass = not ^ !!found;
+       _removeData: function( elem, name ) {
+               return internalRemoveData( elem, name, true );
+       }
+});
 
-                                                       if ( inplace && found != null ) {
-                                                               if ( pass ) {
-                                                                       anyFound = true;
+jQuery.fn.extend({
+       data: function( key, value ) {
+               var i, name, data,
+                       elem = this[0],
+                       attrs = elem && elem.attributes;
 
-                                                               } else {
-                                                                       curLoop[i] = false;
-                                                               }
+               // Special expections of .data basically thwart jQuery.access,
+               // so implement the relevant behavior ourselves
 
-                                                       } else if ( pass ) {
-                                                               result.push( item );
-                                                               anyFound = true;
+               // Gets all values
+               if ( key === undefined ) {
+                       if ( this.length ) {
+                               data = jQuery.data( elem );
+
+                               if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+                                       i = attrs.length;
+                                       while ( i-- ) {
+
+                                               // Support: IE11+
+                                               // The attrs elements can be null (#14894)
+                                               if ( attrs[ i ] ) {
+                                                       name = attrs[ i ].name;
+                                                       if ( name.indexOf( "data-" ) === 0 ) {
+                                                               name = jQuery.camelCase( name.slice(5) );
+                                                               dataAttr( elem, name, data[ name ] );
                                                        }
                                                }
                                        }
+                                       jQuery._data( elem, "parsedAttrs", true );
                                }
+                       }
 
-                               if ( found !== undefined ) {
-                                       if ( !inplace ) {
-                                               curLoop = result;
-                                       }
-
-                                       expr = expr.replace( Expr.match[ type ], "" );
-
-                                       if ( !anyFound ) {
-                                               return [];
-                                       }
+                       return data;
+               }
 
-                                       break;
-                               }
-                       }
+               // Sets multiple values
+               if ( typeof key === "object" ) {
+                       return this.each(function() {
+                               jQuery.data( this, key );
+                       });
                }
 
-               // Improper expression
-               if ( expr === old ) {
-                       if ( anyFound == null ) {
-                               Sizzle.error( expr );
+               return arguments.length > 1 ?
 
-                       } else {
-                               break;
-                       }
-               }
+                       // Sets one value
+                       this.each(function() {
+                               jQuery.data( this, key, value );
+                       }) :
 
-               old = expr;
+                       // Gets one value
+                       // Try to fetch any internally stored data first
+                       elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
+       },
+
+       removeData: function( key ) {
+               return this.each(function() {
+                       jQuery.removeData( this, key );
+               });
        }
+});
 
-       return curLoop;
-};
 
-Sizzle.error = function( msg ) {
-       throw "Syntax error, unrecognized expression: " + msg;
-};
+jQuery.extend({
+       queue: function( elem, type, data ) {
+               var queue;
 
-var Expr = Sizzle.selectors = {
-       order: [ "ID", "NAME", "TAG" ],
+               if ( elem ) {
+                       type = ( type || "fx" ) + "queue";
+                       queue = jQuery._data( elem, type );
 
-       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\))?/
+                       // Speed up dequeue by getting out quickly if this is just a lookup
+                       if ( data ) {
+                               if ( !queue || jQuery.isArray(data) ) {
+                                       queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+                               } else {
+                                       queue.push( data );
+                               }
+                       }
+                       return queue || [];
+               }
        },
 
-       leftMatch: {},
+       dequeue: function( elem, type ) {
+               type = type || "fx";
 
-       attrMap: {
-               "class": "className",
-               "for": "htmlFor"
-       },
+               var queue = jQuery.queue( elem, type ),
+                       startLength = queue.length,
+                       fn = queue.shift(),
+                       hooks = jQuery._queueHooks( elem, type ),
+                       next = function() {
+                               jQuery.dequeue( elem, type );
+                       };
 
-       attrHandle: {
-               href: function( elem ) {
-                       return elem.getAttribute( "href" );
-               },
-               type: function( elem ) {
-                       return elem.getAttribute( "type" );
+               // If the fx queue is dequeued, always remove the progress sentinel
+               if ( fn === "inprogress" ) {
+                       fn = queue.shift();
+                       startLength--;
                }
-       },
 
-       relative: {
-               "+": function(checkSet, part){
-                       var isPartStr = typeof part === "string",
-                               isTag = isPartStr && !rNonWord.test( part ),
-                               isPartStrNotTag = isPartStr && !isTag;
+               if ( fn ) {
 
-                       if ( isTag ) {
-                               part = part.toLowerCase();
+                       // Add a progress sentinel to prevent the fx queue from being
+                       // automatically dequeued
+                       if ( type === "fx" ) {
+                               queue.unshift( "inprogress" );
                        }
 
-                       for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
-                               if ( (elem = checkSet[i]) ) {
-                                       while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+                       // clear up the last queue stop function
+                       delete hooks.stop;
+                       fn.call( elem, next, hooks );
+               }
 
-                                       checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
-                                               elem || false :
-                                               elem === part;
-                               }
-                       }
+               if ( !startLength && hooks ) {
+                       hooks.empty.fire();
+               }
+       },
 
-                       if ( isPartStrNotTag ) {
-                               Sizzle.filter( part, checkSet, true );
-                       }
-               },
+       // not intended for public consumption - generates a queueHooks object, or returns the current one
+       _queueHooks: function( elem, type ) {
+               var key = type + "queueHooks";
+               return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+                       empty: jQuery.Callbacks("once memory").add(function() {
+                               jQuery._removeData( elem, type + "queue" );
+                               jQuery._removeData( elem, key );
+                       })
+               });
+       }
+});
 
-               ">": function( checkSet, part ) {
-                       var elem,
-                               isPartStr = typeof part === "string",
-                               i = 0,
-                               l = checkSet.length;
+jQuery.fn.extend({
+       queue: function( type, data ) {
+               var setter = 2;
 
-                       if ( isPartStr && !rNonWord.test( part ) ) {
-                               part = part.toLowerCase();
+               if ( typeof type !== "string" ) {
+                       data = type;
+                       type = "fx";
+                       setter--;
+               }
 
-                               for ( ; i < l; i++ ) {
-                                       elem = checkSet[i];
+               if ( arguments.length < setter ) {
+                       return jQuery.queue( this[0], type );
+               }
 
-                                       if ( elem ) {
-                                               var parent = elem.parentNode;
-                                               checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
-                                       }
-                               }
+               return data === undefined ?
+                       this :
+                       this.each(function() {
+                               var queue = jQuery.queue( this, type, data );
 
-                       } else {
-                               for ( ; i < l; i++ ) {
-                                       elem = checkSet[i];
+                               // ensure a hooks for this queue
+                               jQuery._queueHooks( this, type );
 
-                                       if ( elem ) {
-                                               checkSet[i] = isPartStr ?
-                                                       elem.parentNode :
-                                                       elem.parentNode === part;
-                                       }
+                               if ( type === "fx" && queue[0] !== "inprogress" ) {
+                                       jQuery.dequeue( this, type );
                                }
-
-                               if ( isPartStr ) {
-                                       Sizzle.filter( part, checkSet, true );
+                       });
+       },
+       dequeue: function( type ) {
+               return this.each(function() {
+                       jQuery.dequeue( this, type );
+               });
+       },
+       clearQueue: function( type ) {
+               return this.queue( type || "fx", [] );
+       },
+       // Get a promise resolved when queues of a certain type
+       // are emptied (fx is the type by default)
+       promise: function( type, obj ) {
+               var tmp,
+                       count = 1,
+                       defer = jQuery.Deferred(),
+                       elements = this,
+                       i = this.length,
+                       resolve = function() {
+                               if ( !( --count ) ) {
+                                       defer.resolveWith( elements, [ elements ] );
                                }
-                       }
-               },
+                       };
 
-               "": function(checkSet, part, isXML){
-                       var nodeCheck,
-                               doneName = done++,
-                               checkFn = dirCheck;
+               if ( typeof type !== "string" ) {
+                       obj = type;
+                       type = undefined;
+               }
+               type = type || "fx";
 
-                       if ( typeof part === "string" && !rNonWord.test( part ) ) {
-                               part = part.toLowerCase();
-                               nodeCheck = part;
-                               checkFn = dirNodeCheck;
+               while ( i-- ) {
+                       tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+                       if ( tmp && tmp.empty ) {
+                               count++;
+                               tmp.empty.add( resolve );
                        }
+               }
+               resolve();
+               return defer.promise( obj );
+       }
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
 
-                       checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
-               },
-
-               "~": function( checkSet, part, isXML ) {
-                       var nodeCheck,
-                               doneName = done++,
-                               checkFn = dirCheck;
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
 
-                       if ( typeof part === "string" && !rNonWord.test( part ) ) {
-                               part = part.toLowerCase();
-                               nodeCheck = part;
-                               checkFn = dirNodeCheck;
-                       }
+var isHidden = function( elem, el ) {
+               // isHidden might be called from jQuery#filter function;
+               // in that case, element will be second argument
+               elem = el || elem;
+               return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+       };
 
-                       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] );
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+       var i = 0,
+               length = elems.length,
+               bulk = key == null;
 
-                               for ( var i = 0, l = results.length; i < l; i++ ) {
-                                       if ( results[i].getAttribute("name") === match[1] ) {
-                                               ret.push( results[i] );
-                                       }
-                               }
+       // Sets many values
+       if ( jQuery.type( key ) === "object" ) {
+               chainable = true;
+               for ( i in key ) {
+                       jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+               }
 
-                               return ret.length === 0 ? null : ret;
-                       }
-               },
+       // Sets one value
+       } else if ( value !== undefined ) {
+               chainable = true;
 
-               TAG: function( match, context ) {
-                       if ( typeof context.getElementsByTagName !== "undefined" ) {
-                               return context.getElementsByTagName( match[1] );
-                       }
+               if ( !jQuery.isFunction( value ) ) {
+                       raw = true;
                }
-       },
-       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 );
-                                               }
+               if ( bulk ) {
+                       // Bulk operations run against the entire set
+                       if ( raw ) {
+                               fn.call( elems, value );
+                               fn = null;
 
-                                       } else if ( inplace ) {
-                                               curLoop[i] = false;
-                                       }
-                               }
+                       // ...except when executing function values
+                       } else {
+                               bulk = fn;
+                               fn = function( elem, key, value ) {
+                                       return bulk.call( jQuery( elem ), value );
+                               };
                        }
+               }
 
-                       return false;
-               },
-
-               ID: function( match ) {
-                       return match[1].replace( rBackslash, "" );
-               },
-
-               TAG: function( match, curLoop ) {
-                       return match[1].replace( rBackslash, "" ).toLowerCase();
-               },
+               if ( fn ) {
+                       for ( ; i < length; i++ ) {
+                               fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+                       }
+               }
+       }
 
-               CHILD: function( match ) {
-                       if ( match[1] === "nth" ) {
-                               if ( !match[2] ) {
-                                       Sizzle.error( match[0] );
-                               }
+       return chainable ?
+               elems :
 
-                               match[2] = match[2].replace(/^\+|\s*/g, '');
+               // Gets
+               bulk ?
+                       fn.call( elems ) :
+                       length ? fn( elems[0], key ) : emptyGet;
+};
+var rcheckableType = (/^(?:checkbox|radio)$/i);
 
-                               // 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++;
+(function() {
+       // Minified: var a,b,c
+       var input = document.createElement( "input" ),
+               div = document.createElement( "div" ),
+               fragment = document.createDocumentFragment();
 
-                       return match;
-               },
+       // Setup
+       div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
 
-               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];
-                       }
+       // IE strips leading whitespace when .innerHTML is used
+       support.leadingWhitespace = div.firstChild.nodeType === 3;
 
-                       // Handle if an un-quoted value was used
-                       match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
+       // Make sure that tbody elements aren't automatically inserted
+       // IE will insert them into empty tables
+       support.tbody = !div.getElementsByTagName( "tbody" ).length;
 
-                       if ( match[2] === "~=" ) {
-                               match[4] = " " + match[4] + " ";
-                       }
+       // Make sure that link elements get serialized correctly by innerHTML
+       // This requires a wrapper element in IE
+       support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
 
-                       return match;
-               },
+       // Makes sure cloning an html5 element does not cause problems
+       // Where outerHTML is undefined, this still works
+       support.html5Clone =
+               document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
 
-               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);
+       // Check if a disconnected checkbox will retain its checked
+       // value of true after appended to the DOM (IE6/7)
+       input.type = "checkbox";
+       input.checked = true;
+       fragment.appendChild( input );
+       support.appendChecked = input.checked;
 
-                               } else {
-                                       var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+       // Make sure textarea (and checkbox) defaultValue is properly cloned
+       // Support: IE6-IE11+
+       div.innerHTML = "<textarea>x</textarea>";
+       support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
 
-                                       if ( !inplace ) {
-                                               result.push.apply( result, ret );
-                                       }
+       // #11217 - WebKit loses check when the name is after the checked attribute
+       fragment.appendChild( div );
+       div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
 
-                                       return false;
-                               }
+       // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
+       // old WebKit doesn't clone checked state correctly in fragments
+       support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
 
-                       } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
-                               return true;
-                       }
-                       
-                       return match;
-               },
+       // Support: IE<9
+       // Opera does not clone events (and typeof div.attachEvent === undefined).
+       // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+       support.noCloneEvent = true;
+       if ( div.attachEvent ) {
+               div.attachEvent( "onclick", function() {
+                       support.noCloneEvent = false;
+               });
 
-               POS: function( match ) {
-                       match.unshift( true );
+               div.cloneNode( true ).click();
+       }
 
-                       return match;
+       // Execute the test only if not already executed in another module.
+       if (support.deleteExpando == null) {
+               // Support: IE<9
+               support.deleteExpando = true;
+               try {
+                       delete div.test;
+               } catch( e ) {
+                       support.deleteExpando = false;
                }
-       },
-       
-       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;
-               },
+(function() {
+       var i, eventName,
+               div = document.createElement( "div" );
 
-               header: function( elem ) {
-                       return (/h\d/i).test( elem.nodeName );
-               },
+       // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
+       for ( i in { submit: true, change: true, focusin: true }) {
+               eventName = "on" + i;
 
-               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 );
-               },
+               if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
+                       // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
+                       div.setAttribute( eventName, "t" );
+                       support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
+               }
+       }
 
-               radio: function( elem ) {
-                       return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
-               },
+       // Null elements to avoid leaks in IE.
+       div = null;
+})();
 
-               checkbox: function( elem ) {
-                       return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
-               },
 
-               file: function( elem ) {
-                       return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
-               },
+var rformElems = /^(?:input|select|textarea)$/i,
+       rkeyEvent = /^key/,
+       rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
+       rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+       rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
 
-               password: function( elem ) {
-                       return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
-               },
+function returnTrue() {
+       return true;
+}
 
-               submit: function( elem ) {
-                       var name = elem.nodeName.toLowerCase();
-                       return (name === "input" || name === "button") && "submit" === elem.type;
-               },
+function returnFalse() {
+       return false;
+}
 
-               image: function( elem ) {
-                       return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
-               },
+function safeActiveElement() {
+       try {
+               return document.activeElement;
+       } catch ( err ) { }
+}
 
-               reset: function( elem ) {
-                       return elem.nodeName.toLowerCase() === "input" && "reset" === elem.type;
-               },
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
 
-               button: function( elem ) {
-                       var name = elem.nodeName.toLowerCase();
-                       return name === "input" && "button" === elem.type || name === "button";
-               },
+       global: {},
 
-               input: function( elem ) {
-                       return (/input|select|textarea|button/i).test( elem.nodeName );
-               },
+       add: function( elem, types, handler, data, selector ) {
+               var tmp, events, t, handleObjIn,
+                       special, eventHandle, handleObj,
+                       handlers, type, namespaces, origType,
+                       elemData = jQuery._data( elem );
 
-               focus: function( elem ) {
-                       return elem === elem.ownerDocument.activeElement;
+               // Don't attach events to noData or text/comment nodes (but allow plain objects)
+               if ( !elemData ) {
+                       return;
                }
-       },
-       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;
-               },
+               // Caller can pass in an object of custom data in lieu of the handler
+               if ( handler.handler ) {
+                       handleObjIn = handler;
+                       handler = handleObjIn.handler;
+                       selector = handleObjIn.selector;
+               }
 
-               odd: function( elem, i ) {
-                       return i % 2 === 1;
-               },
+               // Make sure that the handler has a unique ID, used to find/remove it later
+               if ( !handler.guid ) {
+                       handler.guid = jQuery.guid++;
+               }
 
-               lt: function( elem, i, match ) {
-                       return i < match[3] - 0;
-               },
+               // Init the element's event structure and main handler, if this is the first
+               if ( !(events = elemData.events) ) {
+                       events = elemData.events = {};
+               }
+               if ( !(eventHandle = elemData.handle) ) {
+                       eventHandle = elemData.handle = function( e ) {
+                               // Discard the second event of a jQuery.event.trigger() and
+                               // when an event is called after a page has unloaded
+                               return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
+                                       jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+                                       undefined;
+                       };
+                       // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+                       eventHandle.elem = elem;
+               }
 
-               gt: function( elem, i, match ) {
-                       return i > match[3] - 0;
-               },
+               // Handle multiple events separated by a space
+               types = ( types || "" ).match( rnotwhite ) || [ "" ];
+               t = types.length;
+               while ( t-- ) {
+                       tmp = rtypenamespace.exec( types[t] ) || [];
+                       type = origType = tmp[1];
+                       namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+                       // There *must* be a type, no attaching namespace-only handlers
+                       if ( !type ) {
+                               continue;
+                       }
 
-               nth: function( elem, i, match ) {
-                       return match[3] - 0 === i;
-               },
+                       // If event changes its type, use the special event handlers for the changed type
+                       special = jQuery.event.special[ type ] || {};
 
-               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 selector defined, determine special event api type, otherwise given type
+                       type = ( selector ? special.delegateType : special.bindType ) || type;
 
-                       if ( filter ) {
-                               return filter( elem, i, match, array );
+                       // Update special based on newly reset type
+                       special = jQuery.event.special[ type ] || {};
 
-                       } else if ( name === "contains" ) {
-                               return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
+                       // handleObj is passed to all event handlers
+                       handleObj = jQuery.extend({
+                               type: type,
+                               origType: origType,
+                               data: data,
+                               handler: handler,
+                               guid: handler.guid,
+                               selector: selector,
+                               needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+                               namespace: namespaces.join(".")
+                       }, handleObjIn );
+
+                       // Init the event handler queue if we're the first
+                       if ( !(handlers = events[ type ]) ) {
+                               handlers = events[ type ] = [];
+                               handlers.delegateCount = 0;
 
-                       } else if ( name === "not" ) {
-                               var not = match[3];
+                               // 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 );
 
-                               for ( var j = 0, l = not.length; j < l; j++ ) {
-                                       if ( not[j] === elem ) {
-                                               return false;
+                                       } else if ( elem.attachEvent ) {
+                                               elem.attachEvent( "on" + type, eventHandle );
                                        }
                                }
+                       }
 
-                               return true;
+                       if ( special.add ) {
+                               special.add.call( elem, handleObj );
 
-                       } else {
-                               Sizzle.error( name );
+                               if ( !handleObj.handler.guid ) {
+                                       handleObj.handler.guid = handler.guid;
+                               }
                        }
-               },
 
-               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; 
-                                       }
+                       // Add to the element's handler list, delegates in front
+                       if ( selector ) {
+                               handlers.splice( handlers.delegateCount++, 0, handleObj );
+                       } else {
+                               handlers.push( handleObj );
+                       }
 
-                                       node = elem;
+                       // Keep track of which events have ever been used, for event optimization
+                       jQuery.event.global[ type ] = true;
+               }
 
-                               case "last":
-                                       while ( (node = node.nextSibling) )      {
-                                               if ( node.nodeType === 1 ) { 
-                                                       return false; 
-                                               }
-                                       }
+               // Nullify elem to prevent memory leaks in IE
+               elem = null;
+       },
 
-                                       return true;
+       // Detach an event or set of events from an element
+       remove: function( elem, types, handler, selector, mappedTypes ) {
+               var j, handleObj, tmp,
+                       origCount, t, events,
+                       special, handlers, type,
+                       namespaces, origType,
+                       elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+               if ( !elemData || !(events = elemData.events) ) {
+                       return;
+               }
 
-                               case "nth":
-                                       var first = match[2],
-                                               last = match[3];
+               // Once for each type.namespace in types; type may be omitted
+               types = ( types || "" ).match( rnotwhite ) || [ "" ];
+               t = types.length;
+               while ( t-- ) {
+                       tmp = rtypenamespace.exec( types[t] ) || [];
+                       type = origType = tmp[1];
+                       namespaces = ( tmp[2] || "" ).split( "." ).sort();
 
-                                       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;
-                                                       }
-                                               } 
+                       // Unbind all events (on this namespace, if provided) for the element
+                       if ( !type ) {
+                               for ( type in events ) {
+                                       jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+                               }
+                               continue;
+                       }
 
-                                               parent.sizcache = doneName;
+                       special = jQuery.event.special[ type ] || {};
+                       type = ( selector ? special.delegateType : special.bindType ) || type;
+                       handlers = events[ type ] || [];
+                       tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+                       // Remove matching events
+                       origCount = j = handlers.length;
+                       while ( j-- ) {
+                               handleObj = handlers[ j ];
+
+                               if ( ( mappedTypes || origType === handleObj.origType ) &&
+                                       ( !handler || handler.guid === handleObj.guid ) &&
+                                       ( !tmp || tmp.test( handleObj.namespace ) ) &&
+                                       ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+                                       handlers.splice( j, 1 );
+
+                                       if ( handleObj.selector ) {
+                                               handlers.delegateCount--;
                                        }
-                                       
-                                       var diff = elem.nodeIndex - last;
-
-                                       if ( first === 0 ) {
-                                               return diff === 0;
-
-                                       } else {
-                                               return ( diff % first === 0 && diff / first >= 0 );
+                                       if ( special.remove ) {
+                                               special.remove.call( elem, handleObj );
                                        }
+                               }
                        }
-               },
-
-               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 ];
+                       // Remove generic event handler if we removed something and no more handlers exist
+                       // (avoids potential for endless recursion during removal of special event handlers)
+                       if ( origCount && !handlers.length ) {
+                               if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+                                       jQuery.removeEvent( elem, type, elemData.handle );
+                               }
 
-                       if ( filter ) {
-                               return filter( elem, i, match, array );
+                               delete events[ type ];
                        }
                }
-       }
-};
-
-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] );
-                               }
+               // Remove the expando if it's no longer used
+               if ( jQuery.isEmptyObject( events ) ) {
+                       delete elemData.handle;
 
-                       } else {
-                               for ( ; array[i]; i++ ) {
-                                       ret.push( array[i] );
-                               }
-                       }
+                       // removeData also checks for emptiness and clears the expando if empty
+                       // so use it instead of delete
+                       jQuery._removeData( elem, "events" );
                }
+       },
 
-               return ret;
-       };
-}
+       trigger: function( event, data, elem, onlyHandlers ) {
+               var handle, ontype, cur,
+                       bubbleType, special, tmp, i,
+                       eventPath = [ elem || document ],
+                       type = hasOwn.call( event, "type" ) ? event.type : event,
+                       namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
 
-var sortOrder, siblingCheck;
+               cur = tmp = elem = elem || document;
 
-if ( document.documentElement.compareDocumentPosition ) {
-       sortOrder = function( a, b ) {
-               if ( a === b ) {
-                       hasDuplicate = true;
-                       return 0;
+               // Don't do events on text and comment nodes
+               if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+                       return;
                }
 
-               if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
-                       return a.compareDocumentPosition ? -1 : 1;
+               // focus/blur morphs to focusin/out; ensure we're not firing them right now
+               if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+                       return;
                }
 
-               return a.compareDocumentPosition(b) & 4 ? -1 : 1;
-       };
-
-} else {
-       sortOrder = function( a, b ) {
-               var al, bl,
-                       ap = [],
-                       bp = [],
-                       aup = a.parentNode,
-                       bup = b.parentNode,
-                       cur = aup;
-
-               // The nodes are identical, we can exit early
-               if ( a === b ) {
-                       hasDuplicate = true;
-                       return 0;
-
-               // If the nodes are siblings (or identical) we can do a quick check
-               } else if ( aup === bup ) {
-                       return siblingCheck( a, b );
+               if ( type.indexOf(".") >= 0 ) {
+                       // Namespaced trigger; create a regexp to match event type in handle()
+                       namespaces = type.split(".");
+                       type = namespaces.shift();
+                       namespaces.sort();
+               }
+               ontype = type.indexOf(":") < 0 && "on" + type;
 
-               // If no parents were found then the nodes are disconnected
-               } else if ( !aup ) {
-                       return -1;
+               // Caller can pass in a jQuery.Event object, Object, or just an event type string
+               event = event[ jQuery.expando ] ?
+                       event :
+                       new jQuery.Event( type, typeof event === "object" && event );
 
-               } else if ( !bup ) {
-                       return 1;
-               }
+               // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+               event.isTrigger = onlyHandlers ? 2 : 3;
+               event.namespace = namespaces.join(".");
+               event.namespace_re = event.namespace ?
+                       new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+                       null;
 
-               // 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;
+               // Clean up the event in case it is being reused
+               event.result = undefined;
+               if ( !event.target ) {
+                       event.target = elem;
                }
 
-               cur = bup;
+               // Clone any incoming data and prepend the event, creating the handler arg list
+               data = data == null ?
+                       [ event ] :
+                       jQuery.makeArray( data, [ event ] );
 
-               while ( cur ) {
-                       bp.unshift( cur );
-                       cur = cur.parentNode;
+               // Allow special events to draw outside the lines
+               special = jQuery.event.special[ type ] || {};
+               if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+                       return;
                }
 
-               al = ap.length;
-               bl = bp.length;
+               // Determine event propagation path in advance, per W3C events spec (#9951)
+               // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+               if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
 
-               // 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] );
+                       bubbleType = special.delegateType || type;
+                       if ( !rfocusMorph.test( bubbleType + type ) ) {
+                               cur = cur.parentNode;
+                       }
+                       for ( ; cur; cur = cur.parentNode ) {
+                               eventPath.push( cur );
+                               tmp = cur;
                        }
-               }
-
-               // 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;
+                       // Only add window if we got to document (e.g., not plain obj or detached DOM)
+                       if ( tmp === (elem.ownerDocument || document) ) {
+                               eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+                       }
                }
 
-               var cur = a.nextSibling;
+               // Fire handlers on the event path
+               i = 0;
+               while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
 
-               while ( cur ) {
-                       if ( cur === b ) {
-                               return -1;
+                       event.type = i > 1 ?
+                               bubbleType :
+                               special.bindType || type;
+
+                       // jQuery handler
+                       handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+                       if ( handle ) {
+                               handle.apply( cur, data );
                        }
 
-                       cur = cur.nextSibling;
+                       // Native handler
+                       handle = ontype && cur[ ontype ];
+                       if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+                               event.result = handle.apply( cur, data );
+                               if ( event.result === false ) {
+                                       event.preventDefault();
+                               }
+                       }
                }
+               event.type = type;
 
-               return 1;
-       };
-}
+               // If nobody prevented the default action, do it now
+               if ( !onlyHandlers && !event.isDefaultPrevented() ) {
 
-// Utility function for retreiving the text value of an array of DOM nodes
-Sizzle.getText = function( elems ) {
-       var ret = "", elem;
+                       if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+                               jQuery.acceptData( elem ) ) {
 
-       for ( var i = 0; elems[i]; i++ ) {
-               elem = elems[i];
+                               // Call a native DOM method on the target with the same name name as the event.
+                               // Can't use an .isFunction() check here because IE6/7 fails that test.
+                               // Don't do default actions on window, that's where global variables be (#6170)
+                               if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
 
-               // Get the text from text nodes and CDATA nodes
-               if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
-                       ret += elem.nodeValue;
+                                       // Don't re-trigger an onFOO event when we call its FOO() method
+                                       tmp = elem[ ontype ];
 
-               // Traverse everything else, except comment nodes
-               } else if ( elem.nodeType !== 8 ) {
-                       ret += Sizzle.getText( elem.childNodes );
-               }
-       }
+                                       if ( tmp ) {
+                                               elem[ ontype ] = null;
+                                       }
 
-       return ret;
-};
+                                       // Prevent re-triggering of the same event, since we already bubbled it above
+                                       jQuery.event.triggered = type;
+                                       try {
+                                               elem[ type ]();
+                                       } catch ( e ) {
+                                               // IE<9 dies on focus/blur to hidden element (#1486,#12518)
+                                               // only reproducible on winXP IE8 native, not IE9 in IE8 mode
+                                       }
+                                       jQuery.event.triggered = undefined;
 
-// 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;
+                                       if ( tmp ) {
+                                               elem[ ontype ] = tmp;
+                                       }
+                               }
+                       }
+               }
 
-       form.innerHTML = "<a name='" + id + "'/>";
+               return event.result;
+       },
 
-       // Inject it into the root element, check its status, and remove it quickly
-       root.insertBefore( form, root.firstChild );
+       dispatch: function( event ) {
 
-       // 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]);
+               // Make a writable jQuery.Event from the native event object
+               event = jQuery.event.fix( event );
 
-                               return m ?
-                                       m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
-                                               [m] :
-                                               undefined :
-                                       [];
-                       }
-               };
+               var i, ret, handleObj, matched, j,
+                       handlerQueue = [],
+                       args = slice.call( arguments ),
+                       handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+                       special = jQuery.event.special[ event.type ] || {};
 
-               Expr.filter.ID = function( elem, match ) {
-                       var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+               // Use the fix-ed jQuery.Event rather than the (read-only) native event
+               args[0] = event;
+               event.delegateTarget = this;
 
-                       return elem.nodeType === 1 && node && node.nodeValue === match;
-               };
-       }
+               // Call the preDispatch hook for the mapped type, and let it bail if desired
+               if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+                       return;
+               }
 
-       root.removeChild( form );
+               // Determine handlers
+               handlerQueue = jQuery.event.handlers.call( this, event, handlers );
 
-       // release memory in IE
-       root = form = null;
-})();
+               // Run delegates first; they may want to stop propagation beneath us
+               i = 0;
+               while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+                       event.currentTarget = matched.elem;
 
-(function(){
-       // Check to see if the browser returns only elements
-       // when doing getElementsByTagName("*")
+                       j = 0;
+                       while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
 
-       // Create a fake element
-       var div = document.createElement("div");
-       div.appendChild( document.createComment("") );
+                               // Triggered event must either 1) have no namespace, or
+                               // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+                               if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
 
-       // Make sure no comments are found
-       if ( div.getElementsByTagName("*").length > 0 ) {
-               Expr.find.TAG = function( match, context ) {
-                       var results = context.getElementsByTagName( match[1] );
+                                       event.handleObj = handleObj;
+                                       event.data = handleObj.data;
 
-                       // Filter out possible comments
-                       if ( match[1] === "*" ) {
-                               var tmp = [];
+                                       ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+                                                       .apply( matched.elem, args );
 
-                               for ( var i = 0; results[i]; i++ ) {
-                                       if ( results[i].nodeType === 1 ) {
-                                               tmp.push( results[i] );
+                                       if ( ret !== undefined ) {
+                                               if ( (event.result = ret) === false ) {
+                                                       event.preventDefault();
+                                                       event.stopPropagation();
+                                               }
                                        }
                                }
-
-                               results = tmp;
                        }
+               }
 
-                       return results;
-               };
-       }
-
-       // Check to see if an attribute returns normalized href attributes
-       div.innerHTML = "<a href='#'></a>";
-
-       if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
-                       div.firstChild.getAttribute("href") !== "#" ) {
+               // Call the postDispatch hook for the mapped type
+               if ( special.postDispatch ) {
+                       special.postDispatch.call( this, event );
+               }
 
-               Expr.attrHandle.href = function( elem ) {
-                       return elem.getAttribute( "href", 2 );
-               };
-       }
+               return event.result;
+       },
 
-       // release memory in IE
-       div = null;
-})();
+       handlers: function( event, handlers ) {
+               var sel, handleObj, matches, i,
+                       handlerQueue = [],
+                       delegateCount = handlers.delegateCount,
+                       cur = event.target;
 
-if ( document.querySelectorAll ) {
-       (function(){
-               var oldSizzle = Sizzle,
-                       div = document.createElement("div"),
-                       id = "__sizzle__";
+               // Find delegate handlers
+               // Black-hole SVG <use> instance trees (#13180)
+               // Avoid non-left-click bubbling in Firefox (#3861)
+               if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
 
-               div.innerHTML = "<p class='TEST'></p>";
+                       /* jshint eqeqeq: false */
+                       for ( ; cur != this; cur = cur.parentNode || this ) {
+                               /* jshint eqeqeq: true */
 
-               // 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 );
+                               // Don't check non-elements (#13208)
+                               // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+                               if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+                                       matches = [];
+                                       for ( i = 0; i < delegateCount; i++ ) {
+                                               handleObj = handlers[ i ];
 
-                                       if ( !old ) {
-                                               context.setAttribute( "id", nid );
-                                       } else {
-                                               nid = nid.replace( /'/g, "\\$&" );
-                                       }
-                                       if ( relativeHierarchySelector && hasParent ) {
-                                               context = context.parentNode;
-                                       }
+                                               // Don't conflict with Object.prototype properties (#13203)
+                                               sel = handleObj.selector + " ";
 
-                                       try {
-                                               if ( !relativeHierarchySelector || hasParent ) {
-                                                       return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
+                                               if ( matches[ sel ] === undefined ) {
+                                                       matches[ sel ] = handleObj.needsContext ?
+                                                               jQuery( sel, this ).index( cur ) >= 0 :
+                                                               jQuery.find( sel, this, null, [ cur ] ).length;
                                                }
-
-                                       } catch(pseudoError) {
-                                       } finally {
-                                               if ( !old ) {
-                                                       oldContext.removeAttribute( "id" );
+                                               if ( matches[ sel ] ) {
+                                                       matches.push( handleObj );
                                                }
                                        }
+                                       if ( matches.length ) {
+                                               handlerQueue.push({ elem: cur, handlers: matches });
+                                       }
                                }
                        }
-               
-                       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) {}
-                       }
+               // Add the remaining (directly-bound) handlers
+               if ( delegateCount < handlers.length ) {
+                       handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+               }
 
-                       return Sizzle(expr, null, null, [node]).length > 0;
-               };
-       }
-})();
+               return handlerQueue;
+       },
 
-(function(){
-       var div = document.createElement("div");
+       fix: function( event ) {
+               if ( event[ jQuery.expando ] ) {
+                       return event;
+               }
 
-       div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+               // Create a writable copy of the event object and normalize some properties
+               var i, prop, copy,
+                       type = event.type,
+                       originalEvent = event,
+                       fixHook = this.fixHooks[ type ];
 
-       // 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;
-       }
+               if ( !fixHook ) {
+                       this.fixHooks[ type ] = fixHook =
+                               rmouseEvent.test( type ) ? this.mouseHooks :
+                               rkeyEvent.test( type ) ? this.keyHooks :
+                               {};
+               }
+               copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
 
-       // Safari caches class attributes, doesn't catch changes (in 3.2)
-       div.lastChild.className = "e";
+               event = new jQuery.Event( originalEvent );
 
-       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]);
+               i = copy.length;
+               while ( i-- ) {
+                       prop = copy[ i ];
+                       event[ prop ] = originalEvent[ prop ];
                }
-       };
 
-       // release memory in IE
-       div = null;
-})();
+               // Support: IE<9
+               // Fix target property (#1925)
+               if ( !event.target ) {
+                       event.target = originalEvent.srcElement || document;
+               }
 
-function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
-       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
-               var elem = checkSet[i];
+               // Support: Chrome 23+, Safari?
+               // Target should not be a text node (#504, #13143)
+               if ( event.target.nodeType === 3 ) {
+                       event.target = event.target.parentNode;
+               }
 
-               if ( elem ) {
-                       var match = false;
+               // Support: IE<9
+               // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+               event.metaKey = !!event.metaKey;
 
-                       elem = elem[dir];
+               return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+       },
 
-                       while ( elem ) {
-                               if ( elem.sizcache === doneName ) {
-                                       match = checkSet[elem.sizset];
-                                       break;
-                               }
+       // Includes some event props shared by KeyEvent and MouseEvent
+       props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
 
-                               if ( elem.nodeType === 1 && !isXML ){
-                                       elem.sizcache = doneName;
-                                       elem.sizset = i;
-                               }
+       fixHooks: {},
 
-                               if ( elem.nodeName.toLowerCase() === cur ) {
-                                       match = elem;
-                                       break;
-                               }
+       keyHooks: {
+               props: "char charCode key keyCode".split(" "),
+               filter: function( event, original ) {
 
-                               elem = elem[dir];
+                       // Add which for key events
+                       if ( event.which == null ) {
+                               event.which = original.charCode != null ? original.charCode : original.keyCode;
                        }
 
-                       checkSet[i] = match;
+                       return event;
                }
-       }
-}
-
-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;
-                               }
+       mouseHooks: {
+               props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+               filter: function( event, original ) {
+                       var body, eventDoc, doc,
+                               button = original.button,
+                               fromElement = original.fromElement;
 
-                               if ( elem.nodeType === 1 ) {
-                                       if ( !isXML ) {
-                                               elem.sizcache = doneName;
-                                               elem.sizset = i;
-                                       }
+                       // Calculate pageX/Y if missing and clientX/Y available
+                       if ( event.pageX == null && original.clientX != null ) {
+                               eventDoc = event.target.ownerDocument || document;
+                               doc = eventDoc.documentElement;
+                               body = eventDoc.body;
 
-                                       if ( typeof cur !== "string" ) {
-                                               if ( elem === cur ) {
-                                                       match = true;
-                                                       break;
-                                               }
+                               event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+                               event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+                       }
 
-                                       } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
-                                               match = elem;
-                                               break;
-                                       }
-                               }
+                       // Add relatedTarget, if necessary
+                       if ( !event.relatedTarget && fromElement ) {
+                               event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+                       }
 
-                               elem = elem[dir];
+                       // Add which for click: 1 === left; 2 === middle; 3 === right
+                       // Note: button is not normalized, so don't use it
+                       if ( !event.which && button !== undefined ) {
+                               event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
                        }
 
-                       checkSet[i] = match;
+                       return event;
                }
-       }
-}
+       },
 
-if ( document.documentElement.contains ) {
-       Sizzle.contains = function( a, b ) {
-               return a !== b && (a.contains ? a.contains(b) : true);
-       };
+       special: {
+               load: {
+                       // Prevent triggered image.load events from bubbling to window.load
+                       noBubble: true
+               },
+               focus: {
+                       // Fire native event if possible so blur/focus sequence is correct
+                       trigger: function() {
+                               if ( this !== safeActiveElement() && this.focus ) {
+                                       try {
+                                               this.focus();
+                                               return false;
+                                       } catch ( e ) {
+                                               // Support: IE<9
+                                               // If we error on focus to hidden element (#1486, #12518),
+                                               // let .trigger() run the handlers
+                                       }
+                               }
+                       },
+                       delegateType: "focusin"
+               },
+               blur: {
+                       trigger: function() {
+                               if ( this === safeActiveElement() && this.blur ) {
+                                       this.blur();
+                                       return false;
+                               }
+                       },
+                       delegateType: "focusout"
+               },
+               click: {
+                       // For checkbox, fire native event so checked state will be right
+                       trigger: function() {
+                               if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+                                       this.click();
+                                       return false;
+                               }
+                       },
 
-} else if ( document.documentElement.compareDocumentPosition ) {
-       Sizzle.contains = function( a, b ) {
-               return !!(a.compareDocumentPosition(b) & 16);
-       };
+                       // For cross-browser consistency, don't fire native .click() on links
+                       _default: function( event ) {
+                               return jQuery.nodeName( event.target, "a" );
+                       }
+               },
 
-} else {
-       Sizzle.contains = function() {
-               return false;
-       };
-}
+               beforeunload: {
+                       postDispatch: function( event ) {
 
-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;
+                               // Support: Firefox 20+
+                               // Firefox doesn't alert if the returnValue field is not set.
+                               if ( event.result !== undefined && event.originalEvent ) {
+                                       event.originalEvent.returnValue = event.result;
+                               }
+                       }
+               }
+       },
 
-       return documentElement ? documentElement.nodeName !== "HTML" : false;
+       simulate: function( type, elem, event, bubble ) {
+               // Piggyback on a donor event to simulate a different one.
+               // Fake originalEvent to avoid donor's stopPropagation, but if the
+               // simulated event prevents default then we do the same on the donor.
+               var e = jQuery.extend(
+                       new jQuery.Event(),
+                       event,
+                       {
+                               type: type,
+                               isSimulated: true,
+                               originalEvent: {}
+                       }
+               );
+               if ( bubble ) {
+                       jQuery.event.trigger( e, null, elem );
+               } else {
+                       jQuery.event.dispatch.call( elem, e );
+               }
+               if ( e.isDefaultPrevented() ) {
+                       event.preventDefault();
+               }
+       }
 };
 
-var posProcess = function( selector, context ) {
-       var match,
-               tmpSet = [],
-               later = "",
-               root = context.nodeType ? [context] : context;
+jQuery.removeEvent = document.removeEventListener ?
+       function( elem, type, handle ) {
+               if ( elem.removeEventListener ) {
+                       elem.removeEventListener( type, handle, false );
+               }
+       } :
+       function( elem, type, handle ) {
+               var name = "on" + type;
+
+               if ( elem.detachEvent ) {
+
+                       // #8545, #7054, preventing memory leaks for custom events in IE6-8
+                       // detachEvent needed property on element, by name of that event, to properly expose it to GC
+                       if ( typeof elem[ name ] === strundefined ) {
+                               elem[ name ] = null;
+                       }
+
+                       elem.detachEvent( name, handle );
+               }
+       };
 
-       // 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, "" );
+jQuery.Event = function( src, props ) {
+       // Allow instantiation without the 'new' keyword
+       if ( !(this instanceof jQuery.Event) ) {
+               return new jQuery.Event( src, props );
        }
 
-       selector = Expr.relative[selector] ? selector + "*" : selector;
+       // Event object
+       if ( src && src.type ) {
+               this.originalEvent = src;
+               this.type = src.type;
+
+               // Events bubbling up the document may have been marked as prevented
+               // by a handler lower down the tree; reflect the correct value.
+               this.isDefaultPrevented = src.defaultPrevented ||
+                               src.defaultPrevented === undefined &&
+                               // Support: IE < 9, Android < 4.0
+                               src.returnValue === false ?
+                       returnTrue :
+                       returnFalse;
 
-       for ( var i = 0, l = root.length; i < l; i++ ) {
-               Sizzle( selector, root[i], tmpSet );
+       // Event type
+       } else {
+               this.type = src;
        }
 
-       return Sizzle.filter( later, tmpSet );
-};
+       // Put explicitly provided properties onto the event object
+       if ( props ) {
+               jQuery.extend( this, props );
+       }
 
-// 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;
+       // Create a timestamp if incoming event doesn't have one
+       this.timeStamp = src && src.timeStamp || jQuery.now();
 
+       // Mark it as fixed
+       this[ jQuery.expando ] = true;
+};
 
-})();
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+       isDefaultPrevented: returnFalse,
+       isPropagationStopped: returnFalse,
+       isImmediatePropagationStopped: returnFalse,
 
+       preventDefault: function() {
+               var e = this.originalEvent;
 
-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
-       };
+               this.isDefaultPrevented = returnTrue;
+               if ( !e ) {
+                       return;
+               }
 
-jQuery.fn.extend({
-       find: function( selector ) {
-               var self = this,
-                       i, l;
+               // If preventDefault exists, run it on the original event
+               if ( e.preventDefault ) {
+                       e.preventDefault();
 
-               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;
-                                       }
-                               }
-                       });
+               // Support: IE
+               // Otherwise set the returnValue property of the original event to false
+               } else {
+                       e.returnValue = false;
                }
+       },
+       stopPropagation: function() {
+               var e = this.originalEvent;
 
-               var ret = this.pushStack( "", "find", selector ),
-                       length, n, r;
+               this.isPropagationStopped = returnTrue;
+               if ( !e ) {
+                       return;
+               }
+               // If stopPropagation exists, run it on the original event
+               if ( e.stopPropagation ) {
+                       e.stopPropagation();
+               }
 
-               for ( i = 0, l = this.length; i < l; i++ ) {
-                       length = ret.length;
-                       jQuery.find( selector, this[i], ret );
+               // Support: IE
+               // Set the cancelBubble property of the original event to true
+               e.cancelBubble = true;
+       },
+       stopImmediatePropagation: function() {
+               var e = this.originalEvent;
 
-                       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;
-                                               }
-                                       }
-                               }
+               this.isImmediatePropagationStopped = returnTrue;
+
+               if ( e && e.stopImmediatePropagation ) {
+                       e.stopImmediatePropagation();
+               }
+
+               this.stopPropagation();
+       }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+       mouseenter: "mouseover",
+       mouseleave: "mouseout",
+       pointerenter: "pointerover",
+       pointerleave: "pointerout"
+}, function( orig, fix ) {
+       jQuery.event.special[ orig ] = {
+               delegateType: fix,
+               bindType: fix,
+
+               handle: function( event ) {
+                       var ret,
+                               target = this,
+                               related = event.relatedTarget,
+                               handleObj = event.handleObj;
+
+                       // For mousenter/leave call the handler if related is outside the target.
+                       // NB: No relatedTarget if the mouse left/entered the browser window
+                       if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+                               event.type = handleObj.origType;
+                               ret = handleObj.handler.apply( this, arguments );
+                               event.type = fix;
                        }
+                       return ret;
                }
+       };
+});
 
-               return ret;
-       },
+// IE submit delegation
+if ( !support.submitBubbles ) {
 
-       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;
+       jQuery.event.special.submit = {
+               setup: function() {
+                       // Only need this for delegated form submit events
+                       if ( jQuery.nodeName( this, "form" ) ) {
+                               return false;
+                       }
+
+                       // Lazy-add a submit handler when a descendant form may potentially be submitted
+                       jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+                               // Node name check avoids a VML-related crash in IE (#9807)
+                               var elem = e.target,
+                                       form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+                               if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+                                       jQuery.event.add( form, "submit._submit", function( event ) {
+                                               event._submit_bubble = true;
+                                       });
+                                       jQuery._data( form, "submitBubbles", true );
+                               }
+                       });
+                       // return undefined since we don't need an event listener
+               },
+
+               postDispatch: function( event ) {
+                       // If form was submitted by the user, bubble the event up the tree
+                       if ( event._submit_bubble ) {
+                               delete event._submit_bubble;
+                               if ( this.parentNode && !event.isTrigger ) {
+                                       jQuery.event.simulate( "submit", this.parentNode, event, true );
                                }
                        }
-               });
-       },
+               },
 
-       not: function( selector ) {
-               return this.pushStack( winnow(this, selector, false), "not", selector);
-       },
+               teardown: function() {
+                       // Only need this for delegated form submit events
+                       if ( jQuery.nodeName( this, "form" ) ) {
+                               return false;
+                       }
 
-       filter: function( selector ) {
-               return this.pushStack( winnow(this, selector, true), "filter", selector );
-       },
+                       // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+                       jQuery.event.remove( this, "._submit" );
+               }
+       };
+}
 
-       is: function( selector ) {
-               return !!selector && ( typeof selector === "string" ?
-                       jQuery.filter( selector, this ).length > 0 :
-                       this.filter( selector ).length > 0 );
-       },
+// IE change delegation and checkbox/radio fix
+if ( !support.changeBubbles ) {
 
-       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;
-                                       }
-                               }
+       jQuery.event.special.change = {
 
-                               while ( cur && cur.ownerDocument && cur !== context ) {
-                                       for ( selector in matches ) {
-                                               match = matches[ selector ];
+               setup: function() {
 
-                                               if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {
-                                                       ret.push({ selector: selector, elem: cur, level: level });
+                       if ( rformElems.test( this.nodeName ) ) {
+                               // IE doesn't fire change on a check/radio until blur; trigger it on click
+                               // after a propertychange. Eat the blur-change in special.change.handle.
+                               // This still fires onchange a second time for check/radio after blur.
+                               if ( this.type === "checkbox" || this.type === "radio" ) {
+                                       jQuery.event.add( this, "propertychange._change", function( event ) {
+                                               if ( event.originalEvent.propertyName === "checked" ) {
+                                                       this._just_changed = true;
                                                }
-                                       }
+                                       });
+                                       jQuery.event.add( this, "click._change", function( event ) {
+                                               if ( this._just_changed && !event.isTrigger ) {
+                                                       this._just_changed = false;
+                                               }
+                                               // Allow triggered, simulated change events (#11500)
+                                               jQuery.event.simulate( "change", this, event, true );
+                                       });
+                               }
+                               return false;
+                       }
+                       // Delegated event; lazy-add a change handler on descendant inputs
+                       jQuery.event.add( this, "beforeactivate._change", function( e ) {
+                               var elem = e.target;
 
-                                       cur = cur.parentNode;
-                                       level++;
+                               if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+                                       jQuery.event.add( elem, "change._change", function( event ) {
+                                               if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+                                                       jQuery.event.simulate( "change", this.parentNode, event, true );
+                                               }
+                                       });
+                                       jQuery._data( elem, "changeBubbles", true );
                                }
+                       });
+               },
+
+               handle: function( event ) {
+                       var elem = event.target;
+
+                       // Swallow native change events from checkbox/radio, we already triggered them above
+                       if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+                               return event.handleObj.handler.apply( this, arguments );
                        }
+               },
 
-                       return ret;
+               teardown: function() {
+                       jQuery.event.remove( this, "._change" );
+
+                       return !rformElems.test( this.nodeName );
                }
+       };
+}
 
-               // String
-               var pos = POS.test( selectors ) || typeof selectors !== "string" ?
-                               jQuery( selectors, context || this.context ) :
-                               0;
+// Create "bubbling" focus and blur events
+if ( !support.focusinBubbles ) {
+       jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+               // Attach a single capturing handler on the document while someone wants focusin/focusout
+               var handler = function( event ) {
+                               jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+                       };
 
-               for ( i = 0, l = this.length; i < l; i++ ) {
-                       cur = this[i];
+               jQuery.event.special[ fix ] = {
+                       setup: function() {
+                               var doc = this.ownerDocument || this,
+                                       attaches = jQuery._data( doc, fix );
 
-                       while ( cur ) {
-                               if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
-                                       ret.push( cur );
-                                       break;
+                               if ( !attaches ) {
+                                       doc.addEventListener( orig, handler, true );
+                               }
+                               jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
+                       },
+                       teardown: function() {
+                               var doc = this.ownerDocument || this,
+                                       attaches = jQuery._data( doc, fix ) - 1;
 
+                               if ( !attaches ) {
+                                       doc.removeEventListener( orig, handler, true );
+                                       jQuery._removeData( doc, fix );
                                } else {
-                                       cur = cur.parentNode;
-                                       if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
-                                               break;
-                                       }
+                                       jQuery._data( doc, fix, attaches );
                                }
                        }
-               }
+               };
+       });
+}
 
-               ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+jQuery.fn.extend({
 
-               return this.pushStack( ret, "closest", selectors );
-       },
+       on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+               var type, origFn;
 
-       // Determine the position of an element within
-       // the matched set of elements
-       index: function( elem ) {
-               if ( !elem || typeof elem === "string" ) {
-                       return jQuery.inArray( this[0],
-                               // If it receives a string, the selector is used
-                               // If it receives nothing, the siblings are used
-                               elem ? jQuery( elem ) : this.parent().children() );
+               // Types can be a map of types/handlers
+               if ( typeof types === "object" ) {
+                       // ( types-Object, selector, data )
+                       if ( typeof selector !== "string" ) {
+                               // ( types-Object, data )
+                               data = data || selector;
+                               selector = undefined;
+                       }
+                       for ( type in types ) {
+                               this.on( type, selector, data, types[ type ], one );
+                       }
+                       return this;
                }
-               // 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 );
+               if ( data == null && fn == null ) {
+                       // ( types, fn )
+                       fn = selector;
+                       data = selector = undefined;
+               } else if ( fn == null ) {
+                       if ( typeof selector === "string" ) {
+                               // ( types, selector, fn )
+                               fn = data;
+                               data = undefined;
+                       } else {
+                               // ( types, data, fn )
+                               fn = data;
+                               data = selector;
+                               selector = undefined;
+                       }
+               }
+               if ( fn === false ) {
+                       fn = returnFalse;
+               } else if ( !fn ) {
+                       return this;
+               }
 
-               return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
-                       all :
-                       jQuery.unique( all ) );
+               if ( one === 1 ) {
+                       origFn = fn;
+                       fn = function( event ) {
+                               // Can use an empty set, since event contains the info
+                               jQuery().off( event );
+                               return origFn.apply( this, arguments );
+                       };
+                       // Use same guid so caller can remove using origFn
+                       fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+               }
+               return this.each( function() {
+                       jQuery.event.add( this, types, fn, data, selector );
+               });
+       },
+       one: function( types, selector, data, fn ) {
+               return this.on( types, selector, data, fn, 1 );
+       },
+       off: function( types, selector, fn ) {
+               var handleObj, type;
+               if ( types && types.preventDefault && types.handleObj ) {
+                       // ( event )  dispatched jQuery.Event
+                       handleObj = types.handleObj;
+                       jQuery( types.delegateTarget ).off(
+                               handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+                               handleObj.selector,
+                               handleObj.handler
+                       );
+                       return this;
+               }
+               if ( typeof types === "object" ) {
+                       // ( types-object [, selector] )
+                       for ( type in types ) {
+                               this.off( type, selector, types[ type ] );
+                       }
+                       return this;
+               }
+               if ( selector === false || typeof selector === "function" ) {
+                       // ( types [, fn] )
+                       fn = selector;
+                       selector = undefined;
+               }
+               if ( fn === false ) {
+                       fn = returnFalse;
+               }
+               return this.each(function() {
+                       jQuery.event.remove( this, types, fn, selector );
+               });
        },
 
-       andSelf: function() {
-               return this.add( this.prevObject );
+       trigger: function( type, data ) {
+               return this.each(function() {
+                       jQuery.event.trigger( type, data, this );
+               });
+       },
+       triggerHandler: function( type, data ) {
+               var elem = this[0];
+               if ( elem ) {
+                       return jQuery.event.trigger( type, data, elem, true );
+               }
        }
 });
 
-// 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;
-               }
+function createSafeFragment( document ) {
+       var list = nodeNames.split( "|" ),
+               safeFrag = document.createDocumentFragment();
 
-               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();
+       if ( safeFrag.createElement ) {
+               while ( list.length ) {
+                       safeFrag.createElement(
+                               list.pop()
+                       );
                }
+       }
+       return safeFrag;
+}
 
-               return this.pushStack( ret, name, args.join(",") );
-       };
-});
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+               "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+       rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+       rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+       rleadingWhitespace = /^\s+/,
+       rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+       rtagName = /<([\w:]+)/,
+       rtbody = /<tbody/i,
+       rhtml = /<|&#?\w+;/,
+       rnoInnerhtml = /<(?:script|style|link)/i,
+       // checked="checked" or checked
+       rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+       rscriptType = /^$|\/(?:java|ecma)script/i,
+       rscriptTypeMasked = /^true\/(.*)/,
+       rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
 
-jQuery.extend({
-       filter: function( expr, elems, not ) {
-               if ( not ) {
-                       expr = ":not(" + expr + ")";
-               }
+       // We have to close these tags to support XHTML (#13200)
+       wrapMap = {
+               option: [ 1, "<select multiple='multiple'>", "</select>" ],
+               legend: [ 1, "<fieldset>", "</fieldset>" ],
+               area: [ 1, "<map>", "</map>" ],
+               param: [ 1, "<object>", "</object>" ],
+               thead: [ 1, "<table>", "</table>" ],
+               tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+               col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+               td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
 
-               return elems.length === 1 ?
-                       jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
-                       jQuery.find.matches(expr, elems);
+               // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+               // unless wrapped in a div with non-breaking characters in front of it.
+               _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
        },
+       safeFragment = createSafeFragment( document ),
+       fragmentDiv = safeFragment.appendChild( document.createElement("div") );
 
-       dir: function( elem, dir, until ) {
-               var matched = [],
-                       cur = elem[ dir ];
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
 
-               while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
-                       if ( cur.nodeType === 1 ) {
-                               matched.push( cur );
+function getAll( context, tag ) {
+       var elems, elem,
+               i = 0,
+               found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
+                       typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
+                       undefined;
+
+       if ( !found ) {
+               for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+                       if ( !tag || jQuery.nodeName( elem, tag ) ) {
+                               found.push( elem );
+                       } else {
+                               jQuery.merge( found, getAll( elem, tag ) );
                        }
-                       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 tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+               jQuery.merge( [ context ], found ) :
+               found;
+}
 
-               return cur;
-       },
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+       if ( rcheckableType.test( elem.type ) ) {
+               elem.defaultChecked = elem.checked;
+       }
+}
 
-       sibling: function( n, elem ) {
-               var r = [];
+// Support: IE<8
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+       return jQuery.nodeName( elem, "table" ) &&
+               jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
 
-               for ( ; n; n = n.nextSibling ) {
-                       if ( n.nodeType === 1 && n !== elem ) {
-                               r.push( n );
-                       }
-               }
+               elem.getElementsByTagName("tbody")[0] ||
+                       elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+               elem;
+}
 
-               return r;
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+       elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
+       return elem;
+}
+function restoreScript( elem ) {
+       var match = rscriptTypeMasked.exec( elem.type );
+       if ( match ) {
+               elem.type = match[1];
+       } else {
+               elem.removeAttribute("type");
        }
-});
+       return elem;
+}
 
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, keep ) {
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+       var elem,
+               i = 0;
+       for ( ; (elem = elems[i]) != null; i++ ) {
+               jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+       }
+}
 
-       // Can't pass null or undefined to indexOf in Firefox 4
-       // Set to 0 to skip string check
-       qualifier = qualifier || 0;
+function cloneCopyEvent( src, dest ) {
 
-       if ( jQuery.isFunction( qualifier ) ) {
-               return jQuery.grep(elements, function( elem, i ) {
-                       var retVal = !!qualifier.call( elem, i, elem );
-                       return retVal === keep;
-               });
+       if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+               return;
+       }
 
-       } else if ( qualifier.nodeType ) {
-               return jQuery.grep(elements, function( elem, i ) {
-                       return (elem === qualifier) === keep;
-               });
+       var type, i, l,
+               oldData = jQuery._data( src ),
+               curData = jQuery._data( dest, oldData ),
+               events = oldData.events;
 
-       } else if ( typeof qualifier === "string" ) {
-               var filtered = jQuery.grep(elements, function( elem ) {
-                       return elem.nodeType === 1;
-               });
+       if ( events ) {
+               delete curData.handle;
+               curData.events = {};
 
-               if ( isSimple.test( qualifier ) ) {
-                       return jQuery.filter(qualifier, filtered, !keep);
-               } else {
-                       qualifier = jQuery.filter( qualifier, filtered );
+               for ( type in events ) {
+                       for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+                               jQuery.event.add( dest, type, events[ type ][ i ] );
+                       }
                }
        }
 
-       return jQuery.grep(elements, function( elem, i ) {
-               return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
-       });
+       // make the cloned public data object a copy from the original
+       if ( curData.data ) {
+               curData.data = jQuery.extend( {}, curData.data );
+       }
 }
 
+function fixCloneNodeIssues( src, dest ) {
+       var nodeName, e, data;
 
+       // We do not need to do anything for non-Elements
+       if ( dest.nodeType !== 1 ) {
+               return;
+       }
 
+       nodeName = dest.nodeName.toLowerCase();
 
-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 = /<tbody/i,
-       rhtml = /<|&#?\w+;/,
-       rnocache = /<(?:script|object|embed|option|style)/i,
-       // checked="checked" or checked
-       rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
-       rscriptType = /\/(java|ecma)script/i,
-       wrapMap = {
-               option: [ 1, "<select multiple='multiple'>", "</select>" ],
-               legend: [ 1, "<fieldset>", "</fieldset>" ],
-               thead: [ 1, "<table>", "</table>" ],
-               tr: [ 2, "<table><tbody>", "</tbody></table>" ],
-               td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
-               col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
-               area: [ 1, "<map>", "</map>" ],
-               _default: [ 0, "", "" ]
-       };
+       // IE6-8 copies events bound via attachEvent when using cloneNode.
+       if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
+               data = jQuery._data( dest );
 
-wrapMap.optgroup = wrapMap.option;
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
+               for ( e in data.events ) {
+                       jQuery.removeEvent( dest, e, data.handle );
+               }
 
-// IE can't serialize <link> and <script> tags normally
-if ( !jQuery.support.htmlSerialize ) {
-       wrapMap._default = [ 1, "div<div>", "</div>" ];
-}
+               // Event data gets referenced instead of copied if the expando gets copied too
+               dest.removeAttribute( jQuery.expando );
+       }
 
-jQuery.fn.extend({
-       text: function( text ) {
-               if ( jQuery.isFunction(text) ) {
-                       return this.each(function(i) {
-                               var self = jQuery( this );
+       // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+       if ( nodeName === "script" && dest.text !== src.text ) {
+               disableScript( dest ).text = src.text;
+               restoreScript( dest );
 
-                               self.text( text.call(this, i, self.text()) );
-                       });
+       // IE6-10 improperly clones children of object elements using classid.
+       // IE10 throws NoModificationAllowedError if parent is null, #12132.
+       } else if ( nodeName === "object" ) {
+               if ( dest.parentNode ) {
+                       dest.outerHTML = src.outerHTML;
                }
 
-               if ( typeof text !== "object" && text !== undefined ) {
-                       return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+               // This path appears unavoidable for IE9. When cloning an object
+               // element in IE9, the outerHTML strategy above is not sufficient.
+               // If the src has innerHTML and the destination does not,
+               // copy the src.innerHTML into the dest.innerHTML. #10324
+               if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+                       dest.innerHTML = src.innerHTML;
                }
 
-               return jQuery.text( this );
-       },
+       } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+               // IE6-8 fails to persist the checked state of a cloned checkbox
+               // or radio button. Worse, IE6-7 fail to give the cloned element
+               // a checked appearance if the defaultChecked value isn't also set
 
-       wrapAll: function( html ) {
-               if ( jQuery.isFunction( html ) ) {
-                       return this.each(function(i) {
-                               jQuery(this).wrapAll( html.call(this, i) );
-                       });
+               dest.defaultChecked = dest.checked = src.checked;
+
+               // IE6-7 get confused and end up setting the value of a cloned
+               // checkbox/radio button to an empty string instead of "on"
+               if ( dest.value !== src.value ) {
+                       dest.value = src.value;
                }
 
-               if ( this[0] ) {
-                       // The elements to wrap the target around
-                       var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+       // IE6-8 fails to return the selected option to the default selected
+       // state when cloning options
+       } else if ( nodeName === "option" ) {
+               dest.defaultSelected = dest.selected = src.defaultSelected;
 
-                       if ( this[0].parentNode ) {
-                               wrap.insertBefore( this[0] );
-                       }
+       // IE6-8 fails to set the defaultValue to the correct value when
+       // cloning other types of input fields
+       } else if ( nodeName === "input" || nodeName === "textarea" ) {
+               dest.defaultValue = src.defaultValue;
+       }
+}
 
-                       wrap.map(function() {
-                               var elem = this;
+jQuery.extend({
+       clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+               var destElements, node, clone, i, srcElements,
+                       inPage = jQuery.contains( elem.ownerDocument, elem );
 
-                               while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
-                                       elem = elem.firstChild;
-                               }
+               if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+                       clone = elem.cloneNode( true );
 
-                               return elem;
-                       }).append( this );
+               // IE<=8 does not properly clone detached, unknown element nodes
+               } else {
+                       fragmentDiv.innerHTML = elem.outerHTML;
+                       fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
                }
 
-               return this;
-       },
+               if ( (!support.noCloneEvent || !support.noCloneChecked) &&
+                               (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
 
-       wrapInner: function( html ) {
-               if ( jQuery.isFunction( html ) ) {
-                       return this.each(function(i) {
-                               jQuery(this).wrapInner( html.call(this, i) );
-                       });
-               }
+                       // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+                       destElements = getAll( clone );
+                       srcElements = getAll( elem );
 
-               return this.each(function() {
-                       var self = jQuery( this ),
-                               contents = self.contents();
+                       // Fix all IE cloning issues
+                       for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+                               // Ensure that the destination node is not null; Fixes #9587
+                               if ( destElements[i] ) {
+                                       fixCloneNodeIssues( node, destElements[i] );
+                               }
+                       }
+               }
 
-                       if ( contents.length ) {
-                               contents.wrapAll( html );
+               // Copy the events from the original to the clone
+               if ( dataAndEvents ) {
+                       if ( deepDataAndEvents ) {
+                               srcElements = srcElements || getAll( elem );
+                               destElements = destElements || getAll( clone );
 
+                               for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+                                       cloneCopyEvent( node, destElements[i] );
+                               }
                        } else {
-                               self.append( html );
+                               cloneCopyEvent( elem, clone );
                        }
-               });
-       },
+               }
 
-       wrap: function( html ) {
-               return this.each(function() {
-                       jQuery( this ).wrapAll( html );
-               });
-       },
+               // Preserve script evaluation history
+               destElements = getAll( clone, "script" );
+               if ( destElements.length > 0 ) {
+                       setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+               }
 
-       unwrap: function() {
-               return this.parent().each(function() {
-                       if ( !jQuery.nodeName( this, "body" ) ) {
-                               jQuery( this ).replaceWith( this.childNodes );
-                       }
-               }).end();
-       },
+               destElements = srcElements = node = null;
 
-       append: function() {
-               return this.domManip(arguments, true, function( elem ) {
-                       if ( this.nodeType === 1 ) {
-                               this.appendChild( elem );
-                       }
-               });
+               // Return the cloned set
+               return clone;
        },
 
-       prepend: function() {
-               return this.domManip(arguments, true, function( elem ) {
-                       if ( this.nodeType === 1 ) {
-                               this.insertBefore( elem, this.firstChild );
-                       }
-               });
-       },
+       buildFragment: function( elems, context, scripts, selection ) {
+               var j, elem, contains,
+                       tmp, tag, tbody, wrap,
+                       l = elems.length,
 
-       before: function() {
-               if ( this[0] && this[0].parentNode ) {
-                       return this.domManip(arguments, false, function( elem ) {
-                               this.parentNode.insertBefore( elem, this );
-                       });
-               } else if ( arguments.length ) {
-                       var set = jQuery(arguments[0]);
-                       set.push.apply( set, this.toArray() );
-                       return this.pushStack( set, "before", arguments );
-               }
-       },
+                       // Ensure a safe fragment
+                       safe = createSafeFragment( context ),
 
-       after: function() {
-               if ( this[0] && this[0].parentNode ) {
-                       return this.domManip(arguments, false, function( elem ) {
-                               this.parentNode.insertBefore( elem, this.nextSibling );
-                       });
-               } else if ( arguments.length ) {
-                       var set = this.pushStack( this, "after", arguments );
-                       set.push.apply( set, jQuery(arguments[0]).toArray() );
-                       return set;
-               }
-       },
+                       nodes = [],
+                       i = 0;
 
-       // keepData is for internal use only--do not document
-       remove: function( selector, keepData ) {
-               for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
-                       if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
-                               if ( !keepData && elem.nodeType === 1 ) {
-                                       jQuery.cleanData( elem.getElementsByTagName("*") );
-                                       jQuery.cleanData( [ elem ] );
-                               }
+               for ( ; i < l; i++ ) {
+                       elem = elems[ i ];
 
-                               if ( elem.parentNode ) {
-                                       elem.parentNode.removeChild( elem );
-                               }
-                       }
-               }
+                       if ( elem || elem === 0 ) {
 
-               return this;
-       },
+                               // Add nodes directly
+                               if ( jQuery.type( elem ) === "object" ) {
+                                       jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
 
-       empty: function() {
-               for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
-                       // Remove element nodes and prevent memory leaks
-                       if ( elem.nodeType === 1 ) {
-                               jQuery.cleanData( elem.getElementsByTagName("*") );
-                       }
+                               // Convert non-html into a text node
+                               } else if ( !rhtml.test( elem ) ) {
+                                       nodes.push( context.createTextNode( elem ) );
 
-                       // Remove any remaining nodes
-                       while ( elem.firstChild ) {
-                               elem.removeChild( elem.firstChild );
-                       }
-               }
+                               // Convert html into DOM nodes
+                               } else {
+                                       tmp = tmp || safe.appendChild( context.createElement("div") );
 
-               return this;
-       },
+                                       // Deserialize a standard representation
+                                       tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
+                                       wrap = wrapMap[ tag ] || wrapMap._default;
 
-       clone: function( dataAndEvents, deepDataAndEvents ) {
-               dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
-               deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+                                       tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
 
-               return this.map( function () {
-                       return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
-               });
-       },
+                                       // Descend through wrappers to the right content
+                                       j = wrap[0];
+                                       while ( j-- ) {
+                                               tmp = tmp.lastChild;
+                                       }
 
-       html: function( value ) {
-               if ( value === undefined ) {
-                       return this[0] && this[0].nodeType === 1 ?
-                               this[0].innerHTML.replace(rinlinejQuery, "") :
-                               null;
+                                       // Manually add leading whitespace removed by IE
+                                       if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+                                               nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+                                       }
+
+                                       // Remove IE's autoinserted <tbody> from table fragments
+                                       if ( !support.tbody ) {
+
+                                               // String was a <table>, *may* have spurious <tbody>
+                                               elem = tag === "table" && !rtbody.test( elem ) ?
+                                                       tmp.firstChild :
+
+                                                       // String was a bare <thead> or <tfoot>
+                                                       wrap[1] === "<table>" && !rtbody.test( elem ) ?
+                                                               tmp :
+                                                               0;
+
+                                               j = elem && elem.childNodes.length;
+                                               while ( j-- ) {
+                                                       if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+                                                               elem.removeChild( tbody );
+                                                       }
+                                               }
+                                       }
 
-               // See if we can take a shortcut and just use innerHTML
-               } else if ( typeof value === "string" && !rnocache.test( value ) &&
-                       (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
-                       !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+                                       jQuery.merge( nodes, tmp.childNodes );
 
-                       value = value.replace(rxhtmlTag, "<$1></$2>");
+                                       // Fix #12392 for WebKit and IE > 9
+                                       tmp.textContent = "";
 
-                       try {
-                               for ( var i = 0, l = this.length; i < l; i++ ) {
-                                       // Remove element nodes and prevent memory leaks
-                                       if ( this[i].nodeType === 1 ) {
-                                               jQuery.cleanData( this[i].getElementsByTagName("*") );
-                                               this[i].innerHTML = value;
+                                       // Fix #12392 for oldIE
+                                       while ( tmp.firstChild ) {
+                                               tmp.removeChild( tmp.firstChild );
                                        }
+
+                                       // Remember the top-level container for proper cleanup
+                                       tmp = safe.lastChild;
                                }
+                       }
+               }
 
-                       // If using innerHTML throws an exception, use the fallback method
-                       } catch(e) {
-                               this.empty().append( value );
+               // Fix #11356: Clear elements from fragment
+               if ( tmp ) {
+                       safe.removeChild( tmp );
+               }
+
+               // Reset defaultChecked for any radios and checkboxes
+               // about to be appended to the DOM in IE 6/7 (#8060)
+               if ( !support.appendChecked ) {
+                       jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+               }
+
+               i = 0;
+               while ( (elem = nodes[ i++ ]) ) {
+
+                       // #4087 - If origin and destination elements are the same, and this is
+                       // that element, do not do anything
+                       if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+                               continue;
                        }
 
-               } else if ( jQuery.isFunction( value ) ) {
-                       this.each(function(i){
-                               var self = jQuery( this );
+                       contains = jQuery.contains( elem.ownerDocument, elem );
 
-                               self.html( value.call(this, i, self.html()) );
-                       });
+                       // Append to fragment
+                       tmp = getAll( safe.appendChild( elem ), "script" );
 
-               } else {
-                       this.empty().append( value );
+                       // Preserve script evaluation history
+                       if ( contains ) {
+                               setGlobalEval( tmp );
+                       }
+
+                       // Capture executables
+                       if ( scripts ) {
+                               j = 0;
+                               while ( (elem = tmp[ j++ ]) ) {
+                                       if ( rscriptType.test( elem.type || "" ) ) {
+                                               scripts.push( elem );
+                                       }
+                               }
+                       }
                }
 
-               return this;
+               tmp = null;
+
+               return safe;
        },
 
-       replaceWith: function( value ) {
-               if ( this[0] && this[0].parentNode ) {
-                       // Make sure that the elements are removed from the DOM before they are inserted
-                       // this can help fix replacing a parent with child elements
-                       if ( jQuery.isFunction( value ) ) {
-                               return this.each(function(i) {
-                                       var self = jQuery(this), old = self.html();
-                                       self.replaceWith( value.call( this, i, old ) );
-                               });
-                       }
+       cleanData: function( elems, /* internal */ acceptData ) {
+               var elem, type, id, data,
+                       i = 0,
+                       internalKey = jQuery.expando,
+                       cache = jQuery.cache,
+                       deleteExpando = support.deleteExpando,
+                       special = jQuery.event.special;
 
-                       if ( typeof value !== "string" ) {
-                               value = jQuery( value ).detach();
-                       }
+               for ( ; (elem = elems[i]) != null; i++ ) {
+                       if ( acceptData || jQuery.acceptData( elem ) ) {
 
-                       return this.each(function() {
-                               var next = this.nextSibling,
-                                       parent = this.parentNode;
+                               id = elem[ internalKey ];
+                               data = id && cache[ id ];
 
-                               jQuery( this ).remove();
+                               if ( data ) {
+                                       if ( data.events ) {
+                                               for ( type in data.events ) {
+                                                       if ( special[ type ] ) {
+                                                               jQuery.event.remove( elem, type );
 
-                               if ( next ) {
-                                       jQuery(next).before( value );
-                               } else {
-                                       jQuery(parent).append( value );
+                                                       // This is a shortcut to avoid jQuery.event.remove's overhead
+                                                       } else {
+                                                               jQuery.removeEvent( elem, type, data.handle );
+                                                       }
+                                               }
+                                       }
+
+                                       // Remove cache only if it was not already removed by jQuery.event.remove
+                                       if ( cache[ id ] ) {
+
+                                               delete cache[ id ];
+
+                                               // IE does not allow us to delete expando properties from nodes,
+                                               // nor does it have a removeAttribute function on Document nodes;
+                                               // we must handle all of these cases
+                                               if ( deleteExpando ) {
+                                                       delete elem[ internalKey ];
+
+                                               } else if ( typeof elem.removeAttribute !== strundefined ) {
+                                                       elem.removeAttribute( internalKey );
+
+                                               } else {
+                                                       elem[ internalKey ] = null;
+                                               }
+
+                                               deletedIds.push( id );
+                                       }
                                }
-                       });
-               } else {
-                       return this.length ?
-                               this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
-                               this;
+                       }
                }
+       }
+});
+
+jQuery.fn.extend({
+       text: function( value ) {
+               return access( this, function( value ) {
+                       return value === undefined ?
+                               jQuery.text( this ) :
+                               this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+               }, null, value, arguments.length );
        },
 
-       detach: function( selector ) {
-               return this.remove( selector, true );
+       append: function() {
+               return this.domManip( arguments, function( elem ) {
+                       if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+                               var target = manipulationTarget( this, elem );
+                               target.appendChild( elem );
+                       }
+               });
        },
 
-       domManip: function( args, table, callback ) {
-               var results, first, fragment, parent,
-                       value = args[0],
-                       scripts = [];
+       prepend: function() {
+               return this.domManip( arguments, function( elem ) {
+                       if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+                               var target = manipulationTarget( this, elem );
+                               target.insertBefore( elem, target.firstChild );
+                       }
+               });
+       },
 
-               // We can't cloneNode fragments that contain checked, in WebKit
-               if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
-                       return this.each(function() {
-                               jQuery(this).domManip( args, table, callback, true );
-                       });
-               }
+       before: function() {
+               return this.domManip( arguments, function( elem ) {
+                       if ( this.parentNode ) {
+                               this.parentNode.insertBefore( elem, this );
+                       }
+               });
+       },
 
-               if ( jQuery.isFunction(value) ) {
-                       return this.each(function(i) {
-                               var self = jQuery(this);
-                               args[0] = value.call(this, i, table ? self.html() : undefined);
-                               self.domManip( args, table, callback );
-                       });
-               }
+       after: function() {
+               return this.domManip( arguments, function( elem ) {
+                       if ( this.parentNode ) {
+                               this.parentNode.insertBefore( elem, this.nextSibling );
+                       }
+               });
+       },
 
-               if ( this[0] ) {
-                       parent = value && value.parentNode;
+       remove: function( selector, keepData /* Internal Use Only */ ) {
+               var elem,
+                       elems = selector ? jQuery.filter( selector, this ) : this,
+                       i = 0;
 
-                       // If we're in a fragment, just use that instead of building a new one
-                       if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
-                               results = { fragment: parent };
+               for ( ; (elem = elems[i]) != null; i++ ) {
 
-                       } else {
-                               results = jQuery.buildFragment( args, this, scripts );
+                       if ( !keepData && elem.nodeType === 1 ) {
+                               jQuery.cleanData( getAll( elem ) );
+                       }
+
+                       if ( elem.parentNode ) {
+                               if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+                                       setGlobalEval( getAll( elem, "script" ) );
+                               }
+                               elem.parentNode.removeChild( elem );
                        }
+               }
+
+               return this;
+       },
 
-                       fragment = results.fragment;
+       empty: function() {
+               var elem,
+                       i = 0;
 
-                       if ( fragment.childNodes.length === 1 ) {
-                               first = fragment = fragment.firstChild;
-                       } else {
-                               first = fragment.firstChild;
+               for ( ; (elem = this[i]) != null; i++ ) {
+                       // Remove element nodes and prevent memory leaks
+                       if ( elem.nodeType === 1 ) {
+                               jQuery.cleanData( getAll( elem, false ) );
                        }
 
-                       if ( first ) {
-                               table = table && jQuery.nodeName( first, "tr" );
-
-                               for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
-                                       callback.call(
-                                               table ?
-                                                       root(this[i], first) :
-                                                       this[i],
-                                               // Make sure that we do not leak memory by inadvertently discarding
-                                               // the original fragment (which might have attached data) instead of
-                                               // using it; in addition, use the original fragment object for the last
-                                               // item instead of first because it can end up being emptied incorrectly
-                                               // in certain situations (Bug #8070).
-                                               // Fragments from the fragment cache must always be cloned and never used
-                                               // in place.
-                                               results.cacheable || (l > 1 && i < lastIndex) ?
-                                                       jQuery.clone( fragment, true, true ) :
-                                                       fragment
-                                       );
-                               }
+                       // Remove any remaining nodes
+                       while ( elem.firstChild ) {
+                               elem.removeChild( elem.firstChild );
                        }
 
-                       if ( scripts.length ) {
-                               jQuery.each( scripts, evalScript );
+                       // If this is a select, ensure that it displays empty (#12336)
+                       // Support: IE<9
+                       if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+                               elem.options.length = 0;
                        }
                }
 
                return this;
-       }
-});
+       },
 
-function root( elem, cur ) {
-       return jQuery.nodeName(elem, "table") ?
-               (elem.getElementsByTagName("tbody")[0] ||
-               elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
-               elem;
-}
+       clone: function( dataAndEvents, deepDataAndEvents ) {
+               dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+               deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
 
-function cloneCopyEvent( src, dest ) {
+               return this.map(function() {
+                       return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+               });
+       },
 
-       if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
-               return;
-       }
+       html: function( value ) {
+               return access( this, function( value ) {
+                       var elem = this[ 0 ] || {},
+                               i = 0,
+                               l = this.length;
 
-       var internalKey = jQuery.expando,
-               oldData = jQuery.data( src ),
-               curData = jQuery.data( dest, oldData );
+                       if ( value === undefined ) {
+                               return elem.nodeType === 1 ?
+                                       elem.innerHTML.replace( rinlinejQuery, "" ) :
+                                       undefined;
+                       }
 
-       // Switch to use the internal data object, if it exists, for the next
-       // stage of data copying
-       if ( (oldData = oldData[ internalKey ]) ) {
-               var events = oldData.events;
-                               curData = curData[ internalKey ] = jQuery.extend({}, oldData);
+                       // See if we can take a shortcut and just use innerHTML
+                       if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+                               ( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
+                               ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+                               !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
 
-               if ( events ) {
-                       delete curData.handle;
-                       curData.events = {};
+                               value = value.replace( rxhtmlTag, "<$1></$2>" );
 
-                       for ( var type in events ) {
-                               for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
-                                       jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
-                               }
+                               try {
+                                       for (; i < l; i++ ) {
+                                               // Remove element nodes and prevent memory leaks
+                                               elem = this[i] || {};
+                                               if ( elem.nodeType === 1 ) {
+                                                       jQuery.cleanData( getAll( elem, false ) );
+                                                       elem.innerHTML = value;
+                                               }
+                                       }
+
+                                       elem = 0;
+
+                               // If using innerHTML throws an exception, use the fallback method
+                               } catch(e) {}
                        }
-               }
-       }
-}
 
-function cloneFixAttributes( src, dest ) {
-       var nodeName;
+                       if ( elem ) {
+                               this.empty().append( value );
+                       }
+               }, null, value, arguments.length );
+       },
 
-       // We do not need to do anything for non-Elements
-       if ( dest.nodeType !== 1 ) {
-               return;
-       }
+       replaceWith: function() {
+               var arg = arguments[ 0 ];
 
-       // clearAttributes removes the attributes, which we don't want,
-       // but also removes the attachEvent events, which we *do* want
-       if ( dest.clearAttributes ) {
-               dest.clearAttributes();
-       }
+               // Make the changes, replacing each context element with the new content
+               this.domManip( arguments, function( elem ) {
+                       arg = this.parentNode;
 
-       // mergeAttributes, in contrast, only merges back on the
-       // original attributes, not the events
-       if ( dest.mergeAttributes ) {
-               dest.mergeAttributes( src );
-       }
+                       jQuery.cleanData( getAll( this ) );
 
-       nodeName = dest.nodeName.toLowerCase();
+                       if ( arg ) {
+                               arg.replaceChild( elem, this );
+                       }
+               });
 
-       // IE6-8 fail to clone children inside object elements that use
-       // the proprietary classid attribute value (rather than the type
-       // attribute) to identify the type of content to display
-       if ( nodeName === "object" ) {
-               dest.outerHTML = src.outerHTML;
+               // Force removal if there was no new content (e.g., from empty arguments)
+               return arg && (arg.length || arg.nodeType) ? this : this.remove();
+       },
 
-       } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
-               // IE6-8 fails to persist the checked state of a cloned checkbox
-               // or radio button. Worse, IE6-7 fail to give the cloned element
-               // a checked appearance if the defaultChecked value isn't also set
-               if ( src.checked ) {
-                       dest.defaultChecked = dest.checked = src.checked;
-               }
+       detach: function( selector ) {
+               return this.remove( selector, true );
+       },
 
-               // IE6-7 get confused and end up setting the value of a cloned
-               // checkbox/radio button to an empty string instead of "on"
-               if ( dest.value !== src.value ) {
-                       dest.value = src.value;
+       domManip: function( args, callback ) {
+
+               // Flatten any nested arrays
+               args = concat.apply( [], args );
+
+               var first, node, hasScripts,
+                       scripts, doc, fragment,
+                       i = 0,
+                       l = this.length,
+                       set = this,
+                       iNoClone = l - 1,
+                       value = args[0],
+                       isFunction = jQuery.isFunction( value );
+
+               // We can't cloneNode fragments that contain checked, in WebKit
+               if ( isFunction ||
+                               ( l > 1 && typeof value === "string" &&
+                                       !support.checkClone && rchecked.test( value ) ) ) {
+                       return this.each(function( index ) {
+                               var self = set.eq( index );
+                               if ( isFunction ) {
+                                       args[0] = value.call( this, index, self.html() );
+                               }
+                               self.domManip( args, callback );
+                       });
                }
 
-       // IE6-8 fails to return the selected option to the default selected
-       // state when cloning options
-       } else if ( nodeName === "option" ) {
-               dest.selected = src.defaultSelected;
+               if ( l ) {
+                       fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+                       first = fragment.firstChild;
 
-       // IE6-8 fails to set the defaultValue to the correct value when
-       // cloning other types of input fields
-       } else if ( nodeName === "input" || nodeName === "textarea" ) {
-               dest.defaultValue = src.defaultValue;
-       }
+                       if ( fragment.childNodes.length === 1 ) {
+                               fragment = first;
+                       }
 
-       // Event data gets referenced instead of copied if the expando
-       // gets copied too
-       dest.removeAttribute( jQuery.expando );
-}
+                       if ( first ) {
+                               scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+                               hasScripts = scripts.length;
 
-jQuery.buildFragment = function( args, nodes, scripts ) {
-       var fragment, cacheable, cacheresults,
-               doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
+                               // Use the original fragment for the last item instead of the first because it can end up
+                               // being emptied incorrectly in certain situations (#8070).
+                               for ( ; i < l; i++ ) {
+                                       node = fragment;
 
-       // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
-       // Cloning options loses the selected state, so don't cache them
-       // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
-       // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
-       if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
-               args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
+                                       if ( i !== iNoClone ) {
+                                               node = jQuery.clone( node, true, true );
 
-               cacheable = true;
+                                               // Keep references to cloned scripts for later restoration
+                                               if ( hasScripts ) {
+                                                       jQuery.merge( scripts, getAll( node, "script" ) );
+                                               }
+                                       }
 
-               cacheresults = jQuery.fragments[ args[0] ];
-               if ( cacheresults && cacheresults !== 1 ) {
-                       fragment = cacheresults;
-               }
-       }
+                                       callback.call( this[i], node, i );
+                               }
 
-       if ( !fragment ) {
-               fragment = doc.createDocumentFragment();
-               jQuery.clean( args, doc, fragment, scripts );
-       }
+                               if ( hasScripts ) {
+                                       doc = scripts[ scripts.length - 1 ].ownerDocument;
 
-       if ( cacheable ) {
-               jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
-       }
+                                       // Reenable scripts
+                                       jQuery.map( scripts, restoreScript );
 
-       return { fragment: fragment, cacheable: cacheable };
-};
+                                       // Evaluate executable scripts on first document insertion
+                                       for ( i = 0; i < hasScripts; i++ ) {
+                                               node = scripts[ i ];
+                                               if ( rscriptType.test( node.type || "" ) &&
+                                                       !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+                                                       if ( node.src ) {
+                                                               // Optional AJAX dependency, but won't run scripts if not present
+                                                               if ( jQuery._evalUrl ) {
+                                                                       jQuery._evalUrl( node.src );
+                                                               }
+                                                       } else {
+                                                               jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               // Fix #11809: Avoid leaking memory
+                               fragment = first = null;
+                       }
+               }
 
-jQuery.fragments = {};
+               return this;
+       }
+});
 
 jQuery.each({
        appendTo: "append",
@@ -5861,312 +6005,631 @@ jQuery.each({
        replaceAll: "replaceWith"
 }, function( name, original ) {
        jQuery.fn[ name ] = function( selector ) {
-               var ret = [],
+               var elems,
+                       i = 0,
+                       ret = [],
                        insert = jQuery( selector ),
-                       parent = this.length === 1 && this[0].parentNode;
-
-               if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
-                       insert[ original ]( this[0] );
-                       return this;
+                       last = insert.length - 1;
 
-               } else {
-                       for ( var i = 0, l = insert.length; i < l; i++ ) {
-                               var elems = (i > 0 ? this.clone(true) : this).get();
-                               jQuery( insert[i] )[ original ]( elems );
-                               ret = ret.concat( elems );
-                       }
+               for ( ; i <= last; i++ ) {
+                       elems = i === last ? this : this.clone(true);
+                       jQuery( insert[i] )[ original ]( elems );
 
-                       return this.pushStack( ret, name, insert.selector );
+                       // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+                       push.apply( ret, elems.get() );
                }
+
+               return this.pushStack( ret );
        };
 });
 
-function getAll( elem ) {
-       if ( "getElementsByTagName" in elem ) {
-               return elem.getElementsByTagName( "*" );
-       
-       } else if ( "querySelectorAll" in elem ) {
-               return elem.querySelectorAll( "*" );
-
-       } else {
-               return [];
-       }
-}
 
-// Used in clean, fixes the defaultChecked property
-function fixDefaultChecked( elem ) {
-       if ( elem.type === "checkbox" || elem.type === "radio" ) {
-               elem.defaultChecked = elem.checked;
-       }
-}
-// Finds all inputs and passes them to fixDefaultChecked
-function findInputs( elem ) {
-       if ( jQuery.nodeName( elem, "input" ) ) {
-               fixDefaultChecked( elem );
-       } else if ( elem.getElementsByTagName ) {
-               jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
-       }
-}
+var iframe,
+       elemdisplay = {};
 
-jQuery.extend({
-       clone: function( elem, dataAndEvents, deepDataAndEvents ) {
-               var clone = elem.cloneNode(true),
-                               srcElements,
-                               destElements,
-                               i;
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+       var style,
+               elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
 
-               if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
-                               (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
-                       // IE copies events bound via attachEvent when using cloneNode.
-                       // Calling detachEvent on the clone will also remove the events
-                       // from the original. In order to get around this, we use some
-                       // proprietary methods to clear the events. Thanks to MooTools
-                       // guys for this hotness.
+               // getDefaultComputedStyle might be reliably used only on attached element
+               display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
 
-                       cloneFixAttributes( elem, clone );
+                       // Use of this method is a temporary fix (more like optmization) until something better comes along,
+                       // since it was removed from specification and supported only in FF
+                       style.display : jQuery.css( elem[ 0 ], "display" );
 
-                       // Using Sizzle here is crazy slow, so we use getElementsByTagName
-                       // instead
-                       srcElements = getAll( elem );
-                       destElements = getAll( clone );
+       // We don't have any data stored on the element,
+       // so use "detach" method as fast way to get rid of the element
+       elem.detach();
 
-                       // Weird iteration because IE will replace the length property
-                       // with an element if you are cloning the body and one of the
-                       // elements on the page has a name or id of "length"
-                       for ( i = 0; srcElements[i]; ++i ) {
-                               cloneFixAttributes( srcElements[i], destElements[i] );
-                       }
-               }
+       return display;
+}
 
-               // Copy the events from the original to the clone
-               if ( dataAndEvents ) {
-                       cloneCopyEvent( elem, clone );
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+       var doc = document,
+               display = elemdisplay[ nodeName ];
 
-                       if ( deepDataAndEvents ) {
-                               srcElements = getAll( elem );
-                               destElements = getAll( clone );
+       if ( !display ) {
+               display = actualDisplay( nodeName, doc );
 
-                               for ( i = 0; srcElements[i]; ++i ) {
-                                       cloneCopyEvent( srcElements[i], destElements[i] );
-                               }
-                       }
-               }
+               // If the simple way fails, read from inside an iframe
+               if ( display === "none" || !display ) {
 
-               // Return the cloned set
-               return clone;
-       },
+                       // Use the already-created iframe if possible
+                       iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
 
-       clean: function( elems, context, fragment, scripts ) {
-               var checkScriptType;
+                       // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+                       doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
 
-               context = context || document;
+                       // Support: IE
+                       doc.write();
+                       doc.close();
 
-               // !context.createElement fails in IE with an error but returns typeof 'object'
-               if ( typeof context.createElement === "undefined" ) {
-                       context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+                       display = actualDisplay( nodeName, doc );
+                       iframe.detach();
                }
 
-               var ret = [];
+               // Store the correct default display
+               elemdisplay[ nodeName ] = display;
+       }
 
-               for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
-                       if ( typeof elem === "number" ) {
-                               elem += "";
+       return display;
+}
+
+
+(function() {
+       var shrinkWrapBlocksVal;
+
+       support.shrinkWrapBlocks = function() {
+               if ( shrinkWrapBlocksVal != null ) {
+                       return shrinkWrapBlocksVal;
+               }
+
+               // Will be changed later if needed.
+               shrinkWrapBlocksVal = false;
+
+               // Minified: var b,c,d
+               var div, body, container;
+
+               body = document.getElementsByTagName( "body" )[ 0 ];
+               if ( !body || !body.style ) {
+                       // Test fired too early or in an unsupported environment, exit.
+                       return;
+               }
+
+               // Setup
+               div = document.createElement( "div" );
+               container = document.createElement( "div" );
+               container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+               body.appendChild( container ).appendChild( div );
+
+               // Support: IE6
+               // Check if elements with layout shrink-wrap their children
+               if ( typeof div.style.zoom !== strundefined ) {
+                       // Reset CSS: box-sizing; display; margin; border
+                       div.style.cssText =
+                               // Support: Firefox<29, Android 2.3
+                               // Vendor-prefix box-sizing
+                               "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+                               "box-sizing:content-box;display:block;margin:0;border:0;" +
+                               "padding:1px;width:1px;zoom:1";
+                       div.appendChild( document.createElement( "div" ) ).style.width = "5px";
+                       shrinkWrapBlocksVal = div.offsetWidth !== 3;
+               }
+
+               body.removeChild( container );
+
+               return shrinkWrapBlocksVal;
+       };
+
+})();
+var rmargin = (/^margin/);
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+
+
+var getStyles, curCSS,
+       rposition = /^(top|right|bottom|left)$/;
+
+if ( window.getComputedStyle ) {
+       getStyles = function( elem ) {
+               // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
+               // IE throws on elements created in popups
+               // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+               if ( elem.ownerDocument.defaultView.opener ) {
+                       return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
+               }
+
+               return window.getComputedStyle( elem, null );
+       };
+
+       curCSS = function( elem, name, computed ) {
+               var width, minWidth, maxWidth, ret,
+                       style = elem.style;
+
+               computed = computed || getStyles( elem );
+
+               // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+               ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+               if ( computed ) {
+
+                       if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+                               ret = jQuery.style( elem, name );
                        }
 
-                       if ( !elem ) {
-                               continue;
+                       // A tribute to the "awesome hack by Dean Edwards"
+                       // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+                       // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+                       // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+                       if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+                               // Remember the original values
+                               width = style.width;
+                               minWidth = style.minWidth;
+                               maxWidth = style.maxWidth;
+
+                               // Put in the new values to get a computed value out
+                               style.minWidth = style.maxWidth = style.width = ret;
+                               ret = computed.width;
+
+                               // Revert the changed values
+                               style.width = width;
+                               style.minWidth = minWidth;
+                               style.maxWidth = maxWidth;
                        }
+               }
 
-                       // Convert html string into DOM nodes
-                       if ( typeof elem === "string" ) {
-                               if ( !rhtml.test( elem ) ) {
-                                       elem = context.createTextNode( elem );
-                               } else {
-                                       // Fix "XHTML"-style tags in all browsers
-                                       elem = elem.replace(rxhtmlTag, "<$1></$2>");
+               // Support: IE
+               // IE returns zIndex value as an integer.
+               return ret === undefined ?
+                       ret :
+                       ret + "";
+       };
+} else if ( document.documentElement.currentStyle ) {
+       getStyles = function( elem ) {
+               return elem.currentStyle;
+       };
 
-                                       // Trim whitespace, otherwise indexOf won't work as expected
-                                       var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
-                                               wrap = wrapMap[ tag ] || wrapMap._default,
-                                               depth = wrap[0],
-                                               div = context.createElement("div");
+       curCSS = function( elem, name, computed ) {
+               var left, rs, rsLeft, ret,
+                       style = elem.style;
 
-                                       // Go to html and back, then peel off extra wrappers
-                                       div.innerHTML = wrap[1] + elem + wrap[2];
+               computed = computed || getStyles( elem );
+               ret = computed ? computed[ name ] : undefined;
 
-                                       // Move to the right depth
-                                       while ( depth-- ) {
-                                               div = div.lastChild;
-                                       }
+               // Avoid setting ret to empty string here
+               // so we don't default to auto
+               if ( ret == null && style && style[ name ] ) {
+                       ret = style[ name ];
+               }
 
-                                       // Remove IE's autoinserted <tbody> from table fragments
-                                       if ( !jQuery.support.tbody ) {
+               // From the awesome hack by Dean Edwards
+               // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
 
-                                               // String was a <table>, *may* have spurious <tbody>
-                                               var hasBody = rtbody.test(elem),
-                                                       tbody = tag === "table" && !hasBody ?
-                                                               div.firstChild && div.firstChild.childNodes :
-
-                                                               // String was a bare <thead> or <tfoot>
-                                                               wrap[1] === "<table>" && !hasBody ?
-                                                                       div.childNodes :
-                                                                       [];
-
-                                               for ( var j = tbody.length - 1; j >= 0 ; --j ) {
-                                                       if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
-                                                               tbody[ j ].parentNode.removeChild( tbody[ j ] );
-                                                       }
-                                               }
-                                       }
+               // If we're not dealing with a regular pixel number
+               // but a number that has a weird ending, we need to convert it to pixels
+               // but not position css attributes, as those are proportional to the parent element instead
+               // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+               if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
 
-                                       // IE completely kills leading whitespace when innerHTML is used
-                                       if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
-                                               div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
-                                       }
+                       // Remember the original values
+                       left = style.left;
+                       rs = elem.runtimeStyle;
+                       rsLeft = rs && rs.left;
 
-                                       elem = div.childNodes;
-                               }
+                       // Put in the new values to get a computed value out
+                       if ( rsLeft ) {
+                               rs.left = elem.currentStyle.left;
                        }
+                       style.left = name === "fontSize" ? "1em" : ret;
+                       ret = style.pixelLeft + "px";
 
-                       // Resets defaultChecked for any radios and checkboxes
-                       // about to be appended to the DOM in IE 6/7 (#8060)
-                       var len;
-                       if ( !jQuery.support.appendChecked ) {
-                               if ( elem[0] && typeof (len = elem.length) === "number" ) {
-                                       for ( i = 0; i < len; i++ ) {
-                                               findInputs( elem[i] );
-                                       }
-                               } else {
-                                       findInputs( elem );
-                               }
+                       // Revert the changed values
+                       style.left = left;
+                       if ( rsLeft ) {
+                               rs.left = rsLeft;
                        }
+               }
 
-                       if ( elem.nodeType ) {
-                               ret.push( elem );
-                       } else {
-                               ret = jQuery.merge( ret, elem );
+               // Support: IE
+               // IE returns zIndex value as an integer.
+               return ret === undefined ?
+                       ret :
+                       ret + "" || "auto";
+       };
+}
+
+
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+       // Define the hook, we'll check on the first run if it's really needed.
+       return {
+               get: function() {
+                       var condition = conditionFn();
+
+                       if ( condition == null ) {
+                               // The test was not ready at this point; screw the hook this time
+                               // but check again when needed next time.
+                               return;
+                       }
+
+                       if ( condition ) {
+                               // Hook not needed (or it's not possible to use it due to missing dependency),
+                               // remove it.
+                               // Since there are no other hooks for marginRight, remove the whole object.
+                               delete this.get;
+                               return;
                        }
+
+                       // Hook needed; redefine it so that the support test is not executed again.
+
+                       return (this.get = hookFn).apply( this, arguments );
                }
+       };
+}
 
-               if ( fragment ) {
-                       checkScriptType = function( elem ) {
-                               return !elem.type || rscriptType.test( elem.type );
-                       };
-                       for ( i = 0; ret[i]; i++ ) {
-                               if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
-                                       scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
 
-                               } else {
-                                       if ( ret[i].nodeType === 1 ) {
-                                               var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
+(function() {
+       // Minified: var b,c,d,e,f,g, h,i
+       var div, style, a, pixelPositionVal, boxSizingReliableVal,
+               reliableHiddenOffsetsVal, reliableMarginRightVal;
 
-                                               ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
-                                       }
-                                       fragment.appendChild( ret[i] );
-                               }
+       // Setup
+       div = document.createElement( "div" );
+       div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+       a = div.getElementsByTagName( "a" )[ 0 ];
+       style = a && a.style;
+
+       // Finish early in limited (non-browser) environments
+       if ( !style ) {
+               return;
+       }
+
+       style.cssText = "float:left;opacity:.5";
+
+       // Support: IE<9
+       // Make sure that element opacity exists (as opposed to filter)
+       support.opacity = style.opacity === "0.5";
+
+       // Verify style float existence
+       // (IE uses styleFloat instead of cssFloat)
+       support.cssFloat = !!style.cssFloat;
+
+       div.style.backgroundClip = "content-box";
+       div.cloneNode( true ).style.backgroundClip = "";
+       support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+       // Support: Firefox<29, Android 2.3
+       // Vendor-prefix box-sizing
+       support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
+               style.WebkitBoxSizing === "";
+
+       jQuery.extend(support, {
+               reliableHiddenOffsets: function() {
+                       if ( reliableHiddenOffsetsVal == null ) {
+                               computeStyleTests();
+                       }
+                       return reliableHiddenOffsetsVal;
+               },
+
+               boxSizingReliable: function() {
+                       if ( boxSizingReliableVal == null ) {
+                               computeStyleTests();
+                       }
+                       return boxSizingReliableVal;
+               },
+
+               pixelPosition: function() {
+                       if ( pixelPositionVal == null ) {
+                               computeStyleTests();
+                       }
+                       return pixelPositionVal;
+               },
+
+               // Support: Android 2.3
+               reliableMarginRight: function() {
+                       if ( reliableMarginRightVal == null ) {
+                               computeStyleTests();
                        }
+                       return reliableMarginRightVal;
                }
+       });
 
-               return ret;
+       function computeStyleTests() {
+               // Minified: var b,c,d,j
+               var div, body, container, contents;
+
+               body = document.getElementsByTagName( "body" )[ 0 ];
+               if ( !body || !body.style ) {
+                       // Test fired too early or in an unsupported environment, exit.
+                       return;
+               }
+
+               // Setup
+               div = document.createElement( "div" );
+               container = document.createElement( "div" );
+               container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+               body.appendChild( container ).appendChild( div );
+
+               div.style.cssText =
+                       // Support: Firefox<29, Android 2.3
+                       // Vendor-prefix box-sizing
+                       "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
+                       "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
+                       "border:1px;padding:1px;width:4px;position:absolute";
+
+               // Support: IE<9
+               // Assume reasonable values in the absence of getComputedStyle
+               pixelPositionVal = boxSizingReliableVal = false;
+               reliableMarginRightVal = true;
+
+               // Check for getComputedStyle so that this code is not run in IE<9.
+               if ( window.getComputedStyle ) {
+                       pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+                       boxSizingReliableVal =
+                               ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+                       // Support: Android 2.3
+                       // Div with explicit width and no margin-right incorrectly
+                       // gets computed margin-right based on width of container (#3333)
+                       // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+                       contents = div.appendChild( document.createElement( "div" ) );
+
+                       // Reset CSS: box-sizing; display; margin; border; padding
+                       contents.style.cssText = div.style.cssText =
+                               // Support: Firefox<29, Android 2.3
+                               // Vendor-prefix box-sizing
+                               "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+                               "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
+                       contents.style.marginRight = contents.style.width = "0";
+                       div.style.width = "1px";
+
+                       reliableMarginRightVal =
+                               !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
+
+                       div.removeChild( contents );
+               }
+
+               // Support: IE8
+               // 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).
+               div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+               contents = div.getElementsByTagName( "td" );
+               contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
+               reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+               if ( reliableHiddenOffsetsVal ) {
+                       contents[ 0 ].style.display = "";
+                       contents[ 1 ].style.display = "none";
+                       reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+               }
+
+               body.removeChild( container );
+       }
+
+})();
+
+
+// A method for quickly swapping in/out CSS properties to get correct calculations.
+jQuery.swap = function( elem, options, callback, args ) {
+       var ret, name,
+               old = {};
+
+       // Remember the old values, and insert the new ones
+       for ( name in options ) {
+               old[ name ] = elem.style[ name ];
+               elem.style[ name ] = options[ name ];
+       }
+
+       ret = callback.apply( elem, args || [] );
+
+       // Revert the old values
+       for ( name in options ) {
+               elem.style[ name ] = old[ name ];
+       }
+
+       return ret;
+};
+
+
+var
+               ralpha = /alpha\([^)]*\)/i,
+       ropacity = /opacity\s*=\s*([^)]*)/,
+
+       // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+       // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+       rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+       rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
+       rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
+
+       cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+       cssNormalTransform = {
+               letterSpacing: "0",
+               fontWeight: "400"
        },
 
-       cleanData: function( elems ) {
-               var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
-                       deleteExpando = jQuery.support.deleteExpando;
+       cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
 
-               for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
-                       if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
-                               continue;
-                       }
 
-                       id = elem[ jQuery.expando ];
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
 
-                       if ( id ) {
-                               data = cache[ id ] && cache[ id ][ internalKey ];
+       // shortcut for names that are not vendor prefixed
+       if ( name in style ) {
+               return name;
+       }
 
-                               if ( data && data.events ) {
-                                       for ( var type in data.events ) {
-                                               if ( special[ type ] ) {
-                                                       jQuery.event.remove( elem, type );
+       // check for vendor prefixed names
+       var capName = name.charAt(0).toUpperCase() + name.slice(1),
+               origName = name,
+               i = cssPrefixes.length;
 
-                                               // This is a shortcut to avoid jQuery.event.remove's overhead
-                                               } else {
-                                                       jQuery.removeEvent( elem, type, data.handle );
-                                               }
-                                       }
+       while ( i-- ) {
+               name = cssPrefixes[ i ] + capName;
+               if ( name in style ) {
+                       return name;
+               }
+       }
 
-                                       // Null the DOM reference to avoid IE6/7/8 leak (#7054)
-                                       if ( data.handle ) {
-                                               data.handle.elem = null;
-                                       }
-                               }
+       return origName;
+}
 
-                               if ( deleteExpando ) {
-                                       delete elem[ jQuery.expando ];
+function showHide( elements, show ) {
+       var display, elem, hidden,
+               values = [],
+               index = 0,
+               length = elements.length;
 
-                               } else if ( elem.removeAttribute ) {
-                                       elem.removeAttribute( jQuery.expando );
-                               }
+       for ( ; index < length; index++ ) {
+               elem = elements[ index ];
+               if ( !elem.style ) {
+                       continue;
+               }
+
+               values[ index ] = jQuery._data( elem, "olddisplay" );
+               display = elem.style.display;
+               if ( show ) {
+                       // Reset the inline display of this element to learn if it is
+                       // being hidden by cascaded rules or not
+                       if ( !values[ index ] && display === "none" ) {
+                               elem.style.display = "";
+                       }
+
+                       // Set elements which have been overridden with display: none
+                       // in a stylesheet to whatever the default browser style is
+                       // for such an element
+                       if ( elem.style.display === "" && isHidden( elem ) ) {
+                               values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+                       }
+               } else {
+                       hidden = isHidden( elem );
 
-                               delete cache[ id ];
+                       if ( display && display !== "none" || !hidden ) {
+                               jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
                        }
                }
        }
-});
 
-function evalScript( i, elem ) {
-       if ( elem.src ) {
-               jQuery.ajax({
-                       url: elem.src,
-                       async: false,
-                       dataType: "script"
-               });
-       } else {
-               jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+       // Set the display of most of the elements in a second loop
+       // to avoid the constant reflow
+       for ( index = 0; index < length; index++ ) {
+               elem = elements[ index ];
+               if ( !elem.style ) {
+                       continue;
+               }
+               if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+                       elem.style.display = show ? values[ index ] || "" : "none";
+               }
        }
 
-       if ( elem.parentNode ) {
-               elem.parentNode.removeChild( elem );
-       }
+       return elements;
 }
 
+function setPositiveNumber( elem, value, subtract ) {
+       var matches = rnumsplit.exec( value );
+       return matches ?
+               // Guard against undefined "subtract", e.g., when used as in cssHooks
+               Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+               value;
+}
 
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+       var i = extra === ( isBorderBox ? "border" : "content" ) ?
+               // If we already have the right measurement, avoid augmentation
+               4 :
+               // Otherwise initialize for horizontal or vertical properties
+               name === "width" ? 1 : 0,
 
+               val = 0;
 
-var ralpha = /alpha\([^)]*\)/i,
-       ropacity = /opacity=([^)]*)/,
-       rdashAlpha = /-([a-z])/ig,
-       // fixed for IE9, see #8346
-       rupper = /([A-Z]|^ms)/g,
-       rnumpx = /^-?\d+(?:px)?$/i,
-       rnum = /^-?\d/,
-       rrelNum = /^[+\-]=/,
-       rrelNumFilter = /[^+\-\.\de]+/g,
+       for ( ; i < 4; i += 2 ) {
+               // both box models exclude margin, so add it if we want it
+               if ( extra === "margin" ) {
+                       val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+               }
 
-       cssShow = { position: "absolute", visibility: "hidden", display: "block" },
-       cssWidth = [ "Left", "Right" ],
-       cssHeight = [ "Top", "Bottom" ],
-       curCSS,
+               if ( isBorderBox ) {
+                       // border-box includes padding, so remove it if we want content
+                       if ( extra === "content" ) {
+                               val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+                       }
 
-       getComputedStyle,
-       currentStyle,
+                       // at this point, extra isn't border nor margin, so remove border
+                       if ( extra !== "margin" ) {
+                               val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+                       }
+               } else {
+                       // at this point, extra isn't content, so add padding
+                       val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
 
-       fcamelCase = function( all, letter ) {
-               return letter.toUpperCase();
-       };
+                       // at this point, extra isn't content nor padding, so add border
+                       if ( extra !== "padding" ) {
+                               val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+                       }
+               }
+       }
 
-jQuery.fn.css = function( name, value ) {
-       // Setting 'undefined' is a no-op
-       if ( arguments.length === 2 && value === undefined ) {
-               return this;
+       return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+       // Start with offset property, which is equivalent to the border-box value
+       var valueIsBorderBox = true,
+               val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+               styles = getStyles( elem ),
+               isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+       // some non-html elements return undefined for offsetWidth, so check for null/undefined
+       // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+       // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+       if ( val <= 0 || val == null ) {
+               // Fall back to computed then uncomputed css if necessary
+               val = curCSS( elem, name, styles );
+               if ( val < 0 || val == null ) {
+                       val = elem.style[ name ];
+               }
+
+               // Computed unit is not pixels. Stop here and return.
+               if ( rnumnonpx.test(val) ) {
+                       return val;
+               }
+
+               // we need the check for style in case a browser which returns unreliable values
+               // for getComputedStyle silently falls back to the reliable elem.style
+               valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+               // Normalize "", auto, and prepare for extra
+               val = parseFloat( val ) || 0;
        }
 
-       return jQuery.access( this, name, value, true, function( elem, name, value ) {
-               return value !== undefined ?
-                       jQuery.style( elem, name, value ) :
-                       jQuery.css( elem, name );
-       });
-};
+       // use the active box-sizing model to add/subtract irrelevant styles
+       return ( val +
+               augmentWidthOrHeight(
+                       elem,
+                       name,
+                       extra || ( isBorderBox ? "border" : "content" ),
+                       valueIsBorderBox,
+                       styles
+               )
+       ) + "px";
+}
 
 jQuery.extend({
        // Add in style property hooks for overriding the default
@@ -6176,32 +6639,34 @@ jQuery.extend({
                        get: function( elem, computed ) {
                                if ( computed ) {
                                        // We should always get a number back from opacity
-                                       var ret = curCSS( elem, "opacity", "opacity" );
+                                       var ret = curCSS( elem, "opacity" );
                                        return ret === "" ? "1" : ret;
-
-                               } else {
-                                       return elem.style.opacity;
                                }
                        }
                }
        },
 
-       // Exclude the following css properties to add px
+       // Don't automatically add "px" to these possibly-unitless properties
        cssNumber: {
-               "zIndex": true,
+               "columnCount": true,
+               "fillOpacity": true,
+               "flexGrow": true,
+               "flexShrink": true,
                "fontWeight": true,
-               "opacity": true,
-               "zoom": true,
                "lineHeight": true,
+               "opacity": true,
+               "order": true,
+               "orphans": true,
                "widows": true,
-               "orphans": true
+               "zIndex": true,
+               "zoom": true
        },
 
        // Add in properties whose names you wish to fix before
        // setting or getting the value
        cssProps: {
                // normalize float css property
-               "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+               "float": support.cssFloat ? "cssFloat" : "styleFloat"
        },
 
        // Get and set the style property on a DOM Node
@@ -6212,23 +6677,30 @@ jQuery.extend({
                }
 
                // Make sure that we're working with the right name
-               var ret, type, origName = jQuery.camelCase( name ),
-                       style = elem.style, hooks = jQuery.cssHooks[ origName ];
+               var ret, type, hooks,
+                       origName = jQuery.camelCase( name ),
+                       style = elem.style;
 
-               name = jQuery.cssProps[ origName ] || origName;
+               name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+               // gets hook for the prefixed version
+               // followed by the unprefixed version
+               hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
 
                // Check if we're setting a value
                if ( value !== undefined ) {
                        type = typeof value;
 
-                       // Make sure that NaN and null values aren't set. See: #7116
-                       if ( type === "number" && isNaN( value ) || value == null ) {
-                               return;
+                       // convert relative number strings (+= or -=) to relative numbers. #7345
+                       if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+                               value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+                               // Fixes bug #9237
+                               type = "number";
                        }
 
-                       // convert relative number strings (+= or -=) to relative numbers. #7345
-                       if ( type === "string" && rrelNum.test( value ) ) {
-                               value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) );
+                       // Make sure that null and NaN values aren't set. See: #7116
+                       if ( value == null || value !== value ) {
+                               return;
                        }
 
                        // If a number was passed in, add 'px' to the (except for certain CSS properties)
@@ -6236,10 +6708,17 @@ jQuery.extend({
                                value += "px";
                        }
 
+                       // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+                       // but it would mean to define eight (for every problematic property) identical functions
+                       if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+                               style[ name ] = "inherit";
+                       }
+
                        // If a hook was provided, use that value, otherwise just set the specified value
-                       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
-                               // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
-                               // Fixes bug #5509
+                       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+                               // Support: IE
+                               // Swallow errors from 'invalid' CSS values (#5509)
                                try {
                                        style[ name ] = value;
                                } catch(e) {}
@@ -6256,135 +6735,107 @@ jQuery.extend({
                }
        },
 
-       css: function( elem, name, extra ) {
-               var ret, hooks;
+       css: function( elem, name, extra, styles ) {
+               var num, val, hooks,
+                       origName = jQuery.camelCase( name );
 
                // Make sure that we're working with the right name
-               name = jQuery.camelCase( name );
-               hooks = jQuery.cssHooks[ name ];
-               name = jQuery.cssProps[ name ] || name;
+               name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
 
-               // cssFloat needs a special treatment
-               if ( name === "cssFloat" ) {
-                       name = "float";
-               }
+               // gets hook for the prefixed version
+               // followed by the unprefixed version
+               hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
 
                // If a hook was provided get the computed value from there
-               if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
-                       return ret;
+               if ( hooks && "get" in hooks ) {
+                       val = hooks.get( elem, true, extra );
+               }
 
                // Otherwise, if a way to get the computed value exists, use that
-               } else if ( curCSS ) {
-                       return curCSS( elem, name );
+               if ( val === undefined ) {
+                       val = curCSS( elem, name, styles );
                }
-       },
 
-       // A method for quickly swapping in/out CSS properties to get correct calculations
-       swap: function( elem, options, callback ) {
-               var old = {};
-
-               // Remember the old values, and insert the new ones
-               for ( var name in options ) {
-                       old[ name ] = elem.style[ name ];
-                       elem.style[ name ] = options[ name ];
+               //convert "normal" to computed value
+               if ( val === "normal" && name in cssNormalTransform ) {
+                       val = cssNormalTransform[ name ];
                }
 
-               callback.call( elem );
-
-               // Revert the old values
-               for ( name in options ) {
-                       elem.style[ name ] = old[ name ];
+               // Return, converting to number if forced or a qualifier was provided and val looks numeric
+               if ( extra === "" || extra ) {
+                       num = parseFloat( val );
+                       return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
                }
-       },
-
-       camelCase: function( string ) {
-               return string.replace( rdashAlpha, fcamelCase );
+               return val;
        }
 });
 
-// DEPRECATED, Use jQuery.css() instead
-jQuery.curCSS = jQuery.css;
-
-jQuery.each(["height", "width"], function( i, name ) {
+jQuery.each([ "height", "width" ], function( i, name ) {
        jQuery.cssHooks[ name ] = {
                get: function( elem, computed, extra ) {
-                       var val;
-
                        if ( computed ) {
-                               if ( elem.offsetWidth !== 0 ) {
-                                       val = getWH( elem, name, extra );
-
-                               } else {
+                               // certain elements can have dimension info if we invisibly show them
+                               // however, it must have a current display style that would benefit from this
+                               return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
                                        jQuery.swap( elem, cssShow, function() {
-                                               val = getWH( elem, name, extra );
-                                       });
-                               }
-
-                               if ( val <= 0 ) {
-                                       val = curCSS( elem, name, name );
-
-                                       if ( val === "0px" && currentStyle ) {
-                                               val = currentStyle( elem, name, name );
-                                       }
-
-                                       if ( val != null ) {
-                                               // Should return "auto" instead of 0, use 0 for
-                                               // temporary backwards-compat
-                                               return val === "" || val === "auto" ? "0px" : val;
-                                       }
-                               }
-
-                               if ( val < 0 || val == null ) {
-                                       val = elem.style[ name ];
-
-                                       // Should return "auto" instead of 0, use 0 for
-                                       // temporary backwards-compat
-                                       return val === "" || val === "auto" ? "0px" : val;
-                               }
-
-                               return typeof val === "string" ? val : val + "px";
+                                               return getWidthOrHeight( elem, name, extra );
+                                       }) :
+                                       getWidthOrHeight( elem, name, extra );
                        }
                },
 
-               set: function( elem, value ) {
-                       if ( rnumpx.test( value ) ) {
-                               // ignore negative width and height values #1599
-                               value = parseFloat(value);
-
-                               if ( value >= 0 ) {
-                                       return value + "px";
-                               }
-
-                       } else {
-                               return value;
-                       }
+               set: function( elem, value, extra ) {
+                       var styles = extra && getStyles( elem );
+                       return setPositiveNumber( elem, value, extra ?
+                               augmentWidthOrHeight(
+                                       elem,
+                                       name,
+                                       extra,
+                                       support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+                                       styles
+                               ) : 0
+                       );
                }
        };
 });
 
-if ( !jQuery.support.opacity ) {
+if ( !support.opacity ) {
        jQuery.cssHooks.opacity = {
                get: function( elem, computed ) {
                        // IE uses filters for opacity
                        return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
-                               ( parseFloat( RegExp.$1 ) / 100 ) + "" :
+                               ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
                                computed ? "1" : "";
                },
 
                set: function( elem, value ) {
                        var style = elem.style,
-                               currentStyle = elem.currentStyle;
+                               currentStyle = elem.currentStyle,
+                               opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+                               filter = currentStyle && currentStyle.filter || style.filter || "";
 
                        // IE has trouble with opacity if it does not have layout
                        // Force it by setting the zoom level
                        style.zoom = 1;
 
-                       // Set the alpha filter to set the opacity
-                       var opacity = jQuery.isNaN( value ) ?
-                               "" :
-                               "alpha(opacity=" + value * 100 + ")",
-                               filter = currentStyle && currentStyle.filter || style.filter || "";
+                       // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+                       // if value === "", then remove inline opacity #12685
+                       if ( ( value >= 1 || value === "" ) &&
+                                       jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+                                       style.removeAttribute ) {
+
+                               // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+                               // if "filter:" is present at all, clearType is disabled, we want to avoid this
+                               // style.removeAttribute is IE Only, but so apparently is this code path...
+                               style.removeAttribute( "filter" );
+
+                               // if there is no filter style applied in a css rule or unset inline opacity, we are done
+                               if ( value === "" || currentStyle && !currentStyle.filter ) {
+                                       return;
+                               }
+                       }
 
+                       // otherwise, set new filter values
                        style.filter = ralpha.test( filter ) ?
                                filter.replace( ralpha, opacity ) :
                                filter + " " + opacity;
@@ -6392,431 +6843,2036 @@ if ( !jQuery.support.opacity ) {
        };
 }
 
-jQuery(function() {
-       // This hook cannot be added until DOM ready because the support test
-       // for it is not run until after DOM ready
-       if ( !jQuery.support.reliableMarginRight ) {
-               jQuery.cssHooks.marginRight = {
-                       get: function( elem, computed ) {
-                               // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
-                               // Work around by temporarily setting element display to inline-block
-                               var ret;
-                               jQuery.swap( elem, { "display": "inline-block" }, function() {
-                                       if ( computed ) {
-                                               ret = curCSS( elem, "margin-right", "marginRight" );
-                                       } else {
-                                               ret = elem.style.marginRight;
-                                       }
-                               });
-                               return ret;
-                       }
-               };
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+       function( elem, computed ) {
+               if ( computed ) {
+                       // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+                       // Work around by temporarily setting element display to inline-block
+                       return jQuery.swap( elem, { "display": "inline-block" },
+                               curCSS, [ elem, "marginRight" ] );
+               }
        }
-});
-
-if ( document.defaultView && document.defaultView.getComputedStyle ) {
-       getComputedStyle = function( elem, name ) {
-               var ret, defaultView, computedStyle;
+);
 
-               name = name.replace( rupper, "-$1" ).toLowerCase();
+// These hooks are used by animate to expand properties
+jQuery.each({
+       margin: "",
+       padding: "",
+       border: "Width"
+}, function( prefix, suffix ) {
+       jQuery.cssHooks[ prefix + suffix ] = {
+               expand: function( value ) {
+                       var i = 0,
+                               expanded = {},
 
-               if ( !(defaultView = elem.ownerDocument.defaultView) ) {
-                       return undefined;
-               }
+                               // assumes a single number if not a string
+                               parts = typeof value === "string" ? value.split(" ") : [ value ];
 
-               if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
-                       ret = computedStyle.getPropertyValue( name );
-                       if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
-                               ret = jQuery.style( elem, name );
+                       for ( ; i < 4; i++ ) {
+                               expanded[ prefix + cssExpand[ i ] + suffix ] =
+                                       parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
                        }
-               }
 
-               return ret;
+                       return expanded;
+               }
        };
-}
 
-if ( document.documentElement.currentStyle ) {
-       currentStyle = function( elem, name ) {
-               var left,
-                       ret = elem.currentStyle && elem.currentStyle[ name ],
-                       rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
-                       style = elem.style;
+       if ( !rmargin.test( prefix ) ) {
+               jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+       }
+});
 
-               // From the awesome hack by Dean Edwards
-               // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+jQuery.fn.extend({
+       css: function( name, value ) {
+               return access( this, function( elem, name, value ) {
+                       var styles, len,
+                               map = {},
+                               i = 0;
 
-               // If we're not dealing with a regular pixel number
-               // but a number that has a weird ending, we need to convert it to pixels
-               if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
-                       // Remember the original values
-                       left = style.left;
+                       if ( jQuery.isArray( name ) ) {
+                               styles = getStyles( elem );
+                               len = name.length;
 
-                       // Put in the new values to get a computed value out
-                       if ( rsLeft ) {
-                               elem.runtimeStyle.left = elem.currentStyle.left;
-                       }
-                       style.left = name === "fontSize" ? "1em" : (ret || 0);
-                       ret = style.pixelLeft + "px";
+                               for ( ; i < len; i++ ) {
+                                       map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+                               }
 
-                       // Revert the changed values
-                       style.left = left;
-                       if ( rsLeft ) {
-                               elem.runtimeStyle.left = rsLeft;
+                               return map;
                        }
+
+                       return value !== undefined ?
+                               jQuery.style( elem, name, value ) :
+                               jQuery.css( elem, name );
+               }, name, value, arguments.length > 1 );
+       },
+       show: function() {
+               return showHide( this, true );
+       },
+       hide: function() {
+               return showHide( this );
+       },
+       toggle: function( state ) {
+               if ( typeof state === "boolean" ) {
+                       return state ? this.show() : this.hide();
                }
 
-               return ret === "" ? "auto" : ret;
-       };
-}
+               return this.each(function() {
+                       if ( isHidden( this ) ) {
+                               jQuery( this ).show();
+                       } else {
+                               jQuery( this ).hide();
+                       }
+               });
+       }
+});
 
-curCSS = getComputedStyle || currentStyle;
 
-function getWH( elem, name, extra ) {
-       var which = name === "width" ? cssWidth : cssHeight,
-               val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
+function Tween( elem, options, prop, end, easing ) {
+       return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
 
-       if ( extra === "border" ) {
-               return val;
-       }
+Tween.prototype = {
+       constructor: Tween,
+       init: function( elem, options, prop, end, easing, unit ) {
+               this.elem = elem;
+               this.prop = prop;
+               this.easing = easing || "swing";
+               this.options = options;
+               this.start = this.now = this.cur();
+               this.end = end;
+               this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+       },
+       cur: function() {
+               var hooks = Tween.propHooks[ this.prop ];
+
+               return hooks && hooks.get ?
+                       hooks.get( this ) :
+                       Tween.propHooks._default.get( this );
+       },
+       run: function( percent ) {
+               var eased,
+                       hooks = Tween.propHooks[ this.prop ];
 
-       jQuery.each( which, function() {
-               if ( !extra ) {
-                       val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
+               if ( this.options.duration ) {
+                       this.pos = eased = jQuery.easing[ this.easing ](
+                               percent, this.options.duration * percent, 0, 1, this.options.duration
+                       );
+               } else {
+                       this.pos = eased = percent;
                }
+               this.now = ( this.end - this.start ) * eased + this.start;
 
-               if ( extra === "margin" ) {
-                       val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
+               if ( this.options.step ) {
+                       this.options.step.call( this.elem, this.now, this );
+               }
 
+               if ( hooks && hooks.set ) {
+                       hooks.set( this );
                } else {
-                       val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
+                       Tween.propHooks._default.set( this );
                }
-       });
+               return this;
+       }
+};
 
-       return val;
-}
+Tween.prototype.init.prototype = Tween.prototype;
 
-if ( jQuery.expr && jQuery.expr.filters ) {
-       jQuery.expr.filters.hidden = function( elem ) {
-               var width = elem.offsetWidth,
-                       height = elem.offsetHeight;
+Tween.propHooks = {
+       _default: {
+               get: function( tween ) {
+                       var result;
 
-               return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
-       };
+                       if ( tween.elem[ tween.prop ] != null &&
+                               (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+                               return tween.elem[ tween.prop ];
+                       }
 
-       jQuery.expr.filters.visible = function( elem ) {
-               return !jQuery.expr.filters.hidden( elem );
-       };
-}
+                       // passing an empty string as a 3rd parameter to .css will automatically
+                       // attempt a parseFloat and fallback to a string if the parse fails
+                       // so, simple values such as "10px" are parsed to Float.
+                       // complex values such as "rotate(1rad)" are returned as is.
+                       result = jQuery.css( tween.elem, tween.prop, "" );
+                       // Empty strings, null, undefined and "auto" are converted to 0.
+                       return !result || result === "auto" ? 0 : result;
+               },
+               set: function( tween ) {
+                       // use step hook for back compat - use cssHook if its there - use .style if its
+                       // available and use plain properties where available
+                       if ( jQuery.fx.step[ tween.prop ] ) {
+                               jQuery.fx.step[ tween.prop ]( tween );
+                       } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+                               jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+                       } else {
+                               tween.elem[ tween.prop ] = tween.now;
+                       }
+               }
+       }
+};
 
+// Support: IE <=9
+// Panic based approach to setting things on disconnected nodes
 
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+       set: function( tween ) {
+               if ( tween.elem.nodeType && tween.elem.parentNode ) {
+                       tween.elem[ tween.prop ] = tween.now;
+               }
+       }
+};
 
+jQuery.easing = {
+       linear: function( p ) {
+               return p;
+       },
+       swing: function( p ) {
+               return 0.5 - Math.cos( p * Math.PI ) / 2;
+       }
+};
 
-var r20 = /%20/g,
-       rbracket = /\[\]$/,
-       rCRLF = /\r?\n/g,
-       rhash = /#.*$/,
-       rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
-       rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
-       // #7653, #8125, #8152: local protocol detection
-       rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/,
-       rnoContent = /^(?:GET|HEAD)$/,
-       rprotocol = /^\/\//,
-       rquery = /\?/,
-       rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
-       rselectTextarea = /^(?:select|textarea)/i,
-       rspacesAjax = /\s+/,
-       rts = /([?&])_=[^&]*/,
-       rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
+jQuery.fx = Tween.prototype.init;
 
-       // Keep a copy of the old load method
-       _load = jQuery.fn.load,
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
 
-       /* Prefilters
-        * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
-        * 2) These are called:
-        *    - BEFORE asking for a transport
-        *    - AFTER param serialization (s.data is a string if s.processData is true)
-        * 3) key is the dataType
-        * 4) the catchall symbol "*" can be used
-        * 5) execution will start with transport dataType and THEN continue down to "*" if needed
-        */
-       prefilters = {},
 
-       /* Transports bindings
-        * 1) key is the dataType
-        * 2) the catchall symbol "*" can be used
-        * 3) selection will start with transport dataType and THEN go to "*" if needed
-        */
-       transports = {},
 
-       // Document location
-       ajaxLocation,
 
-       // Document location segments
-       ajaxLocParts;
+var
+       fxNow, timerId,
+       rfxtypes = /^(?:toggle|show|hide)$/,
+       rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
+       rrun = /queueHooks$/,
+       animationPrefilters = [ defaultPrefilter ],
+       tweeners = {
+               "*": [ function( prop, value ) {
+                       var tween = this.createTween( prop, value ),
+                               target = tween.cur(),
+                               parts = rfxnum.exec( value ),
+                               unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+                               // Starting value computation is required for potential unit mismatches
+                               start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+                                       rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+                               scale = 1,
+                               maxIterations = 20;
+
+                       if ( start && start[ 3 ] !== unit ) {
+                               // Trust units reported by jQuery.css
+                               unit = unit || start[ 3 ];
+
+                               // Make sure we update the tween properties later on
+                               parts = parts || [];
+
+                               // Iteratively approximate from a nonzero starting point
+                               start = +target || 1;
+
+                               do {
+                                       // If previous iteration zeroed out, double until we get *something*
+                                       // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+                                       scale = scale || ".5";
+
+                                       // Adjust and apply
+                                       start = start / scale;
+                                       jQuery.style( tween.elem, prop, start + unit );
+
+                               // Update scale, tolerating zero or NaN from tween.cur()
+                               // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+                               } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+                       }
+
+                       // Update tween properties
+                       if ( parts ) {
+                               start = tween.start = +start || +target || 0;
+                               tween.unit = unit;
+                               // If a +=/-= token was provided, we're doing a relative animation
+                               tween.end = parts[ 1 ] ?
+                                       start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+                                       +parts[ 2 ];
+                       }
+
+                       return tween;
+               } ]
+       };
 
-// #8138, IE may throw an exception when accessing
-// a field from window.location if document.domain has been set
-try {
-       ajaxLocation = location.href;
-} catch( e ) {
-       // Use the href attribute of an A element
-       // since IE will modify it given document.location
-       ajaxLocation = document.createElement( "a" );
-       ajaxLocation.href = "";
-       ajaxLocation = ajaxLocation.href;
+// Animations created synchronously will run synchronously
+function createFxNow() {
+       setTimeout(function() {
+               fxNow = undefined;
+       });
+       return ( fxNow = jQuery.now() );
 }
 
-// Segment location into parts
-ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+       var which,
+               attrs = { height: type },
+               i = 0;
+
+       // if we include width, step value is 1 to do all cssExpand values,
+       // if we don't include width, step value is 2 to skip over Left and Right
+       includeWidth = includeWidth ? 1 : 0;
+       for ( ; i < 4 ; i += 2 - includeWidth ) {
+               which = cssExpand[ i ];
+               attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+       }
 
-// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
-function addToPrefiltersOrTransports( structure ) {
+       if ( includeWidth ) {
+               attrs.opacity = attrs.width = type;
+       }
 
-       // dataTypeExpression is optional and defaults to "*"
-       return function( dataTypeExpression, func ) {
+       return attrs;
+}
 
-               if ( typeof dataTypeExpression !== "string" ) {
-                       func = dataTypeExpression;
-                       dataTypeExpression = "*";
-               }
+function createTween( value, prop, animation ) {
+       var tween,
+               collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+               index = 0,
+               length = collection.length;
+       for ( ; index < length; index++ ) {
+               if ( (tween = collection[ index ].call( animation, prop, value )) ) {
 
-               if ( jQuery.isFunction( func ) ) {
-                       var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
-                               i = 0,
-                               length = dataTypes.length,
-                               dataType,
-                               list,
-                               placeBefore;
+                       // we're done with this property
+                       return tween;
+               }
+       }
+}
 
-                       // For each dataType in the dataTypeExpression
-                       for(; i < length; i++ ) {
-                               dataType = dataTypes[ i ];
-                               // We control if we're asked to add before
-                               // any existing element
-                               placeBefore = /^\+/.test( dataType );
-                               if ( placeBefore ) {
-                                       dataType = dataType.substr( 1 ) || "*";
+function defaultPrefilter( elem, props, opts ) {
+       /* jshint validthis: true */
+       var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+               anim = this,
+               orig = {},
+               style = elem.style,
+               hidden = elem.nodeType && isHidden( elem ),
+               dataShow = jQuery._data( elem, "fxshow" );
+
+       // handle queue: false promises
+       if ( !opts.queue ) {
+               hooks = jQuery._queueHooks( elem, "fx" );
+               if ( hooks.unqueued == null ) {
+                       hooks.unqueued = 0;
+                       oldfire = hooks.empty.fire;
+                       hooks.empty.fire = function() {
+                               if ( !hooks.unqueued ) {
+                                       oldfire();
                                }
-                               list = structure[ dataType ] = structure[ dataType ] || [];
-                               // then we add to the structure accordingly
-                               list[ placeBefore ? "unshift" : "push" ]( func );
-                       }
+                       };
                }
-       };
-}
+               hooks.unqueued++;
 
-// Base inspection function for prefilters and transports
-function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
-               dataType /* internal */, inspected /* internal */ ) {
+               anim.always(function() {
+                       // doing this makes sure that the complete handler will be called
+                       // before this completes
+                       anim.always(function() {
+                               hooks.unqueued--;
+                               if ( !jQuery.queue( elem, "fx" ).length ) {
+                                       hooks.empty.fire();
+                               }
+                       });
+               });
+       }
 
-       dataType = dataType || options.dataTypes[ 0 ];
-       inspected = inspected || {};
+       // height/width overflow pass
+       if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+               // Make sure that nothing sneaks out
+               // Record all 3 overflow attributes because IE does not
+               // change the overflow attribute when overflowX and
+               // overflowY are set to the same value
+               opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
 
-       inspected[ dataType ] = true;
+               // Set display property to inline-block for height/width
+               // animations on inline elements that are having width/height animated
+               display = jQuery.css( elem, "display" );
 
-       var list = structure[ dataType ],
-               i = 0,
-               length = list ? list.length : 0,
-               executeOnly = ( structure === prefilters ),
-               selection;
-
-       for(; i < length && ( executeOnly || !selection ); i++ ) {
-               selection = list[ i ]( options, originalOptions, jqXHR );
-               // If we got redirected to another dataType
-               // we try there if executing only and not done already
-               if ( typeof selection === "string" ) {
-                       if ( !executeOnly || inspected[ selection ] ) {
-                               selection = undefined;
+               // Test default display if display is currently "none"
+               checkDisplay = display === "none" ?
+                       jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+               if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+
+                       // inline-level elements accept inline-block;
+                       // block-level elements need to be inline with layout
+                       if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
+                               style.display = "inline-block";
                        } else {
-                               options.dataTypes.unshift( selection );
-                               selection = inspectPrefiltersOrTransports(
-                                               structure, options, originalOptions, jqXHR, selection, inspected );
+                               style.zoom = 1;
                        }
                }
        }
-       // If we're only executing or nothing was selected
-       // we try the catchall dataType if not done already
-       if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
-               selection = inspectPrefiltersOrTransports(
-                               structure, options, originalOptions, jqXHR, "*", inspected );
+
+       if ( opts.overflow ) {
+               style.overflow = "hidden";
+               if ( !support.shrinkWrapBlocks() ) {
+                       anim.always(function() {
+                               style.overflow = opts.overflow[ 0 ];
+                               style.overflowX = opts.overflow[ 1 ];
+                               style.overflowY = opts.overflow[ 2 ];
+                       });
+               }
        }
-       // unnecessary when only executing (prefilters)
-       // but it'll be ignored by the caller in that case
-       return selection;
-}
 
-jQuery.fn.extend({
-       load: function( url, params, callback ) {
-               if ( typeof url !== "string" && _load ) {
-                       return _load.apply( this, arguments );
+       // show/hide pass
+       for ( prop in props ) {
+               value = props[ prop ];
+               if ( rfxtypes.exec( value ) ) {
+                       delete props[ prop ];
+                       toggle = toggle || value === "toggle";
+                       if ( value === ( hidden ? "hide" : "show" ) ) {
+
+                               // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+                               if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+                                       hidden = true;
+                               } else {
+                                       continue;
+                               }
+                       }
+                       orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
 
-               // Don't do a request if no elements are being requested
-               } else if ( !this.length ) {
-                       return this;
+               // Any non-fx value stops us from restoring the original display value
+               } else {
+                       display = undefined;
+               }
+       }
+
+       if ( !jQuery.isEmptyObject( orig ) ) {
+               if ( dataShow ) {
+                       if ( "hidden" in dataShow ) {
+                               hidden = dataShow.hidden;
+                       }
+               } else {
+                       dataShow = jQuery._data( elem, "fxshow", {} );
+               }
+
+               // store state if its toggle - enables .stop().toggle() to "reverse"
+               if ( toggle ) {
+                       dataShow.hidden = !hidden;
+               }
+               if ( hidden ) {
+                       jQuery( elem ).show();
+               } else {
+                       anim.done(function() {
+                               jQuery( elem ).hide();
+                       });
                }
+               anim.done(function() {
+                       var prop;
+                       jQuery._removeData( elem, "fxshow" );
+                       for ( prop in orig ) {
+                               jQuery.style( elem, prop, orig[ prop ] );
+                       }
+               });
+               for ( prop in orig ) {
+                       tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+                       if ( !( prop in dataShow ) ) {
+                               dataShow[ prop ] = tween.start;
+                               if ( hidden ) {
+                                       tween.end = tween.start;
+                                       tween.start = prop === "width" || prop === "height" ? 1 : 0;
+                               }
+                       }
+               }
+
+       // If this is a noop like .hide().hide(), restore an overwritten display value
+       } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
+               style.display = display;
+       }
+}
+
+function propFilter( props, specialEasing ) {
+       var index, name, easing, value, hooks;
 
-               var off = url.indexOf( " " );
-               if ( off >= 0 ) {
-                       var selector = url.slice( off, url.length );
-                       url = url.slice( 0, off );
+       // camelCase, specialEasing and expand cssHook pass
+       for ( index in props ) {
+               name = jQuery.camelCase( index );
+               easing = specialEasing[ name ];
+               value = props[ index ];
+               if ( jQuery.isArray( value ) ) {
+                       easing = value[ 1 ];
+                       value = props[ index ] = value[ 0 ];
                }
 
-               // Default to a GET request
-               var type = "GET";
+               if ( index !== name ) {
+                       props[ name ] = value;
+                       delete props[ index ];
+               }
 
-               // If the second parameter was provided
-               if ( params ) {
-                       // If it's a function
-                       if ( jQuery.isFunction( params ) ) {
-                               // We assume that it's the callback
-                               callback = params;
-                               params = undefined;
+               hooks = jQuery.cssHooks[ name ];
+               if ( hooks && "expand" in hooks ) {
+                       value = hooks.expand( value );
+                       delete props[ name ];
 
-                       // Otherwise, build a param string
-                       } else if ( typeof params === "object" ) {
-                               params = jQuery.param( params, jQuery.ajaxSettings.traditional );
-                               type = "POST";
+                       // not quite $.extend, this wont overwrite keys already present.
+                       // also - reusing 'index' from above because we have the correct "name"
+                       for ( index in value ) {
+                               if ( !( index in props ) ) {
+                                       props[ index ] = value[ index ];
+                                       specialEasing[ index ] = easing;
+                               }
                        }
+               } else {
+                       specialEasing[ name ] = easing;
                }
+       }
+}
 
-               var self = this;
+function Animation( elem, properties, options ) {
+       var result,
+               stopped,
+               index = 0,
+               length = animationPrefilters.length,
+               deferred = jQuery.Deferred().always( function() {
+                       // don't match elem in the :animated selector
+                       delete tick.elem;
+               }),
+               tick = function() {
+                       if ( stopped ) {
+                               return false;
+                       }
+                       var currentTime = fxNow || createFxNow(),
+                               remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+                               // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+                               temp = remaining / animation.duration || 0,
+                               percent = 1 - temp,
+                               index = 0,
+                               length = animation.tweens.length;
 
-               // Request the remote document
-               jQuery.ajax({
-                       url: url,
-                       type: type,
-                       dataType: "html",
-                       data: params,
-                       // Complete callback (responseText is used internally)
-                       complete: function( jqXHR, status, responseText ) {
-                               // Store the response as specified by the jqXHR object
-                               responseText = jqXHR.responseText;
-                               // If successful, inject the HTML into all the matched elements
-                               if ( jqXHR.isResolved() ) {
-                                       // #4825: Get the actual response in case
-                                       // a dataFilter is present in ajaxSettings
-                                       jqXHR.done(function( r ) {
-                                               responseText = r;
-                                       });
-                                       // See if a selector was specified
-                                       self.html( selector ?
-                                               // Create a dummy div to hold the results
-                                               jQuery("<div>")
-                                                       // inject the contents of the document in, removing the scripts
-                                                       // to avoid any 'Permission Denied' errors in IE
-                                                       .append(responseText.replace(rscript, ""))
-
-                                                       // Locate the specified elements
-                                                       .find(selector) :
-
-                                               // If not, just inject the full result
-                                               responseText );
+                       for ( ; index < length ; index++ ) {
+                               animation.tweens[ index ].run( percent );
+                       }
+
+                       deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+                       if ( percent < 1 && length ) {
+                               return remaining;
+                       } else {
+                               deferred.resolveWith( elem, [ animation ] );
+                               return false;
+                       }
+               },
+               animation = deferred.promise({
+                       elem: elem,
+                       props: jQuery.extend( {}, properties ),
+                       opts: jQuery.extend( true, { specialEasing: {} }, options ),
+                       originalProperties: properties,
+                       originalOptions: options,
+                       startTime: fxNow || createFxNow(),
+                       duration: options.duration,
+                       tweens: [],
+                       createTween: function( prop, end ) {
+                               var tween = jQuery.Tween( elem, animation.opts, prop, end,
+                                               animation.opts.specialEasing[ prop ] || animation.opts.easing );
+                               animation.tweens.push( tween );
+                               return tween;
+                       },
+                       stop: function( gotoEnd ) {
+                               var index = 0,
+                                       // if we are going to the end, we want to run all the tweens
+                                       // otherwise we skip this part
+                                       length = gotoEnd ? animation.tweens.length : 0;
+                               if ( stopped ) {
+                                       return this;
+                               }
+                               stopped = true;
+                               for ( ; index < length ; index++ ) {
+                                       animation.tweens[ index ].run( 1 );
                                }
 
-                               if ( callback ) {
-                                       self.each( callback, [ responseText, status, jqXHR ] );
+                               // resolve when we played the last frame
+                               // otherwise, reject
+                               if ( gotoEnd ) {
+                                       deferred.resolveWith( elem, [ animation, gotoEnd ] );
+                               } else {
+                                       deferred.rejectWith( elem, [ animation, gotoEnd ] );
                                }
+                               return this;
                        }
-               });
+               }),
+               props = animation.props;
 
-               return this;
-       },
+       propFilter( props, animation.opts.specialEasing );
 
-       serialize: function() {
-               return jQuery.param( this.serializeArray() );
-       },
+       for ( ; index < length ; index++ ) {
+               result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+               if ( result ) {
+                       return result;
+               }
+       }
 
-       serializeArray: function() {
-               return this.map(function(){
-                       return this.elements ? jQuery.makeArray( this.elements ) : this;
-               })
-               .filter(function(){
-                       return this.name && !this.disabled &&
-                               ( this.checked || rselectTextarea.test( this.nodeName ) ||
-                                       rinput.test( this.type ) );
+       jQuery.map( props, createTween, animation );
+
+       if ( jQuery.isFunction( animation.opts.start ) ) {
+               animation.opts.start.call( elem, animation );
+       }
+
+       jQuery.fx.timer(
+               jQuery.extend( tick, {
+                       elem: elem,
+                       anim: animation,
+                       queue: animation.opts.queue
                })
-               .map(function( i, elem ){
-                       var val = jQuery( this ).val();
+       );
 
-                       return val == null ?
-                               null :
-                               jQuery.isArray( val ) ?
-                                       jQuery.map( val, function( val, i ){
-                                               return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
-                                       }) :
-                                       { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
-               }).get();
+       // attach callbacks from options
+       return animation.progress( animation.opts.progress )
+               .done( animation.opts.done, animation.opts.complete )
+               .fail( animation.opts.fail )
+               .always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+       tweener: function( props, callback ) {
+               if ( jQuery.isFunction( props ) ) {
+                       callback = props;
+                       props = [ "*" ];
+               } else {
+                       props = props.split(" ");
+               }
+
+               var prop,
+                       index = 0,
+                       length = props.length;
+
+               for ( ; index < length ; index++ ) {
+                       prop = props[ index ];
+                       tweeners[ prop ] = tweeners[ prop ] || [];
+                       tweeners[ prop ].unshift( callback );
+               }
+       },
+
+       prefilter: function( callback, prepend ) {
+               if ( prepend ) {
+                       animationPrefilters.unshift( callback );
+               } else {
+                       animationPrefilters.push( callback );
+               }
        }
 });
 
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
-       jQuery.fn[ o ] = function( f ){
-               return this.bind( o, f );
+jQuery.speed = function( speed, easing, fn ) {
+       var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+               complete: fn || !fn && easing ||
+                       jQuery.isFunction( speed ) && speed,
+               duration: speed,
+               easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
        };
-});
 
-jQuery.each( [ "get", "post" ], function( i, method ) {
-       jQuery[ method ] = function( url, data, callback, type ) {
-               // shift arguments if data argument was omitted
-               if ( jQuery.isFunction( data ) ) {
-                       type = type || callback;
-                       callback = data;
-                       data = undefined;
+       opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+               opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+       // normalize opt.queue - true/undefined/null -> "fx"
+       if ( opt.queue == null || opt.queue === true ) {
+               opt.queue = "fx";
+       }
+
+       // Queueing
+       opt.old = opt.complete;
+
+       opt.complete = function() {
+               if ( jQuery.isFunction( opt.old ) ) {
+                       opt.old.call( this );
                }
 
-               return jQuery.ajax({
-                       type: method,
-                       url: url,
-                       data: data,
-                       success: callback,
-                       dataType: type
+               if ( opt.queue ) {
+                       jQuery.dequeue( this, opt.queue );
+               }
+       };
+
+       return opt;
+};
+
+jQuery.fn.extend({
+       fadeTo: function( speed, to, easing, callback ) {
+
+               // show any hidden elements after setting opacity to 0
+               return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+                       // animate to the value specified
+                       .end().animate({ opacity: to }, speed, easing, callback );
+       },
+       animate: function( prop, speed, easing, callback ) {
+               var empty = jQuery.isEmptyObject( prop ),
+                       optall = jQuery.speed( speed, easing, callback ),
+                       doAnimation = function() {
+                               // Operate on a copy of prop so per-property easing won't be lost
+                               var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+                               // Empty animations, or finishing resolves immediately
+                               if ( empty || jQuery._data( this, "finish" ) ) {
+                                       anim.stop( true );
+                               }
+                       };
+                       doAnimation.finish = doAnimation;
+
+               return empty || optall.queue === false ?
+                       this.each( doAnimation ) :
+                       this.queue( optall.queue, doAnimation );
+       },
+       stop: function( type, clearQueue, gotoEnd ) {
+               var stopQueue = function( hooks ) {
+                       var stop = hooks.stop;
+                       delete hooks.stop;
+                       stop( gotoEnd );
+               };
+
+               if ( typeof type !== "string" ) {
+                       gotoEnd = clearQueue;
+                       clearQueue = type;
+                       type = undefined;
+               }
+               if ( clearQueue && type !== false ) {
+                       this.queue( type || "fx", [] );
+               }
+
+               return this.each(function() {
+                       var dequeue = true,
+                               index = type != null && type + "queueHooks",
+                               timers = jQuery.timers,
+                               data = jQuery._data( this );
+
+                       if ( index ) {
+                               if ( data[ index ] && data[ index ].stop ) {
+                                       stopQueue( data[ index ] );
+                               }
+                       } else {
+                               for ( index in data ) {
+                                       if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+                                               stopQueue( data[ index ] );
+                                       }
+                               }
+                       }
+
+                       for ( index = timers.length; index--; ) {
+                               if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+                                       timers[ index ].anim.stop( gotoEnd );
+                                       dequeue = false;
+                                       timers.splice( index, 1 );
+                               }
+                       }
+
+                       // start the next in the queue if the last step wasn't forced
+                       // timers currently will call their complete callbacks, which will dequeue
+                       // but only if they were gotoEnd
+                       if ( dequeue || !gotoEnd ) {
+                               jQuery.dequeue( this, type );
+                       }
+               });
+       },
+       finish: function( type ) {
+               if ( type !== false ) {
+                       type = type || "fx";
+               }
+               return this.each(function() {
+                       var index,
+                               data = jQuery._data( this ),
+                               queue = data[ type + "queue" ],
+                               hooks = data[ type + "queueHooks" ],
+                               timers = jQuery.timers,
+                               length = queue ? queue.length : 0;
+
+                       // enable finishing flag on private data
+                       data.finish = true;
+
+                       // empty the queue first
+                       jQuery.queue( this, type, [] );
+
+                       if ( hooks && hooks.stop ) {
+                               hooks.stop.call( this, true );
+                       }
+
+                       // look for any active animations, and finish them
+                       for ( index = timers.length; index--; ) {
+                               if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+                                       timers[ index ].anim.stop( true );
+                                       timers.splice( index, 1 );
+                               }
+                       }
+
+                       // look for any animations in the old queue and finish them
+                       for ( index = 0; index < length; index++ ) {
+                               if ( queue[ index ] && queue[ index ].finish ) {
+                                       queue[ index ].finish.call( this );
+                               }
+                       }
+
+                       // turn off finishing flag
+                       delete data.finish;
+               });
+       }
+});
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+       var cssFn = jQuery.fn[ name ];
+       jQuery.fn[ name ] = function( speed, easing, callback ) {
+               return speed == null || typeof speed === "boolean" ?
+                       cssFn.apply( this, arguments ) :
+                       this.animate( genFx( name, true ), speed, easing, callback );
+       };
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+       slideDown: genFx("show"),
+       slideUp: genFx("hide"),
+       slideToggle: genFx("toggle"),
+       fadeIn: { opacity: "show" },
+       fadeOut: { opacity: "hide" },
+       fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+       jQuery.fn[ name ] = function( speed, easing, callback ) {
+               return this.animate( props, speed, easing, callback );
+       };
+});
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+       var timer,
+               timers = jQuery.timers,
+               i = 0;
+
+       fxNow = jQuery.now();
+
+       for ( ; i < timers.length; i++ ) {
+               timer = timers[ i ];
+               // Checks the timer has not already been removed
+               if ( !timer() && timers[ i ] === timer ) {
+                       timers.splice( i--, 1 );
+               }
+       }
+
+       if ( !timers.length ) {
+               jQuery.fx.stop();
+       }
+       fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+       jQuery.timers.push( timer );
+       if ( timer() ) {
+               jQuery.fx.start();
+       } else {
+               jQuery.timers.pop();
+       }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+       if ( !timerId ) {
+               timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+       }
+};
+
+jQuery.fx.stop = function() {
+       clearInterval( timerId );
+       timerId = null;
+};
+
+jQuery.fx.speeds = {
+       slow: 600,
+       fast: 200,
+       // Default speed
+       _default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+       time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+       type = type || "fx";
+
+       return this.queue( type, function( next, hooks ) {
+               var timeout = setTimeout( next, time );
+               hooks.stop = function() {
+                       clearTimeout( timeout );
+               };
+       });
+};
+
+
+(function() {
+       // Minified: var a,b,c,d,e
+       var input, div, select, a, opt;
+
+       // Setup
+       div = document.createElement( "div" );
+       div.setAttribute( "className", "t" );
+       div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+       a = div.getElementsByTagName("a")[ 0 ];
+
+       // First batch of tests.
+       select = document.createElement("select");
+       opt = select.appendChild( document.createElement("option") );
+       input = div.getElementsByTagName("input")[ 0 ];
+
+       a.style.cssText = "top:1px";
+
+       // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+       support.getSetAttribute = div.className !== "t";
+
+       // Get the style information from getAttribute
+       // (IE uses .cssText instead)
+       support.style = /top/.test( a.getAttribute("style") );
+
+       // Make sure that URLs aren't manipulated
+       // (IE normalizes it by default)
+       support.hrefNormalized = a.getAttribute("href") === "/a";
+
+       // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+       support.checkOn = !!input.value;
+
+       // 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)
+       support.optSelected = opt.selected;
+
+       // Tests for enctype support on a form (#6743)
+       support.enctype = !!document.createElement("form").enctype;
+
+       // 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;
+
+       // Support: IE8 only
+       // Check if we can trust getAttribute("value")
+       input = document.createElement( "input" );
+       input.setAttribute( "value", "" );
+       support.input = input.getAttribute( "value" ) === "";
+
+       // Check if an input maintains its value after becoming a radio
+       input.value = "t";
+       input.setAttribute( "type", "radio" );
+       support.radioValue = input.value === "t";
+})();
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend({
+       val: function( value ) {
+               var hooks, ret, isFunction,
+                       elem = this[0];
+
+               if ( !arguments.length ) {
+                       if ( elem ) {
+                               hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+                               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;
+               }
+
+               isFunction = jQuery.isFunction( value );
+
+               return this.each(function( i ) {
+                       var val;
+
+                       if ( this.nodeType !== 1 ) {
+                               return;
+                       }
+
+                       if ( isFunction ) {
+                               val = value.call( this, i, jQuery( this ).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.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+                       // 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 ) {
+                               var val = jQuery.find.attr( elem, "value" );
+                               return val != null ?
+                                       val :
+                                       // Support: IE10-11+
+                                       // option.text throws exceptions (#14686, #14858)
+                                       jQuery.trim( jQuery.text( elem ) );
+                       }
+               },
+               select: {
+                       get: function( elem ) {
+                               var value, option,
+                                       options = elem.options,
+                                       index = elem.selectedIndex,
+                                       one = elem.type === "select-one" || index < 0,
+                                       values = one ? null : [],
+                                       max = one ? index + 1 : options.length,
+                                       i = index < 0 ?
+                                               max :
+                                               one ? index : 0;
+
+                               // Loop through all the selected options
+                               for ( ; i < max; i++ ) {
+                                       option = options[ i ];
+
+                                       // oldIE doesn't update selected after form reset (#2551)
+                                       if ( ( option.selected || i === index ) &&
+                                                       // Don't return options that are disabled or in a disabled optgroup
+                                                       ( 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 );
+                                       }
+                               }
+
+                               return values;
+                       },
+
+                       set: function( elem, value ) {
+                               var optionSet, option,
+                                       options = elem.options,
+                                       values = jQuery.makeArray( value ),
+                                       i = options.length;
+
+                               while ( i-- ) {
+                                       option = options[ i ];
+
+                                       if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
+
+                                               // Support: IE6
+                                               // When new option element is added to select box we need to
+                                               // force reflow of newly added node in order to workaround delay
+                                               // of initialization properties
+                                               try {
+                                                       option.selected = optionSet = true;
+
+                                               } catch ( _ ) {
+
+                                                       // Will be executed only in IE6
+                                                       option.scrollHeight;
+                                               }
+
+                                       } else {
+                                               option.selected = false;
+                                       }
+                               }
+
+                               // Force browsers to behave consistently when non-matching value is set
+                               if ( !optionSet ) {
+                                       elem.selectedIndex = -1;
+                               }
+
+                               return options;
+                       }
+               }
+       }
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+       jQuery.valHooks[ this ] = {
+               set: function( elem, value ) {
+                       if ( jQuery.isArray( value ) ) {
+                               return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+                       }
+               }
+       };
+       if ( !support.checkOn ) {
+               jQuery.valHooks[ this ].get = function( elem ) {
+                       // Support: Webkit
+                       // "" is returned instead of "on" if a value isn't specified
+                       return elem.getAttribute("value") === null ? "on" : elem.value;
+               };
+       }
+});
+
+
+
+
+var nodeHook, boolHook,
+       attrHandle = jQuery.expr.attrHandle,
+       ruseDefault = /^(?:checked|selected)$/i,
+       getSetAttribute = support.getSetAttribute,
+       getSetInput = support.input;
+
+jQuery.fn.extend({
+       attr: function( name, value ) {
+               return access( this, jQuery.attr, name, value, arguments.length > 1 );
+       },
+
+       removeAttr: function( name ) {
+               return this.each(function() {
+                       jQuery.removeAttr( this, name );
+               });
+       }
+});
+
+jQuery.extend({
+       attr: function( elem, name, value ) {
+               var hooks, ret,
+                       nType = elem.nodeType;
+
+               // don't get/set attributes on text, comment and attribute nodes
+               if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+                       return;
+               }
+
+               // Fallback to prop when attributes are not supported
+               if ( typeof elem.getAttribute === strundefined ) {
+                       return jQuery.prop( elem, name, value );
+               }
+
+               // All attributes are lowercase
+               // Grab necessary hook if one is defined
+               if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+                       name = name.toLowerCase();
+                       hooks = jQuery.attrHooks[ name ] ||
+                               ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+               }
+
+               if ( value !== undefined ) {
+
+                       if ( value === null ) {
+                               jQuery.removeAttr( elem, name );
+
+                       } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+                               return ret;
+
+                       } else {
+                               elem.setAttribute( name, value + "" );
+                               return value;
+                       }
+
+               } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+                       return ret;
+
+               } else {
+                       ret = jQuery.find.attr( elem, name );
+
+                       // Non-existent attributes return null, we normalize to undefined
+                       return ret == null ?
+                               undefined :
+                               ret;
+               }
+       },
+
+       removeAttr: function( elem, value ) {
+               var name, propName,
+                       i = 0,
+                       attrNames = value && value.match( rnotwhite );
+
+               if ( attrNames && elem.nodeType === 1 ) {
+                       while ( (name = attrNames[i++]) ) {
+                               propName = jQuery.propFix[ name ] || name;
+
+                               // Boolean attributes get special treatment (#10870)
+                               if ( jQuery.expr.match.bool.test( name ) ) {
+                                       // Set corresponding property to false
+                                       if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+                                               elem[ propName ] = false;
+                                       // Support: IE<9
+                                       // Also clear defaultChecked/defaultSelected (if appropriate)
+                                       } else {
+                                               elem[ jQuery.camelCase( "default-" + name ) ] =
+                                                       elem[ propName ] = false;
+                                       }
+
+                               // See #9699 for explanation of this approach (setting first, then removal)
+                               } else {
+                                       jQuery.attr( elem, name, "" );
+                               }
+
+                               elem.removeAttribute( getSetAttribute ? name : propName );
+                       }
+               }
+       },
+
+       attrHooks: {
+               type: {
+                       set: function( elem, value ) {
+                               if ( !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 default in case type is set after value during creation
+                                       var val = elem.value;
+                                       elem.setAttribute( "type", value );
+                                       if ( val ) {
+                                               elem.value = val;
+                                       }
+                                       return value;
+                               }
+                       }
+               }
+       }
+});
+
+// Hook for boolean attributes
+boolHook = {
+       set: function( elem, value, name ) {
+               if ( value === false ) {
+                       // Remove boolean attributes when set to false
+                       jQuery.removeAttr( elem, name );
+               } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+                       // IE<8 needs the *property* name
+                       elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+               // Use defaultChecked and defaultSelected for oldIE
+               } else {
+                       elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+               }
+
+               return name;
+       }
+};
+
+// Retrieve booleans specially
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+
+       var getter = attrHandle[ name ] || jQuery.find.attr;
+
+       attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
+               function( elem, name, isXML ) {
+                       var ret, handle;
+                       if ( !isXML ) {
+                               // Avoid an infinite loop by temporarily removing this function from the getter
+                               handle = attrHandle[ name ];
+                               attrHandle[ name ] = ret;
+                               ret = getter( elem, name, isXML ) != null ?
+                                       name.toLowerCase() :
+                                       null;
+                               attrHandle[ name ] = handle;
+                       }
+                       return ret;
+               } :
+               function( elem, name, isXML ) {
+                       if ( !isXML ) {
+                               return elem[ jQuery.camelCase( "default-" + name ) ] ?
+                                       name.toLowerCase() :
+                                       null;
+                       }
+               };
+});
+
+// fix oldIE attroperties
+if ( !getSetInput || !getSetAttribute ) {
+       jQuery.attrHooks.value = {
+               set: function( elem, value, name ) {
+                       if ( jQuery.nodeName( elem, "input" ) ) {
+                               // Does not return so that setAttribute is also used
+                               elem.defaultValue = value;
+                       } else {
+                               // Use nodeHook if defined (#1954); otherwise setAttribute is fine
+                               return nodeHook && nodeHook.set( elem, value, name );
+                       }
+               }
+       };
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+       // Use this for any attribute in IE6/7
+       // This fixes almost every IE6/7 issue
+       nodeHook = {
+               set: function( elem, value, name ) {
+                       // Set the existing or create a new attribute node
+                       var ret = elem.getAttributeNode( name );
+                       if ( !ret ) {
+                               elem.setAttributeNode(
+                                       (ret = elem.ownerDocument.createAttribute( name ))
+                               );
+                       }
+
+                       ret.value = value += "";
+
+                       // Break association with cloned elements by also using setAttribute (#9646)
+                       if ( name === "value" || value === elem.getAttribute( name ) ) {
+                               return value;
+                       }
+               }
+       };
+
+       // Some attributes are constructed with empty-string values when not defined
+       attrHandle.id = attrHandle.name = attrHandle.coords =
+               function( elem, name, isXML ) {
+                       var ret;
+                       if ( !isXML ) {
+                               return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
+                                       ret.value :
+                                       null;
+                       }
+               };
+
+       // Fixing value retrieval on a button requires this module
+       jQuery.valHooks.button = {
+               get: function( elem, name ) {
+                       var ret = elem.getAttributeNode( name );
+                       if ( ret && ret.specified ) {
+                               return ret.value;
+                       }
+               },
+               set: nodeHook.set
+       };
+
+       // Set contenteditable to false on removals(#10429)
+       // Setting to empty string throws an error as an invalid value
+       jQuery.attrHooks.contenteditable = {
+               set: function( elem, value, name ) {
+                       nodeHook.set( elem, value === "" ? false : value, name );
+               }
+       };
+
+       // 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 ] = {
+                       set: function( elem, value ) {
+                               if ( value === "" ) {
+                                       elem.setAttribute( name, "auto" );
+                                       return value;
+                               }
+                       }
+               };
+       });
+}
+
+if ( !support.style ) {
+       jQuery.attrHooks.style = {
+               get: function( elem ) {
+                       // Return undefined in the case of empty string
+                       // Note: IE uppercases css property names, but if we were to .toLowerCase()
+                       // .cssText, that would destroy case senstitivity in URL's, like in "background"
+                       return elem.style.cssText || undefined;
+               },
+               set: function( elem, value ) {
+                       return ( elem.style.cssText = value + "" );
+               }
+       };
+}
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button|object)$/i,
+       rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend({
+       prop: function( name, value ) {
+               return access( this, jQuery.prop, name, value, arguments.length > 1 );
+       },
+
+       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 ) {}
+               });
+       }
+});
+
+jQuery.extend({
+       propFix: {
+               "for": "htmlFor",
+               "class": "className"
+       },
+
+       prop: function( elem, name, value ) {
+               var ret, hooks, notxml,
+                       nType = elem.nodeType;
+
+               // don't get/set properties on text, comment and attribute nodes
+               if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+                       return;
+               }
+
+               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 ) {
+                       return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+                               ret :
+                               ( elem[ name ] = value );
+
+               } else {
+                       return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+                               ret :
+                               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/
+                               // Use proper attribute retrieval(#12072)
+                               var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+                               return tabindex ?
+                                       parseInt( tabindex, 10 ) :
+                                       rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+                                               0 :
+                                               -1;
+                       }
+               }
+       }
+});
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !support.hrefNormalized ) {
+       // href/src property should get the full normalized URL (#10299/#12915)
+       jQuery.each([ "href", "src" ], function( i, name ) {
+               jQuery.propHooks[ name ] = {
+                       get: function( elem ) {
+                               return elem.getAttribute( name, 4 );
+                       }
+               };
+       });
+}
+
+// Support: Safari, IE9+
+// mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !support.optSelected ) {
+       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;
+               }
+       };
+}
+
+jQuery.each([
+       "tabIndex",
+       "readOnly",
+       "maxLength",
+       "cellSpacing",
+       "cellPadding",
+       "rowSpan",
+       "colSpan",
+       "useMap",
+       "frameBorder",
+       "contentEditable"
+], function() {
+       jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+// IE6/7 call enctype encoding
+if ( !support.enctype ) {
+       jQuery.propFix.enctype = "encoding";
+}
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+jQuery.fn.extend({
+       addClass: function( value ) {
+               var classes, elem, cur, clazz, j, finalValue,
+                       i = 0,
+                       len = this.length,
+                       proceed = typeof value === "string" && value;
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function( j ) {
+                               jQuery( this ).addClass( value.call( this, j, this.className ) );
+                       });
+               }
+
+               if ( proceed ) {
+                       // The disjunction here is for better compressibility (see removeClass)
+                       classes = ( value || "" ).match( rnotwhite ) || [];
+
+                       for ( ; i < len; i++ ) {
+                               elem = this[ i ];
+                               cur = elem.nodeType === 1 && ( elem.className ?
+                                       ( " " + elem.className + " " ).replace( rclass, " " ) :
+                                       " "
+                               );
+
+                               if ( cur ) {
+                                       j = 0;
+                                       while ( (clazz = classes[j++]) ) {
+                                               if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+                                                       cur += clazz + " ";
+                                               }
+                                       }
+
+                                       // only assign if different to avoid unneeded rendering.
+                                       finalValue = jQuery.trim( cur );
+                                       if ( elem.className !== finalValue ) {
+                                               elem.className = finalValue;
+                                       }
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       removeClass: function( value ) {
+               var classes, elem, cur, clazz, j, finalValue,
+                       i = 0,
+                       len = this.length,
+                       proceed = arguments.length === 0 || typeof value === "string" && value;
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function( j ) {
+                               jQuery( this ).removeClass( value.call( this, j, this.className ) );
+                       });
+               }
+               if ( proceed ) {
+                       classes = ( value || "" ).match( rnotwhite ) || [];
+
+                       for ( ; i < len; i++ ) {
+                               elem = this[ i ];
+                               // This expression is here for better compressibility (see addClass)
+                               cur = elem.nodeType === 1 && ( elem.className ?
+                                       ( " " + elem.className + " " ).replace( rclass, " " ) :
+                                       ""
+                               );
+
+                               if ( cur ) {
+                                       j = 0;
+                                       while ( (clazz = classes[j++]) ) {
+                                               // Remove *all* instances
+                                               while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+                                                       cur = cur.replace( " " + clazz + " ", " " );
+                                               }
+                                       }
+
+                                       // only assign if different to avoid unneeded rendering.
+                                       finalValue = value ? jQuery.trim( cur ) : "";
+                                       if ( elem.className !== finalValue ) {
+                                               elem.className = finalValue;
+                                       }
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       toggleClass: function( value, stateVal ) {
+               var type = typeof value;
+
+               if ( typeof stateVal === "boolean" && type === "string" ) {
+                       return stateVal ? this.addClass( value ) : this.removeClass( value );
+               }
+
+               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 ),
+                                       classNames = value.match( rnotwhite ) || [];
+
+                               while ( (className = classNames[ i++ ]) ) {
+                                       // check each className given, space separated list
+                                       if ( self.hasClass( className ) ) {
+                                               self.removeClass( className );
+                                       } else {
+                                               self.addClass( className );
+                                       }
+                               }
+
+                       // Toggle whole class name
+                       } else if ( type === strundefined || type === "boolean" ) {
+                               if ( this.className ) {
+                                       // store className if set
+                                       jQuery._data( this, "__className__", this.className );
+                               }
+
+                               // If the element has a class name or if we're passed "false",
+                               // then remove the whole classname (if there was one, the above saved it).
+                               // Otherwise bring back whatever was previously saved (if anything),
+                               // falling back to the empty string if nothing was stored.
+                               this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+                       }
                });
+       },
+
+       hasClass: function( selector ) {
+               var className = " " + selector + " ",
+                       i = 0,
+                       l = this.length;
+               for ( ; i < l; i++ ) {
+                       if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+});
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+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 contextmenu").split(" "), function( i, name ) {
+
+       // Handle event binding
+       jQuery.fn[ name ] = function( data, fn ) {
+               return arguments.length > 0 ?
+                       this.on( name, null, data, fn ) :
+                       this.trigger( name );
+       };
+});
+
+jQuery.fn.extend({
+       hover: function( fnOver, fnOut ) {
+               return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+       },
+
+       bind: function( types, data, fn ) {
+               return this.on( types, null, data, fn );
+       },
+       unbind: function( types, fn ) {
+               return this.off( types, null, fn );
+       },
+
+       delegate: function( selector, types, data, fn ) {
+               return this.on( types, selector, data, fn );
+       },
+       undelegate: function( selector, types, fn ) {
+               // ( namespace ) or ( selector, types [, fn] )
+               return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+       }
+});
+
+
+var nonce = jQuery.now();
+
+var rquery = (/\?/);
+
+
+
+var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
+
+jQuery.parseJSON = function( data ) {
+       // Attempt to parse using the native JSON parser first
+       if ( window.JSON && window.JSON.parse ) {
+               // Support: Android 2.3
+               // Workaround failure to string-cast null input
+               return window.JSON.parse( data + "" );
+       }
+
+       var requireNonComma,
+               depth = null,
+               str = jQuery.trim( data + "" );
+
+       // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
+       // after removing valid tokens
+       return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
+
+               // Force termination if we see a misplaced comma
+               if ( requireNonComma && comma ) {
+                       depth = 0;
+               }
+
+               // Perform no more replacements after returning to outermost depth
+               if ( depth === 0 ) {
+                       return token;
+               }
+
+               // Commas must not follow "[", "{", or ","
+               requireNonComma = open || comma;
+
+               // Determine new depth
+               // array/object open ("[" or "{"): depth += true - false (increment)
+               // array/object close ("]" or "}"): depth += false - true (decrement)
+               // other cases ("," or primitive): depth += true - true (numeric cast)
+               depth += !close - !open;
+
+               // Remove this token
+               return "";
+       }) ) ?
+               ( Function( "return " + str ) )() :
+               jQuery.error( "Invalid JSON: " + data );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+       var xml, tmp;
+       if ( !data || typeof data !== "string" ) {
+               return null;
+       }
+       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;
+};
+
+
+var
+       // Document location
+       ajaxLocParts,
+       ajaxLocation,
+
+       rhash = /#.*$/,
+       rts = /([?&])_=[^&]*/,
+       rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+       // #7653, #8125, #8152: local protocol detection
+       rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+       rnoContent = /^(?:GET|HEAD)$/,
+       rprotocol = /^\/\//,
+       rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
+
+       /* Prefilters
+        * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+        * 2) These are called:
+        *    - BEFORE asking for a transport
+        *    - AFTER param serialization (s.data is a string if s.processData is true)
+        * 3) key is the dataType
+        * 4) the catchall symbol "*" can be used
+        * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+        */
+       prefilters = {},
+
+       /* Transports bindings
+        * 1) key is the dataType
+        * 2) the catchall symbol "*" can be used
+        * 3) selection will start with transport dataType and THEN go to "*" if needed
+        */
+       transports = {},
+
+       // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+       allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+       ajaxLocation = location.href;
+} catch( e ) {
+       // Use the href attribute of an A element
+       // since IE will modify it given document.location
+       ajaxLocation = document.createElement( "a" );
+       ajaxLocation.href = "";
+       ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+       // dataTypeExpression is optional and defaults to "*"
+       return function( dataTypeExpression, func ) {
+
+               if ( typeof dataTypeExpression !== "string" ) {
+                       func = dataTypeExpression;
+                       dataTypeExpression = "*";
+               }
+
+               var dataType,
+                       i = 0,
+                       dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+               if ( jQuery.isFunction( func ) ) {
+                       // For each dataType in the dataTypeExpression
+                       while ( (dataType = dataTypes[i++]) ) {
+                               // Prepend if requested
+                               if ( dataType.charAt( 0 ) === "+" ) {
+                                       dataType = dataType.slice( 1 ) || "*";
+                                       (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+                               // Otherwise append
+                               } else {
+                                       (structure[ dataType ] = structure[ dataType ] || []).push( func );
+                               }
+                       }
+               }
        };
-});
+}
 
-jQuery.extend({
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+       var inspected = {},
+               seekingTransport = ( structure === transports );
+
+       function inspect( dataType ) {
+               var selected;
+               inspected[ dataType ] = true;
+               jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+                       var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+                       if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+                               options.dataTypes.unshift( dataTypeOrTransport );
+                               inspect( dataTypeOrTransport );
+                               return false;
+                       } else if ( seekingTransport ) {
+                               return !( selected = dataTypeOrTransport );
+                       }
+               });
+               return selected;
+       }
 
-       getScript: function( url, callback ) {
-               return jQuery.get( url, undefined, callback, "script" );
-       },
+       return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
 
-       getJSON: function( url, data, callback ) {
-               return jQuery.get( url, data, callback, "json" );
-       },
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+       var deep, key,
+               flatOptions = jQuery.ajaxSettings.flatOptions || {};
 
-       // Creates a full fledged settings object into target
-       // with both ajaxSettings and settings fields.
-       // If target is omitted, writes into ajaxSettings.
-       ajaxSetup: function ( target, settings ) {
-               if ( !settings ) {
-                       // Only one parameter, we extend ajaxSettings
-                       settings = target;
-                       target = jQuery.extend( true, jQuery.ajaxSettings, settings );
-               } else {
-                       // target was provided, we extend into it
-                       jQuery.extend( true, target, jQuery.ajaxSettings, settings );
+       for ( key in src ) {
+               if ( src[ key ] !== undefined ) {
+                       ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+               }
+       }
+       if ( deep ) {
+               jQuery.extend( true, target, deep );
+       }
+
+       return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+       var firstDataType, ct, finalDataType, type,
+               contents = s.contents,
+               dataTypes = s.dataTypes;
+
+       // Remove auto dataType and get content-type in the process
+       while ( dataTypes[ 0 ] === "*" ) {
+               dataTypes.shift();
+               if ( ct === undefined ) {
+                       ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
                }
-               // Flatten fields we don't want deep extended
-               for( var field in { context: 1, url: 1 } ) {
-                       if ( field in settings ) {
-                               target[ field ] = settings[ field ];
-                       } else if( field in jQuery.ajaxSettings ) {
-                               target[ field ] = jQuery.ajaxSettings[ field ];
+       }
+
+       // Check if we're dealing with a known content-type
+       if ( ct ) {
+               for ( type in contents ) {
+                       if ( contents[ type ] && contents[ type ].test( ct ) ) {
+                               dataTypes.unshift( type );
+                               break;
                        }
                }
-               return target;
-       },
+       }
+
+       // Check to see if we have a response for the expected dataType
+       if ( dataTypes[ 0 ] in responses ) {
+               finalDataType = dataTypes[ 0 ];
+       } else {
+               // Try convertible dataTypes
+               for ( type in responses ) {
+                       if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+                               finalDataType = type;
+                               break;
+                       }
+                       if ( !firstDataType ) {
+                               firstDataType = type;
+                       }
+               }
+               // Or just use first one
+               finalDataType = finalDataType || firstDataType;
+       }
+
+       // If we found a dataType
+       // We add the dataType to the list if needed
+       // and return the corresponding response
+       if ( finalDataType ) {
+               if ( finalDataType !== dataTypes[ 0 ] ) {
+                       dataTypes.unshift( finalDataType );
+               }
+               return responses[ finalDataType ];
+       }
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+       var conv2, current, conv, tmp, prev,
+               converters = {},
+               // Work with a copy of dataTypes in case we need to modify it for conversion
+               dataTypes = s.dataTypes.slice();
+
+       // Create converters map with lowercased keys
+       if ( dataTypes[ 1 ] ) {
+               for ( conv in s.converters ) {
+                       converters[ conv.toLowerCase() ] = s.converters[ conv ];
+               }
+       }
+
+       current = dataTypes.shift();
+
+       // Convert to each sequential dataType
+       while ( current ) {
+
+               if ( s.responseFields[ current ] ) {
+                       jqXHR[ s.responseFields[ current ] ] = response;
+               }
+
+               // Apply the dataFilter if provided
+               if ( !prev && isSuccess && s.dataFilter ) {
+                       response = s.dataFilter( response, s.dataType );
+               }
+
+               prev = current;
+               current = dataTypes.shift();
+
+               if ( current ) {
+
+                       // There's only work to do if current dataType is non-auto
+                       if ( current === "*" ) {
+
+                               current = prev;
+
+                       // Convert response if prev dataType is non-auto and differs from current
+                       } else if ( prev !== "*" && prev !== current ) {
+
+                               // Seek a direct converter
+                               conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+                               // If none found, seek a pair
+                               if ( !conv ) {
+                                       for ( conv2 in converters ) {
+
+                                               // If conv2 outputs current
+                                               tmp = conv2.split( " " );
+                                               if ( tmp[ 1 ] === current ) {
+
+                                                       // If prev can be converted to accepted input
+                                                       conv = converters[ prev + " " + tmp[ 0 ] ] ||
+                                                               converters[ "* " + tmp[ 0 ] ];
+                                                       if ( conv ) {
+                                                               // Condense equivalence converters
+                                                               if ( conv === true ) {
+                                                                       conv = converters[ conv2 ];
+
+                                                               // Otherwise, insert the intermediate dataType
+                                                               } else if ( converters[ conv2 ] !== true ) {
+                                                                       current = tmp[ 0 ];
+                                                                       dataTypes.unshift( tmp[ 1 ] );
+                                                               }
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               // Apply converter (if not an equivalence)
+                               if ( conv !== true ) {
+
+                                       // Unless errors are allowed to bubble, catch and return them
+                                       if ( conv && s[ "throws" ] ) {
+                                               response = conv( response );
+                                       } else {
+                                               try {
+                                                       response = conv( response );
+                                               } catch ( e ) {
+                                                       return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return { state: "success", data: response };
+}
+
+jQuery.extend({
+
+       // Counter for holding the number of active queries
+       active: 0,
+
+       // Last-Modified header cache for next request
+       lastModified: {},
+       etag: {},
 
        ajaxSettings: {
                url: ajaxLocation,
+               type: "GET",
                isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
                global: true,
-               type: "GET",
-               contentType: "application/x-www-form-urlencoded",
                processData: true,
                async: true,
+               contentType: "application/x-www-form-urlencoded; charset=UTF-8",
                /*
                timeout: 0,
                data: null,
@@ -6824,16 +8880,17 @@ jQuery.extend({
                username: null,
                password: null,
                cache: null,
+               throws: false,
                traditional: false,
                headers: {},
                */
 
                accepts: {
-                       xml: "application/xml, text/xml",
-                       html: "text/html",
+                       "*": allTypes,
                        text: "text/plain",
-                       json: "application/json, text/javascript",
-                       "*": "*/*"
+                       html: "text/html",
+                       xml: "application/xml, text/xml",
+                       json: "application/json, text/javascript"
                },
 
                contents: {
@@ -6844,16 +8901,16 @@ jQuery.extend({
 
                responseFields: {
                        xml: "responseXML",
-                       text: "responseText"
+                       text: "responseText",
+                       json: "responseJSON"
                },
 
-               // List of data converters
-               // 1) key format is "source_type destination_type" (a single space in-between)
-               // 2) the catchall symbol "*" can be used for source_type
+               // Data converters
+               // Keys separate source (or catchall "*") and destination types with a single space
                converters: {
 
                        // Convert anything to text
-                       "* text": window.String,
+                       "* text": String,
 
                        // Text to html (true = no transformation)
                        "text html": true,
@@ -6863,9 +8920,31 @@ jQuery.extend({
 
                        // Parse text as xml
                        "text xml": jQuery.parseXML
+               },
+
+               // For options that shouldn't be deep extended:
+               // you can add your own custom options here if
+               // and when you create one that shouldn't be
+               // deep extended (see ajaxExtend)
+               flatOptions: {
+                       url: true,
+                       context: true
                }
        },
 
+       // Creates a full fledged settings object into target
+       // with both ajaxSettings and settings fields.
+       // If target is omitted, writes into ajaxSettings.
+       ajaxSetup: function( target, settings ) {
+               return settings ?
+
+                       // Building a settings object
+                       ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+                       // Extending ajaxSettings
+                       ajaxExtend( jQuery.ajaxSettings, target );
+       },
+
        ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
        ajaxTransport: addToPrefiltersOrTransports( transports ),
 
@@ -6881,74 +8960,75 @@ jQuery.extend({
                // Force options to be an object
                options = options || {};
 
-               var // Create the final options object
+               var // Cross-domain detection vars
+                       parts,
+                       // Loop variable
+                       i,
+                       // URL without anti-cache param
+                       cacheURL,
+                       // Response headers as string
+                       responseHeadersString,
+                       // timeout handle
+                       timeoutTimer,
+
+                       // To know if global events are to be dispatched
+                       fireGlobals,
+
+                       transport,
+                       // Response headers
+                       responseHeaders,
+                       // Create the final options object
                        s = jQuery.ajaxSetup( {}, options ),
                        // Callbacks context
                        callbackContext = s.context || s,
-                       // Context for global events
-                       // It's the callbackContext if one was provided in the options
-                       // and if it's a DOM node or a jQuery collection
-                       globalEventContext = callbackContext !== s &&
-                               ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
-                                               jQuery( callbackContext ) : jQuery.event,
+                       // Context for global events is callbackContext if it is a DOM node or jQuery collection
+                       globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+                               jQuery( callbackContext ) :
+                               jQuery.event,
                        // Deferreds
                        deferred = jQuery.Deferred(),
-                       completeDeferred = jQuery._Deferred(),
+                       completeDeferred = jQuery.Callbacks("once memory"),
                        // Status-dependent callbacks
                        statusCode = s.statusCode || {},
-                       // ifModified key
-                       ifModifiedKey,
                        // Headers (they are sent all at once)
                        requestHeaders = {},
                        requestHeadersNames = {},
-                       // Response headers
-                       responseHeadersString,
-                       responseHeaders,
-                       // transport
-                       transport,
-                       // timeout handle
-                       timeoutTimer,
-                       // Cross-domain detection vars
-                       parts,
                        // The jqXHR state
                        state = 0,
-                       // To know if global events are to be dispatched
-                       fireGlobals,
-                       // Loop variable
-                       i,
+                       // Default abort message
+                       strAbort = "canceled",
                        // Fake xhr
                        jqXHR = {
-
                                readyState: 0,
 
-                               // Caches the header
-                               setRequestHeader: function( name, value ) {
-                                       if ( !state ) {
-                                               var lname = name.toLowerCase();
-                                               name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
-                                               requestHeaders[ name ] = value;
-                                       }
-                                       return this;
-                               },
-
-                               // Raw string
-                               getAllResponseHeaders: function() {
-                                       return state === 2 ? responseHeadersString : null;
-                               },
-
                                // Builds headers hashtable if needed
                                getResponseHeader: function( key ) {
                                        var match;
                                        if ( state === 2 ) {
                                                if ( !responseHeaders ) {
                                                        responseHeaders = {};
-                                                       while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+                                                       while ( (match = rheaders.exec( responseHeadersString )) ) {
                                                                responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
                                                        }
                                                }
                                                match = responseHeaders[ key.toLowerCase() ];
                                        }
-                                       return match === undefined ? null : match;
+                                       return match == null ? null : match;
+                               },
+
+                               // Raw string
+                               getAllResponseHeaders: function() {
+                                       return state === 2 ? responseHeadersString : null;
+                               },
+
+                               // Caches the header
+                               setRequestHeader: function( name, value ) {
+                                       var lname = name.toLowerCase();
+                                       if ( !state ) {
+                                               name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+                                               requestHeaders[ name ] = value;
+                                       }
+                                       return this;
                                },
 
                                // Overrides response content-type header
@@ -6959,166 +9039,58 @@ jQuery.extend({
                                        return this;
                                },
 
+                               // Status-dependent callbacks
+                               statusCode: function( map ) {
+                                       var code;
+                                       if ( map ) {
+                                               if ( state < 2 ) {
+                                                       for ( code in map ) {
+                                                               // Lazy-add the new callback in a way that preserves old ones
+                                                               statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+                                                       }
+                                               } else {
+                                                       // Execute the appropriate callbacks
+                                                       jqXHR.always( map[ jqXHR.status ] );
+                                               }
+                                       }
+                                       return this;
+                               },
+
                                // Cancel the request
                                abort: function( statusText ) {
-                                       statusText = statusText || "abort";
+                                       var finalText = statusText || strAbort;
                                        if ( transport ) {
-                                               transport.abort( statusText );
+                                               transport.abort( finalText );
                                        }
-                                       done( 0, statusText );
+                                       done( 0, finalText );
                                        return this;
                                }
                        };
 
-               // Callback for when everything is done
-               // It is defined here because jslint complains if it is declared
-               // at the end of the function (which would be more logical and readable)
-               function done( status, statusText, responses, headers ) {
-
-                       // Called once
-                       if ( state === 2 ) {
-                               return;
-                       }
-
-                       // State is "done" now
-                       state = 2;
-
-                       // Clear timeout if it exists
-                       if ( timeoutTimer ) {
-                               clearTimeout( timeoutTimer );
-                       }
-
-                       // Dereference transport for early garbage collection
-                       // (no matter how long the jqXHR object will be used)
-                       transport = undefined;
-
-                       // Cache response headers
-                       responseHeadersString = headers || "";
-
-                       // Set readyState
-                       jqXHR.readyState = status ? 4 : 0;
-
-                       var isSuccess,
-                               success,
-                               error,
-                               response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
-                               lastModified,
-                               etag;
-
-                       // If successful, handle type chaining
-                       if ( status >= 200 && status < 300 || status === 304 ) {
-
-                               // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
-                               if ( s.ifModified ) {
-
-                                       if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
-                                               jQuery.lastModified[ ifModifiedKey ] = lastModified;
-                                       }
-                                       if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
-                                               jQuery.etag[ ifModifiedKey ] = etag;
-                                       }
-                               }
-
-                               // If not modified
-                               if ( status === 304 ) {
-
-                                       statusText = "notmodified";
-                                       isSuccess = true;
-
-                               // If we have data
-                               } else {
-
-                                       try {
-                                               success = ajaxConvert( s, response );
-                                               statusText = "success";
-                                               isSuccess = true;
-                                       } catch(e) {
-                                               // We have a parsererror
-                                               statusText = "parsererror";
-                                               error = e;
-                                       }
-                               }
-                       } else {
-                               // We extract error from statusText
-                               // then normalize statusText and status for non-aborts
-                               error = statusText;
-                               if( !statusText || status ) {
-                                       statusText = "error";
-                                       if ( status < 0 ) {
-                                               status = 0;
-                                       }
-                               }
-                       }
-
-                       // Set data for the fake xhr object
-                       jqXHR.status = status;
-                       jqXHR.statusText = statusText;
-
-                       // Success/Error
-                       if ( isSuccess ) {
-                               deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
-                       } else {
-                               deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
-                       }
-
-                       // Status-dependent callbacks
-                       jqXHR.statusCode( statusCode );
-                       statusCode = undefined;
-
-                       if ( fireGlobals ) {
-                               globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
-                                               [ jqXHR, s, isSuccess ? success : error ] );
-                       }
-
-                       // Complete
-                       completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );
-
-                       if ( fireGlobals ) {
-                               globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] );
-                               // Handle the global AJAX counter
-                               if ( !( --jQuery.active ) ) {
-                                       jQuery.event.trigger( "ajaxStop" );
-                               }
-                       }
-               }
-
                // Attach deferreds
-               deferred.promise( jqXHR );
+               deferred.promise( jqXHR ).complete = completeDeferred.add;
                jqXHR.success = jqXHR.done;
                jqXHR.error = jqXHR.fail;
-               jqXHR.complete = completeDeferred.done;
-
-               // Status-dependent callbacks
-               jqXHR.statusCode = function( map ) {
-                       if ( map ) {
-                               var tmp;
-                               if ( state < 2 ) {
-                                       for( tmp in map ) {
-                                               statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
-                                       }
-                               } else {
-                                       tmp = map[ jqXHR.status ];
-                                       jqXHR.then( tmp, tmp );
-                               }
-                       }
-                       return this;
-               };
 
                // Remove hash character (#7531: and string promotion)
                // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+               // Handle falsy url in the settings object (#10093: consistency with old signature)
                // We also use the url parameter if available
-               s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+               s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+               // Alias method option to type as per ticket #12004
+               s.type = options.method || options.type || s.method || s.type;
 
                // Extract dataTypes list
-               s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
+               s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
 
-               // Determine if a cross-domain request is in order
+               // A cross-domain request is in order when we have a protocol:host:port mismatch
                if ( s.crossDomain == null ) {
                        parts = rurl.exec( s.url.toLowerCase() );
                        s.crossDomain = !!( parts &&
-                               ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
-                                       ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
-                                               ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+                               ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+                                       ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+                                               ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
                        );
                }
 
@@ -7130,13 +9102,19 @@ jQuery.extend({
                // Apply prefilters
                inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
 
-               // If request was aborted inside a prefiler, stop there
+               // If request was aborted inside a prefilter, stop there
                if ( state === 2 ) {
-                       return false;
+                       return jqXHR;
                }
 
                // We can fire global events as of now if asked to
-               fireGlobals = s.global;
+               // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+               fireGlobals = jQuery.event && s.global;
+
+               // Watch for a new set of requests
+               if ( fireGlobals && jQuery.active++ === 0 ) {
+                       jQuery.event.trigger("ajaxStart");
+               }
 
                // Uppercase the type
                s.type = s.type.toUpperCase();
@@ -7144,55 +9122,52 @@ jQuery.extend({
                // Determine if request has content
                s.hasContent = !rnoContent.test( s.type );
 
-               // Watch for a new set of requests
-               if ( fireGlobals && jQuery.active++ === 0 ) {
-                       jQuery.event.trigger( "ajaxStart" );
-               }
+               // Save the URL in case we're toying with the If-Modified-Since
+               // and/or If-None-Match header later on
+               cacheURL = s.url;
 
                // More options handling for requests with no content
                if ( !s.hasContent ) {
 
                        // If data is available, append data to url
                        if ( s.data ) {
-                               s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+                               cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+                               // #9682: remove data so that it's not used in an eventual retry
+                               delete s.data;
                        }
 
-                       // Get ifModifiedKey before adding the anti-cache parameter
-                       ifModifiedKey = s.url;
-
                        // Add anti-cache in url if needed
                        if ( s.cache === false ) {
+                               s.url = rts.test( cacheURL ) ?
 
-                               var ts = jQuery.now(),
-                                       // try replacing _= if it is there
-                                       ret = s.url.replace( rts, "$1_=" + ts );
+                                       // If there is already a '_' parameter, set its value
+                                       cacheURL.replace( rts, "$1_=" + nonce++ ) :
 
-                               // if nothing was replaced, add timestamp to the end
-                               s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+                                       // Otherwise add one to the end
+                                       cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
                        }
                }
 
-               // Set the correct header, if data is being sent
-               if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
-                       jqXHR.setRequestHeader( "Content-Type", s.contentType );
-               }
-
                // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
                if ( s.ifModified ) {
-                       ifModifiedKey = ifModifiedKey || s.url;
-                       if ( jQuery.lastModified[ ifModifiedKey ] ) {
-                               jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+                       if ( jQuery.lastModified[ cacheURL ] ) {
+                               jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
                        }
-                       if ( jQuery.etag[ ifModifiedKey ] ) {
-                               jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+                       if ( jQuery.etag[ cacheURL ] ) {
+                               jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
                        }
                }
 
+               // Set the correct header, if data is being sent
+               if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+                       jqXHR.setRequestHeader( "Content-Type", s.contentType );
+               }
+
                // Set the Accepts header for the server, depending on the dataType
                jqXHR.setRequestHeader(
                        "Accept",
                        s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
-                               s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
+                               s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
                                s.accepts[ "*" ]
                );
 
@@ -7203,12 +9178,13 @@ jQuery.extend({
 
                // Allow custom headers/mimetypes and early abort
                if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
-                               // Abort if not done already
-                               jqXHR.abort();
-                               return false;
-
+                       // Abort if not done already and return
+                       return jqXHR.abort();
                }
 
+               // aborting is no longer a cancellation
+               strAbort = "abort";
+
                // Install callbacks on deferreds
                for ( i in { success: 1, error: 1, complete: 1 } ) {
                        jqXHR[ i ]( s[ i ] );
@@ -7222,520 +9198,442 @@ jQuery.extend({
                        done( -1, "No Transport" );
                } else {
                        jqXHR.readyState = 1;
+
                        // Send global event
                        if ( fireGlobals ) {
                                globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
                        }
                        // Timeout
                        if ( s.async && s.timeout > 0 ) {
-                               timeoutTimer = setTimeout( function(){
-                                       jqXHR.abort( "timeout" );
+                               timeoutTimer = setTimeout(function() {
+                                       jqXHR.abort("timeout");
                                }, s.timeout );
                        }
 
                        try {
                                state = 1;
                                transport.send( requestHeaders, done );
-                       } catch (e) {
+                       } catch ( e ) {
                                // Propagate exception as error if not done
-                               if ( status < 2 ) {
+                               if ( state < 2 ) {
                                        done( -1, e );
                                // Simply rethrow otherwise
                                } else {
-                                       jQuery.error( e );
+                                       throw e;
                                }
                        }
                }
 
-               return jqXHR;
-       },
-
-       // Serialize an array of form elements or a set of
-       // key/values into a query string
-       param: function( a, traditional ) {
-               var s = [],
-                       add = function( key, value ) {
-                               // If value is a function, invoke it and return its value
-                               value = jQuery.isFunction( value ) ? value() : value;
-                               s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
-                       };
-
-               // Set traditional to true for jQuery <= 1.3.2 behavior.
-               if ( traditional === undefined ) {
-                       traditional = jQuery.ajaxSettings.traditional;
-               }
-
-               // If an array was passed in, assume that it is an array of form elements.
-               if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
-                       // Serialize the form elements
-                       jQuery.each( a, function() {
-                               add( this.name, this.value );
-                       });
+               // Callback for when everything is done
+               function done( status, nativeStatusText, responses, headers ) {
+                       var isSuccess, success, error, response, modified,
+                               statusText = nativeStatusText;
 
-               } else {
-                       // If traditional, encode the "old" way (the way 1.3.2 or older
-                       // did it), otherwise encode params recursively.
-                       for ( var prefix in a ) {
-                               buildParams( prefix, a[ prefix ], traditional, add );
+                       // Called once
+                       if ( state === 2 ) {
+                               return;
                        }
-               }
-
-               // Return the resulting serialization
-               return s.join( "&" ).replace( r20, "+" );
-       }
-});
 
-function buildParams( prefix, obj, traditional, add ) {
-       if ( jQuery.isArray( obj ) ) {
-               // Serialize array item.
-               jQuery.each( obj, function( i, v ) {
-                       if ( traditional || rbracket.test( prefix ) ) {
-                               // Treat each array item as a scalar.
-                               add( prefix, v );
+                       // State is "done" now
+                       state = 2;
 
-                       } else {
-                               // If array item is non-scalar (array or object), encode its
-                               // numeric index to resolve deserialization ambiguity issues.
-                               // Note that rack (as of 1.0.0) can't currently deserialize
-                               // nested arrays properly, and attempting to do so may cause
-                               // a server error. Possible fixes are to modify rack's
-                               // deserialization algorithm or to provide an option or flag
-                               // to force array serialization to be shallow.
-                               buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+                       // Clear timeout if it exists
+                       if ( timeoutTimer ) {
+                               clearTimeout( timeoutTimer );
                        }
-               });
-
-       } else if ( !traditional && obj != null && typeof obj === "object" ) {
-               // Serialize object item.
-               for ( var name in obj ) {
-                       buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
-               }
-
-       } else {
-               // Serialize scalar item.
-               add( prefix, obj );
-       }
-}
-
-// This is still on the jQuery object... for now
-// Want to move this to jQuery.ajax some day
-jQuery.extend({
-
-       // Counter for holding the number of active queries
-       active: 0,
-
-       // Last-Modified header cache for next request
-       lastModified: {},
-       etag: {}
-
-});
-
-/* Handles responses to an ajax request:
- * - sets all responseXXX fields accordingly
- * - finds the right dataType (mediates between content-type and expected dataType)
- * - returns the corresponding response
- */
-function ajaxHandleResponses( s, jqXHR, responses ) {
-
-       var contents = s.contents,
-               dataTypes = s.dataTypes,
-               responseFields = s.responseFields,
-               ct,
-               type,
-               finalDataType,
-               firstDataType;
-
-       // Fill responseXXX fields
-       for( type in responseFields ) {
-               if ( type in responses ) {
-                       jqXHR[ responseFields[type] ] = responses[ type ];
-               }
-       }
-
-       // Remove auto dataType and get content-type in the process
-       while( dataTypes[ 0 ] === "*" ) {
-               dataTypes.shift();
-               if ( ct === undefined ) {
-                       ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
-               }
-       }
 
-       // Check if we're dealing with a known content-type
-       if ( ct ) {
-               for ( type in contents ) {
-                       if ( contents[ type ] && contents[ type ].test( ct ) ) {
-                               dataTypes.unshift( type );
-                               break;
-                       }
-               }
-       }
+                       // Dereference transport for early garbage collection
+                       // (no matter how long the jqXHR object will be used)
+                       transport = undefined;
 
-       // Check to see if we have a response for the expected dataType
-       if ( dataTypes[ 0 ] in responses ) {
-               finalDataType = dataTypes[ 0 ];
-       } else {
-               // Try convertible dataTypes
-               for ( type in responses ) {
-                       if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
-                               finalDataType = type;
-                               break;
-                       }
-                       if ( !firstDataType ) {
-                               firstDataType = type;
-                       }
-               }
-               // Or just use first one
-               finalDataType = finalDataType || firstDataType;
-       }
+                       // Cache response headers
+                       responseHeadersString = headers || "";
 
-       // If we found a dataType
-       // We add the dataType to the list if needed
-       // and return the corresponding response
-       if ( finalDataType ) {
-               if ( finalDataType !== dataTypes[ 0 ] ) {
-                       dataTypes.unshift( finalDataType );
-               }
-               return responses[ finalDataType ];
-       }
-}
+                       // Set readyState
+                       jqXHR.readyState = status > 0 ? 4 : 0;
 
-// Chain conversions given the request and the original response
-function ajaxConvert( s, response ) {
+                       // Determine if successful
+                       isSuccess = status >= 200 && status < 300 || status === 304;
 
-       // Apply the dataFilter if provided
-       if ( s.dataFilter ) {
-               response = s.dataFilter( response, s.dataType );
-       }
+                       // Get response data
+                       if ( responses ) {
+                               response = ajaxHandleResponses( s, jqXHR, responses );
+                       }
 
-       var dataTypes = s.dataTypes,
-               converters = {},
-               i,
-               key,
-               length = dataTypes.length,
-               tmp,
-               // Current and previous dataTypes
-               current = dataTypes[ 0 ],
-               prev,
-               // Conversion expression
-               conversion,
-               // Conversion function
-               conv,
-               // Conversion functions (transitive conversion)
-               conv1,
-               conv2;
-
-       // For each dataType in the chain
-       for( i = 1; i < length; i++ ) {
-
-               // Create converters map
-               // with lowercased keys
-               if ( i === 1 ) {
-                       for( key in s.converters ) {
-                               if( typeof key === "string" ) {
-                                       converters[ key.toLowerCase() ] = s.converters[ key ];
+                       // Convert no matter what (that way responseXXX fields are always set)
+                       response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+                       // If successful, handle type chaining
+                       if ( isSuccess ) {
+
+                               // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+                               if ( s.ifModified ) {
+                                       modified = jqXHR.getResponseHeader("Last-Modified");
+                                       if ( modified ) {
+                                               jQuery.lastModified[ cacheURL ] = modified;
+                                       }
+                                       modified = jqXHR.getResponseHeader("etag");
+                                       if ( modified ) {
+                                               jQuery.etag[ cacheURL ] = modified;
+                                       }
                                }
-                       }
-               }
 
-               // Get the dataTypes
-               prev = current;
-               current = dataTypes[ i ];
-
-               // If current is auto dataType, update it to prev
-               if( current === "*" ) {
-                       current = prev;
-               // If no auto and dataTypes are actually different
-               } else if ( prev !== "*" && prev !== current ) {
-
-                       // Get the converter
-                       conversion = prev + " " + current;
-                       conv = converters[ conversion ] || converters[ "* " + current ];
-
-                       // If there is no direct converter, search transitively
-                       if ( !conv ) {
-                               conv2 = undefined;
-                               for( conv1 in converters ) {
-                                       tmp = conv1.split( " " );
-                                       if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
-                                               conv2 = converters[ tmp[1] + " " + current ];
-                                               if ( conv2 ) {
-                                                       conv1 = converters[ conv1 ];
-                                                       if ( conv1 === true ) {
-                                                               conv = conv2;
-                                                       } else if ( conv2 === true ) {
-                                                               conv = conv1;
-                                                       }
-                                                       break;
-                                               }
+                               // if no content
+                               if ( status === 204 || s.type === "HEAD" ) {
+                                       statusText = "nocontent";
+
+                               // if not modified
+                               } else if ( status === 304 ) {
+                                       statusText = "notmodified";
+
+                               // If we have data, let's convert it
+                               } else {
+                                       statusText = response.state;
+                                       success = response.data;
+                                       error = response.error;
+                                       isSuccess = !error;
+                               }
+                       } else {
+                               // We extract error from statusText
+                               // then normalize statusText and status for non-aborts
+                               error = statusText;
+                               if ( status || !statusText ) {
+                                       statusText = "error";
+                                       if ( status < 0 ) {
+                                               status = 0;
                                        }
                                }
                        }
-                       // If we found no converter, dispatch an error
-                       if ( !( conv || conv2 ) ) {
-                               jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+
+                       // Set data for the fake xhr object
+                       jqXHR.status = status;
+                       jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+                       // Success/Error
+                       if ( isSuccess ) {
+                               deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+                       } else {
+                               deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
                        }
-                       // If found converter is not an equivalence
-                       if ( conv !== true ) {
-                               // Convert with 1 or 2 converters accordingly
-                               response = conv ? conv( response ) : conv2( conv1(response) );
+
+                       // Status-dependent callbacks
+                       jqXHR.statusCode( statusCode );
+                       statusCode = undefined;
+
+                       if ( fireGlobals ) {
+                               globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+                                       [ jqXHR, s, isSuccess ? success : error ] );
                        }
-               }
-       }
-       return response;
-}
 
+                       // Complete
+                       completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
 
+                       if ( fireGlobals ) {
+                               globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+                               // Handle the global AJAX counter
+                               if ( !( --jQuery.active ) ) {
+                                       jQuery.event.trigger("ajaxStop");
+                               }
+                       }
+               }
 
+               return jqXHR;
+       },
 
-var jsc = jQuery.now(),
-       jsre = /(\=)\?(&|$)|\?\?/i;
+       getJSON: function( url, data, callback ) {
+               return jQuery.get( url, data, callback, "json" );
+       },
 
-// Default jsonp settings
-jQuery.ajaxSetup({
-       jsonp: "callback",
-       jsonpCallback: function() {
-               return jQuery.expando + "_" + ( jsc++ );
+       getScript: function( url, callback ) {
+               return jQuery.get( url, undefined, callback, "script" );
        }
 });
 
-// Detect, normalize options and install callbacks for jsonp requests
-jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
-
-       var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
-               ( typeof s.data === "string" );
-
-       if ( s.dataTypes[ 0 ] === "jsonp" ||
-               s.jsonp !== false && ( jsre.test( s.url ) ||
-                               inspectData && jsre.test( s.data ) ) ) {
-
-               var responseContainer,
-                       jsonpCallback = s.jsonpCallback =
-                               jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
-                       previous = window[ jsonpCallback ],
-                       url = s.url,
-                       data = s.data,
-                       replace = "$1" + jsonpCallback + "$2";
-
-               if ( s.jsonp !== false ) {
-                       url = url.replace( jsre, replace );
-                       if ( s.url === url ) {
-                               if ( inspectData ) {
-                                       data = data.replace( jsre, replace );
-                               }
-                               if ( s.data === data ) {
-                                       // Add callback manually
-                                       url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
-                               }
-                       }
+jQuery.each( [ "get", "post" ], function( i, method ) {
+       jQuery[ method ] = function( url, data, callback, type ) {
+               // shift arguments if data argument was omitted
+               if ( jQuery.isFunction( data ) ) {
+                       type = type || callback;
+                       callback = data;
+                       data = undefined;
                }
 
-               s.url = url;
-               s.data = data;
+               return jQuery.ajax({
+                       url: url,
+                       type: method,
+                       dataType: type,
+                       data: data,
+                       success: callback
+               });
+       };
+});
 
-               // Install callback
-               window[ jsonpCallback ] = function( response ) {
-                       responseContainer = [ response ];
-               };
 
-               // Clean-up function
-               jqXHR.always(function() {
-                       // Set callback back to previous value
-                       window[ jsonpCallback ] = previous;
-                       // Call if it was a function and we have a response
-                       if ( responseContainer && jQuery.isFunction( previous ) ) {
-                               window[ jsonpCallback ]( responseContainer[ 0 ] );
-                       }
-               });
+jQuery._evalUrl = function( url ) {
+       return jQuery.ajax({
+               url: url,
+               type: "GET",
+               dataType: "script",
+               async: false,
+               global: false,
+               "throws": true
+       });
+};
 
-               // Use data converter to retrieve json after script execution
-               s.converters["script json"] = function() {
-                       if ( !responseContainer ) {
-                               jQuery.error( jsonpCallback + " was not called" );
+
+jQuery.fn.extend({
+       wrapAll: function( html ) {
+               if ( jQuery.isFunction( html ) ) {
+                       return this.each(function(i) {
+                               jQuery(this).wrapAll( html.call(this, i) );
+                       });
+               }
+
+               if ( this[0] ) {
+                       // The elements to wrap the target around
+                       var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+                       if ( this[0].parentNode ) {
+                               wrap.insertBefore( this[0] );
                        }
-                       return responseContainer[ 0 ];
-               };
 
-               // force json dataType
-               s.dataTypes[ 0 ] = "json";
+                       wrap.map(function() {
+                               var elem = this;
 
-               // Delegate to script
-               return "script";
-       }
-});
+                               while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+                                       elem = elem.firstChild;
+                               }
+
+                               return elem;
+                       }).append( this );
+               }
 
+               return this;
+       },
 
+       wrapInner: function( html ) {
+               if ( jQuery.isFunction( html ) ) {
+                       return this.each(function(i) {
+                               jQuery(this).wrapInner( html.call(this, i) );
+                       });
+               }
 
+               return this.each(function() {
+                       var self = jQuery( this ),
+                               contents = self.contents();
 
-// Install script dataType
-jQuery.ajaxSetup({
-       accepts: {
-               script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+                       if ( contents.length ) {
+                               contents.wrapAll( html );
+
+                       } else {
+                               self.append( html );
+                       }
+               });
        },
-       contents: {
-               script: /javascript|ecmascript/
+
+       wrap: function( html ) {
+               var isFunction = jQuery.isFunction( html );
+
+               return this.each(function(i) {
+                       jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+               });
        },
-       converters: {
-               "text script": function( text ) {
-                       jQuery.globalEval( text );
-                       return text;
-               }
-       }
-});
 
-// Handle cache's special case and global
-jQuery.ajaxPrefilter( "script", function( s ) {
-       if ( s.cache === undefined ) {
-               s.cache = false;
-       }
-       if ( s.crossDomain ) {
-               s.type = "GET";
-               s.global = false;
+       unwrap: function() {
+               return this.parent().each(function() {
+                       if ( !jQuery.nodeName( this, "body" ) ) {
+                               jQuery( this ).replaceWith( this.childNodes );
+                       }
+               }).end();
        }
 });
 
-// Bind script tag hack transport
-jQuery.ajaxTransport( "script", function(s) {
 
-       // This transport only deals with cross domain requests
-       if ( s.crossDomain ) {
+jQuery.expr.filters.hidden = function( elem ) {
+       // Support: Opera <= 12.12
+       // Opera reports offsetWidths and offsetHeights less than zero on some elements
+       return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+               (!support.reliableHiddenOffsets() &&
+                       ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+};
 
-               var script,
-                       head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+jQuery.expr.filters.visible = function( elem ) {
+       return !jQuery.expr.filters.hidden( elem );
+};
 
-               return {
 
-                       send: function( _, callback ) {
 
-                               script = document.createElement( "script" );
 
-                               script.async = "async";
+var r20 = /%20/g,
+       rbracket = /\[\]$/,
+       rCRLF = /\r?\n/g,
+       rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+       rsubmittable = /^(?:input|select|textarea|keygen)/i;
 
-                               if ( s.scriptCharset ) {
-                                       script.charset = s.scriptCharset;
-                               }
+function buildParams( prefix, obj, traditional, add ) {
+       var name;
 
-                               script.src = s.url;
+       if ( jQuery.isArray( obj ) ) {
+               // Serialize array item.
+               jQuery.each( obj, function( i, v ) {
+                       if ( traditional || rbracket.test( prefix ) ) {
+                               // Treat each array item as a scalar.
+                               add( prefix, v );
 
-                               // Attach handlers for all browsers
-                               script.onload = script.onreadystatechange = function( _, isAbort ) {
+                       } else {
+                               // Item is non-scalar (array or object), encode its numeric index.
+                               buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+                       }
+               });
 
-                                       if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+       } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+               // Serialize object item.
+               for ( name in obj ) {
+                       buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+               }
 
-                                               // Handle memory leak in IE
-                                               script.onload = script.onreadystatechange = null;
+       } else {
+               // Serialize scalar item.
+               add( prefix, obj );
+       }
+}
 
-                                               // Remove the script
-                                               if ( head && script.parentNode ) {
-                                                       head.removeChild( script );
-                                               }
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+       var prefix,
+               s = [],
+               add = function( key, value ) {
+                       // If value is a function, invoke it and return its value
+                       value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+                       s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+               };
 
-                                               // Dereference the script
-                                               script = undefined;
+       // Set traditional to true for jQuery <= 1.3.2 behavior.
+       if ( traditional === undefined ) {
+               traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+       }
 
-                                               // Callback if not abort
-                                               if ( !isAbort ) {
-                                                       callback( 200, "success" );
-                                               }
-                                       }
-                               };
-                               // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
-                               // This arises when a base node is used (#2709 and #4378).
-                               head.insertBefore( script, head.firstChild );
-                       },
+       // If an array was passed in, assume that it is an array of form elements.
+       if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+               // Serialize the form elements
+               jQuery.each( a, function() {
+                       add( this.name, this.value );
+               });
 
-                       abort: function() {
-                               if ( script ) {
-                                       script.onload( 0, 1 );
-                               }
-                       }
-               };
+       } else {
+               // If traditional, encode the "old" way (the way 1.3.2 or older
+               // did it), otherwise encode params recursively.
+               for ( prefix in a ) {
+                       buildParams( prefix, a[ prefix ], traditional, add );
+               }
+       }
+
+       // Return the resulting serialization
+       return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend({
+       serialize: function() {
+               return jQuery.param( this.serializeArray() );
+       },
+       serializeArray: function() {
+               return this.map(function() {
+                       // Can add propHook for "elements" to filter or add form elements
+                       var elements = jQuery.prop( this, "elements" );
+                       return elements ? jQuery.makeArray( elements ) : this;
+               })
+               .filter(function() {
+                       var type = this.type;
+                       // Use .is(":disabled") so that fieldset[disabled] works
+                       return this.name && !jQuery( this ).is( ":disabled" ) &&
+                               rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+                               ( this.checked || !rcheckableType.test( type ) );
+               })
+               .map(function( i, elem ) {
+                       var val = jQuery( this ).val();
+
+                       return val == null ?
+                               null :
+                               jQuery.isArray( val ) ?
+                                       jQuery.map( val, function( val ) {
+                                               return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+                                       }) :
+                                       { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+               }).get();
        }
 });
 
 
-
-
-var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
-       xhrOnUnloadAbort = window.ActiveXObject ? function() {
-               // Abort all pending requests
-               for ( var key in xhrCallbacks ) {
-                       xhrCallbacks[ key ]( 0, 1 );
-               }
-       } : false,
-       xhrId = 0,
-       xhrCallbacks;
-
-// Functions to create xhrs
-function createStandardXHR() {
-       try {
-               return new window.XMLHttpRequest();
-       } catch( e ) {}
-}
-
-function createActiveXHR() {
-       try {
-               return new window.ActiveXObject( "Microsoft.XMLHTTP" );
-       } catch( e ) {}
-}
-
 // Create the request object
 // (This is still attached to ajaxSettings for backward compatibility)
-jQuery.ajaxSettings.xhr = window.ActiveXObject ?
-       /* Microsoft failed to properly
-        * implement the XMLHttpRequest in IE7 (can't request local files),
-        * so we use the ActiveXObject when it is available
-        * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
-        * we need a fallback.
-        */
+jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
+       // Support: IE6+
        function() {
-               return !this.isLocal && createStandardXHR() || createActiveXHR();
+
+               // XHR cannot access local files, always use ActiveX for that case
+               return !this.isLocal &&
+
+                       // Support: IE7-8
+                       // oldIE XHR does not support non-RFC2616 methods (#13240)
+                       // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
+                       // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
+                       // Although this check for six methods instead of eight
+                       // since IE also does not support "trace" and "connect"
+                       /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
+
+                       createStandardXHR() || createActiveXHR();
        } :
        // For all other browsers, use the standard XMLHttpRequest object
        createStandardXHR;
 
-// Determine support properties
-(function( xhr ) {
-       jQuery.extend( jQuery.support, {
-               ajax: !!xhr,
-               cors: !!xhr && ( "withCredentials" in xhr )
+var xhrId = 0,
+       xhrCallbacks = {},
+       xhrSupported = jQuery.ajaxSettings.xhr();
+
+// Support: IE<10
+// Open requests must be manually aborted on unload (#5280)
+// See https://support.microsoft.com/kb/2856746 for more info
+if ( window.attachEvent ) {
+       window.attachEvent( "onunload", function() {
+               for ( var key in xhrCallbacks ) {
+                       xhrCallbacks[ key ]( undefined, true );
+               }
        });
-})( jQuery.ajaxSettings.xhr() );
+}
+
+// Determine support properties
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = support.ajax = !!xhrSupported;
 
 // Create transport if the browser can provide an xhr
-if ( jQuery.support.ajax ) {
+if ( xhrSupported ) {
 
-       jQuery.ajaxTransport(function( s ) {
+       jQuery.ajaxTransport(function( options ) {
                // Cross domain only allowed if supported through XMLHttpRequest
-               if ( !s.crossDomain || jQuery.support.cors ) {
+               if ( !options.crossDomain || support.cors ) {
 
                        var callback;
 
                        return {
                                send: function( headers, complete ) {
-
-                                       // Get a new xhr
-                                       var xhr = s.xhr(),
-                                               handle,
-                                               i;
+                                       var i,
+                                               xhr = options.xhr(),
+                                               id = ++xhrId;
 
                                        // Open the socket
-                                       // Passing null username, generates a login popup on Opera (#2865)
-                                       if ( s.username ) {
-                                               xhr.open( s.type, s.url, s.async, s.username, s.password );
-                                       } else {
-                                               xhr.open( s.type, s.url, s.async );
-                                       }
+                                       xhr.open( options.type, options.url, options.async, options.username, options.password );
 
                                        // Apply custom fields if provided
-                                       if ( s.xhrFields ) {
-                                               for ( i in s.xhrFields ) {
-                                                       xhr[ i ] = s.xhrFields[ i ];
+                                       if ( options.xhrFields ) {
+                                               for ( i in options.xhrFields ) {
+                                                       xhr[ i ] = options.xhrFields[ i ];
                                                }
                                        }
 
                                        // Override mime type if needed
-                                       if ( s.mimeType && xhr.overrideMimeType ) {
-                                               xhr.overrideMimeType( s.mimeType );
+                                       if ( options.mimeType && xhr.overrideMimeType ) {
+                                               xhr.overrideMimeType( options.mimeType );
                                        }
 
                                        // X-Requested-With header
@@ -7743,126 +9641,100 @@ if ( jQuery.support.ajax ) {
                                        // akin to a jigsaw puzzle, we simply never set it to be sure.
                                        // (it can always be set on a per-request basis or even using ajaxSetup)
                                        // For same-domain requests, won't change header if already provided.
-                                       if ( !s.crossDomain && !headers["X-Requested-With"] ) {
-                                               headers[ "X-Requested-With" ] = "XMLHttpRequest";
+                                       if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+                                               headers["X-Requested-With"] = "XMLHttpRequest";
                                        }
 
-                                       // Need an extra try/catch for cross domain requests in Firefox 3
-                                       try {
-                                               for ( i in headers ) {
-                                                       xhr.setRequestHeader( i, headers[ i ] );
+                                       // Set headers
+                                       for ( i in headers ) {
+                                               // Support: IE<9
+                                               // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
+                                               // request header to a null-value.
+                                               //
+                                               // To keep consistent with other XHR implementations, cast the value
+                                               // to string and ignore `undefined`.
+                                               if ( headers[ i ] !== undefined ) {
+                                                       xhr.setRequestHeader( i, headers[ i ] + "" );
                                                }
-                                       } catch( _ ) {}
+                                       }
 
                                        // Do send the request
                                        // This may raise an exception which is actually
                                        // handled in jQuery.ajax (so no try/catch here)
-                                       xhr.send( ( s.hasContent && s.data ) || null );
+                                       xhr.send( ( options.hasContent && options.data ) || null );
 
                                        // Listener
                                        callback = function( _, isAbort ) {
-
-                                               var status,
-                                                       statusText,
-                                                       responseHeaders,
-                                                       responses,
-                                                       xml;
-
-                                               // Firefox throws exceptions when accessing properties
-                                               // of an xhr when a network error occured
-                                               // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
-                                               try {
-
-                                                       // Was never called and is aborted or complete
-                                                       if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
-
-                                                               // Only called once
-                                                               callback = undefined;
-
-                                                               // Do not keep as active anymore
-                                                               if ( handle ) {
-                                                                       xhr.onreadystatechange = jQuery.noop;
-                                                                       if ( xhrOnUnloadAbort ) {
-                                                                               delete xhrCallbacks[ handle ];
-                                                                       }
+                                               var status, statusText, responses;
+
+                                               // Was never called and is aborted or complete
+                                               if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+                                                       // Clean up
+                                                       delete xhrCallbacks[ id ];
+                                                       callback = undefined;
+                                                       xhr.onreadystatechange = jQuery.noop;
+
+                                                       // Abort manually if needed
+                                                       if ( isAbort ) {
+                                                               if ( xhr.readyState !== 4 ) {
+                                                                       xhr.abort();
                                                                }
+                                                       } else {
+                                                               responses = {};
+                                                               status = xhr.status;
 
-                                                               // If it's an abort
-                                                               if ( isAbort ) {
-                                                                       // Abort it manually if needed
-                                                                       if ( xhr.readyState !== 4 ) {
-                                                                               xhr.abort();
-                                                                       }
-                                                               } else {
-                                                                       status = xhr.status;
-                                                                       responseHeaders = xhr.getAllResponseHeaders();
-                                                                       responses = {};
-                                                                       xml = xhr.responseXML;
-
-                                                                       // Construct response list
-                                                                       if ( xml && xml.documentElement /* #4958 */ ) {
-                                                                               responses.xml = xml;
-                                                                       }
+                                                               // Support: IE<10
+                                                               // Accessing binary-data responseText throws an exception
+                                                               // (#11426)
+                                                               if ( typeof xhr.responseText === "string" ) {
                                                                        responses.text = xhr.responseText;
+                                                               }
 
-                                                                       // Firefox throws an exception when accessing
-                                                                       // statusText for faulty cross-domain requests
-                                                                       try {
-                                                                               statusText = xhr.statusText;
-                                                                       } catch( e ) {
-                                                                               // We normalize with Webkit giving an empty statusText
-                                                                               statusText = "";
-                                                                       }
+                                                               // Firefox throws an exception when accessing
+                                                               // statusText for faulty cross-domain requests
+                                                               try {
+                                                                       statusText = xhr.statusText;
+                                                               } catch( e ) {
+                                                                       // We normalize with Webkit giving an empty statusText
+                                                                       statusText = "";
+                                                               }
 
-                                                                       // Filter status for non standard behaviors
+                                                               // Filter status for non standard behaviors
 
-                                                                       // If the request is local and we have data: assume a success
-                                                                       // (success with no data won't get notified, that's the best we
-                                                                       // can do given current implementations)
-                                                                       if ( !status && s.isLocal && !s.crossDomain ) {
-                                                                               status = responses.text ? 200 : 404;
-                                                                       // IE - #1450: sometimes returns 1223 when it should be 204
-                                                                       } else if ( status === 1223 ) {
-                                                                               status = 204;
-                                                                       }
+                                                               // If the request is local and we have data: assume a success
+                                                               // (success with no data won't get notified, that's the best we
+                                                               // can do given current implementations)
+                                                               if ( !status && options.isLocal && !options.crossDomain ) {
+                                                                       status = responses.text ? 200 : 404;
+                                                               // IE - #1450: sometimes returns 1223 when it should be 204
+                                                               } else if ( status === 1223 ) {
+                                                                       status = 204;
                                                                }
                                                        }
-                                               } catch( firefoxAccessException ) {
-                                                       if ( !isAbort ) {
-                                                               complete( -1, firefoxAccessException );
-                                                       }
                                                }
 
                                                // Call complete if needed
                                                if ( responses ) {
-                                                       complete( status, statusText, responses, responseHeaders );
+                                                       complete( status, statusText, responses, xhr.getAllResponseHeaders() );
                                                }
                                        };
 
-                                       // if we're in sync mode or it's in cache
-                                       // and has been retrieved directly (IE6 & IE7)
-                                       // we need to manually fire the callback
-                                       if ( !s.async || xhr.readyState === 4 ) {
+                                       if ( !options.async ) {
+                                               // if we're in sync mode we fire the callback
                                                callback();
+                                       } else if ( xhr.readyState === 4 ) {
+                                               // (IE6 & IE7) if it's in cache and has been
+                                               // retrieved directly we need to fire the callback
+                                               setTimeout( callback );
                                        } else {
-                                               handle = ++xhrId;
-                                               if ( xhrOnUnloadAbort ) {
-                                                       // Create the active xhrs callbacks list if needed
-                                                       // and attach the unload handler
-                                                       if ( !xhrCallbacks ) {
-                                                               xhrCallbacks = {};
-                                                               jQuery( window ).unload( xhrOnUnloadAbort );
-                                                       }
-                                                       // Add to list of active xhrs callbacks
-                                                       xhrCallbacks[ handle ] = callback;
-                                               }
-                                               xhr.onreadystatechange = callback;
+                                               // Add to the list of active xhr callbacks
+                                               xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
                                        }
                                },
 
                                abort: function() {
                                        if ( callback ) {
-                                               callback(0,1);
+                                               callback( undefined, true );
                                        }
                                }
                        };
@@ -7870,806 +9742,343 @@ if ( jQuery.support.ajax ) {
        });
 }
 
+// Functions to create xhrs
+function createStandardXHR() {
+       try {
+               return new window.XMLHttpRequest();
+       } catch( e ) {}
+}
 
+function createActiveXHR() {
+       try {
+               return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+       } catch( e ) {}
+}
 
 
-var elemdisplay = {},
-       iframe, iframeDoc,
-       rfxtypes = /^(?:toggle|show|hide)$/,
-       rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
-       timerId,
-       fxAttrs = [
-               // height animations
-               [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
-               // width animations
-               [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
-               // opacity animations
-               [ "opacity" ]
-       ],
-       fxNow,
-       requestAnimationFrame = window.webkitRequestAnimationFrame ||
-           window.mozRequestAnimationFrame ||
-           window.oRequestAnimationFrame;
-
-jQuery.fn.extend({
-       show: function( speed, easing, callback ) {
-               var elem, display;
-
-               if ( speed || speed === 0 ) {
-                       return this.animate( genFx("show", 3), speed, easing, callback);
-
-               } else {
-                       for ( var i = 0, j = this.length; i < j; i++ ) {
-                               elem = this[i];
-
-                               if ( elem.style ) {
-                                       display = elem.style.display;
-
-                                       // Reset the inline display of this element to learn if it is
-                                       // being hidden by cascaded rules or not
-                                       if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
-                                               display = elem.style.display = "";
-                                       }
-
-                                       // Set elements which have been overridden with display: none
-                                       // in a stylesheet to whatever the default browser style is
-                                       // for such an element
-                                       if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
-                                               jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
-                                       }
-                               }
-                       }
-
-                       // Set the display of most of the elements in a second loop
-                       // to avoid the constant reflow
-                       for ( i = 0; i < j; i++ ) {
-                               elem = this[i];
-
-                               if ( elem.style ) {
-                                       display = elem.style.display;
-
-                                       if ( display === "" || display === "none" ) {
-                                               elem.style.display = jQuery._data(elem, "olddisplay") || "";
-                                       }
-                               }
-                       }
-
-                       return this;
-               }
-       },
-
-       hide: function( speed, easing, callback ) {
-               if ( speed || speed === 0 ) {
-                       return this.animate( genFx("hide", 3), speed, easing, callback);
-
-               } else {
-                       for ( var i = 0, j = this.length; i < j; i++ ) {
-                               if ( this[i].style ) {
-                                       var display = jQuery.css( this[i], "display" );
-
-                                       if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
-                                               jQuery._data( this[i], "olddisplay", display );
-                                       }
-                               }
-                       }
-
-                       // Set the display of the elements in a second loop
-                       // to avoid the constant reflow
-                       for ( i = 0; i < j; i++ ) {
-                               if ( this[i].style ) {
-                                       this[i].style.display = "none";
-                               }
-                       }
-
-                       return this;
-               }
-       },
-
-       // Save the old toggle function
-       _toggle: jQuery.fn.toggle,
-
-       toggle: function( fn, fn2, callback ) {
-               var bool = typeof fn === "boolean";
-
-               if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
-                       this._toggle.apply( this, arguments );
-
-               } else if ( fn == null || bool ) {
-                       this.each(function() {
-                               var state = bool ? fn : jQuery(this).is(":hidden");
-                               jQuery(this)[ state ? "show" : "hide" ]();
-                       });
-
-               } else {
-                       this.animate(genFx("toggle", 3), fn, fn2, callback);
-               }
 
-               return this;
-       },
 
-       fadeTo: function( speed, to, easing, callback ) {
-               return this.filter(":hidden").css("opacity", 0).show().end()
-                                       .animate({opacity: to}, speed, easing, callback);
+// Install script dataType
+jQuery.ajaxSetup({
+       accepts: {
+               script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
        },
-
-       animate: function( prop, speed, easing, callback ) {
-               var optall = jQuery.speed(speed, easing, callback);
-
-               if ( jQuery.isEmptyObject( prop ) ) {
-                       return this.each( optall.complete, [ false ] );
-               }
-
-               return this[ optall.queue === false ? "each" : "queue" ](function() {
-                       // XXX 'this' does not always have a nodeName when running the
-                       // test suite
-
-                       if ( optall.queue === false ) {
-                               jQuery._mark( this );
-                       }
-
-                       var opt = jQuery.extend({}, optall),
-                               isElement = this.nodeType === 1,
-                               hidden = isElement && jQuery(this).is(":hidden"),
-                               name, val, p,
-                               display, e,
-                               parts, start, end, unit;
-
-                       // will store per property easing and be used to determine when an animation is complete
-                       opt.animatedProperties = {};
-
-                       for ( p in prop ) {
-
-                               // property name normalization
-                               name = jQuery.camelCase( p );
-                               if ( p !== name ) {
-                                       prop[ name ] = prop[ p ];
-                                       delete prop[ p ];
-                               }
-
-                               val = prop[name];
-
-                               if ( val === "hide" && hidden || val === "show" && !hidden ) {
-                                       return opt.complete.call(this);
-                               }
-
-                               if ( isElement && ( name === "height" || name === "width" ) ) {
-                                       // Make sure that nothing sneaks out
-                                       // Record all 3 overflow attributes because IE does not
-                                       // change the overflow attribute when overflowX and
-                                       // overflowY are set to the same value
-                                       opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
-
-                                       // Set display property to inline-block for height/width
-                                       // animations on inline elements that are having width/height
-                                       // animated
-                                       if ( jQuery.css( this, "display" ) === "inline" &&
-                                                       jQuery.css( this, "float" ) === "none" ) {
-                                               if ( !jQuery.support.inlineBlockNeedsLayout ) {
-                                                       this.style.display = "inline-block";
-
-                                               } else {
-                                                       display = defaultDisplay(this.nodeName);
-
-                                                       // inline-level elements accept inline-block;
-                                                       // block-level elements need to be inline with layout
-                                                       if ( display === "inline" ) {
-                                                               this.style.display = "inline-block";
-
-                                                       } else {
-                                                               this.style.display = "inline";
-                                                               this.style.zoom = 1;
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
-                               opt.animatedProperties[name] = jQuery.isArray( val ) ?
-                                       val[1]:
-                                       opt.specialEasing && opt.specialEasing[name] || opt.easing || 'swing';
-                       }
-
-                       if ( opt.overflow != null ) {
-                               this.style.overflow = "hidden";
-                       }
-
-                       for ( p in prop ) {
-                               e = new jQuery.fx( this, opt, p );
-
-                               val = prop[p];
-
-                               if ( rfxtypes.test(val) ) {
-                                       e[ val === "toggle" ? hidden ? "show" : "hide" : val ]();
-
-                               } else {
-                                       parts = rfxnum.exec(val);
-                                       start = e.cur();
-
-                                       if ( parts ) {
-                                               end = parseFloat( parts[2] );
-                                               unit = parts[3] || ( jQuery.cssNumber[ name ] ? "" : "px" );
-
-                                               // We need to compute starting value
-                                               if ( unit !== "px" ) {
-                                                       jQuery.style( this, p, (end || 1) + unit);
-                                                       start = ((end || 1) / e.cur()) * start;
-                                                       jQuery.style( this, p, start + unit);
-                                               }
-
-                                               // If a +=/-= token was provided, we're doing a relative animation
-                                               if ( parts[1] ) {
-                                                       end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
-                                               }
-
-                                               e.custom( start, end, unit );
-
-                                       } else {
-                                               e.custom( start, val, "" );
-                                       }
-                               }
-                       }
-
-                       // For JS strict compliance
-                       return true;
-               });
+       contents: {
+               script: /(?:java|ecma)script/
        },
-
-       stop: function( clearQueue, gotoEnd ) {
-               if ( clearQueue ) {
-                       this.queue([]);
-               }
-
-               this.each(function() {
-                       var timers = jQuery.timers,
-                               i = timers.length;
-                       // clear marker counters if we know they won't be
-                       if ( !gotoEnd ) {
-                               jQuery._unmark( true, this );
-                       }
-                       // go in reverse order so anything added to the queue during the loop is ignored
-                       while ( i-- ) {
-                               if ( timers[i].elem === this ) {
-                                       if (gotoEnd) {
-                                               // force the next step to be the last
-                                               timers[i](true);
-                                       }
-
-                                       timers.splice(i, 1);
-                               }
-                       }
-               });
-
-               // start the next in the queue if the last step wasn't forced
-               if ( !gotoEnd ) {
-                       this.dequeue();
+       converters: {
+               "text script": function( text ) {
+                       jQuery.globalEval( text );
+                       return text;
                }
-
-               return this;
        }
-
-});
-
-// Animations created synchronously will run synchronously
-function createFxNow() {
-       setTimeout( clearFxNow, 0 );
-       return ( fxNow = jQuery.now() );
-}
-
-function clearFxNow() {
-       fxNow = undefined;
-}
-
-// Generate parameters to create a standard animation
-function genFx( type, num ) {
-       var obj = {};
-
-       jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
-               obj[ this ] = type;
-       });
-
-       return obj;
-}
-
-// Generate shortcuts for custom animations
-jQuery.each({
-       slideDown: genFx("show", 1),
-       slideUp: genFx("hide", 1),
-       slideToggle: genFx("toggle", 1),
-       fadeIn: { opacity: "show" },
-       fadeOut: { opacity: "hide" },
-       fadeToggle: { opacity: "toggle" }
-}, function( name, props ) {
-       jQuery.fn[ name ] = function( speed, easing, callback ) {
-               return this.animate( props, speed, easing, callback );
-       };
 });
 
-jQuery.extend({
-       speed: function( speed, easing, fn ) {
-               var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
-                       complete: fn || !fn && easing ||
-                               jQuery.isFunction( speed ) && speed,
-                       duration: speed,
-                       easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
-               };
-
-               opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
-                       opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
-
-               // Queueing
-               opt.old = opt.complete;
-               opt.complete = function( noUnmark ) {
-                       if ( opt.queue !== false ) {
-                               jQuery.dequeue( this );
-                       } else if ( noUnmark !== false ) {
-                               jQuery._unmark( this );
-                       }
-
-                       if ( jQuery.isFunction( opt.old ) ) {
-                               opt.old.call( this );
-                       }
-               };
-
-               return opt;
-       },
-
-       easing: {
-               linear: function( p, n, firstNum, diff ) {
-                       return firstNum + diff * p;
-               },
-               swing: function( p, n, firstNum, diff ) {
-                       return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
-               }
-       },
-
-       timers: [],
-
-       fx: function( elem, options, prop ) {
-               this.options = options;
-               this.elem = elem;
-               this.prop = prop;
-
-               options.orig = options.orig || {};
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+       if ( s.cache === undefined ) {
+               s.cache = false;
+       }
+       if ( s.crossDomain ) {
+               s.type = "GET";
+               s.global = false;
        }
-
 });
 
-jQuery.fx.prototype = {
-       // Simple function for setting a style value
-       update: function() {
-               if ( this.options.step ) {
-                       this.options.step.call( this.elem, this.now, this );
-               }
-
-               (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
-       },
-
-       // Get the current size
-       cur: function() {
-               if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
-                       return this.elem[ this.prop ];
-               }
-
-               var parsed,
-                       r = jQuery.css( this.elem, this.prop );
-               // Empty strings, null, undefined and "auto" are converted to 0,
-               // complex values such as "rotate(1rad)" are returned as is,
-               // simple values such as "10px" are parsed to Float.
-               return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
-       },
-
-       // Start an animation from one number to another
-       custom: function( from, to, unit ) {
-               var self = this,
-                       fx = jQuery.fx,
-                       raf;
-
-               this.startTime = fxNow || createFxNow();
-               this.start = from;
-               this.end = to;
-               this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
-               this.now = this.start;
-               this.pos = this.state = 0;
-
-               function t( gotoEnd ) {
-                       return self.step(gotoEnd);
-               }
-
-               t.elem = this.elem;
-
-               if ( t() && jQuery.timers.push(t) && !timerId ) {
-                       // Use requestAnimationFrame instead of setInterval if available
-                       if ( requestAnimationFrame ) {
-                               timerId = 1;
-                               raf = function() {
-                                       // When timerId gets set to null at any point, this stops
-                                       if ( timerId ) {
-                                               requestAnimationFrame( raf );
-                                               fx.tick();
-                                       }
-                               };
-                               requestAnimationFrame( raf );
-                       } else {
-                               timerId = setInterval( fx.tick, fx.interval );
-                       }
-               }
-       },
-
-       // Simple 'show' function
-       show: function() {
-               // Remember where we started, so that we can go back to it later
-               this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
-               this.options.show = true;
-
-               // Begin the animation
-               // Make sure that we start at a small width/height to avoid any
-               // flash of content
-               this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
 
-               // Start by showing the element
-               jQuery( this.elem ).show();
-       },
+       // This transport only deals with cross domain requests
+       if ( s.crossDomain ) {
 
-       // Simple 'hide' function
-       hide: function() {
-               // Remember where we started, so that we can go back to it later
-               this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
-               this.options.hide = true;
+               var script,
+                       head = document.head || jQuery("head")[0] || document.documentElement;
 
-               // Begin the animation
-               this.custom(this.cur(), 0);
-       },
+               return {
 
-       // Each step of an animation
-       step: function( gotoEnd ) {
-               var t = fxNow || createFxNow(),
-                       done = true,
-                       elem = this.elem,
-                       options = this.options,
-                       i, n;
+                       send: function( _, callback ) {
 
-               if ( gotoEnd || t >= options.duration + this.startTime ) {
-                       this.now = this.end;
-                       this.pos = this.state = 1;
-                       this.update();
+                               script = document.createElement("script");
 
-                       options.animatedProperties[ this.prop ] = true;
+                               script.async = true;
 
-                       for ( i in options.animatedProperties ) {
-                               if ( options.animatedProperties[i] !== true ) {
-                                       done = false;
+                               if ( s.scriptCharset ) {
+                                       script.charset = s.scriptCharset;
                                }
-                       }
-
-                       if ( done ) {
-                               // Reset the overflow
-                               if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
 
-                                       jQuery.each( [ "", "X", "Y" ], function (index, value) {
-                                               elem.style[ "overflow" + value ] = options.overflow[index];
-                                       });
-                               }
+                               script.src = s.url;
 
-                               // Hide the element if the "hide" operation was done
-                               if ( options.hide ) {
-                                       jQuery(elem).hide();
-                               }
+                               // Attach handlers for all browsers
+                               script.onload = script.onreadystatechange = function( _, isAbort ) {
 
-                               // Reset the properties, if the item has been hidden or shown
-                               if ( options.hide || options.show ) {
-                                       for ( var p in options.animatedProperties ) {
-                                               jQuery.style( elem, p, options.orig[p] );
-                                       }
-                               }
+                                       if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
 
-                               // Execute the complete function
-                               options.complete.call( elem );
-                       }
+                                               // Handle memory leak in IE
+                                               script.onload = script.onreadystatechange = null;
 
-                       return false;
+                                               // Remove the script
+                                               if ( script.parentNode ) {
+                                                       script.parentNode.removeChild( script );
+                                               }
 
-               } else {
-                       // classical easing cannot be used with an Infinity duration
-                       if ( options.duration == Infinity ) {
-                               this.now = t;
-                       } else {
-                               n = t - this.startTime;
+                                               // Dereference the script
+                                               script = null;
 
-                               this.state = n / options.duration;
-                               // Perform the easing function, defaults to swing
-                               this.pos = jQuery.easing[options.animatedProperties[this.prop]](this.state, n, 0, 1, options.duration);
-                               this.now = this.start + ((this.end - this.start) * this.pos);
-                       }
-                       // Perform the next step of the animation
-                       this.update();
-               }
+                                               // Callback if not abort
+                                               if ( !isAbort ) {
+                                                       callback( 200, "success" );
+                                               }
+                                       }
+                               };
 
-               return true;
-       }
-};
+                               // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+                               // Use native DOM manipulation to avoid our domManip AJAX trickery
+                               head.insertBefore( script, head.firstChild );
+                       },
 
-jQuery.extend( jQuery.fx, {
-       tick: function() {
-               var timers = jQuery.timers,
-                       i = timers.length;
-               while ( i-- ) {
-                       if ( !timers[i]() ) {
-                               timers.splice(i, 1);
+                       abort: function() {
+                               if ( script ) {
+                                       script.onload( undefined, true );
+                               }
                        }
-               }
-
-               if ( !timers.length ) {
-                       jQuery.fx.stop();
-               }
-       },
+               };
+       }
+});
 
-       interval: 13,
 
-       stop: function() {
-               clearInterval( timerId );
-               timerId = null;
-       },
 
-       speeds: {
-               slow: 600,
-               fast: 200,
-               // Default speed
-               _default: 400
-       },
 
-       step: {
-               opacity: function( fx ) {
-                       jQuery.style( fx.elem, "opacity", fx.now );
-               },
+var oldCallbacks = [],
+       rjsonp = /(=)\?(?=&|$)|\?\?/;
 
-               _default: function( fx ) {
-                       if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
-                               fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
-                       } else {
-                               fx.elem[ fx.prop ] = fx.now;
-                       }
-               }
+// Default jsonp settings
+jQuery.ajaxSetup({
+       jsonp: "callback",
+       jsonpCallback: function() {
+               var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+               this[ callback ] = true;
+               return callback;
        }
 });
 
-if ( jQuery.expr && jQuery.expr.filters ) {
-       jQuery.expr.filters.animated = function( elem ) {
-               return jQuery.grep(jQuery.timers, function( fn ) {
-                       return elem === fn.elem;
-               }).length;
-       };
-}
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
 
-// Try to restore the default display value of an element
-function defaultDisplay( nodeName ) {
+       var callbackName, overwritten, responseContainer,
+               jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+                       "url" :
+                       typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+               );
 
-       if ( !elemdisplay[ nodeName ] ) {
+       // Handle iff the expected data type is "jsonp" or we have a parameter to set
+       if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
 
-               var elem = jQuery( "<" + nodeName + ">" ).appendTo( "body" ),
-                       display = elem.css( "display" );
+               // Get callback name, remembering preexisting value associated with it
+               callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+                       s.jsonpCallback() :
+                       s.jsonpCallback;
 
-               elem.remove();
+               // Insert callback into url or form data
+               if ( jsonProp ) {
+                       s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+               } else if ( s.jsonp !== false ) {
+                       s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+               }
 
-               // If the simple way fails,
-               // get element's real default display by attaching it to a temp iframe
-               if ( display === "none" || display === "" ) {
-                       // No iframe to use yet, so create it
-                       if ( !iframe ) {
-                               iframe = document.createElement( "iframe" );
-                               iframe.frameBorder = iframe.width = iframe.height = 0;
+               // Use data converter to retrieve json after script execution
+               s.converters["script json"] = function() {
+                       if ( !responseContainer ) {
+                               jQuery.error( callbackName + " was not called" );
                        }
+                       return responseContainer[ 0 ];
+               };
 
-                       document.body.appendChild( iframe );
+               // force json dataType
+               s.dataTypes[ 0 ] = "json";
 
-                       // Create a cacheable copy of the iframe document on first call.
-                       // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake html
-                       // document to it, Webkit & Firefox won't allow reusing the iframe document
-                       if ( !iframeDoc || !iframe.createElement ) {
-                               iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
-                               iframeDoc.write( "<!doctype><html><body></body></html>" );
-                       }
+               // Install callback
+               overwritten = window[ callbackName ];
+               window[ callbackName ] = function() {
+                       responseContainer = arguments;
+               };
 
-                       elem = iframeDoc.createElement( nodeName );
+               // Clean-up function (fires after converters)
+               jqXHR.always(function() {
+                       // Restore preexisting value
+                       window[ callbackName ] = overwritten;
 
-                       iframeDoc.body.appendChild( elem );
+                       // Save back as free
+                       if ( s[ callbackName ] ) {
+                               // make sure that re-using the options doesn't screw things around
+                               s.jsonpCallback = originalSettings.jsonpCallback;
 
-                       display = jQuery.css( elem, "display" );
+                               // save the callback name for future use
+                               oldCallbacks.push( callbackName );
+                       }
 
-                       document.body.removeChild( iframe );
-               }
+                       // Call if it was a function and we have a response
+                       if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+                               overwritten( responseContainer[ 0 ] );
+                       }
 
-               // Store the correct default display
-               elemdisplay[ nodeName ] = display;
-       }
+                       responseContainer = overwritten = undefined;
+               });
 
-       return elemdisplay[ nodeName ];
-}
+               // Delegate to script
+               return "script";
+       }
+});
 
 
 
 
-var rtable = /^t(?:able|d|h)$/i,
-       rroot = /^(?:body|html)$/i;
+// data: string of html
+// context (optional): If specified, the fragment will be created in this context, defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+       if ( !data || typeof data !== "string" ) {
+               return null;
+       }
+       if ( typeof context === "boolean" ) {
+               keepScripts = context;
+               context = false;
+       }
+       context = context || document;
 
-if ( "getBoundingClientRect" in document.documentElement ) {
-       jQuery.fn.offset = function( options ) {
-               var elem = this[0], box;
+       var parsed = rsingleTag.exec( data ),
+               scripts = !keepScripts && [];
 
-               if ( options ) {
-                       return this.each(function( i ) {
-                               jQuery.offset.setOffset( this, options, i );
-                       });
-               }
+       // Single tag
+       if ( parsed ) {
+               return [ context.createElement( parsed[1] ) ];
+       }
 
-               if ( !elem || !elem.ownerDocument ) {
-                       return null;
-               }
+       parsed = jQuery.buildFragment( [ data ], context, scripts );
 
-               if ( elem === elem.ownerDocument.body ) {
-                       return jQuery.offset.bodyOffset( elem );
-               }
+       if ( scripts && scripts.length ) {
+               jQuery( scripts ).remove();
+       }
 
-               try {
-                       box = elem.getBoundingClientRect();
-               } catch(e) {}
+       return jQuery.merge( [], parsed.childNodes );
+};
 
-               var doc = elem.ownerDocument,
-                       docElem = doc.documentElement;
 
-               // Make sure we're not dealing with a disconnected DOM node
-               if ( !box || !jQuery.contains( docElem, elem ) ) {
-                       return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
-               }
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
 
-               var body = doc.body,
-                       win = getWindow(doc),
-                       clientTop  = docElem.clientTop  || body.clientTop  || 0,
-                       clientLeft = docElem.clientLeft || body.clientLeft || 0,
-                       scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
-                       scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
-                       top  = box.top  + scrollTop  - clientTop,
-                       left = box.left + scrollLeft - clientLeft;
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+       if ( typeof url !== "string" && _load ) {
+               return _load.apply( this, arguments );
+       }
 
-               return { top: top, left: left };
-       };
+       var selector, response, type,
+               self = this,
+               off = url.indexOf(" ");
 
-} else {
-       jQuery.fn.offset = function( options ) {
-               var elem = this[0];
+       if ( off >= 0 ) {
+               selector = jQuery.trim( url.slice( off, url.length ) );
+               url = url.slice( 0, off );
+       }
 
-               if ( options ) {
-                       return this.each(function( i ) {
-                               jQuery.offset.setOffset( this, options, i );
-                       });
-               }
+       // If it's a function
+       if ( jQuery.isFunction( params ) ) {
 
-               if ( !elem || !elem.ownerDocument ) {
-                       return null;
-               }
+               // We assume that it's the callback
+               callback = params;
+               params = undefined;
 
-               if ( elem === elem.ownerDocument.body ) {
-                       return jQuery.offset.bodyOffset( elem );
-               }
+       // Otherwise, build a param string
+       } else if ( params && typeof params === "object" ) {
+               type = "POST";
+       }
 
-               jQuery.offset.initialize();
+       // If we have elements to modify, make the request
+       if ( self.length > 0 ) {
+               jQuery.ajax({
+                       url: url,
 
-               var computedStyle,
-                       offsetParent = elem.offsetParent,
-                       prevOffsetParent = elem,
-                       doc = elem.ownerDocument,
-                       docElem = doc.documentElement,
-                       body = doc.body,
-                       defaultView = doc.defaultView,
-                       prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
-                       top = elem.offsetTop,
-                       left = elem.offsetLeft;
+                       // if "type" variable is undefined, then "GET" method will be used
+                       type: type,
+                       dataType: "html",
+                       data: params
+               }).done(function( responseText ) {
 
-               while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
-                       if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
-                               break;
-                       }
+                       // Save response for use in complete callback
+                       response = arguments;
 
-                       computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
-                       top  -= elem.scrollTop;
-                       left -= elem.scrollLeft;
+                       self.html( selector ?
 
-                       if ( elem === offsetParent ) {
-                               top  += elem.offsetTop;
-                               left += elem.offsetLeft;
+                               // If a selector was specified, locate the right elements in a dummy div
+                               // Exclude scripts to avoid IE 'Permission Denied' errors
+                               jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
 
-                               if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
-                                       top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
-                                       left += parseFloat( computedStyle.borderLeftWidth ) || 0;
-                               }
+                               // Otherwise use the full result
+                               responseText );
 
-                               prevOffsetParent = offsetParent;
-                               offsetParent = elem.offsetParent;
-                       }
+               }).complete( callback && function( jqXHR, status ) {
+                       self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+               });
+       }
 
-                       if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
-                               top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
-                               left += parseFloat( computedStyle.borderLeftWidth ) || 0;
-                       }
+       return this;
+};
 
-                       prevComputedStyle = computedStyle;
-               }
 
-               if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
-                       top  += body.offsetTop;
-                       left += body.offsetLeft;
-               }
 
-               if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
-                       top  += Math.max( docElem.scrollTop, body.scrollTop );
-                       left += Math.max( docElem.scrollLeft, body.scrollLeft );
-               }
 
-               return { top: top, left: left };
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+       jQuery.fn[ type ] = function( fn ) {
+               return this.on( type, fn );
        };
-}
-
-jQuery.offset = {
-       initialize: function() {
-               var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
-                       html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
-
-               jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
-
-               container.innerHTML = html;
-               body.insertBefore( container, body.firstChild );
-               innerDiv = container.firstChild;
-               checkDiv = innerDiv.firstChild;
-               td = innerDiv.nextSibling.firstChild.firstChild;
-
-               this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
-               this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+});
 
-               checkDiv.style.position = "fixed";
-               checkDiv.style.top = "20px";
 
-               // safari subtracts parent border width here which is 5px
-               this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
-               checkDiv.style.position = checkDiv.style.top = "";
 
-               innerDiv.style.overflow = "hidden";
-               innerDiv.style.position = "relative";
 
-               this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+jQuery.expr.filters.animated = function( elem ) {
+       return jQuery.grep(jQuery.timers, function( fn ) {
+               return elem === fn.elem;
+       }).length;
+};
 
-               this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
 
-               body.removeChild( container );
-               jQuery.offset.initialize = jQuery.noop;
-       },
 
-       bodyOffset: function( body ) {
-               var top = body.offsetTop,
-                       left = body.offsetLeft;
 
-               jQuery.offset.initialize();
 
-               if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
-                       top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
-                       left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
-               }
+var docElem = window.document.documentElement;
 
-               return { top: top, left: left };
-       },
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+       return jQuery.isWindow( elem ) ?
+               elem :
+               elem.nodeType === 9 ?
+                       elem.defaultView || elem.parentWindow :
+                       false;
+}
 
+jQuery.offset = {
        setOffset: function( elem, options, i ) {
-               var position = jQuery.css( elem, "position" );
+               var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+                       position = jQuery.css( elem, "position" ),
+                       curElem = jQuery( elem ),
+                       props = {};
 
                // set position first, in-case top/left are set even on static elem
                if ( position === "static" ) {
                        elem.style.position = "relative";
                }
 
-               var curElem = jQuery( elem ),
-                       curOffset = curElem.offset(),
-                       curCSSTop = jQuery.css( elem, "top" ),
-                       curCSSLeft = jQuery.css( elem, "left" ),
-                       calculatePosition = (position === "absolute" || position === "fixed") && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
-                       props = {}, curPosition = {}, curTop, curLeft;
+               curOffset = curElem.offset();
+               curCSSTop = jQuery.css( elem, "top" );
+               curCSSLeft = jQuery.css( elem, "left" );
+               calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+                       jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
 
                // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
                if ( calculatePosition ) {
@@ -8685,11 +10094,11 @@ jQuery.offset = {
                        options = options.call( elem, i, curOffset );
                }
 
-               if (options.top != null) {
-                       props.top = (options.top - curOffset.top) + curTop;
+               if ( options.top != null ) {
+                       props.top = ( options.top - curOffset.top ) + curTop;
                }
-               if (options.left != null) {
-                       props.left = (options.left - curOffset.left) + curLeft;
+               if ( options.left != null ) {
+                       props.left = ( options.left - curOffset.left ) + curLeft;
                }
 
                if ( "using" in options ) {
@@ -8700,166 +10109,243 @@ jQuery.offset = {
        }
 };
 
-
 jQuery.fn.extend({
+       offset: function( options ) {
+               if ( arguments.length ) {
+                       return options === undefined ?
+                               this :
+                               this.each(function( i ) {
+                                       jQuery.offset.setOffset( this, options, i );
+                               });
+               }
+
+               var docElem, win,
+                       box = { top: 0, left: 0 },
+                       elem = this[ 0 ],
+                       doc = elem && elem.ownerDocument;
+
+               if ( !doc ) {
+                       return;
+               }
+
+               docElem = doc.documentElement;
+
+               // Make sure it's not a disconnected DOM node
+               if ( !jQuery.contains( docElem, elem ) ) {
+                       return box;
+               }
+
+               // If we don't have gBCR, just use 0,0 rather than error
+               // BlackBerry 5, iOS 3 (original iPhone)
+               if ( typeof elem.getBoundingClientRect !== strundefined ) {
+                       box = elem.getBoundingClientRect();
+               }
+               win = getWindow( doc );
+               return {
+                       top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
+                       left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+               };
+       },
+
        position: function() {
-               if ( !this[0] ) {
-                       return null;
+               if ( !this[ 0 ] ) {
+                       return;
                }
 
-               var elem = this[0],
+               var offsetParent, offset,
+                       parentOffset = { top: 0, left: 0 },
+                       elem = this[ 0 ];
+
+               // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+               if ( jQuery.css( elem, "position" ) === "fixed" ) {
+                       // we assume that getBoundingClientRect is available when computed position is fixed
+                       offset = elem.getBoundingClientRect();
+               } else {
+                       // Get *real* offsetParent
+                       offsetParent = this.offsetParent();
 
-               // Get *real* offsetParent
-               offsetParent = this.offsetParent(),
+                       // Get correct offsets
+                       offset = this.offset();
+                       if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+                               parentOffset = offsetParent.offset();
+                       }
 
-               // Get correct offsets
-               offset       = this.offset(),
-               parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+                       // Add offsetParent borders
+                       parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+                       parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+               }
 
-               // Subtract element margins
+               // Subtract parent offsets and element margins
                // note: when an element has margin: auto the offsetLeft and marginLeft
                // are the same in Safari causing offset.left to incorrectly be 0
-               offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
-               offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
-
-               // Add offsetParent borders
-               parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
-               parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
-
-               // Subtract the two offsets
                return {
-                       top:  offset.top  - parentOffset.top,
-                       left: offset.left - parentOffset.left
+                       top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+                       left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
                };
        },
 
        offsetParent: function() {
                return this.map(function() {
-                       var offsetParent = this.offsetParent || document.body;
-                       while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+                       var offsetParent = this.offsetParent || docElem;
+
+                       while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
                                offsetParent = offsetParent.offsetParent;
                        }
-                       return offsetParent;
+                       return offsetParent || docElem;
                });
        }
 });
 
-
 // Create scrollLeft and scrollTop methods
-jQuery.each( ["Left", "Top"], function( i, name ) {
-       var method = "scroll" + name;
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+       var top = /Y/.test( prop );
 
        jQuery.fn[ method ] = function( val ) {
-               var elem, win;
-
-               if ( val === undefined ) {
-                       elem = this[ 0 ];
+               return access( this, function( elem, method, val ) {
+                       var win = getWindow( elem );
 
-                       if ( !elem ) {
-                               return null;
+                       if ( val === undefined ) {
+                               return win ? (prop in win) ? win[ prop ] :
+                                       win.document.documentElement[ method ] :
+                                       elem[ method ];
                        }
 
-                       win = getWindow( elem );
-
-                       // Return the scroll offset
-                       return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
-                               jQuery.support.boxModel && win.document.documentElement[ method ] ||
-                                       win.document.body[ method ] :
-                               elem[ method ];
-               }
-
-               // Set the scroll offset
-               return this.each(function() {
-                       win = getWindow( this );
-
                        if ( win ) {
                                win.scrollTo(
-                                       !i ? val : jQuery( win ).scrollLeft(),
-                                        i ? val : jQuery( win ).scrollTop()
+                                       !top ? val : jQuery( win ).scrollLeft(),
+                                       top ? val : jQuery( win ).scrollTop()
                                );
 
                        } else {
-                               this[ method ] = val;
+                               elem[ method ] = val;
                        }
-               });
+               }, method, val, arguments.length, null );
        };
 });
 
-function getWindow( elem ) {
-       return jQuery.isWindow( elem ) ?
-               elem :
-               elem.nodeType === 9 ?
-                       elem.defaultView || elem.parentWindow :
-                       false;
-}
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// getComputedStyle returns percent when specified for top/left/bottom/right
+// rather than make the css module depend on the offset module, we just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+       jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+               function( elem, computed ) {
+                       if ( computed ) {
+                               computed = curCSS( elem, prop );
+                               // if curCSS returns percentage, fallback to offset
+                               return rnumnonpx.test( computed ) ?
+                                       jQuery( elem ).position()[ prop ] + "px" :
+                                       computed;
+                       }
+               }
+       );
+});
 
 
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+       jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+               // margin is only for outerHeight, outerWidth
+               jQuery.fn[ funcName ] = function( margin, value ) {
+                       var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+                               extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
 
+                       return access( this, function( elem, type, value ) {
+                               var doc;
 
-// Create innerHeight, innerWidth, outerHeight and outerWidth methods
-jQuery.each([ "Height", "Width" ], function( i, name ) {
+                               if ( jQuery.isWindow( elem ) ) {
+                                       // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+                                       // isn't a whole lot we can do. See pull request at this URL for discussion:
+                                       // https://github.com/jquery/jquery/pull/764
+                                       return elem.document.documentElement[ "client" + name ];
+                               }
 
-       var type = name.toLowerCase();
+                               // Get document width or height
+                               if ( elem.nodeType === 9 ) {
+                                       doc = elem.documentElement;
 
-       // innerHeight and innerWidth
-       jQuery.fn["inner" + name] = function() {
-               return this[0] ?
-                       parseFloat( jQuery.css( this[0], type, "padding" ) ) :
-                       null;
-       };
+                                       // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+                                       // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+                                       return Math.max(
+                                               elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+                                               elem.body[ "offset" + name ], doc[ "offset" + name ],
+                                               doc[ "client" + name ]
+                                       );
+                               }
 
-       // outerHeight and outerWidth
-       jQuery.fn["outer" + name] = function( margin ) {
-               return this[0] ?
-                       parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :
-                       null;
-       };
+                               return value === undefined ?
+                                       // Get width or height on the element, requesting but not forcing parseFloat
+                                       jQuery.css( elem, type, extra ) :
 
-       jQuery.fn[ type ] = function( size ) {
-               // Get window width or height
-               var elem = this[0];
-               if ( !elem ) {
-                       return size == null ? null : this;
-               }
+                                       // Set width or height on the element
+                                       jQuery.style( elem, type, value, extra );
+                       }, type, chainable ? margin : undefined, chainable, null );
+               };
+       });
+});
 
-               if ( jQuery.isFunction( size ) ) {
-                       return this.each(function( i ) {
-                               var self = jQuery( this );
-                               self[ type ]( size.call( this, i, self[ type ]() ) );
-                       });
-               }
 
-               if ( jQuery.isWindow( elem ) ) {
-                       // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
-                       // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
-                       var docElemProp = elem.document.documentElement[ "client" + name ];
-                       return elem.document.compatMode === "CSS1Compat" && docElemProp ||
-                               elem.document.body[ "client" + name ] || docElemProp;
-
-               // Get document width or height
-               } else if ( elem.nodeType === 9 ) {
-                       // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
-                       return Math.max(
-                               elem.documentElement["client" + name],
-                               elem.body["scroll" + name], elem.documentElement["scroll" + name],
-                               elem.body["offset" + name], elem.documentElement["offset" + name]
-                       );
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+       return this.length;
+};
 
-               // Get or set width or height on the element
-               } else if ( size === undefined ) {
-                       var orig = jQuery.css( elem, type ),
-                               ret = parseFloat( orig );
+jQuery.fn.andSelf = jQuery.fn.addBack;
 
-                       return jQuery.isNaN( ret ) ? orig : ret;
 
-               // Set the width or height on the element (default to pixels if value is unitless)
-               } else {
-                       return this.css( type, typeof size === "string" ? size : size + "px" );
-               }
-       };
 
-});
 
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+       define( "jquery", [], function() {
+               return jQuery;
+       });
+}
+
+
+
+
+var
+       // Map over jQuery in case of overwrite
+       _jQuery = window.jQuery,
+
+       // Map over the $ in case of overwrite
+       _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+       if ( window.$ === jQuery ) {
+               window.$ = _$;
+       }
+
+       if ( deep && window.jQuery === jQuery ) {
+               window.jQuery = _jQuery;
+       }
+
+       return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in
+// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+       window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
 
-window.jQuery = window.$ = jQuery;
-})(window);
+}));
diff --git a/www/plugins/crayons/js/jquery.px.js b/www/plugins/crayons/js/jquery.px.js
deleted file mode 100644 (file)
index e6c195d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Ce plugin permet de recuperer css(fontSize) en px meme sous MSIE
-(function($){
-       $.fn.px = function(prop) {
-               var val;
-               if($.browser.msie) {
-                       $('<span><\/span>')
-                       .css({display: 'block', width: '1em'})
-                       .appendTo(this[0])
-                       .each(function(){
-                               val = parseInt($(this).width()) + 'px';
-                       })
-                       .remove();
-               } else {
-                       val = this.css(prop);
-               }
-               return val;
-       };
-})(jQuery);
index 47457dc..19d2419 100644 (file)
@@ -1,76 +1,82 @@
 <traduction module="crayons" gestionnaire="salvatore" url="http://trad.spip.net" source="svn://zone.spip.org/spip-zone/_plugins_/crayons/lang/" reference="fr">
-       <langue code="ar" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ar" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="ar" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ar" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="ast" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ast" total="51" traduits="39" relire="0" modifs="3" nouveaux="9" pourcent="76.47">
+       <langue code="ast" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ast" total="52" traduits="39" relire="0" modifs="3" nouveaux="10" pourcent="75.00">
                <traducteur nom="Xuacu" lien="http://trad.spip.net/auteur/xuacu" />
        </langue>
-       <langue code="br" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=br" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="br" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=br" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="ca" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ca" total="51" traduits="38" relire="0" modifs="2" nouveaux="11" pourcent="74.51">
+       <langue code="ca" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ca" total="52" traduits="38" relire="0" modifs="2" nouveaux="12" pourcent="73.08">
        </langue>
-       <langue code="de" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=de" total="51" traduits="46" relire="0" modifs="3" nouveaux="2" pourcent="90.20">
+       <langue code="de" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=de" total="52" traduits="52" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
                <traducteur nom="klaus++" lien="http://trad.spip.net/auteur/klaus" />
+               <traducteur nom="Torsten Willmann" lien="http://trad.spip.net/auteur/torsten-willmann" />
        </langue>
-       <langue code="en" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=en" total="51" traduits="51" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
+       <langue code="en" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=en" total="52" traduits="52" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
+               <traducteur nom="George" lien="http://trad.spip.net/auteur/جورج-قندلفت" />
                <traducteur nom="Hanjo" lien="http://trad.spip.net/auteur/hanjo" />
                <traducteur nom="kent1" lien="http://trad.spip.net/auteur/kent1" />
                <traducteur nom="Paolo" lien="http://trad.spip.net/auteur/paolo" />
        </langue>
-       <langue code="eo" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=eo" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="eo" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=eo" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="es" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=es" total="51" traduits="47" relire="0" modifs="3" nouveaux="1" pourcent="92.16">
+       <langue code="es" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=es" total="52" traduits="52" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
                <traducteur nom="dani" lien="http://trad.spip.net/auteur/dani" />
                <traducteur nom="Raquel S. Bujaldón" lien="http://trad.spip.net/auteur/raquel-s-bujaldon" />
                <traducteur nom="severo" lien="http://trad.spip.net/auteur/severo" />
        </langue>
-       <langue code="eu" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=eu" total="51" traduits="12" relire="0" modifs="0" nouveaux="39" pourcent="23.53">
+       <langue code="eu" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=eu" total="52" traduits="12" relire="0" modifs="0" nouveaux="40" pourcent="23.08">
        </langue>
-       <langue code="fa" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=fa" total="51" traduits="43" relire="0" modifs="3" nouveaux="5" pourcent="84.31">
+       <langue code="fa" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=fa" total="52" traduits="43" relire="0" modifs="3" nouveaux="6" pourcent="82.69">
                <traducteur nom="Davood Hossein" lien="http://trad.spip.net/auteur/davood-hossein" />
        </langue>
-       <langue code="fr" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=fr" total="51" traduits="51" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
+       <langue code="fr" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=fr" total="52" traduits="52" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
        </langue>
-       <langue code="fr_tu" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=fr_tu" total="51" traduits="47" relire="0" modifs="3" nouveaux="1" pourcent="92.16">
+       <langue code="fr_tu" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=fr_tu" total="52" traduits="47" relire="0" modifs="3" nouveaux="2" pourcent="90.38">
                <traducteur nom="beatnick" lien="http://trad.spip.net/auteur/beatnick" />
                <traducteur nom="Cerf" lien="http://trad.spip.net/auteur/cerf" />
        </langue>
-       <langue code="gl" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=gl" total="51" traduits="15" relire="0" modifs="0" nouveaux="36" pourcent="29.41">
+       <langue code="gl" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=gl" total="52" traduits="15" relire="0" modifs="0" nouveaux="37" pourcent="28.85">
        </langue>
-       <langue code="it" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=it" total="51" traduits="39" relire="0" modifs="3" nouveaux="9" pourcent="76.47">
+       <langue code="it" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=it" total="52" traduits="39" relire="0" modifs="3" nouveaux="10" pourcent="75.00">
                <traducteur nom="Fil" lien="http://trad.spip.net/auteur/fil" />
        </langue>
-       <langue code="it_fem" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=it_fem" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="it_fem" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=it_fem" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="km" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=km" total="51" traduits="5" relire="0" modifs="0" nouveaux="46" pourcent="9.80">
+       <langue code="km" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=km" total="52" traduits="5" relire="0" modifs="0" nouveaux="47" pourcent="9.62">
        </langue>
-       <langue code="lb" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=lb" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="lb" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=lb" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="nl" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=nl" total="51" traduits="51" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
+       <langue code="nl" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=nl" total="52" traduits="52" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
                <traducteur nom="Hanjo" lien="http://trad.spip.net/auteur/hanjo" />
                <traducteur nom="mpossoz" lien="http://trad.spip.net/auteur/mpossoz" />
                <traducteur nom="Suske" lien="http://trad.spip.net/auteur/suske" />
        </langue>
-       <langue code="oc_lnc" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=oc_lnc" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="oc_lnc" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=oc_lnc" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="pt_br" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=pt_br" total="51" traduits="14" relire="0" modifs="2" nouveaux="35" pourcent="27.45">
+       <langue code="oc_ni_mis" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=oc_ni_mis" total="52" traduits="52" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
+               <traducteur nom="sylvain" lien="http://trad.spip.net/auteur/sylvain" />
+       </langue>
+       <langue code="pt_br" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=pt_br" total="52" traduits="52" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
                <traducteur nom="Ricardo Porto" lien="http://trad.spip.net/auteur/ricardo-porto" />
        </langue>
-       <langue code="ro" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ro" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="ro" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ro" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="ru" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ru" total="51" traduits="46" relire="0" modifs="3" nouveaux="2" pourcent="90.20">
+       <langue code="ru" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=ru" total="52" traduits="48" relire="0" modifs="1" nouveaux="3" pourcent="92.31">
+               <traducteur nom="olly" lien="http://trad.spip.net/auteur/olly" />
                <traducteur nom="Serge Markitanenko" lien="http://trad.spip.net/auteur/serge-markitanenko" />
        </langue>
-       <langue code="sk" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=sk" total="51" traduits="51" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
+       <langue code="sk" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=sk" total="52" traduits="52" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
                <traducteur nom="jaro" lien="http://trad.spip.net/auteur/jaro" />
        </langue>
-       <langue code="sv" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=sv" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="sv" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=sv" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="tr" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=tr" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="tr" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=tr" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="tw" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=tw" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="tw" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=tw" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
-       <langue code="zh" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=zh" total="51" traduits="18" relire="0" modifs="14" nouveaux="19" pourcent="35.29">
+       <langue code="zh" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=zh" total="52" traduits="18" relire="0" modifs="14" nouveaux="20" pourcent="34.62">
        </langue>
-       <langue code="zh_tw" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=zh_tw" total="51" traduits="14" relire="0" modifs="0" nouveaux="37" pourcent="27.45">
+       <langue code="zh_tw" url="http://trad.spip.net/tradlang_module/crayons?lang_cible=zh_tw" total="52" traduits="14" relire="0" modifs="0" nouveaux="38" pourcent="26.92">
        </langue>
 </traduction>
index 59d569c..e76b9e6 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=ar
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'الرجاء الانتظار...'
 );
-
-?>
index 8c0a6e6..5ec334e 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=ast
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -75,5 +77,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Un momentu...'
 );
-
-?>
index eb2e2b8..11397a8 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=br
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Gortozit...'
 );
-
-?>
index da5048f..a8f5405 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=ca
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -72,5 +74,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Si us plau, espereu un moment...'
 );
-
-?>
index ad9342d..87da042 100644 (file)
@@ -3,11 +3,14 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=de
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
        // A
+       'absence_cle_primaire' => 'Kein Primärschlüssel vorhanden!',
        'activation_barre_impossible' => 'Ein anderes Plugin verhindert den Einsatz des Federhalters im öffentlichen Bereich.',
        'annuler' => 'Abbrechen',
 
@@ -24,10 +27,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'editer_tout' => 'Alles bearbeiten',
        'effets' => 'Effekte',
        'explication_exec_autorise' => 'Zur Bearbeitung zugelassene Seiten
-  (?exec=...) : (exec-Skripte mit Komma trennen).', # MODIF
-       'explication_introduction_article' => 'Die Einleitung eines Artikels zeigt das Feld "Beschreibung" an. Sollte es leer sein, werden die ersten  600 Zeichen des Artikels aus den Feldern "Kopf" und "Text" angezeigt.', # MODIF
+  (?exec=...) : (exec-Skripte mit Komma trennen).',
+       'explication_introduction_article' => 'Die Einleitung eines Artikels zeigt das Feld "Beschreibung" an. Sollte es leer sein, werden die ersten  600 Zeichen des Artikels aus den Feldern "Kopf" und "Text" angezeigt.',
        'explication_reduire_logo' => 'Logo verkleinern wenn es größer als x Pixel ist.
-Beispiel: 100. (0 = niemals)', # MODIF
+Beispiel: 100. (0 = niemals)',
 
        // I
        'info_experimental' => 'Expérimentell',
@@ -47,6 +50,7 @@ Beispiel: 100. (0 = niemals)', # MODIF
        'label_reduire_logo' => 'Logos verkleinern',
        'label_upload_document' => 'Hinzufügen von Dokumenten durch Ziehen/Ablegen auf den Stift article.texte erlauben.',
        'label_yellow_fade' => 'Ausblenden',
+       'legend_controleur_fichier_remplacer' => 'Ersetze das Dokument "@extension@"',
        'legend_controleur_hyperlien' => 'Hyperlink',
        'legend_controleur_logo' => 'Logoe wählen:',
        'legend_controleur_logo_remplacer' => 'Dieses Logo ersetzen',
@@ -56,6 +60,7 @@ Beispiel: 100. (0 = niemals)', # MODIF
        'legend_documents' => 'Dokumente hochladen',
        'legend_editer_prive' => 'Stifte im Redaktionssystem (experimentell)',
        'legend_introduction_article' => 'Einleitender Text des Artikels',
+       'legend_introduction_rubrique' => 'Einführender Text der Rubrik',
 
        // M
        'message_image_obligatoire' => 'Es muß ein Bild gewählt werden.',
@@ -84,5 +89,3 @@ Beispiel: 100. (0 = niemals)', # MODIF
        // V
        'veuillez_patienter' => 'Bitte etwas Geduld...'
 );
-
-?>
index 1ec094a..61faa60 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=en
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -58,6 +60,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'legend_documents' => 'Upload documents',
        'legend_editer_prive' => 'Use in editing area (experimental)',
        'legend_introduction_article' => 'Introductory text for the article',
+       'legend_introduction_rubrique' => 'Section’s introductory text',
 
        // M
        'message_image_obligatoire' => 'You need to choose an image',
@@ -86,5 +89,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Searching ...'
 );
-
-?>
index a081b8c..6f5cd01 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=eo
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Bonvolu atendi...'
 );
-
-?>
index f1a52ab..30ed514 100644 (file)
@@ -3,11 +3,14 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=es
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
        // A
+       'absence_cle_primaire' => '¡No hay clave primaria!',
        'activation_barre_impossible' => 'Otro plugin impide el uso del porta-plumas en el espacio público.',
        'annuler' => 'Cancelar',
 
@@ -24,10 +27,11 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'editer_tout' => 'Editar todo',
        'effets' => 'Efectos',
        'explication_exec_autorise' => 'Páginas cuya modificación es permitida
-  (?exec=...): (, para separar los exec - * para todas).', # MODIF
-       'explication_introduction_article' => 'La introducción de un artículo enseña la descripción del artículo, o los primeros 600 carácteres (epígrafe y luego texto).', # MODIF
+         (?exec=...): (, para separar los exec - * para todas).',
+       'explication_introduction_article' => 'La introducción de un artículo muestra la descripción del artículo, 
+   si no los primeros 600 carácteres (epígrafe y luego texto).',
        'explication_reduire_logo' => 'Reducir el logotipo si va mas allá
-  del tamaño indicado en píxeles. Ejemplo: 100. (0 = nunca)', # MODIF
+  del tamaño indicado en píxeles. Ejemplo: 100. (0 = nunca)',
 
        // I
        'info_experimental' => 'Experimental',
@@ -57,6 +61,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'legend_documents' => 'Subir documentos',
        'legend_editer_prive' => 'Edición en el espacio privado (experimental)',
        'legend_introduction_article' => 'Texto introductivo del artículo',
+       'legend_introduction_rubrique' => 'Texto introductorio de la sección',
 
        // M
        'message_image_obligatoire' => 'Hay que escoger una imagen',
@@ -85,5 +90,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Favor esperar...'
 );
-
-?>
index 61abab6..aa0ab7d 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=eu
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -33,5 +35,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // S
        'sauvegarder' => 'Aldaketak grabatu ?'
 );
-
-?>
index 7b81532..8d1d863 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=fa
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -78,5 +80,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'لطفأ صبر کنید ...'
 );
-
-?>
index 2f0b72e..0c117d0 100644 (file)
@@ -1,7 +1,9 @@
 <?php
 // This is a SPIP language file  --  Ceci est un fichier langue de SPIP
 // Fichier source, a modifier dans svn://zone.spip.org/spip-zone/_plugins_/crayons/lang/
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -57,6 +59,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'legend_documents' => 'Upload de documents',
        'legend_editer_prive' => 'Éditer l’espace privé (expérimental)',
        'legend_introduction_article' => 'Texte introductif de l’article',
+       'legend_introduction_rubrique' => 'Texte introductif de la rubrique',
 
        // M
        'message_image_obligatoire' => 'Il faut choisir une image',
@@ -85,5 +88,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Veuillez patienter...'
 );
-
-?>
index e40b7aa..93cf39f 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=fr_tu
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -84,5 +86,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Patiente stp...'
 );
-
-?>
index d4f7042..60eb1f0 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=gl
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -40,5 +42,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Teña paciencia ...'
 );
-
-?>
index 250ac4c..2e74f9b 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=it
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -75,5 +77,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Attendere...'
 );
-
-?>
index 1f15e0e..bb64280 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=it_fem
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Attendere...'
 );
-
-?>
index 53683e8..ab6557a 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=km
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -20,5 +22,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'កំពុងស្វែងរក ...'
 );
-
-?>
index 8cefa80..eebe4de 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=lb
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Waart weg...'
 );
-
-?>
index d37c32d..b2b8b3a 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=nl
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -58,6 +60,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'legend_documents' => 'Upload van documenten',
        'legend_editer_prive' => 'Bewerk het private deel (experimenteel)',
        'legend_introduction_article' => 'Aanhef van artikel',
+       'legend_introduction_rubrique' => 'Introductietekst van de rubriek',
 
        // M
        'message_image_obligatoire' => 'U moet een afbeelding kiezen',
@@ -86,5 +89,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Een ogenblik geduld…'
 );
-
-?>
index 7a0de8f..0e64e80 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=oc_lnc
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Mercés d’esperar...'
 );
-
-?>
diff --git a/www/plugins/crayons/lang/crayons_oc_ni_mis.php b/www/plugins/crayons/lang/crayons_oc_ni_mis.php
new file mode 100644 (file)
index 0000000..9264d88
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+// This is a SPIP language file  --  Ceci est un fichier langue de SPIP
+// extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=oc_ni_mis
+// ** ne pas modifier le fichier **
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
+
+$GLOBALS[$GLOBALS['idx_lang']] = array(
+
+       // A
+       'absence_cle_primaire' => 'Mìnga de clau primari !',
+       'activation_barre_impossible' => 'Un autre plugin prouhibì l’usage dóu pouòrta-pluma en l’espaci pùblicou.',
+       'annuler' => 'Anulà',
+
+       // B
+       'bouton_supprimer' => 'Suprimà',
+
+       // D
+       'deja_modifie' => 'Jà moudificat',
+       'donnees_mal_formatees' => 'Dounada mau fourmatadi',
+
+       // E
+       'editer' => 'Edità',
+       'editer_@type@_@id@' => 'Edità @type@ @id@ en entié',
+       'editer_tout' => 'Edità tout',
+       'effets' => 'Efet',
+       'explication_exec_autorise' => 'Pàgina autourisadi a la moudificacioun
+        (?exec=...) : (, da separà lu exec - * per touti).',
+       'explication_introduction_article' => 'L’introuductioun d’un article aficha lou descritiéu de l’article,
+    senoun aficha lu siéu 600 premié caracter (capéu pi tèstou).',
+       'explication_reduire_logo' => 'Redurre lou lògou s’escoumpassa
+        la talha massimala endicada en pixel. Per isemple : 100. (0 = jamai)',
+
+       // I
+       'info_experimental' => 'Esperimental',
+
+       // L
+       'label_activer_barre_typo' => 'Ativà la barra tipougràfica en lu creioun ?',
+       'label_activer_crayons_prive' => 'Ativà creioun per la partida privada.',
+       'label_barre_typo' => 'Barra tipougràfica',
+       'label_clickhide' => 'Un clic endefouòra escounde lu creioun',
+       'label_effets' => 'Chausida dei efet',
+       'label_espaceprive' => 'Creioun en lou privat ?',
+       'label_exec_autorise' => 'Pàgina autourisadi',
+       'label_filet' => 'Ret',
+       'label_message' => 'Outenì un message',
+       'label_msg_abandon' => 'Sus abandoun',
+       'label_msg_no_change' => 'Se mìnga de cambiamen',
+       'label_reduire_logo' => 'Redurre lu lògou',
+       'label_upload_document' => 'Autourisà l’ajoutamen de doucument da resquilhà/depousà soubre lou creioun article.texte',
+       'label_yellow_fade' => 'Fade',
+       'legend_controleur_fichier_remplacer' => 'Remplaçà aquestou doucumen "@extension@"',
+       'legend_controleur_hyperlien' => 'Iperestac',
+       'legend_controleur_logo' => 'Chausì un logou :',
+       'legend_controleur_logo_remplacer' => 'Remplaçà aquestou lògou',
+       'legend_controleur_qui' => 'Qu ?',
+       'legend_controleur_vignette' => 'Chausì una vigneta :',
+       'legend_controleur_vignette_remplacer' => 'Remplaçà aquesta vigneta',
+       'legend_documents' => 'Televersagiamen de doucumen',
+       'legend_editer_prive' => 'Edità l’espaci privat (esperimental)',
+       'legend_introduction_article' => 'Tèstou introudutiéu de l’article',
+       'legend_introduction_rubrique' => 'Tèstou introudutiéu de la rùbrica',
+
+       // M
+       'message_image_obligatoire' => 'Cau chausì una image',
+       'messages' => 'Message',
+       'modifie_par_ailleurs' => 'Moudificat per autre',
+
+       // N
+       'non_autorise' => 'Noun autourisat',
+       'non_implemente' => 'Noun impletut',
+
+       // P
+       'pas_de_modification' => 'Mìnga moudificacioun',
+       'pas_de_valeur' => 'Mìnga valour',
+
+       // S
+       'sauvegarder' => 'Sauvagarda li moudificacioun ?',
+       'svp_copier_coller' => 'Achident, coupiàs/coulàs lu vouòstre cambiamen e recoumençàs',
+
+       // T
+       'titre_config_crayons' => 'Counfigurà lu creioun',
+       'titre_crayons' => 'Creioun',
+
+       // U
+       'update_impossible' => 'La messa a jou a souhit.',
+
+       // V
+       'veuillez_patienter' => 'Vourguès aspera...'
+);
index 010cfed..97c5122 100644 (file)
@@ -3,13 +3,20 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=pt_br
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
        // A
+       'absence_cle_primaire' => 'Sem chave primária!',
+       'activation_barre_impossible' => 'Um outro plugin impede o uso da barra de formatação na área pública.',
        'annuler' => 'Cancelar',
 
+       // B
+       'bouton_supprimer' => 'Excluir',
+
        // D
        'deja_modifie' => 'Já alterado',
        'donnees_mal_formatees' => 'Dados mal formatados',
@@ -18,12 +25,45 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'editer' => 'Editar',
        'editer_@type@_@id@' => 'Editar @type@ @id@ completamente',
        'editer_tout' => 'Editar tudo',
-       'explication_exec_autorise' => 'Pages autorisées à la modification
-               (?exec=...) : (, pour séparer les exec).', # MODIF
-       'explication_reduire_logo' => 'Réduire le logo s’il dépasse
-               la taille maximale indiquee en pixels. Exemple : 100. (0 = jamais)', # MODIF
+       'effets' => 'Efeitos',
+       'explication_exec_autorise' => 'Páginas liberadas para modificação
+               (?exec=...) : (, para separar os exec).',
+       'explication_introduction_article' => 'A introdução de uma matéria exibe a descrição da matéria; se não existir, exibe os seus primeiros 600 caracteres (introdução mais texto).',
+       'explication_reduire_logo' => 'Reduzir o logo se ultrapassar o tamanho máximo indicado em pixels. Exemplo: 100.  (0 = jamais)',
+
+       // I
+       'info_experimental' => 'Experimental',
+
+       // L
+       'label_activer_barre_typo' => 'Ativar a barra de formatação nos crayons?',
+       'label_activer_crayons_prive' => 'Ativar crayons na área restrita.',
+       'label_barre_typo' => 'Barra de formatação',
+       'label_clickhide' => 'Um clique fora esconde os crayons',
+       'label_effets' => 'Escolha dos efeitos',
+       'label_espaceprive' => 'Crayons na área restrita?',
+       'label_exec_autorise' => 'Páginas liberadas',
+       'label_filet' => 'Linha',
+       'label_message' => 'Exibir uma mensagem',
+       'label_msg_abandon' => 'No cancelamento',
+       'label_msg_no_change' => 'Se não houve alteração',
+       'label_reduire_logo' => 'Reduzir os logos',
+       'label_upload_document' => 'Permitir a anexação de documentos por arrastar/soltar no crayon article.texte',
+       'label_yellow_fade' => 'Fade',
+       'legend_controleur_fichier_remplacer' => 'Substituir este documento "@extension@"',
+       'legend_controleur_hyperlien' => 'Hyperlink',
+       'legend_controleur_logo' => 'Escolher um logo:',
+       'legend_controleur_logo_remplacer' => 'substituir este logo',
+       'legend_controleur_qui' => 'Quem?',
+       'legend_controleur_vignette' => 'Escolher uma miniatura:',
+       'legend_controleur_vignette_remplacer' => 'Substituir esta miniatura',
+       'legend_documents' => 'Upload de documentos',
+       'legend_editer_prive' => 'Editar a área restrita (experimental)',
+       'legend_introduction_article' => 'Texto introdutório da matéria',
+       'legend_introduction_rubrique' => 'Texto introdutório da seção',
 
        // M
+       'message_image_obligatoire' => 'É necessário escolher uma imagem',
+       'messages' => 'Mensages',
        'modifie_par_ailleurs' => 'Alterado em outro lugar',
 
        // N
@@ -38,8 +78,13 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'sauvegarder' => 'Fazer cópia de segurança das alterações?',
        'svp_copier_coller' => 'Desculpe, copie/cole as suas alterações e recomece',
 
+       // T
+       'titre_config_crayons' => 'Configurar os crayons',
+       'titre_crayons' => 'Crayons',
+
+       // U
+       'update_impossible' => 'A atualização falhou.',
+
        // V
        'veuillez_patienter' => 'Aguarde, por favor...'
 );
-
-?>
index 0cfdfd5..363b1a2 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=ro
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Va rugam sa asteptati'
 );
-
-?>
index 685e6f1..407bd00 100644 (file)
@@ -3,12 +3,14 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=ru
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
        // A
-       'activation_barre_impossible' => 'Ð\94Ñ\80Ñ\83гой Ð¿Ð»Ð°Ð³Ð¸Ð½ Ð½Ðµ Ð´Ð°Ð¹ÐµÑ\82 Ð¸Ñ\81полÑ\8cзоваÑ\82Ñ\8c porte-plume Ð½Ð° Ñ\81айÑ\82е.',
+       'activation_barre_impossible' => 'Другой плагин не дает использовать porte-plume на сайте.',
        'annuler' => 'Отмена',
 
        // B
@@ -24,9 +26,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'editer_tout' => 'Редактировать полностью',
        'effets' => 'Эффекты',
        'explication_exec_autorise' => 'Страницы, на которых можно редактировать информацию   (?exec=...) : (, разделитель между страницами. * для всех страниц).', # MODIF
-       'explication_introduction_article' => 'Вводная статьи выводит информацию из поля "введение". Если оно пустое, товыводится первые 600 символов текста статьи.', # MODIF
-       'explication_reduire_logo' => 'Уменьшать логотипы если их размер превышает 
-  максимальный размер (в пикселях) Например: 100. (0 = никогда)', # MODIF
+       'explication_introduction_article' => 'Вводная статьи выводит информацию из поля "введение". Если оно пустое, то выводятся первые 600 символов текста статьи.',
+       'explication_reduire_logo' => 'Уменьшать логотипы, если их размер превышает  максимальный размер (в пикселях). Например: 100. (0 = никогда)',
 
        // I
        'info_experimental' => 'Экспериментальная опция',
@@ -35,7 +36,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'label_activer_barre_typo' => 'Включить панель инструментов для плагина?',
        'label_activer_crayons_prive' => 'Включить "Карандаш" в админке сайта',
        'label_barre_typo' => 'Панель инструментов',
-       'label_clickhide' => 'Нажмите вне области редактирования чтобы закрыть экран',
+       'label_clickhide' => 'Нажмите вне области редактирования, чтобы закрыть экран',
        'label_effets' => 'Выбрать эффект',
        'label_espaceprive' => 'Использовать "Карандаш" в админке сайта?',
        'label_exec_autorise' => 'Использовать на страницах',
@@ -83,5 +84,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Идет поиск ...'
 );
-
-?>
index 67ac8e7..b671f99 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=sk
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -58,6 +60,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'legend_documents' => 'Nahrávanie súborov',
        'legend_editer_prive' => 'Použiť v súkromnej zóne (experimentálne)',
        'legend_introduction_article' => 'Úvodný text článku',
+       'legend_introduction_rubrique' => 'Úvodný text rubriky',
 
        // M
        'message_image_obligatoire' => 'Musíte si vybrať obrázok',
@@ -86,5 +89,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Vyhľadáva sa...'
 );
-
-?>
index 3e39ca4..a8842ba 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=sv
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Söker ...'
 );
-
-?>
index 8ebba7b..6882529 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=tr
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => 'Lütfen sabrediniz...'
 );
-
-?>
index fb81ae5..e1e55c4 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=tw
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => '請稍後...'
 );
-
-?>
index c82b8f6..0fa3929 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=zh
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -61,5 +63,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => '请稍后...' # MODIF
 );
-
-?>
index 1c510b6..e3f81bd 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/crayons?lang_cible=zh_tw
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -37,5 +39,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        // V
        'veuillez_patienter' => '請稍後...'
 );
-
-?>
index 0357c88..239cf31 100644 (file)
                <traducteur nom="Hanjo" lien="http://trad.spip.net/auteur/hanjo" />
                <traducteur nom="Suske" lien="http://trad.spip.net/auteur/suske" />
        </langue>
+       <langue code="oc_ni_mis" url="http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=oc_ni_mis" total="3" traduits="3" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
+               <traducteur nom="sylvain" lien="http://trad.spip.net/auteur/sylvain" />
+       </langue>
+       <langue code="pt_br" url="http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=pt_br" total="3" traduits="3" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
+               <traducteur nom="Ricardo Porto" lien="http://trad.spip.net/auteur/ricardo-porto" />
+       </langue>
        <langue code="ru" url="http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=ru" total="3" traduits="3" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
                <traducteur nom="Serge Markitanenko" lien="http://trad.spip.net/auteur/serge-markitanenko" />
        </langue>
index bda2a8a..7dc9876 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=ar
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -15,5 +17,3 @@ _ <code><h1 class="#EDIT{titre} علامات اخرى">#TITRE</h1></code>.',
        'crayons_nom' => 'القلم',
        'crayons_slogan' => 'هذا الملحق، {{المتوافر للاصدار ١'
 );
-
-?>
index c65267d..c9af9c6 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=de
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Der Stift',
        'crayons_slogan' => 'Änderungen in öffentlichen Seiten direkt erledigen, Vorausetzung für Wikis mit SPIP'
 );
-
-?>
index 6c6c838..4156e9f 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=en
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Pencils',
        'crayons_slogan' => 'Quick editing from the public pages of the site'
 );
-
-?>
index 2033181..e7d96d2 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=es
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Lápices',
        'crayons_slogan' => 'Edición rápida desde las páginas publicas del sitio'
 );
-
-?>
index c6d29e6..63a7af1 100644 (file)
@@ -1,7 +1,9 @@
 <?php
 // This is a SPIP language file  --  Ceci est un fichier langue de SPIP
 // Fichier source, a modifier dans svn://zone.spip.org/spip-zone/_plugins_/crayons/lang/
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -10,5 +12,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Crayons',
        'crayons_slogan' => 'Édition rapide depuis les pages publiques du site'
 );
-
-?>
index e011659..3212e44 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=fr_tu
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Crayons',
        'crayons_slogan' => 'Édition rapide depuis les pages publiques du site'
 );
-
-?>
index 4c0bccd..0f893fd 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=it
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Pennarelli',
        'crayons_slogan' => 'Modifica rapida dalle pagine pubbliche del sito'
 );
-
-?>
index d31690d..ed26712 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=nl
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Krijtjes',
        'crayons_slogan' => 'Snel bewerken vanaf de publieke pagina’s van de site.'
 );
-
-?>
diff --git a/www/plugins/crayons/lang/paquet-crayons_oc_ni_mis.php b/www/plugins/crayons/lang/paquet-crayons_oc_ni_mis.php
new file mode 100644 (file)
index 0000000..f7081ae
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+// This is a SPIP language file  --  Ceci est un fichier langue de SPIP
+// extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=oc_ni_mis
+// ** ne pas modifier le fichier **
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
+
+$GLOBALS[$GLOBALS['idx_lang']] = array(
+
+       // C
+       'crayons_description' => 'Edicioun rapide despì li pàgina publiqui dóu sit.',
+       'crayons_nom' => 'Creioun',
+       'crayons_slogan' => 'Edicioun rapide despì li pàgina publiqui dóu sit'
+);
diff --git a/www/plugins/crayons/lang/paquet-crayons_pt_br.php b/www/plugins/crayons/lang/paquet-crayons_pt_br.php
new file mode 100644 (file)
index 0000000..66f6d46
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+// This is a SPIP language file  --  Ceci est un fichier langue de SPIP
+// extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=pt_br
+// ** ne pas modifier le fichier **
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
+
+$GLOBALS[$GLOBALS['idx_lang']] = array(
+
+       // C
+       'crayons_description' => 'Edição rápida diretamente nas páginas públicas do site.',
+       'crayons_nom' => 'Crayons',
+       'crayons_slogan' => 'Edição rápida diretamente nas páginas públicas do site'
+);
index 8ad6491..a14bd92 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=ru
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Карандаш (Crayons)',
        'crayons_slogan' => 'Позволяет редактировать информацию прямо на сайте, не заходя в административную часть'
 );
-
-?>
index 887f14c..a4f5c3e 100644 (file)
@@ -3,7 +3,9 @@
 // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-crayons?lang_cible=sk
 // ** ne pas modifier le fichier **
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
@@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
        'crayons_nom' => 'Farbičky',
        'crayons_slogan' => 'Rýchle úpravy z verejne prístupnej stránky.'
 );
-
-?>
index d3725ba..d0ad5da 100644 (file)
@@ -1,7 +1,7 @@
 <paquet\r
        prefix="crayons"\r
        categorie="edition"\r
-       version="1.20.0"\r
+       version="1.25.0"\r
        etat="stable"\r
        compatibilite="[1.9.0;3.*.*]"\r
        logo="images/crayon-32.png"\r
index b0a96ae..6520240 100644 (file)
@@ -16,7 +16,7 @@
                &#169; 2006-2013 - GNU/GPL\r
        </licence>\r
        <version>\r
-       1.20.0\r
+       1.25.0\r
        </version>\r
        <etat>\r
        stable\r
index 75eae3d..bf4b8fc 100644 (file)
@@ -1,10 +1,10 @@
 <svn_revision>
 <text_version>
 Origine: file:///home/svn/repository/spip-zone/_plugins_/crayons
-Revision: 85059
-Dernier commit: 2014-10-08 16:00:22 +0200 
+Revision: 98168
+Dernier commit: 2016-06-02 06:04:03 +0200 
 </text_version>
 <origine>file:///home/svn/repository/spip-zone/_plugins_/crayons</origine>
-<revision>85059</revision>
-<commit>2014-10-08 16:00:22 +0200 </commit>
+<revision>98168</revision>
+<commit>2016-06-02 06:04:03 +0200 </commit>
 </svn_revision>
\ No newline at end of file
index fa9e19e..ec1504f 100644 (file)
@@ -1,17 +1,17 @@
 <?php
 /**
- * Crayons 
- * plugin for spip 
+ * Crayons
+ * plugin for spip
  * (c) Fil, toggg 2006-2013
  * licence GPL
  *
  */
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 // Compatibilite eventuelle pour les plugins.
 // Ce fichier est normallement inutile.
 
 include_spip('crayons_fonctions');
-
-?>
index 9dacf6e..30dc4c4 100644 (file)
@@ -1,7 +1,9 @@
 <?php
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
-       include_spip('inc/extra');
-       include_spip('inc/presentation');
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
-?>
\ No newline at end of file
+
+include_spip('inc/extra');
+include_spip('inc/presentation');
diff --git a/www/plugins/crayons/vues/rubrique_introduction.html b/www/plugins/crayons/vues/rubrique_introduction.html
new file mode 100644 (file)
index 0000000..3dd8fe8
--- /dev/null
@@ -0,0 +1,9 @@
+[(#REM)
+
+       Vue pour le crayon 'rubrique_introduction'
+
+]
+#CACHE{0}
+<BOUCLE_a(RUBRIQUES){id_rubrique}{statut==.}>
+#INTRODUCTION
+</BOUCLE_a>