如何用jQuery实现这个高级接口?

时间:2009-12-13 23:17:05

标签: javascript jquery

我正在与一个我试图整合的界面展开激烈的战斗。我在CSS& XHTML,但我的jQuery / JavaScript技能并不太令人印象深刻。我正在寻找的不是一个严格的答案,而是一些关于如何进行这些任务的暗示。

我想要实现的是在主内容区域中有一些框的布局,当用户按下侧边栏中的链接或框本身的标题时,可以展开和折叠。

dashboard http://www.timkjaerlange.com/foobar/example-dashboard-v01.gif

此外,我希望浏览器通过设置cookie来记住最后扩展的框。如果这还不够,我还希望能够为每个框添加一个“有限”类,从而禁用它,并且它是相应的sidebar-list-item。

此外,我希望该框具有基于其状态的类(展开,折叠,限制)。

这是我的标记:

<!-- S I D E B A R - L E F T -->    

<div id="sidebar-left">
    <ul class="sidebar-menu-1">
        <li><strong>List headline</strong>
        </li>
        <li><a href="#">Open module 1</a>
        </li>
        <li><a href="#">Open module 2</a>
        </li>
        <li><a href="#">Open module 3</a>
        </li>
    </ul>

</div><!--/sidebar-left-->


<!-- M A I N - C O N T E N T -->    

<div id="main-content">

    <!-- dashboard-module -->
    <div class="dashboard-module">
    <div class="dashboard-module-content limited">
        <h2>Headline 1</h2>
        <p class="teaser">Teaser-text 1</p>
        <div class="expand-collapse">
            [some content]
    ´   </div>
    </div>
    </div><!--/dashboard-module-->


    <!-- dashboard-module -->
    <div class="dashboard-module">
    <div class="dashboard-module-content limited">
        <h2>Headline 2</h2>
        <p class="teaser">Teaser-text 2</p>
        <div class="expand-collapse">
            [some content]
    ´   </div>
    </div>
    </div><!--/dashboard-module-->


    <!-- dashboard-module -->
    <div class="dashboard-module">
    <div class="dashboard-module-content limited">
        <h2>Headline 3</h2>
        <p class="teaser">Teaser-text 3</p>
        <div class="expand-collapse">
            [some content]
    ´   </div>
    </div>
    </div><!--/dashboard-module-->


</div><!--/main-content-->

这是我的jQuery:

// If the dashboard-module is "limited" do this:

$('div[class*=limited]').each( function(index) {
    var countFix = $('div.dashboard-module-content').index(this);
    var countFixPlusTwo = countFix + 2;
    $( 'ul.sidebar-menu-1 li:nth-child(' + countFixPlusTwo + ')' ).unbind('click').removeClass('selected').addClass('sidebar-menu-locked');
    $(this).parent('.dashboard-module').find('h2').unbind('click');
    $(this).find('.expand-collapse').remove();
    $(this).find('.dashboard-module p:hidden').show();
    $(this).addClass('limited-btn');
});

// Check for cookies and do stuff accordingly:

var cookieTest = $.cookie("cookie");

if(cookieTest == null){
    $('.js-hidden').hide();
    $('ul.sidebar-menu-1 li:not(.sidebar-menu-locked):eq(1)').addClass('selected');
    $('.dashboard-module-content:not(.limited):eq(0)' ).toggleClass('hide-btn');    
    $('.dashboard-module-content:not(.limited):not(:eq(0))' ).removeClass('hide-btn');
    $('.expand-collapse:eq(0)' ).show();
    };

if(cookieTest != null){
    var cookieTestPlusTwo = parseInt(cookieTest, 10) + 2;
    $('.dashboard-module-content:eq(' + cookieTest + ')' ).toggleClass('hide-btn'); 
    $('.dashboard-module-content:not(:eq(' + cookieTest + '))' ).removeClass('hide-btn');   
    $('ul.sidebar-menu-1 li:nth-child(' + cookieTestPlusTwo + '):not(.sidebar-menu-locked)').addClass('selected');
    $('ul.sidebar-menu-1 li:not(:nth-child(' + cookieTestPlusTwo + '))').removeClass('selected');
    $('.expand-collapse:eq(' + cookieTest +  ')' ).show();
    $('.expand-collapse:not(:eq(' + cookieTest +  '))').hide();
    };

// When clicking dashboard-module headers do stuff:

$('.dashboard-module h2:not(.limited h2):not(.tooltip h2)').click(function(index) {

    var indexFoo = $('.dashboard-module h2:not(.tooltip h2)').index(this);
    var indexPlusTwo = indexFoo + 2;
    var indexCookie = indexFoo;

    $.cookie("cookie", indexCookie, { expires: 7 });

    $('.dashboard-module-content:eq(' + indexFoo + ')').toggleClass('hide-btn');    
    $('.dashboard-module-content:not(:eq(' + indexFoo + '))' ).removeClass('hide-btn');

    $('ul.sidebar-menu-1 li:nth-child(' + indexPlusTwo + ')').addClass('selected');
    $('ul.sidebar-menu-1 li:not(:nth-child(' + indexPlusTwo + '))').removeClass('selected');

    $('.dashboard-module-content:eq(' + indexFoo + ') .expand-collapse').toggle('fast');
    $('.dashboard-module-content:not(:eq(' + indexFoo + ')) .expand-collapse').hide('fast');

    $('.dashboard-module-content:not(.limited)').each( function(){
        if($(this).parent('.dashboard-module').find('.hide-btn').length == 0){
            $(this).find('p.teaser').show();
        }
        else {
            $(this).find('p.teaser').hide();
        }
    });
});

// When clicking sidebar list-items do stuff:

$('.sidebar-menu-1 li:not(.sidebar-menu-locked)').click(function(index) {

    var indexFoo = ($('.sidebar-menu-1 li').index(this) - 1);
    var indexPlusTwo = indexFoo + 2;
    var indexCookie = indexFoo;

    $.cookie("cookie", indexCookie, { expires: 7 });

    $('.dashboard-module-content:eq(' + indexFoo + ')').toggleClass('hide-btn');    
    $('.dashboard-module-content:not(:eq(' + indexFoo + '))' ).removeClass('hide-btn'); 

    $('ul.sidebar-menu-1 li:nth-child(' + indexPlusTwo + ')').addClass('selected');
    $('ul.sidebar-menu-1 li:not(:nth-child(' + indexPlusTwo + '))').removeClass('selected');

    $('.dashboard-module-content:eq(' + indexFoo + ') .expand-collapse').toggle('fast');
    $('.dashboard-module-content:not(:eq(' + indexFoo + ')) .expand-collapse').hide('fast');

    $('.dashboard-module-content:not(.limited)').each( function(){
        if($(this).parent('.dashboard-module:not(.limited)').find('.hide-btn').length == 0){
            $(this).find('p.teaser').show();
        }
        else {
            $(this).find('p.teaser').hide();
        }
    });

});

至于现在它都可以在FF中运行,但在IE7 + 8中却没有。但我的问题不是关于如何使它在IE中运行,而是更多关于如何进行这种任务?我怀疑我的jQuery并不完全干,但我该如何压缩它呢?

您将如何编写和组织代码?很抱歉,如果这是一个过于宽泛和冗长的问题,但我真的对经验丰富的jQuery设计师如何应对这样的挑战感兴趣。

更新:感谢Tatu Ulmanen的帮助,我成功地将其组合在一起:http://timkjaerlange.com/foobar/jquery-test/index.html

3 个答案:

答案 0 :(得分:4)

打开模块

侧边栏链接 - &gt;内容关系,在侧边栏中使用与主要内容的div的ID相对应的rel标签,如下所示:

<ul id="sidebar">
    <li><a href="#" rel="tab_1">Open tab 1</a></li>
    <li><a href="#" rel="tab_2">Open tab 2</a></li>
    <li><a href="#" rel="tab_3">Open tab 3</a></li>
</ul>

...

<div id="content">
    <div class="module" id="tab_1"> ... </div>
    <div class="module" id="tab_2"> ... </div>
    <div class="module" id="tab_3"> ... </div>
</div>

然后在jQuery中,tab的更改很容易实现:

$('#sidebar a').click(function() {
    $('#content div.module').hide();
    $('#content div#'+$(this).attr('rel')).show();
    return false;
});

模块标题

如果您希望模块的标题始终可见,您可以执行以下操作:

<div id="content">
    <div class="module" id="tab_1">
        <h2>Module header</h2>
        <p class="module_tools">
            <a href="#" class="module_hide">Hide</a>
            <a href="#" class="module_show">Show</a>
        </p>
        <div class="module_contents">
            ...

在jQuery中:

$('#sidebar a').click(function() {
    var $visible_module = $('#content div#'+$(this).attr('rel'));

    $('#content div.module div.module_contents').hide();
    $('#content div.module div.module_contents a.module_hide').hide();
    $('#content div.module div.module_contents a.module_show').show();

    $visible_module.find('div.module_contents').show();
    $visible_module.find('a.module_hide').show();
    $visible_module.find('a.module_show').hide();

    return false;
});

模块显示和隐藏

然后,为了实现模块中的show按钮,我会“欺骗”并按下侧栏中的相应按钮。

$('#content .module_show').click(function() {
    $('#sidebar a[rel='+$(this).closest('div.module').attr('id')).click();
    return false;
});

隐藏按钮易于实现:

$('#content .module_hide').click(function() {
    $(this).closest('div.module').find('div.module_contents').hide();
    return false;
});

锁定模块

最后一件事是实现'锁定'功能。为此,我只是在侧边栏的链接中添加一个类,告诉当前选项卡处于非活动状态,然后根据它修改模块:

<ul id="sidebar">
    <li><a href="#" rel="tab_1">Open tab 1</a></li>
    <li><a href="#" rel="tab_2" class="inactive">Open tab 2</a></li>

在jQuery中:

$('#sidebar a.inactive').each(function() {
    var $target_module = $('#content div#'+$(this).attr('rel'));
    // Remove the links alltogether
    $target_module.find('.module_hide, .module_show').remove();
    return false;        
});

还必须修改侧边栏链接的点击事件:

$('#sidebar a').click(function() {
    if($(this).hasClass('inactive')) return false;
    ...

涵盖了不包括cookie保存的所有基础。希望这能为您提供有关如何简化代码的一些建议。请注意,我没有测试任何这个,所以我不能保证它的工作原理。如果您不理解某些内容,请随时询问。

确保使用CSS样式设置应用程序的初始状态,例如隐藏模块中的所有“隐藏”链接和.module_contents,因为它们可能默认关闭。

答案 1 :(得分:1)

我建议从http://plugins.jquery.com/开始。

查看那里的插件示例。播放演示,文档并查看源代码。

答案 2 :(得分:0)

我认为Tatu发布了一个很棒的答案。但是我使用了一些脚本来更紧密地使用HTML。我发布了working demo for you here ...额外的“}})”在右边缘只出于某种原因出现在bin中(我不知道如何摆脱它)。

CSS

#sidebar-left {
 float:left;
 width: 200px;
 height: 700px;
 background: #444;
 padding: 20px;
}
#main-content {
 float:left;
 width: 600px;
 height: 700px;
 background: #555;
 padding: 20px;
}
.sidebar-menu-1 .selected a { color: #080; }
.sidebar-menu-1 .sidebar-menu-locked a { color: #d00; text-decoration: line-through; }
.dashboard-module h2 {  cursor: pointer; }
.dashboard-module { border: #777 1px solid; padding: 5px 15px; margin-bottom: 5px; }
.dashboard-module-content {}
.limited h2 { text-decoration: line-through; }

.expand-collapse { display: none; }

.show_btn { background: #08c url(http://i46.tinypic.com/2vd3246.gif) 98% 4px no-repeat; }
.hide_btn { background: #080 url(http://i47.tinypic.com/iqadz5.gif) 98% 4px no-repeat; }
.limited_btn { background: #d00 url(http://i47.tinypic.com/209ghzp.gif) 98% 4px no-repeat; }

HTML(仅略微修改)

<!-- S I D E B A R - L E F T -->

<div id="sidebar-left">
 <ul class="sidebar-menu-1">
  <li><strong>List headline</strong></li>
  <li><a href="#m1">Open module 1</a></li>
  <li><a href="#m2">Open module 2</a></li>
  <li><a href="#m3">Open module 3</a></li>
  <li><a href="#m4">Open module 4</a></li>
 </ul>
</div><!--/sidebar-left-->

<!-- M A I N - C O N T E N T -->

<div id="main-content">

    <!-- dashboard-module -->
    <div id="m1" class="dashboard-module">
    <div class="dashboard-module-content">
        <h2>Headline 1</h2>
        <p class="teaser">Teaser-text 1</p>
        <div class="expand-collapse">
                [some content]
        </div>
    </div>
    </div><!--/dashboard-module-->


    <!-- dashboard-module -->
    <div id="m2" class="dashboard-module">
    <div class="dashboard-module-content">
        <h2>Headline 2</h2>
        <p class="teaser">Teaser-text 2</p>
        <div class="expand-collapse">
                [some content]
        </div>
    </div>
    </div><!--/dashboard-module-->


    <!-- dashboard-module -->
    <div id="m3" class="dashboard-module">
    <div class="dashboard-module-content">
        <h2>Headline 3</h2>
        <p class="teaser">Teaser-text 3</p>
        <div class="expand-collapse">
                [some content]
        </div>
    </div>
    </div><!--/dashboard-module-->

    <!-- dashboard-module -->
    <div id="m4" class="dashboard-module">
    <div class="dashboard-module-content limited">
        <h2>Headline 4</h2>
        <p class="teaser">Teaser-text 4</p>
        <div class="expand-collapse">
                [some content]
        </div>
    </div>
    </div><!--/dashboard-module-->

</div><!--/main-content-->

脚本

$(document).ready(function(){
 $('.dashboard-module').each(function(){
  var mod = $(this);
  mod.find('h2').addClass('show_btn'); 
  // If the dashboard-module is "limited" do this:
  if (mod.find('.dashboard-module-content').hasClass('limited')){
   $('.sidebar-menu-1').find('a[href$=' + mod.attr('id') + ']').parent().removeClass('selected').addClass('sidebar-menu-locked');
   mod.find('.expand-collapse').remove();
   mod.find('p:hidden').show();
   mod.find('h2').removeClass('show_btn hide_btn').addClass('limited_btn');
  };
 // Add click to Dashboard Modules
  mod.find('h2').click(function(){
   toggleContent(mod);
  })
 })
 // Add click to Side Menu
 $('.sidebar-menu-1 a').click(function(){
  // The dashboard-module ID is contained in the sidebar-menu link href attribute
  toggleContent( $( $(this).attr('href')) );
  return false;
 })
 function toggleContent(mod){
  // don't open limited content
  if (mod.find('.dashboard-module-content').hasClass('limited')) return false;
  // close open content
  if (!mod.find('h2').hasClass('hide_btn')){
   $('.hide_btn').removeClass('hide_btn').addClass('show_btn').parent().find('.expand-collapse').hide();
   $('.sidebar-menu-1 .selected').removeClass('selected');
  }
  var btn = (mod.find('.expand-collapse').toggle().is(':hidden')) ? 'show_btn' : 'hide_btn';
  mod.find('h2').removeClass('show_btn hide_btn').addClass(btn);
  $('.sidebar-menu-1').find('a[href$=' + mod.attr('id') + ']').parent().toggleClass('selected');
 }
})