admin管理员组

文章数量:1221301

I'm trying to make the slides within jQuery UI tabs look as if they're next to each other and somewhat attached. I think I'll be able to achieve this by running the show and hide animations at the same time.

Currently jQuery slides the current panel out and then the next one. How can I slide out the current panel while at the same time slide in the next one?

$("#tabs").tabs({
hide:{effect:"slide", direction:"right"},
show:{effect:"slide", direction:"left"}
});

/

I want to start both the hide: and show: effects at the same time rather than one after the other

I'm trying to make the slides within jQuery UI tabs look as if they're next to each other and somewhat attached. I think I'll be able to achieve this by running the show and hide animations at the same time.

Currently jQuery slides the current panel out and then the next one. How can I slide out the current panel while at the same time slide in the next one?

$("#tabs").tabs({
hide:{effect:"slide", direction:"right"},
show:{effect:"slide", direction:"left"}
});

http://jsfiddle.net/CnEUh/2372/

I want to start both the hide: and show: effects at the same time rather than one after the other

Share Improve this question edited Dec 9, 2015 at 15:28 asked Dec 7, 2015 at 15:00 user3758078user3758078 11
  • I don't understand what you are asking for. If you want, you can use fadeIn / fadeOut effect if you don't want the sliding effect? – JonH Commented Dec 7, 2015 at 15:03
  • I'm trying to show and hide the tabs slides at the same time so that it looks like their next to each other. I don't want to use fade effects. – user3758078 Commented Dec 7, 2015 at 15:05
  • Note sure this is even possible given JQuery UI methodology. – Paulie_D Commented Dec 7, 2015 at 15:37
  • There has to be a way. – user3758078 Commented Dec 7, 2015 at 15:46
  • Seems like you'd be better off using a carousel, which does exactly that. You can style the controls as tabs if you like. – isherwood Commented Dec 7, 2015 at 18:26
 |  Show 6 more comments

5 Answers 5

Reset to default 5 +150

Here's the version based on my original comment.

This keeps jQuery's tab system, but hides the existing tabs. New slidingTabs div contains the sliding tabs so they can be animated.

Update

As per request, the initial content remains as it was before.

function makeTabsIntoSlidingTabs($tabs) {
  $tabs.find("div").wrapAll("<div style='display:none' />");
  $tabs.append("<div class='slidingTabs' />");
  $tabs.children("div").first().find("div").each(function(i) {
    $tabs.find(".slidingTabs").append($("<div />").addClass("tab").html($(this).html()));
  });

  $tabs.tabs({
    activate: function(event, ui) {
      var tab = $tabs.tabs("option", "active");
      $tabs.find(".slidingTabs div").first().animate({
        marginLeft: (tab * -100) + '%'
      }, 400, function() {});
    }
  });
}

makeTabsIntoSlidingTabs($("#tabs"));
.slidingTabs {
  white-space: nowrap;
  overflow-x: hidden;
}
.slidingTabs .tab {
  width: 100%;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/base/jquery-ui.css" rel="stylesheet" />


<div id="tabs">
  <ul>
    <li><a href="#tabs-1">Tab 1</a>
    </li>
    <li><a href="#tabs-2">Tab 2</a>
    </li>
    <li><a href="#tabs-3">Tab 3</a>
    </li>
  </ul>
  <div id="tabs-1">
    <p>Content for Tab 1</p>
  </div>
  <div id="tabs-2">
    <p>Content for Tab 2</p>
  </div>
  <div id="tabs-3">
    <p>Content for Tab 3</p>
  </div>
</div>

I think the proper way to change the behavior of a jQuery's widget is to extends it.

This way the solution is extensible, leave room for customization while allowing the tabs to remain a ui.widget, preserving jQuery's styling and state control.

$(document).ready(function() {
  // Clean whitespaces before creating tabs
  $('#tabs').cleanWhitespace();

  /* retains most of $.ui.tabs options, but now since both
   * hide & show animations are combined there's a
   * shared direction & duration
   */
  $("#tabs").customSlideTabs({
    direction: "left",
    duration: 500
  });
});


$.widget("nameSpace.customSlideTabs", $.ui.tabs, {
  _toggle: function(event, eventData) {
    var that = this,
      toShow = eventData.newPanel,
      toHide = eventData.oldPanel;

    this.running = true;

    var container = $(toHide.parent());
    var originalContainerOverflow = container.css("overflow");

    function complete() {
      container.css("overflow", originalContainerOverflow);

      eventData.newTab.closest("li").addClass("ui-tabs-active ui-state-active");
      eventData.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active");

      that.running = false;
      that._trigger("activate", event, eventData);
    }

    // start out by hiding, then showing, then completing
    if (toHide.length && toShow.length) {
      if (!this.options.duration) this.options.duration = 300;

      container.css({
        "overflow": "hidden",
        "white-space": "nowrap"
      });

      var fromX, toX;

      if (this.options.direction == "right") {
        toHide.appendTo(container);
        fromX = "-100%";
        toX = 0;
      } else {
        toShow.appendTo(container);
        fromX = 0;
        toX = "-100%";
      }

      toShow.css({
        "width": "100%",
        "box-sizing": "border-box",
        "display": "inline-block",
        "vertical-align": "top",
        "position": "relative",
        "left": fromX,
        "white-space": "wrap"
      });
      toHide.css({
        "width": "100%",
        "box-sizing": "border-box",
        "display": "inline-block",
        "vertical-align": "top",
        "position": "relative",
        "left": fromX,
        "white-space": "wrap"
      });

      toShow.animate({
        "left": toX
      }, {
        duration: that.options.duration,
        complete: function() {
          toShow.attr("style", "display: block;");
        }
      });

      toHide.animate({
        "left": toX
      }, {
        duration: that.options.duration,
        complete: function() {
          toHide.attr("style", "display: none;");
          complete();
        }
      });
    } else {
      toHide.hide();
      toShow.show();
      complete();
    }

    toHide.attr({
      "aria-expanded": "false",
      "aria-hidden": "true"
    });
    eventData.oldTab.attr("aria-selected", "false");
    // If we're switching tabs, remove the old tab from the tab order.
    // If we're opening from collapsed state, remove the previous tab from the tab order.
    // If we're collapsing, then keep the collapsing tab in the tab order.
    if (toShow.length && toHide.length) {
      eventData.oldTab.attr("tabIndex", -1);
    } else if (toShow.length) {
      this.tabs.filter(function() {
          return $(this).attr("tabIndex") === 0;
        })
        .attr("tabIndex", -1);
    }

    toShow.attr({
      "aria-expanded": "true",
      "aria-hidden": "false"
    });
    eventData.newTab.attr({
      "aria-selected": "true",
      tabIndex: 0
    });
  }
});

// Gratitues http://stackoverflow.com/a/2587356/1645830
$.fn.cleanWhitespace = function() {
  textNodes = this.contents().filter(
      function() {
        return (this.nodeType == 3 && !/\S/.test(this.nodeValue));
      })
    .remove();
  return this;
}
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>

<div id="tabs">
  <ul>
    <li><a href="#tabs-1">Tab 1</a>
    </li>
    <li><a href="#tabs-2">Tab 2</a>
    </li>
    <li><a href="#tabs-3">Tab 3</a>
    </li>
  </ul>
  <div id="tabs-1" class="tab">
    <p>Content for Tab 1</p>
  </div>
  <div id="tabs-2" class="tab">
    <p>Content for Tab 2</p>
    <p>Content for Tab 2</p>
  </div>
  <div id="tabs-3" class="tab">
    <p>Content for Tab 3</p>
  </div>
</div>
<div id="tabid"></div>

This is by no mean complete, since it only support sliding left & right and not the full set of animations from jQuery, but I think it's a good base to work on.

Try this out .Hope this is what you needed.i have used the css transition for the slide effect.

$(document).ready(function() {
$("#tabs").tabs({
  beforeActivate: function(event, ui) {
    var index = ui.newTab.find('a').attr('href');
    var currentPage = $(index).index();
    //530 is the width of the frame or you can say the overall width including padding and margin for the content tabs.
    $('.inner').css('left', '-' + (currentPage) * 530 + 'px');
  },
});
 
});
body {
  background-color: #eef;
}

#tabs {
  width: 95%;
  margin-left: auto;
  margin-right: auto;
  margin-top: 10px;
}

#maindiv {
  position: relative;
  overflow: hidden;
  width: 530px;
}

.inner {
  position: relative;
  display: inline-flex;
  height: 100%;
  transition: -webkit-transition: left .6s ease-in-out;
  transition: left .6s ease-in-out;
}

#tabs-1,
#tabs-2,
#tabs-3 {
  outline: solid 5px red;
  outline-offset: -5px;
  float: left;
  display: block !important;
  width: 480px;
}
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>

<div id="tabs">
  <ul>
    <li><a href="#tabs-1">Tab 1</a>
    </li>
    <li><a href="#tabs-2">Tab 2</a>
    </li>
    <li><a href="#tabs-3">Tab 3</a>
    </li>
  </ul>
  <div id="maindiv">
    <div class="inner" style="left:0px;">
      <div id="tabs-1">
        <p>Content for Tab 1</p>
      </div>
      <div id="tabs-2">
        <p>Content for Tab 2</p>
      </div>
      <div id="tabs-3">
        <p>Content for Tab 3</p>
      </div>
    </div>
  </div>
</div>
<div id="tabid"></div>

you can check the js fiddle Here.

This is NOT what you may be looking for, but you can always look for other solutions outside what jqueryui libraries gives you.

in this example I have removed the slide effect, I have wrapped your tabcontent divs into a container with nowrap and displayed them as inline-block so they are standing side by side even if you don't see them (overflow:hidden at the parent), then with little jquery adding and removing classes to this new container when you click on the tabs and a css transition you may have what you are looking for.

Ugly as hell imho but it's an example of a work around

$("#tabs").tabs({
    hide:{

  },
    show:{

  }
});
$('#ui-id-1').click(function() {
    $('.container').removeClass("move1");
    $('.container').removeClass("move2");
});
$('#ui-id-2').click(function() {
    $('.container').addClass("move1");
    $('.container').removeClass("move2");    
});
$('#ui-id-3').click(function() {
    $('.container').addClass("move2");
}); 

JSFIDDLE

It's not possible to achieve this effect, without changing tabs js script. You can use a workaround with beforeActivate method. Eg.:

$("#tabs").tabs({
    hide:{effect:"slide", direction:"right"},
    beforeActivate: function( event, ui ){ui.newPanel.show("slide", { direction: "left" });}
});

But then there's a problem with tabs positioning. I written quick workaround for this problem, but i think it's better solution to use some custom js. jsFiddle

$("#tabs").tabs({
  hide: {
    effect: "slide",
    direction: "right"
  },
  beforeActivate: function(event, ui) {
    setTimeout(function() {
      ui.newPanel.css({
        'position': 'absolute',
        'width': '100%',
        'top': ui.oldPanel.offset().top - 11
      });
      ui.newPanel.show("slide", {
        direction: "left"
      }, function() {
        ui.newPanel.css({
          'position': 'relative',
          'width': 'auto',
          'top': 0
        });
      });
    }, 15)
  }
});
body {
  background-color: #eef;
}
#tabs {
  width: 95%;
  margin-left: auto;
  margin-right: auto;
  margin-top: 10px;
  position: relative;
  overflow: hidden;
}
#tabs-1,
#tabs-2,
#tabs-3 {
  outline: solid 5px red;
  outline-offset: -5px;
}
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<div id="tabs">
  <ul>
    <li><a href="#tabs-1">Tab 1</a>
    </li>
    <li><a href="#tabs-2">Tab 2</a>
    </li>
    <li><a href="#tabs-3">Tab 3</a>
    </li>
  </ul>
  <div id="tabs-1">
    <p>Content for Tab 1
      <br/>
    </p>
  </div>
  <div id="tabs-2">
    <p>Content for Tab 2</p>
  </div>
  <div id="tabs-3">
    <p>Content for Tab 3</p>
  </div>
</div>
<div id="tabid"></div>

本文标签: javascriptHow to slide tabs in and out together like a carouselStack Overflow