11488 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

J'ai retravaillé le tuto de l'accordéon jquery du site. Pas de problème sauf à la ligne 97, cette portion de code.


else {
   $('li.toggleSubMenu').each( function() {
      if ($(this).hasClass('open'))
         $('.toggleSubMenu.open > a').attr({title: 'Cacher le menu'});
      else $('.toggleSubMenu > a').attr({title: 'Afficher le menu'});
   });
}


Pas d'explications, c'est plutôt explicite. C'est une des nombreuses solutions que j'ai testé. Pour l'instant, je n'obtient que "afficher le menu". Donc, pour moi, c'est la ligne 99(hasClass) qui n'est pas correcte. Comment cibler ces liens en fontion de la classe open?

Je vous joint le code complet, c'est un test Smiley cligne



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr-FR">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<meta http-equiv="Content-Language" content="fr-FR" dir="ltr" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta http-equiv="imagetoolbar" content="no" />
<meta name="Robots" content="none" />
<title>tests jquery</title>
<!--<link rel="stylesheet" rev="stylesheet" type="text/css" href="skins/defaut/css/styles.css" media="all" />-->
<style type="text/css">
html,body {
	font-size: 10pt;
	font-family: Verdana, Geneva, Arial, Helvetica, "DejaVu Sans Mono", "Bitstream Vera Sans Mono", sans-serif;
	color: #444;
}
#centre {
	/*background: url(../images/header2.png) top left no-repeat;*/
	margin-left: auto;
	margin-right: auto;
	width: 780px;
	height: 100%;
	text-align: left;
}
#navigation {
	margin: 0;
	padding: 0;
	list-style: none;
	background-color: #404040;
	color: #fff;
	width: 200px;
}

#navigation a,#navigation span {
	display: block;
	padding: 6px 10px;
	color: #fff;
	text-decoration: none;
	height: 18px;
	/*background: #000 url(skins/defaut/images/menu-item.png) no-repeat left bottom;*/
	background-color: #404040;
}

#navigation .toggleSubMenu a,#navigation .toggleSubMenu span {
	background: #000 url(skins/defaut/images/menu-item-deroule.png) no-repeat left top;
}

#navigation .open a,#navigation .open span {
	background: #000 url(skins/defaut/images/menu-item-enroule.png) no-repeat left top;
}

#navigation a:hover,#navigation a:focus,#navigation a:active {
	color: #C00;
}

#navigation .subMenu {
	background: #ccc url(skins/defaut/images/subMenu.png) repeat-x 0 0;
	margin: 0;
	padding: 0;
	border-bottom: 1px solid #666;
	border-top: 1px solid #666;
}

#navigation ul.subMenu a {
	background: none;
	padding: 3px 20px;
}
</style>
<!--[if lte IE 6]>
	<style type="text/css">
		li {
			height: 1px;
			}
	</style>
<![endif]-->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<!-- <script type="text/javascript" src="skins/defaut/js/jquery-1.4.4.min.js"></script> -->
<!--<script type="text/javascript" src="skins/defaut/js/plugins/jquery.menus.js"></script>-->
<script type="text/javascript">
$(document).ready(function() {
	//$().menus({sens: 'vertical',multiNiveaux: false});
	function charge() {
		if ($('ul.subMenu').hasClass('open_at_load')) {
			titre(true);
			$("ul.subMenu:not('.open_at_load')").hide();
			$('.subMenu.open_at_load').parent('li.toggleSubMenu').addClass('open');
			$('.toggleSubMenu.open > a').attr({title: 'Cacher le menu'});
		} else titre(true);
	}
	function titre(tous) {
		if (tous == true) {
			$('li.toggleSubMenu span').each( function() {
			  var TexteSpan = $(this).text();
			  $(this).replaceWith('<a href="" title="ouvrir le menu">' + TexteSpan + '</a>');
			});
		}
		else {
			$('li.toggleSubMenu > a').each( function() {
				if ($('li.toggleSubMenu').hasClass('open'))
					$('.toggleSubMenu.open > a').attr({title: 'Cacher le menu'});
				else $('.toggleSubMenu > a').attr({title: 'Afficher le menu'});
			});
		}
	}
	charge();
	$("li.toggleSubMenu > a").click(function() {
	  if ($(this).next("ul.subMenu:visible").length != 0) {
          $(this).next("ul.subMenu")
          .slideUp("normal", 
          function() { 
            $(this).parent().removeClass("open");
            //$(this).parent('a.remp').attr({title: 'Afficher le menu'});
          });
          titre(false);
      }
      else {
          $("ul.subMenu")
          .slideUp("normal", 
          function() {
            $(this).parent().removeClass("open");
            //titre(false);
            //$(this).parent('a.remp').attr({title: 'Afficher le menu'});
          });
          $(this).next("ul.subMenu")
          .slideDown("normal", 
          function() {
            $(this).parent().addClass("open");
            //titre(false);
            //$(this).parent('a.remp').attr({title: 'cacher le menu'});
          });
          titre(false);
      }
      this.blur();
      return false;
  });// fin fonction
});
</script>
</head>
<body id="haut">
<div id="centre">
<ul id="navigation">
        <li><a href="" title="">Item 1</a></li>
        <li class="toggleSubMenu"><span>Item 2</span>
            <ul class="subMenu open_at_load">
                <li><a href="" title="">Item 2.1</a></li>
                <li><a href="" title="">Item 2.2</a></li>
                <li><a href="" title="">Item 2.3</a></li>
            </ul>
        </li>
        <li class="toggleSubMenu"><span>Item 3</span>
            <ul class="subMenu">
                <li><a href="" title="">Item 3.1</a></li>
                <li><a href="" title="">Item 3.2</a></li>
            </ul>
        </li>
        <li><a href="" title="">Item 4</a></li>
    </ul>
</div>
</body>
</html>

Modifié par keran (10 Mar 2011 - 00:22)
Bonjour,

si je ne m'abuse, dans le code complet que tu nous colles, je ne retrouve pas le code en question. Il me semble voir une similitude avec la sous-partie else de la fonction titre(tous); ...

Si c'est bien la même chose - et ça colle avec la fameuse ligne 99 - alors tu ne cibles pas les bons éléments. Dans ton code complet, à la ligne 98, tu cibles toutes les ancres des éléments li.toggleSubMenu, mais à la ligne 99, tu check les mêmes éléments li, et pas l'élément courant $(this). Ceci devrait expliquer celà Smiley smile

J'espère t'avoir aidé !
Salut


a écrit :
si je ne m'abuse, dans le code complet que tu nous colles, je ne retrouve pas le code en question.


Erreur de c/c, désolé. Mais le code y est puisque tu l'as trouver Smiley cligne et merci de t'être penché sur mon problème.

a écrit :
alors tu ne cibles pas les bons éléments


C'est bien tout mon problème, je le sait. Mais même avec le this, rien à faire. Je ne suis pourtant un perdreau de l'année en la matière mais là, je suis paumé avec le code tel-que. Et justement, je veux garder ce lien avec son title, aucun autre accordéon ne propose çà, j'ai trouvé ce tuto en cherchant l'inspiration pour le faire intelligement. Sur le tuto il affiche "afficher le menu" même si il est déjà ouvert, ce qui n'est pas top, idem avec la classe "open_at_load", j'ai donc rajouter la méthode charge qui elle fonctionne bien. Beaucoup ne comprenne pas l'utilité de ce lien avec title, d'après ce que j'ai pu lire sur les forums, dommage.


Bref, j'ai tester des dizaines de solutions, aucunes ne fonctionne. C'est fou çà. Donc, pour celles et ceux qui voudraient me filer la main, le bug ce trouve dans le else de la méthode titre et plus précisement içi :

$('li.toggleSubMenu > a').each( function() { 
if ($('li.toggleSubMenu').hasClass('open'))



Vous l'aurez compris, le ciblage n'est pas correct. A votre bon coeur m'ssieurs dames Smiley smile
Essaye ça Smiley cligne :

else {
    $('li.toggleSubMenu > a').each( function() { 
        if ($(this).parent().hasClass('open')) { 
            $(this).attr({title: 'Cacher le menu'});
        } else {
            $(this).attr({title: 'Afficher le menu'}); 
        }
    }); 
}


Parce que tu veux cibler l'élément li qui contient l'ancre courante, et non pas tous les li.toggleSubMenu ...
Modifié par MAD's (07 Mar 2011 - 22:14)
salut mad's

Merci mais çà ne fonctionne pas non plus. j'ai rajouter une classe aux liens et tester ceci.


else {
   $('a.remp').each( function() {
     if ($(this).parent('.open')) {
        $(this).attr({title: 'fermer le menu'});
     }
   });
}


çà fonctionne à moitiè Smiley lol il remplace par "fermer le menu" mais pour tous les liens parent...mais on s'approche. une condition supplémentaire dans le if, je pense. j'y retourne. C'est fou, je viens de finir un plugin accordeon horizontal bien plus compliqué et là un simple ciblage de lien. Je crois que je vais changer le code et virer ces span.
Bonjour,


EDIT TER : Je suis completement HS Smiley lol , mais je reviendrais ce soir parce que ca va pas quand même.



	$(document).ready(function(){
		function Change_title() {
			$(".subMenu.open").siblings('a').attr('title','Fermer le menu');
			$(".subMenu:not('.open')").siblings('a').attr('title','Ouvrir le menu');
		};
				
		$(".subMenu:not('.open_at_load')").hide();
		$(".open_at_load").toggleClass('open open_at_load');

                // Pourrait être remplacer par $(".subMenu:not('.open')").hide(); si on utilise directement la class open
		
		$(".subMenu").each(function(){
			$(this).siblings('span').replaceWith('<a href="#" class="toggleMenu">'+$(this).siblings('span').text()+'</a>');
			Change_title();
		});
		
		$(".toggleMenu").click(function(e){
			$(this).siblings('ul').toggleClass('open').slideToggle('slow', function() {				
    			Change_title()
  				});			
			e.preventDefault();
		});
		
	});


Et Comme ca ? Visible a cette adresse http://cherche.job.59.free.fr/menu_submenu.html j'ai pas trop cherché à bidouiller le CSS.


EDIT : Simplification des selecteurs Jquery.
EDIT BIS : A moins d'avoir des contraintes, c'est beaucoup trop complexe pour un menu si simple, mais je regarderais ca ce soir.
Modifié par rs459 (09 Mar 2011 - 08:31)
salut


Et ben, çà fonctionne encore à moitiè... Puisque oui, les liens sont ciblés mais le menu ouvert ne se replie pas. preventDefault, j'y pensé aussi mais false c'est mieux içi, return false ne fait pas qu'inhiber le lien, il déclenche trois fonctions, cf: la doc. Intéréssant ce code, plus concis et optimisé jquery, bien. Je considére que c'est résolu pour le reste pas de soucis. Merci à vous deux.

édit : en fait, le code n'est plus du tout celui du début, les classes css ont changées de place et forcement, le ciblage, ce qui fait que avec les images +/- il n'y à pas de remplacement. Donc non résolu. Je vais voir çà ce soir. Mais le code est sympà, il casse seulement la logique du début. D'ailleurs le blur de fin avec ce code ne fonctionne pas non plus alors qu'il fait son boulôt avec mon code originel.
Modifié par keran (09 Mar 2011 - 20:08)
J'avais bien compris que ca n'allait pas aller, du l'édition "TER".

J'ai fait un autre test sans changer les classes ou trés peu.

C'est visible à cette adresse http://cherche.job.59.free.fr/menu_submenu2.html

Et le code JS :

$(document).ready(function(){
		$(".toggleSubMenu > span").each(function(){
			$(this).replaceWith('<a href="#">'+ $(this).text() +'</a>');
		});
		
		function Change_title() {
			$(".open > a").attr('title','Fermer le menu');
			$(".toggleSubMenu:not('.open') > a").attr('title','Ouvrir le menu');
		};
				
		$(".toggleSubMenu > a").click(function(e){
			if ($(this).next("ul:visible").length != 0) {
				$(this).next("ul").slideUp("normal").parent('li').removeClass('open');
			}
			else {
				$(".open > ul").slideUp("normal").parent('li').removeClass('open');
				$(this).next("ul").slideDown("normal").parent('li').addClass('open');;
			};
			Change_title();						
			e.preventDefault();
		})
		
		$(".open_at_load").toggleClass('open open_at_load');
		$(".toggleSubMenu:not('.open') > ul").hide();
		Change_title();
	});


Le css comme d'hab est à bidouiller aprés , mais le concept est là.
salut

et merci, c'est nickel. une bonne base. Bien joué et merci encore.

édit après avoir lu la source


.toggleSubMenu.open:before {
   content:'-';
   ....
}
.toggleSubMenu:before {
   content:'+';
   .....
}
 ou

-moz-box-shadow : inset 0 0 4px #333;


Inutile(?) de préciser que çà ne fonctionne pas avec ie6/7/8. Juste pour les débutants qui viendraient lire ce post. Joli rendu sous firefox. Tu devrais soumettre cette maj à l'auteur du tuto.
Modifié par keran (10 Mar 2011 - 00:37)
Je t'en prie Smiley cligne

keran a écrit :


Inutile(?) de préciser que çà ne fonctionne pas avec ie6/7/8. Juste pour les débutants qui viendraient lire ce post. Joli rendu sous firefox. Tu devrais soumettre cette maj à l'auteur du tuto.


Effectivement c'était plutôt pour la preuve de concept.

Je ne suis pas expert en javascript j'apprends tout doucement, parce qu'il me semble que l'intégration simple va rapidement devenir obsolète, avec l'avènement du HTML5 et toutes ses API javascript.

D'ailleurs je ne suis pas persuadé que ca soit la meilleure manière de faire. Toutefois l'exercice est intéressant à faire.