Como posso expandir e recolher um <div> usando javascript?

96

Eu criei uma lista no meu site. Esta lista é criada por um loop foreach que é construído com informações do meu banco de dados. Cada item é um contêiner com seções diferentes, portanto, esta não é uma lista como 1, 2, 3 ... etc. Estou listando seções repetidas com informações. Em cada seção, há uma subseção. A construção geral é a seguinte:

<div>
    <fieldset class="majorpoints" onclick="majorpointsexpand($(this).find('legend').innerHTML)">
    <legend class="majorpointslegend">Expand</legend>
    <div style="display:none" >
        <ul>
            <li></li>
            <li></li>
        </ul>
    </div>
</div>

Portanto, estou tentando chamar uma função com onclick = "majorpointsexpand ($ (this) .find ('legend'). InnerHTML)"

A div que estou tentando manipular é style = "display: none" por padrão, e desejo usar javascript para torná-la visível ao clicar.

O "$ (this) .find ('legend'). InnerHTML" está tentando passar, neste caso, "Expand" como um argumento na função.

Aqui está o javascript:

function majorpointsexpand(expand)
    {
        if (expand == "Expand")
            {
                document.write.$(this).find('div').style = "display:inherit";
                document.write.$(this).find('legend').innerHTML = "Collapse";
            }
        else
            {
                document.write.$(this).find('div').style = "display:none";
                document.write.$(this).find('legend').innerHTML = "Expand";
            }
    }

Tenho quase 100% de certeza de que meu problema é a sintaxe e não tenho muita noção de como funciona o javascript.

Eu tenho o jQuery vinculado ao documento com:

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>

Na <head></head>seção.

Ryan Mortensen
fonte
2
Acho que o que você está tentando alcançar é um acordeão jqueryui.com/accordion
Marc
1
$ isto sou eu tentando dizer "em relação ao" elemento HTML do qual a função é acionada.
Ryan Mortensen
1
@hungerpain - Acho que quem fez a pergunta pode ser novo no jQuery e simplesmente esqueceu o parêntese $(this). Espero que isto ajude.
jmort253
2
Acho que você deveria estudar mais sobre jQuery primeiro. Aparentemente, você não sabe muito sobre a diferença entre jQuery e JavaScript
tom10271 01 de
1
@aokaddaoc você estava absolutamente certo;)
Ryan Mortensen

Respostas:

181

Ok, então você tem duas opções aqui:

  1. Use o acordeão do jQuery UI - é bom, fácil e rápido. Veja mais informações aqui
  2. Ou, se você ainda quiser fazer isso sozinho, pode remover o fieldset(não é semanticamente correto usá-lo para isso de qualquer maneira) e criar uma estrutura você mesmo.

Veja como você faz isso. Crie uma estrutura HTML como esta:

<div class="container">
    <div class="header"><span>Expand</span>

    </div>
    <div class="content">
        <ul>
            <li>This is just some random content.</li>
            <li>This is just some random content.</li>
            <li>This is just some random content.</li>
            <li>This is just some random content.</li>
        </ul>
    </div>
</div>

Com este CSS: (Isso é para esconder as .contentcoisas quando a página carrega.

.container .content {
    display: none;
    padding : 5px;
}

Em seguida, usando jQuery, escreva um clickevento para o cabeçalho.

$(".header").click(function () {

    $header = $(this);
    //getting the next element
    $content = $header.next();
    //open up the content needed - toggle the slide- if visible, slide up, if not slidedown.
    $content.slideToggle(500, function () {
        //execute this after slideToggle is done
        //change text of header based on visibility of content div
        $header.text(function () {
            //change text based on condition
            return $content.is(":visible") ? "Collapse" : "Expand";
        });
    });

});

Aqui está uma demonstração: http://jsfiddle.net/hungerpain/eK8X5/7/

Krishwader
fonte
9
+1, pois isso resolveria o problema se houvesse mais de um elemento DIV na página. Em outras palavras, como você está direcionando o conteúdo dentro do cabeçalho clicado, isso se dimensiona bem.
jmort253
2
O fieldset não é obrigatório. Vou me livrar dele e usar apenas uma borda. Isso é excelente porque seleciona o div para expandir em relação ao cabeçalho em que cliquei, o que é importante porque posso ter vários números diferentes de itens listados, dependendo das configurações do usuário e outros fatores.
Ryan Mortensen
1
@Unipartisandev veja isto: jsfiddle.net/hungerpain/476Nq exemplo completo :)
krishwader
Eu realmente agradeço a ajuda. Haverá outras partes do site que, sem dúvida, precisarão usar um acordeão, embora essa coisa em particular seja mais um exemplo de exibição do tudo ou nada. Ainda estou tendo problemas. Meu jQuery estava desatualizado e não carregava. Isso foi corrigido, mas ainda não estou fazendo funcionar. Eu baguncei com isso por uma boa hora agora, vou dormir sobre isso. Talvez amanhã isso me acerte.
Ryan Mortensen
Maravilhoso, obrigado. Economizei muito tempo!
Basil Musa
21

e quanto a:

jQuery:

$('.majorpoints').click(function(){
    $(this).find('.hider').toggle();
});

HTML

<div>
  <fieldset class="majorpoints">
    <legend class="majorpointslegend">Expand</legend>
    <div class="hider" style="display:none" >
        <ul>
            <li>cccc</li>
            <li></li>
        </ul>
    </div>
</div>

Violino

Desta forma, você está vinculando o evento click à .majorpointsclasse e não precisa escrevê-lo no HTML todas as vezes.

raam86
fonte
Oi raam86, Eu daria um passo adiante e faria um .find no div usando uma classe em vez de um id. Se o solicitante tiver vários desses conjuntos de campos na página, ele desejará direcionar o ocultador para aquele relacionado ao conjunto de campos específico clicado. Espero que isto ajude! :) Por exemplo, você pode usar .closest para obter uma referência ao div pai e, em seguida, usar .find para localizar o div com class = "hider".
jmort253
1
Eu sei que são 3 da manhã;), mas acabei de notar que você ainda está usando id's em seu jsFiddle. Isso pode resultar em um comportamento indefinido, uma vez que a especificação W3C diz que cada id deve ser único. Se você alterar o hider para uma classe, isso será mais imune a bugs ou comportamento estranho e inexplicável em outros navegadores. Espero que isto ajude!
jmort253
deveria ser $ ('. majorpointslegend'). click (function () {$ (this) .parent (). find ('. hider'). toggle ();}); OU então, quando qualquer lugar no fieldset for clicado, ele entrará em colapso.
Awatatah
7

Então, em primeiro lugar, seu Javascript nem está usando jQuery. Existem algumas maneiras de fazer isso. Por exemplo:

Primeira maneira, usando o togglemétodo jQuery :

<div class="expandContent">
        <a href="#">Click Here to Display More Content</a>
 </div>
<div class="showMe" style="display:none">
        This content was hidden, but now shows up
</div>

<script>  
    $('.expandContent').click(function(){
        $('.showMe').toggle();
    });
</script>

jsFiddle: http://jsfiddle.net/pM3DF/

Outra maneira é simplesmente usar o showmétodo jQuery :

<div class="expandContent">
        <a href="#">Click Here to Display More Content</a>
 </div>
<div class="showMe" style="display:none">
        This content was hidden, but now shows up
</div>

<script>
    $('.expandContent').click(function(){
        $('.showMe').show();
    });
</script>

jsFiddle: http://jsfiddle.net/Q2wfM/

Ainda uma terceira maneira é usar o slideTogglemétodo de jQuery que permite alguns efeitos. Como o $('#showMe').slideToggle('slow');que exibirá lentamente o div oculto.

Michael Hawkins
fonte
Suponha que ele tenha mais de um desses elementos showMe na página. Lembre-se de que ele está usando um loop for para construir uma lista desses, portanto, direcionar class = "showMe" afetaria apenas a primeira instância desse elemento. Minha sugestão é fazer referência ao elemento showMe em relação ao clicado. Então esta seria uma boa solução. Espero que isto ajude! :)
jmort253
Certo, mas ele está usando o loop para construir a lista em uma série de <li>elementos, não divs. De qualquer forma, ele poderia simplesmente usar o ID do elemento para ocultá-lo.
Michael Hawkins
Você está pensando nas subseções e esquecendo que haverá mais dessas. Cada seção é preenchida com elementos li em uma subseção . "Esta lista é criada por um loop foreach que constrói com informações do meu banco de dados. Cada item é um contêiner com seções diferentes, portanto, esta não é uma lista como 1, 2, 3 ... etc. Estou listando seções repetidas com informações . Em cada seção, há uma subseção. " em suma, ele apenas mostrou a você apenas uma seção, embora haja mais.
jmort253
6

Você pode querer dar uma olhada neste método simples de Javascript a ser chamado ao clicar em um link para expandir ou recolher um painel / div.

<script language="javascript"> 
function toggle(elementId) {
    var ele = document.getElementById(elementId);
    if(ele.style.display == "block") {
            ele.style.display = "none";
    }
    else {
        ele.style.display = "block";
    }
} 
</script>

Você pode passar o ID div e ele alternará entre exibir 'nenhum' ou 'bloco'.

Fonte original em snip2code - Como recolher um div em html

Mike Scattoni
fonte
6

Muitos problemas aqui

Eu configurei um violino que funciona para você: http://jsfiddle.net/w9kSU/

$('.majorpointslegend').click(function(){
    if($(this).text()=='Expand'){
        $('#mylist').show();
        $(this).text('Colapse');
    }else{
        $('#mylist').hide();
        $(this).text('Expand');
    }
});
David Lin
fonte
3

tente jquery,

  <div>
        <a href="#" class="majorpoints" onclick="majorpointsexpand(" + $('.majorpointslegend').html() + ")"/>
        <legend class="majorpointslegend">Expand</legend>
        <div id="data" style="display:none" >
            <ul>
                <li></li>
                <li></li>
            </ul>
        </div>
    </div>


function majorpointsexpand(expand)
    {
        if (expand == "Expand")
            {
                $('#data').css("display","inherit");
                $(".majorpointslegend").html("Collapse");
            }
        else
            {
                $('#data').css("display","none");
                $(".majorpointslegend").html("Expand");
            }
    }
nmanandhan
fonte
3

Aqui está meu exemplo de animação de uma lista de funcionários com uma descrição expandida.

<html>
  <head>
    <style>
      .staff {            margin:10px 0;}
      .staff-block{       float: left; width:48%; padding-left: 10px; padding-bottom: 10px;}
      .staff-title{       font-family: Verdana, Tahoma, Arial, Serif; background-color: #1162c5; color: white; padding:4px; border: solid 1px #2e3d7a; border-top-left-radius:3px; border-top-right-radius: 6px; font-weight: bold;}
      .staff-name {       font-family: Myriad Web Pro; font-size: 11pt; line-height:30px; padding: 0 10px;}
      .staff-name:hover { background-color: silver !important; cursor: pointer;}
      .staff-section {    display:inline-block; padding-left: 10px;}
      .staff-desc {       font-family: Myriad Web Pro; height: 0px; padding: 3px; overflow:hidden; background-color:#def; display: block; border: solid 1px silver;}
      .staff-desc p {     text-align: justify; margin-top: 5px;}
      .staff-desc img {   margin: 5px 10px 5px 5px; float:left; height: 185px; }
    </style>
  </head>
<body>
<!-- START STAFF SECTION -->
<div class="staff">
  <div class="staff-block">
    <div  class="staff-title">Staff</div>
    <div class="staff-section">
        <div class="staff-name">Maria Beavis</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Maria earned a Bachelor of Commerce degree from McGill University in 2006 with concentrations in Finance and International Business. She has completed her wealth Management Essentials course with the Canadian Securities Institute and has worked in the industry since 2007.</p>
        </div>
        <div class="staff-name">Diana Smitt</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Diana joined the Diana Smitt Group to help contribute to its ongoing commitment to provide superior investement advice and exceptional service. She has a Bachelor of Commerce degree from the John Molson School of Business with a major in Finance and has been continuing her education by completing courses.</p>
        </div>
        <div class="staff-name">Mike Ford</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Mike: A graduate of École des hautes études commerciales (HEC Montreal), Guillaume holds the Chartered Investment Management designation (CIM). After having been active in the financial services industry for 4 years at a leading competitor he joined the Mike Ford Group.</p>
        </div>
    </div>
  </div>

  <div class="staff-block">
    <div  class="staff-title">Technical Advisors</div>
    <div class="staff-section">
        <div class="staff-name">TA Elvira Bett</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Elvira has completed her wealth Management Essentials course with the Canadian Securities Institute and has worked in the industry since 2007. Laura works directly with Caroline Hild, aiding in revising client portfolios, maintaining investment objectives, and executing client trades.</p>
        </div>
        <div class="staff-name">TA Sonya Rosman</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Sonya has a Bachelor of Commerce degree from the John Molson School of Business with a major in Finance and has been continuing her education by completing courses through the Canadian Securities Institute. She recently completed her Wealth Management Essentials course and became an Investment Associate.</p>
        </div>
        <div class="staff-name">TA Tim Herson</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Tim joined his father&#8217;s group in order to continue advising affluent families in Quebec. He is currently President of the Mike Ford Professionals Association and a member of various other organisations.</p>
        </div>
    </div>
  </div>
</div>
<!-- STOP STAFF SECTION -->

<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

<script language="javascript"><!--
//<![CDATA[
$('.staff-name').hover(function() {
    $(this).toggleClass('hover');
});
var lastItem;
    $('.staff-name').click(function(currentItem) {
        var currentItem = $(this);
      if ($(this).next().height() == 0) {
          $(lastItem).css({'font-weight':'normal'});
          $(lastItem).next().animate({height: '0px'},400,'swing');
          $(this).css({'font-weight':'bold'});
          $(this).next().animate({height: '300px',opacity: 1},400,'swing');
      } else {
          $(this).css({'font-weight':'normal'});
          $(this).next().animate({height: '0px',opacity: 1},400,'swing');
      }
      lastItem = $(this);
    });
//]]>
--></script>

</body></html>

Violino

Intacto
fonte
3

Dê uma olhada no toggle() jQuery função :

http://api.jquery.com/toggle/

Além disso, a função innerHTML jQuery é .html().

isso é amor
fonte
1
Olá, bem-vindo ao Stack Overflow! Você deve mostrar um exemplo para que sua resposta seja mais completa. Se o link quebrasse, sua resposta ainda seria útil para futuros visitantes. Boa sorte! :)
jmort253
Você pode editar para adicionar um exemplo ou adicionar isso como um comentário. Obrigado.
JGallardo de
2

Como você tem jQuery na página, pode remover esse onclickatributo e a majorpointsexpandfunção. Adicione o seguinte script ao final da página ou, de preferência, a um arquivo .js externo:

$(function(){

  $('.majorpointslegend').click(function(){
    $(this).next().toggle().text( $(this).is(':visible')?'Collapse':'Expand' );
  });

});

Esta solução deve funcionar com o seu HTML como está, mas não é realmente uma resposta muito robusta. Se você alterar seu fieldsetlayout, ele pode quebrá-lo. Sugiro que você coloque um classatributo nesse div oculto, goste class="majorpointsdetail"e use este código em seu lugar:

$(function(){

  $('.majorpoints').on('click', '.majorpointslegend', function(event){
    $(event.currentTarget).find('.majorpointsdetail').toggle();
    $(this).text( $(this).is(':visible')?'Collapse':'Expand' );
  });

});

Obs: não há </fieldset>tag de fechamento em sua pergunta, então estou assumindo que o div oculto está dentro do fieldset.

sergiopereira
fonte
Você está certo. Há um fieldset de fechamento, mas não o vi na minha pergunta. Ele vem imediatamente após o fechamento interno </div> e antes do fechamento externo </div>
Ryan Mortensen
1

Se você usou a função de dados recolhível, por exemplo

    <div id="selector" data-role="collapsible" data-collapsed="true">
    html......
    </div>

então fechará o div expandido

    $("#selector").collapsible().collapsible("collapse");   
Atif Hussain
fonte
1

Confira o Readmore.js de Jed Foster biblioteca .

Seu uso é tão simples quanto:

$(document).ready(function() {
  $('article').readmore({collapsedHeight: 100});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script src="https://fastcdn.org/Readmore.js/2.1.0/readmore.min.js" type="text/javascript"></script>

<article>
  <p>From this distant vantage point, the Earth might not seem of any particular interest. But for us, it's different. Consider again that dot. That's here. That's home. That's us. On it everyone you love, everyone you know, everyone you ever heard of, every human being who ever was, lived out their lives. The aggregate of our joy and suffering, thousands of confident religions, ideologies, and economic doctrines, every hunter and forager, every hero and coward, every creator and destroyer of civilization, every king and peasant, every young couple in love, every mother and father, hopeful child, inventor and explorer, every teacher of morals, every corrupt politician, every "superstar," every "supreme leader," every saint and sinner in the history of our species lived there – on a mote of dust suspended in a sunbeam.</p>

  <p>Space, the final frontier. These are the voyages of the starship Enterprise. Its five year mission: to explore strange new worlds, to seek out new life and new civilizations, to boldly go where no man has gone before!</p>

  <p>Here's how it is: Earth got used up, so we terraformed a whole new galaxy of Earths, some rich and flush with the new technologies, some not so much. Central Planets, them was formed the Alliance, waged war to bring everyone under their rule; a few idiots tried to fight it, among them myself. I'm Malcolm Reynolds, captain of Serenity. Got a good crew: fighters, pilot, mechanic. We even picked up a preacher, and a bona fide companion. There's a doctor, too, took his genius sister out of some Alliance camp, so they're keeping a low profile. You got a job, we can do it, don't much care what it is.</p>

  <p>Space, the final frontier. These are the voyages of the starship Enterprise. Its five year mission: to explore strange new worlds, to seek out new life and new civilizations, to boldly go where no man has gone before!</p>
</article>

Aqui estão as opções disponíveis para configurar seu widget:

{
  speed: 100,
  collapsedHeight: 200,
  heightMargin: 16,
  moreLink: '<a href="#">Read More</a>',
  lessLink: '<a href="#">Close</a>',
  embedCSS: true,
  blockCSS: 'display: block; width: 100%;',
  startOpen: false,

  // callbacks
  blockProcessed: function() {},
  beforeToggle: function() {},
  afterToggle: function() {}
},

Use pode usá-lo como:

$('article').readmore({
  collapsedHeight: 100,
  moreLink: '<a href="#" class="you-can-also-add-classes-here">Continue reading...</a>',
});

Espero que ajude.

Heitor Althmann
fonte