JavaScript - Javascript Accordion Slide-up Problem???
I'm making an JS accordion and I just miss the final step.
That is - say: I click menu 1, content 1 slides down (shows up). After that, I click menu 2, content 2 slides down but content 1 of menu 1 just display: none (abruptly disappers) but not slides up. For the slide up effect, I wrote a function called cutHeight(). The cutHeight function works perfectly independently but not coherent with the accordion function. Is there anything wrong with my scripts? Code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Untitled Document</title> <script> function accordion(openAccordionID){ document.getElementById("content"+openAccordionID).style.display = (document.getElementById("content"+openAccordionID).style.display == "none") ? "block" : "none" ; var sumAccordion; if(document.all){ sumAccordion = document.body.getElementsByTagName("div").length/2; } else {sumAccordion = document.getElementsByClassName("content").length;} for(var closeAccordionID=1; closeAccordionID<=sumAccordion; closeAccordionID++){ if(closeAccordionID == openAccordionID){continue;} document.getElementById("content"+closeAccordionID).style.display = "none"; } addHeight(openAccordionID); cutHeight(closeAccordionID); } var h=0; var t; function addHeight(openAccordionID){ clearInterval(t); document.getElementById("content"+openAccordionID).style.height = h+"px"; h+=1; t = setInterval("addHeight('"+openAccordionID+"')",10); if(h==100){clearInterval(t);h=0;} } var T; function cutHeight(closeAccordionID){ var h=100; clearInterval(T); document.getElementById("content"+closeAccordionID).style.height = h+"px"; h-=1; T = setInterval("cutHeight('"+closeAccordionID+"')",10); if(h==0){clearInterval(T);} } </script> <style> .menu { background-color: #6F6; width: 200px; height: 50px;} .content { display: none; background-color: yellow; width: 200px; height:0px; overflow: hidden;} </style> </head> <body> <div onclick="accordion(1)" class="menu">Menu 1</div> <div id="content1" class="content">Content 1</div> <div onclick="accordion(2)" class="menu">Menu 2</div> <div id="content2" class="content">Content 2</div> <div onclick="accordion(3)" class="menu">Menu 3</div> <div id="content3" class="content">Content 3</div> </body> </html> Similar TutorialsHello, i would like to advise me on sthg. I have built a website using a)MySQL b)HTML c)PHP and d)Javascript. My website consists of basic html pages/templates which have links to the left and point to another templates/pages. For example, i have 4 templates in my site 1st template is for: News 2nd : Library 3nd : Articles 4th : E-shop Each template consists of 1. a small menu with links,every link points to another page 2.space for the content/text of the html page 3. a form for searching in the website using php and a mysql database. Well, i'm thinking of adding some animation in my website using the jquery library.Let's say we have an accordion which has 4 choices and when the user clicks on the first choice the 1st template(NEWS) appears inside the slide of accordion,loads in the same slide, not in a new page!!!This is what i would like to do, place in each slide of the accordion one of my templates. CAn this be done??? Which are the disadvantages of adding in each slide of the accordion a different template for my site and remain in the same slide when the user clicks in one of the links of the template??? Consider that i'm using dynamic content and not static, i have a MySQL database behind. Also,as i have seen in most examples the options of accordion usually contain an image, a content, a text or links which open in a new window or tab not inside the slide!!!These links do not load in the same slide!!i would like to have a template which loads in the slide each time the user clicks on a link of it. CAn this be done?? I would be glad if sm could advise me! Thanks, in advance!!! I am working on a custom accordion. A type 2 accordion works but type 1 and 3 don't work. Does anyone know how to correct this syntax? Also, if you see any ways to make this code better, please post your fixes in this post Code: /* To use these, insert your content between a div tag. For example: <div id="2011" style="display: none"> This is the content in the accordion </div> You can have as many of these on the page as you wish but they all must have a different div tag. You will be creating a different button for each div tag. To make an item display on page load, change that div tag display from "none" to "inline". For the button that toggles the accordion: <a href="javascript:accordion('2011', '2', eventyear)">2011</a> Here is what all of these variables do: 1. Id of the div tag you want to toggle 2. The type of accordion you want 3. Only needed if it is a type 1 or 2 accordion, this refers to an array of all of the other div id's in the accordion. If you are using a type 1 or 2 array, create a array under the arrays comment of all of the div id's in your accordion. Types: 1 = One open at a time. Open and close 2 = One open at a time. Open no close 3 = No limit. Open and close. 3 doesn't use an array */ //Arrays; var eventyear=new Array("2011","2010","2009"); var months=new Array("January","February","March","April","May","June","July","August","September","October","November","December"); function accordion(click,type,array) { var click = document.getElementById(click); if ((click.style.display = "inline") && ((type == "1") || (type == "3"))) { click.style.display = "none"; } else if ((click.style.display = "none") && ((type == "1") || (type == "2"))) { var c; for(c in array) { document.getElementById(array[c]).style.display = "none"; } click.style.display = "inline"; } else if ((click.style.display = "none") && (type == "3")) { click.style.display = "inline"; }} Hi friends, Am customizing a Joomla website and i need to know how to get a nice and fine javascript accordion horizontal panel which is so smooth and good looking to add in Joomla Home page. Please suggest me some horizontal javascript accordion with images and link to another page. Thanks in Advance. Hey, I'm having trouble with this site http://bit.ly/hL0u0w... If you go to the services section you will see a sub navigation on the left of the box. The idea of this is to have sub sections within the main headings that expand/collapse when selected. Insted when any one link is clicked the whole menu expands and not just the related sub sections. This is the javascript Quote: <script type="text/javascript"> $(document).ready (function() { $('#link1').click(function() { $('.slide').slideToggle('fast'); }); $('.close').click(function() { $('.slide').slideUp('fast'); }); $(document).ready (function() { $('#link2').click(function() { $('.slide').slideToggle('fast'); }); $('.close').click(function() { $('.slide').slideUp('fast'); }); }); $(document).ready (function() { $('#link3').click(function() { $('.slide').slideToggle('fast'); }); $('.close').click(function() { $('.slide').slideUp('fast'); }); }); }); </script> and here is the html Quote: <div id="subnav4"> <ul class="navigation4 pagination"> <li class="tab4"><a rel="1" id="link1" href="#">heading 1</a></li> <li style="display: none;" class="dome slide"><a href="#">corporate id</a></li> <li style="display: none;" class="dome slide"><a href="#">branding</a></li> <li style="display: none;" class="dome slide"><a href="#">brochures</a></li> <li style="display: none;" class="dome slide"><a href="#">direct mail</a></li> <li class="tab4"><a id="link2" href="#">heading 2</a></li> <li style="display: none;" class="dome slide"><a href="#">email marketing</a></li> <li style="display: none;" class="dome slide"><a href="#">websites</a></li> <li class="tab4"><a id="link3" href="#">heading 3</a></li> <li style="display: none;" class="dome slide"><a href="#">advertising</a></li> <li style="display: none;" class="dome slide"><a href="#">audiovisual</a></li> <li class="tab4"><a id="heading 3" href="#">exhibitions</a></li> </ul> </div> Hope someone can help with this! Many thanks! hi guys I am looking at this template: http://www.csstemplatesfree.org/prev...ero/index.html I think the sliding at the top happens way too frequently. How can I slow it down? I think it would be better if the slides change once every 6 seconds. Hy every one, i need help .I have a program made in visual c++ witch detect motion and makes a file.jpg every time when detects something. I would like to make a web pages witch makes the autorefresh with the last image generated by this program. How do i do that with javascript? I think i must declare a golbal variable witch kepps the path to the most younger file, or to make a list witch keeps all the images and sort it ascended but i don't know how to make this in java script. Can enyone help me ?Thanks in advance I used the slideshow technique described here and was successful: http://www.javascriptkit.com/howto/show2.shtml But when I try to repeat the process to add additional images to the show, it doesn't work. It sticks to the three original images. Any tips as to how to add to this? thanks!! hi all hope someone can help me out here. The code below i found online and it works well but I would like it to slide rather than jump into posistion. Anyone know how I can adapt this or have another way of doing it?? what i like about this script is that it wont allow you to go beyond the bounds of the content when pressing the forward and back links but the transition needs a nice slide!!!. Example of how it works here Link Code: <head> <style> #contents{ position: relative; top: 0; left: 0; width: 786px; height: auto;} #scrollable{ overflow: hidden; width: 786px; height: 400px; border: 1px solid black;} </style> <script> var t = 0; function myback() { t += 786; with(document.getElementById("contents")) { if (t > 0) t = 0; if(style) style.left = t + "px"; else setAttribute("style", "left: " + t + "px"); } } function myforward() { t -= 786; with(document.getElementById("contents")) { if(t < -clientWidth) t = -clientWidth; if(style) style.left = t + "px"; else setAttribute("style", "left: " + t + "px"); } } </script> </head> <body> <table> <tr> <td rowspan="2"> <div id="scrollable"><div id="contents"> <table width="1572" border="0" cellspacing="0" cellpadding="5"> <tr> <td width="776" valign="top" bgcolor="#FFFF99">Some text!!!</td> <td width="776" valign="top" bgcolor="#66FFFF"> Some Text!!!</td> </tr> </table> </div> </div> </td> </tr> </table> <a href="javascript:void(0)" onclick="myback()">back</a> <a href="javascript:void(0)" onclick="myforward()">forward</a> </body> Hope this is clear. Thanks. i want to create a slide show with javascript, but i don't know how to write a code, i have try full screen image slideshow in javascriptkit.com, but i don't know how to resize, not full screen because i want to insert another think, not only a slide show. how can i make an edit with full screen image slideshow coding?or is there someone can help me with the slide show in javascript, but with fadingtime, not an instant change?
Hi all, I'm having an issue with a slide out menu and would appreciate some assistance. I feel like its most likely an easy fix which has escaped me over the last couple of days. Basically, I'm using tabbed navigation panes in the center column of a 3-column CSS layout. I'm wanting to place a functional slide out menu in EACH tab. As of now, I have one working perfectly in the intial tab, but I'm unable to achieve the same functionality in the remaining tabs. I can get the content loaded, but it is completely expanded...losing the collapsing/slide out action(s). I have added code for the content to be loaded into the 2nd tab, but have left the rest blank. I figure if the issue for tab 2 is resolved, I can apply it to the rest of the tabs. I am 99% sure the issue resides in the slide-out-menu-new.js file, but I can't seem to figure out where the functionality is being lost. Please assist if you would like. It would be GREATLY appreciated...this is the last hurdle I have before adding real content to the site. Please find the zip file containing all associated code/files by visiting the link below (a quick page posted for storage purposes only). http://www.truckerslifeline.com/siteHelp Thanks! Hi People, I've used the Concertina Menu from Stu Nicholls on one of my websites and am trying to get the Menu slider to slide up automatically after a certain time. Currently it only slides up on a mouseclick. The working link can be found at www.atomwhale.com/share/clients/branch/website/home.html Hope someone can help me in getting this to work. thanks, Jeriel. I have a background slide show from codelifter.com that normally runs in the body - I would like to use it as the background in a table cell. Thanks in advance for any help, Cyber-guys Here is the code: [CODE] <html> <head> <style> body{ background-repeat: no-repeat; background-position: 200 100;} </style> <script language="JavaScript"> <!-- // (C) 2006 CodeLifter.com var speed = 3000; var crossFadeDuration = 2; var Pic = new Array(); Pic[0] = 'slideshow1_1.jpg'; Pic[1] = 'slideshow1_2.jpg'; Pic[2] = 'slideshow1_3.jpg'; Pic[3] = 'slideshow1_4.jpg'; Pic[4] = 'slideshow1_5.jpg'; var t; var j = 0; var p = Pic.length; var preLoad = new Array(); for (i = 0; i < p; i++){ preLoad[i] = new Image(); preLoad[i].src = Pic[i];} function runSlideShow(){ if (document.all){ document.body.style.filter="blendTrans(duration=crossFadeDuration)"; document.body.filters.blendTrans.Apply(); document.body.filters.blendTrans.Play();} if (document.body){ document.body.background = Pic[j]; j = j + 1 if (j > (p-1)) j=0 t = setTimeout('runSlideShow()', speed)} } //--> </script> <title> CodeLifter.com :: Background Image Slideshow With Crossfade </title> </head> <body onload="runSlideShow()" bgcolor="#000000"> <table border="0" width="444" cellpadding="0" cellspacing="0"> <tr> <td> <font size="2" face="Verdana,Arial" color="#FFFFFF"> Lorem ipsum dolor situm amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer... </font> </td> </tr> </table> </body> </html> I am having two problems with the script. 1. Sometimes when the page opens the slideout submenu shows on the left side of page, this always happens when my browser is full screen. 2. After clicking on 2 or more submenu links the submenu then overlaps the verticle black bar. http://villagehomegoods.com Appreciate any help. I realize this is an overly simple question, but I'm rather horrible at javascript. What I'm doing is changing an img src and having it loop through images. I want it to only start looping when I click and than stop if I click again. It loops through when I click once, but when I click again it starts changing its rate of image switching. Starts off switching at 1000 milliseconds than upon clicking again it switches through two images quickly and than slows again. Code: var myImage = document.getElementById("mainImage"); var imageArray=["1.jpg","2.jpg","3.jpg","4.jpg" ]; var imageIndex=0; What I assume is the trouble causing function: Code: function changeImage(){ myImage.setAttribute("src", imageArray[imageIndex]); imageIndex++; if(imageIndex >= imageArray.length) { imageIndex=0; } } How the trouble function is being called: Code: var imgSwtch=0; myImage.onclick= function(){ if(imgSwtch==0){ var intervalHandle = setInterval(changeImage,1000); imgSwtch=1; console.log("start"); } else{ clearInterval(intervalHandle); imgSwtch=0; console.log("stop"); } }; Hi guys, I am currently stuck up on something.. check this page http://dev.andrewfopalan.com/new_slider.html Well for starters.. I am trying to mimic this effect.. http://www.vogue.com/ The slider on the very top.. A quick preview of what I did was.. I used this plugin.. easyslider().. And then edited it.. since I am still learning jQuery and javascript.. so I made changes to the controls... usually the elements for design.. all I did was that.. The first problem was how to make it center like the one on the vogue.. so it was done... Second the masking problem.. I had alot of trouble thinking how I am going to do this.. because whenever I used absolute position on masks and the controls, everything is messed up on all browser.. So my problem primarily was how to make the effect like vogue mask, so what I did was used opacity on the list... and add a class active that regains the opacity 1 on the middle part of the slider.. so that was done.. My follow up problem is whenever I am navigating through the slider.. I add the "active" class on the next item on the list.. up until there I am fine.. but when I am at almost at the end, at the 5th slider, I am not getting the active class? and after a couple of clicks on the "next".. it wont navigate through... here's the code for the next button: Code: // this gets the current location of the active slider on the list.. $("a#"+options.nextId).click(function(e){ var id= $('.active').attr('id'); //this removes the "active" class on the slider.. and then goes to the next item on the list.. and then add the class "active" to the next image slide.. $("ul li:nth-child("+(id)+")").removeClass('active').next().addClass('active'); // this is the plugin's animation to move to the next slide.. animate("next",true); Heres' the code for the animate Code: function animate(dir,clicked){ if (clickable){ clickable = false; var ot = t; switch(dir){ case "next": t = (ot>=ts) ? (options.continuous ? t+1 : ts) : t+1; break; case "prev": t = (t<=0) ? (options.continuous ? t-1 : 0) : t-1; break; case "first": t = 0; break; case "last": t = ts; break; default: t = dir; break; }; var diff = Math.abs(ot-t); var speed = diff*options.speed; if(!options.vertical) { p = (t*w*-1); $("ul",obj).animate( { marginLeft: p}, { queue:false, duration:speed, complete:adjust, } ); } else { p = (t*h*-1); $("ul",obj).animate( { marginTop: p }, { queue:false, duration:speed, complete:adjust } ); }; heres the adjust code function Code: function adjust(){ if(t>ts) t=0; if(t<0) t=ts; if(!options.vertical) { $("ul",obj).css("margin-left",(t*w*-1)); } else { $("ul",obj).css("margin-left",(t*h*-1)); } clickable = true; if(options.numeric) setCurrent(t); }; I am very still new to this jQuery thing.. but I am trying my best to learn.. Hope someone could teach me and help me on this... Hi, I'm a complete novice using javascript. I'm trying to get a mootools plugin to work with a slide in/slide out javascript using multiple divs. Here's the page: http://pawsdogs.com/test/Site/work2.htm The mootools code (Noobslide) slides a main image on the right when you click thumbnails on the left, which are wrapped in a thumb mask using CSS. The first row of thumbnails works perfectly, but when it's passed on to the next div the mask isn't passed on and the effect breaks down. Thanks so much if anyone can help! Here's the html: Code: <li><a href="#" id="slidecontrol_2" class="slidecontrol">Click Here</a> <div id="slidedisplay_2" style="display:none;"> <div id="thumbs7"> <div class="thumbs"> <div><img src="images2/img4.jpg" alt="Photo Thumb" /></div> <div><img src="images2/img5.jpg" alt="Photo Thumb" /></div> <div><img src="images2/img6.jpg" alt="Photo Thumb" /></div> </div> <div id="thumbs_mask7"></div> <p id="thumbs_handles7"> <span></span> <span></span> <span></span> </p> </div> </div></li> <li><a href="#" id="slidecontrol_3" class="slidecontrol">asdf</a> <div id="slidedisplay_3" style="display:none;"> <div id="thumbs7"> <div class="thumbs"> <div><img src="images2/img2.jpg" alt="Photo Thumb" /></div> <div><img src="images2/img3.jpg" alt="Photo Thumb" /></div> </div> <div id="thumbs_mask7"></div> <p id="thumbs_handles7"> <span></span> <span></span> </p> </div> </div> The javascript: Code: $(document).ready(function () { $('a.slidecontrol').click(function(){ var $this = $(this); var divID = $this.attr("id").replace("slidecontrol_", "slidedisplay_"); var $div = $('#'+divID); if ($div.is(':visible')) { $div.slideUp(500); } else { $div.slideDown(500); } return false; }); }); The CSS: Code: #thumbs7{ position:relative; width:200px; clear:both; height:41px; overflow:hidden; } #thumbs7 .thumbs, #thumbs_handles7, #thumbs_mask7{ position:absolute; top:0; width:100%; height:41px; } #thumbs7 .thumbs div, #thumbs_handles7 span{ display:block; width:60px; height:41px; margin:0; float:left; cursor:pointer; } #thumbs7 .thumbs div img{ width:54px; float:right; } #thumbs_handles7 span{ background:url(../images2/thumb_invisible.gif) no-repeat; } #thumbs_mask7{ width:1200px; background:url(../images2/thumbs_mask.gif) no-repeat center top; } Hi All, So i have been trying over the past few weeks (among other things) to get this menu figured out. I would really appreciate some advice/help/direction with this... Please see attached pic... what i have is three elements: "Home" "Services" "Contact". What i want is on page load they are all 100px wide... now whenever user hovers over an item it expands to be 200px wide while the other two shrink to 50px... remove hover they revert to original... I am not too familiar with javascript as i mainly use C# to do the tasks normally done by javascript (i work on asp.net platform)... i have presented a similar question to this in ajax section (thinkin that what i had was an ajax work around) but upon further reading of sources i think that is not really what i want... I am unsure where to begin and what to do... i know i need to set up a function and i have the math part figured out (i think)... i guess what i am really unclear as to whether this is a modification to the accordion menu frame... the issues i see are that i do not want the menu to have a traditional "content" area that collapses; i want the menu "headers" to expand... i also need them to expand horizontally not vertically... i am not looking for someone to "do this" for me; i am looking for advice and guidance... possibly a link to a tutorial? i have tried this but it does not work right... i can revisit it (possibly type-Oed something) but i havent because it is not really what i am looking for Hello to all, I have a little problem with my accordion menu and I CRAVE for your help! I try to make this: when you visit my page I need the menu to be all collapsed. Also the history of clicks (it remembers which menus where left opened) works fine on IE but not on firefox. Here is the js code: function add_menu_event_handlers() { var elems = document.getElementsByTagName('h3'); for (i = 0; i < elems.length; i++) { switch (elems[i].parentNode.className) { /*case 'moduletable': case 'moduletable_menu':*/ case 'left_module_title': case 'left_module_title_menu': { if (elems[i].parentNode.parentNode.parentNode.id == 'xp-left') { xplike_addEvent(elems[i], 'click', function(){menu_header_click(this);}); // menu_header_click(elems[i]); //Load status from cookies and collapse if required var cookie_array = document.cookie.split(';'); for(var j=0; j<cookie_array.length; j++) { var c = cookie_array[j]; while (c.charAt(0)==' ') c = c.substring(1,c.length); if (c.indexOf('xplike_menu_status_' + elems[i].firstChild.nodeValue.replace('.', '_').replace(' ', '_')) == 0) { var menu_cookie = c.split('=') if (menu_cookie.length == 2 && menu_cookie[1] == '1') { menu_header_click(elems[i]); } } } } } } } } And it also has this for the history thing. function save_menu_status(menu_title, value, how_many_days) { var date = new Date(); date.setTime(date.getTime()+(how_many_days*24*60*6 0*1000)); var expires = ""; document.cookie = 'xplike_menu_status_' + menu_title.replace('.', '_').replace(' ', '_') + '=' + value + expires + '; path=/'; } It might be easy and stupid, I know, but since I'm a designer - not a developer - all look weird to me! Any thoughts? Hi All, I want an accordion menu and which is as follows 1.it should be a vertical accordion menu 2.every menu should display with image and link 3.if i click on image or link then only menu should display or open to show sub menu otherwise it should not display. Please tell the solution for the above ThanksAhead Venkat I'm creating a Jquery UI accordion and here are my customize options... http://jqueryui.com/demos/accordion/ These options do not include how to make all the accordions start off closed or choosing which one you want open as default when a user sees the page. Right now the user sees the first accordion open. I want to keep them all closed by default or have the option to have the last one open by default. Any guidance would be great... also not sure what code to post here but I guess I'll add the javaScript used to create the accordion with Jquery.... Code: /* * jQuery UI Accordion 1.8.16 * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Accordion * * Depends: * jquery.ui.core.js * jquery.ui.widget.js */ (function( $, undefined ) { $.widget( "ui.accordion", { options: { active: 0, animated: "slide", autoHeight: true, clearStyle: false, collapsible: false, event: "click", fillSpace: false, header: "> li > :first-child,> :not(li):even", icons: { header: "ui-icon-triangle-1-e", headerSelected: "ui-icon-triangle-1-s" }, navigation: false, navigationFilter: function() { return this.href.toLowerCase() === location.href.toLowerCase(); } }, _create: function() { var self = this, options = self.options; self.running = 0; self.element .addClass( "ui-accordion ui-widget ui-helper-reset" ) // in lack of child-selectors in CSS // we need to mark top-LIs in a UL-accordion for some IE-fix .children( "li" ) .addClass( "ui-accordion-li-fix" ); self.headers = self.element.find( options.header ) .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ) .bind( "mouseenter.accordion", function() { if ( options.disabled ) { return; } $( this ).addClass( "ui-state-hover" ); }) .bind( "mouseleave.accordion", function() { if ( options.disabled ) { return; } $( this ).removeClass( "ui-state-hover" ); }) .bind( "focus.accordion", function() { if ( options.disabled ) { return; } $( this ).addClass( "ui-state-focus" ); }) .bind( "blur.accordion", function() { if ( options.disabled ) { return; } $( this ).removeClass( "ui-state-focus" ); }); self.headers.next() .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); if ( options.navigation ) { var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 ); if ( current.length ) { var header = current.closest( ".ui-accordion-header" ); if ( header.length ) { // anchor within header self.active = header; } else { // anchor within content self.active = current.closest( ".ui-accordion-content" ).prev(); } } } self.active = self._findActive( self.active || options.active ) .addClass( "ui-state-default ui-state-active" ) .toggleClass( "ui-corner-all" ) .toggleClass( "ui-corner-top" ); self.active.next().addClass( "ui-accordion-content-active" ); self._createIcons(); self.resize(); // ARIA self.element.attr( "role", "tablist" ); self.headers .attr( "role", "tab" ) .bind( "keydown.accordion", function( event ) { return self._keydown( event ); }) .next() .attr( "role", "tabpanel" ); self.headers .not( self.active || "" ) .attr({ "aria-expanded": "false", "aria-selected": "false", tabIndex: -1 }) .next() .hide(); // make sure at least one header is in the tab order if ( !self.active.length ) { self.headers.eq( 0 ).attr( "tabIndex", 0 ); } else { self.active .attr({ "aria-expanded": "true", "aria-selected": "true", tabIndex: 0 }); } // only need links in tab order for Safari if ( !$.browser.safari ) { self.headers.find( "a" ).attr( "tabIndex", -1 ); } if ( options.event ) { self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) { self._clickHandler.call( self, event, this ); event.preventDefault(); }); } }, _createIcons: function() { var options = this.options; if ( options.icons ) { $( "<span></span>" ) .addClass( "ui-icon " + options.icons.header ) .prependTo( this.headers ); this.active.children( ".ui-icon" ) .toggleClass(options.icons.header) .toggleClass(options.icons.headerSelected); this.element.addClass( "ui-accordion-icons" ); } }, _destroyIcons: function() { this.headers.children( ".ui-icon" ).remove(); this.element.removeClass( "ui-accordion-icons" ); }, destroy: function() { var options = this.options; this.element .removeClass( "ui-accordion ui-widget ui-helper-reset" ) .removeAttr( "role" ); this.headers .unbind( ".accordion" ) .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) .removeAttr( "role" ) .removeAttr( "aria-expanded" ) .removeAttr( "aria-selected" ) .removeAttr( "tabIndex" ); this.headers.find( "a" ).removeAttr( "tabIndex" ); this._destroyIcons(); var contents = this.headers.next() .css( "display", "" ) .removeAttr( "role" ) .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" ); if ( options.autoHeight || options.fillHeight ) { contents.css( "height", "" ); } return $.Widget.prototype.destroy.call( this ); }, _setOption: function( key, value ) { $.Widget.prototype._setOption.apply( this, arguments ); if ( key == "active" ) { this.activate( value ); } if ( key == "icons" ) { this._destroyIcons(); if ( value ) { this._createIcons(); } } // #5332 - opacity doesn't cascade to positioned elements in IE // so we need to add the disabled class to the headers and panels if ( key == "disabled" ) { this.headers.add(this.headers.next()) [ value ? "addClass" : "removeClass" ]( "ui-accordion-disabled ui-state-disabled" ); } }, _keydown: function( event ) { if ( this.options.disabled || event.altKey || event.ctrlKey ) { return; } var keyCode = $.ui.keyCode, length = this.headers.length, currentIndex = this.headers.index( event.target ), toFocus = false; switch ( event.keyCode ) { case keyCode.RIGHT: case keyCode.DOWN: toFocus = this.headers[ ( currentIndex + 1 ) % length ]; break; case keyCode.LEFT: case keyCode.UP: toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; break; case keyCode.SPACE: case keyCode.ENTER: this._clickHandler( { target: event.target }, event.target ); event.preventDefault(); } if ( toFocus ) { $( event.target ).attr( "tabIndex", -1 ); $( toFocus ).attr( "tabIndex", 0 ); toFocus.focus(); return false; } return true; }, resize: function() { var options = this.options, maxHeight; if ( options.fillSpace ) { if ( $.browser.msie ) { var defOverflow = this.element.parent().css( "overflow" ); this.element.parent().css( "overflow", "hidden"); } maxHeight = this.element.parent().height(); if ($.browser.msie) { this.element.parent().css( "overflow", defOverflow ); } this.headers.each(function() { maxHeight -= $( this ).outerHeight( true ); }); this.headers.next() .each(function() { $( this ).height( Math.max( 0, maxHeight - $( this ).innerHeight() + $( this ).height() ) ); }) .css( "overflow", "auto" ); } else if ( options.autoHeight ) { maxHeight = 0; this.headers.next() .each(function() { maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); }) .height( maxHeight ); } return this; }, activate: function( index ) { // TODO this gets called on init, changing the option without an explicit call for that this.options.active = index; // call clickHandler with custom event var active = this._findActive( index )[ 0 ]; this._clickHandler( { target: active }, active ); return this; }, _findActive: function( selector ) { return selector ? typeof selector === "number" ? this.headers.filter( ":eq(" + selector + ")" ) : this.headers.not( this.headers.not( selector ) ) : selector === false ? $( [] ) : this.headers.filter( ":eq(0)" ); }, // TODO isn't event.target enough? why the separate target argument? _clickHandler: function( event, target ) { var options = this.options; if ( options.disabled ) { return; } // called only when using activate(false) to close all parts programmatically if ( !event.target ) { if ( !options.collapsible ) { return; } this.active .removeClass( "ui-state-active ui-corner-top" ) .addClass( "ui-state-default ui-corner-all" ) .children( ".ui-icon" ) .removeClass( options.icons.headerSelected ) .addClass( options.icons.header ); this.active.next().addClass( "ui-accordion-content-active" ); var toHide = this.active.next(), data = { options: options, newHeader: $( [] ), oldHeader: options.active, newContent: $( [] ), oldContent: toHide }, toShow = ( this.active = $( [] ) ); this._toggle( toShow, toHide, data ); return; } // get the click target var clicked = $( event.currentTarget || target ), clickedIsActive = clicked[0] === this.active[0]; // TODO the option is changed, is that correct? // TODO if it is correct, shouldn't that happen after determining that the click is valid? options.active = options.collapsible && clickedIsActive ? false : this.headers.index( clicked ); // if animations are still active, or the active header is the target, ignore click if ( this.running || ( !options.collapsible && clickedIsActive ) ) { return; } // find elements to show and hide var active = this.active, toShow = clicked.next(), toHide = this.active.next(), data = { options: options, newHeader: clickedIsActive && options.collapsible ? $([]) : clicked, oldHeader: this.active, newContent: clickedIsActive && options.collapsible ? $([]) : toShow, oldContent: toHide }, down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); // when the call to ._toggle() comes after the class changes // it causes a very odd bug in IE 8 (see #6720) this.active = clickedIsActive ? $([]) : clicked; this._toggle( toShow, toHide, data, clickedIsActive, down ); // switch classes active .removeClass( "ui-state-active ui-corner-top" ) .addClass( "ui-state-default ui-corner-all" ) .children( ".ui-icon" ) .removeClass( options.icons.headerSelected ) .addClass( options.icons.header ); if ( !clickedIsActive ) { clicked .removeClass( "ui-state-default ui-corner-all" ) .addClass( "ui-state-active ui-corner-top" ) .children( ".ui-icon" ) .removeClass( options.icons.header ) .addClass( options.icons.headerSelected ); clicked .next() .addClass( "ui-accordion-content-active" ); } return; }, _toggle: function( toShow, toHide, data, clickedIsActive, down ) { var self = this, options = self.options; self.toShow = toShow; self.toHide = toHide; self.data = data; var complete = function() { if ( !self ) { return; } return self._completed.apply( self, arguments ); }; // trigger changestart event self._trigger( "changestart", null, self.data ); // count elements to animate self.running = toHide.size() === 0 ? toShow.size() : toHide.size(); if ( options.animated ) { var animOptions = {}; if ( options.collapsible && clickedIsActive ) { animOptions = { toShow: $( [] ), toHide: toHide, complete: complete, down: down, autoHeight: options.autoHeight || options.fillSpace }; } else { animOptions = { toShow: toShow, toHide: toHide, complete: complete, down: down, autoHeight: options.autoHeight || options.fillSpace }; } if ( !options.proxied ) { options.proxied = options.animated; } if ( !options.proxiedDuration ) { options.proxiedDuration = options.duration; } options.animated = $.isFunction( options.proxied ) ? options.proxied( animOptions ) : options.proxied; options.duration = $.isFunction( options.proxiedDuration ) ? options.proxiedDuration( animOptions ) : options.proxiedDuration; var animations = $.ui.accordion.animations, duration = options.duration, easing = options.animated; if ( easing && !animations[ easing ] && !$.easing[ easing ] ) { easing = "slide"; } if ( !animations[ easing ] ) { animations[ easing ] = function( options ) { this.slide( options, { easing: easing, duration: duration || 700 }); }; } animations[ easing ]( animOptions ); } else { if ( options.collapsible && clickedIsActive ) { toShow.toggle(); } else { toHide.hide(); toShow.show(); } complete( true ); } // TODO assert that the blur and focus triggers are really necessary, remove otherwise toHide.prev() .attr({ "aria-expanded": "false", "aria-selected": "false", tabIndex: -1 }) .blur(); toShow.prev() .attr({ "aria-expanded": "true", "aria-selected": "true", tabIndex: 0 }) .focus(); }, _completed: function( cancel ) { this.running = cancel ? 0 : --this.running; if ( this.running ) { return; } if ( this.options.clearStyle ) { this.toShow.add( this.toHide ).css({ height: "", overflow: "" }); } // other classes are removed before the animation; this one needs to stay until completed this.toHide.removeClass( "ui-accordion-content-active" ); // Work around for rendering bug in IE (#5421) if ( this.toHide.length ) { this.toHide.parent()[0].className = this.toHide.parent()[0].className; } this._trigger( "change", null, this.data ); } }); $.extend( $.ui.accordion, { version: "1.8.16", animations: { slide: function( options, additions ) { options = $.extend({ easing: "swing", duration: 300 }, options, additions ); if ( !options.toHide.size() ) { options.toShow.animate({ height: "show", paddingTop: "show", paddingBottom: "show" }, options ); return; } if ( !options.toShow.size() ) { options.toHide.animate({ height: "hide", paddingTop: "hide", paddingBottom: "hide" }, options ); return; } var overflow = options.toShow.css( "overflow" ), percentDone = 0, showProps = {}, hideProps = {}, fxAttrs = [ "height", "paddingTop", "paddingBottom" ], originalWidth; // fix width before calculating height of hidden element var s = options.toShow; originalWidth = s[0].style.width; s.width( parseInt( s.parent().width(), 10 ) - parseInt( s.css( "paddingLeft" ), 10 ) - parseInt( s.css( "paddingRight" ), 10 ) - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 ) - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) ); $.each( fxAttrs, function( i, prop ) { hideProps[ prop ] = "hide"; var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ); showProps[ prop ] = { value: parts[ 1 ], unit: parts[ 2 ] || "px" }; }); options.toShow.css({ height: 0, overflow: "hidden" }).show(); options.toHide .filter( ":hidden" ) .each( options.complete ) .end() .filter( ":visible" ) .animate( hideProps, { step: function( now, settings ) { // only calculate the percent when animating height // IE gets very inconsistent results when animating elements // with small values, which is common for padding if ( settings.prop == "height" ) { percentDone = ( settings.end - settings.start === 0 ) ? 0 : ( settings.now - settings.start ) / ( settings.end - settings.start ); } options.toShow[ 0 ].style[ settings.prop ] = ( percentDone * showProps[ settings.prop ].value ) + showProps[ settings.prop ].unit; }, duration: options.duration, easing: options.easing, complete: function() { if ( !options.autoHeight ) { options.toShow.css( "height", "" ); } options.toShow.css({ width: originalWidth, overflow: overflow }); options.complete(); } }); }, bounceslide: function( options ) { this.slide( options, { easing: options.down ? "easeOutBounce" : "swing", duration: options.down ? 1000 : 200 }); } } }); })( jQuery ); |