For example, you can view a large amount of information and use it when using multiple window frameworks on Web pages. Now there are many jquery Tab controls on the Internet. I have used idtabs before, which is simple and practical, it is also flexible, but more encoding is required for complex situations, which is too simple. There is also the tab control in jquery UI (I have never used it, but I am not familiar with jquery ui). In addition, it is the tab control in easyui, which was first seen on javaeye, the interface is pretty, because it has not been open-source before, so it has not followed up (it seems that it has been open-source recently. I downloaded it a few days ago. The encoding style is a bit like prototype, and I cannot see jquery's shadow, I don't know why it's called jquery easyui. It's hard to make other comments because it's not too deep ). After talking so much about it, let's go back to the theme. For various reasons, we have to think about developing one by ourselves. So we have this article. Let's take a look at the effect.
Is a single-page, Multi-Window Frame
Is the result of the call example provided at the end of this article.
You can see that ExtJs is still used. In fact, CSS basically directly copies it. I think it looks very nice. Of course, you can use it in your own way.
First, let's start with HTML.
Note: The idea of the first control is always to determine the HTML structure first, followed by the style, and finally the event method implemented by js.
In fact, we can basically determine the figure. The tab control mainly consists of two parts: the html header, which is used to put the tab; the other is the body, which is the content container. The tab control is divided into two parts: header and body.
The header contains multiple tabs, so it is easy to think of ul + li. Let's take a look at the actual html structure in the header.
Here, li is a tab, the first a is the close button, and the second a is the actual content. through nested labels, the left and right background image settings are implemented (this practice is more common ). Of course, it can have a good effect, but it still depends on CSS support. You must have a certain understanding of CSS.
The structure of the Body is simpler, that is, the div nested div is over.
Second CSS style sheet
Because CSS is copy EXTJS, I will not introduce it much. You can refer to the actual code in the Code download. If you have any questions, you can communicate with each other.
Third, I started writing JS.
The old rule comes with a complete piece of JS Code. There are about 500 lines of code. In fact, the line feed is very diligent, and the actual amount of code is actually relatively small.
Copy codeThe Code is as follows:; (function ($ ){
$. Fn. tabpanel = function (option ){
Var dfop = {
Items: [], // tab data item {id, text, classes, disabled, closeable, content, url, cuscall, onactive}
Width: 500,
Height: 400,
Scrollwidth: 100, // If a scroll bar exists, click the button to scroll each time.
Autoscroll: true // automatically add the scroll button when the tab width is greater than the container
};
Var headerheight = 28;
$. Extend (dfop, option );
Var me = $ (this). addClass ("x-tab-panel"). width (dfop. width );
Innerwidth = dfop. width-2;
// Construct the Html of the Tab
Var tcs = dfop. autoscroll? "X-tab-scrolling-top ":"";
Var header = $ ("<div class = 'x-tab-panel-header x-unselectable" + tcs + "'unselectable = 'on' style = 'width: "+ innerwidth +" px; MozUserSelect: none; KhtmlUserSelect: none; '> </div> ");
Var stripwrap = $ ("<div class = 'x-tab-strip-wrap'/> ");
Var scrollerright = $ ("<div class = 'x-tab-scroller-right x-unselectable' style = 'height: 24px; visibility: hidden; login userselect: none; khtmluserselect: none; 'unselectable = 'on'/> ");
Var scrollerleft = $ ("<div class = 'x-tab-scroller-left x-unselectable' style = 'height: 24px; visibility: hidden; login userselect: none; khtmluserselect: none; 'unselectable = 'on'/> ");
Var ulwrap = $ ("<ul class = 'x-tab-strip x-tab-strip-top '> </ul> ");
Var stripspacer =$ ("<div class = 'x-tab-strip-spacer'/> ");
Var litemp = [];
For (var I = 0, l = dfop. items. length; I <l; I ++)
{
Var item = dfop. items [I];
Builditemlihtml (item, litemp );
}
Litemp. push ("<li class = 'x-tab-edge '/> <div class = 'x-clear'> </div> ");
Ulwrap.html (litemp. join (""));
Litemp = null;
Stripwrap. append (ulwrap );
If (dfop. autoscroll)
{
Header. append (scrollerright). append (scrollerleft );
}
Header. append (stripwrap). append (stripspacer );
Var bodyheight = dfop. height-headerheight;
Var bodywrap = $ ("<div class = 'x-tab-panel-bwrap '/> ");
Var body = $ ("<div class = 'x-tab-panel-body x-tab-panel-body-top '/>" detail .css ({width: innerwidth, height: bodyheight });
Var bodytemp = [];
For (var I = 0, l = dfop. items. length; I <l; I ++ ){
Var item = dfop. items [I];
Builditembodyhtml (item, bodytemp );
}
Body.html (bodytemp. join (""). appendTo (bodywrap );
Me. append (header). append (bodywrap );
Initevents ();
Function builditemlihtml (item, parray)
{
Parray. push ("<li id = 'tab _ li _", item. id, "'class = '", item. isactive? "X-tab-strip-active": "", item. disabled? "X-tab-strip-disabled": "", item. closeable? "X-tab-strip-closable": "", item. classes? "X-tab-with-icon": "", "'> ");
Parray. push ("<a class = 'x-tab-strip-close 'onclick = 'Return false; '/> ");
Parray. push ("<a class = 'x-tab-Right' onclick = 'Return false; 'href = '#'> ");
Parray. push ("<em class = 'x-tab-left'> <span class = 'x-tab-strip-inner '> <span class = 'x-tab-strip- text ", item. classes | "", "'>", item. text, "</span> </em> ");
Parray. push ("</a> </li> ");
}
Function builditembodyhtml (item, parray)
{
Parray. push ("<div class = 'x-panel x-panel-noborder", item. isactive? "": "X-hide-display", "'id = 'tab _ item _", item. id, "'style = 'width:", innerwidth, "px"> ");
Parray. push ("<div class = 'x-panel-bwrap'> ");
Parray. push ("<div class = 'x-panel-body x-panel-body-noheader x-panel-body-noborder 'id = 'tab _ item_content _", item. id, "'style = 'position: relative; width:", innerwidth, "px; height:", bodyheight, "px; overflow: auto; '> ");
If (item. url ){
Parray. push ("<iframe name = 'tab _ item_frame _", item. id, "'width = '000000' height = '000000' id = 'tab _ item_frame _", item. id, "'src = 'about: blank 'frameBorder = '0'/> ");
}
Else if (item. cuscall ){
Parray. push ("<div class = 'loadingicon '/> ");
}
Else {
Parray. push (item. content );
}
Parray. push ("</div> ");
}
Function initevents ()
{
// Reset scoller
Resetscoller ();
Scollerclick ();
Ulwrap. find ("li: not (. x-tab-edge)"). each (function (e ){
Inititemevents (this );
});
}
Function inititemevents (liitem)
{
Liswaphover. call (liitem );
Liclick. call (liitem );
Closeitemclick. call (liitem );
}
Function scollerclick ()
{
If (dfop. autoscroll)
{
Scrollerleft. click (function (e) {scolling ("left ")});
Scrollerright. click (function (e) {scolling ("right ")});
}
}
Function resetscoller ()
{
If (dfop. autoscroll)
{
Var edge = ulwrap. find ("li. x-tab-edge ");
Var eleft = edge. position (). left;
Var sleft = stripwrap. attr ("scrollLeft ");
If (sleft + eleft> innerwidth)
{
Header. addClass ("x-tab-scrolling ");
Scrollerleft.css ("visibility", "visible ");
Scrollerright.css ("visibility", "visible ");
If (sleft> 0)
{
Scrollerleft. removeClass ("x-tab-scroller-left-disabled ");
}
Else {
Scrollerleft. addClass ("x-tab-scroller-left-disabled ");
}
If (eleft> innerwidth)
{
Scrollerright. removeClass ("x-tab-scroller-right-disabled ");
}
Else {
Scrollerright. addClass ("x-tab-scroller-right-disabled ");
}
Dfop. showscrollnow = true;
}
Else
{
Header. removeClass ("x-tab-scrolling ");
Stripwrap. animate ({"scrollLeft": 0}, "fast ");
Scrollerleft.css ("visibility", "hidden ");
Scrollerright.css ("visibility", "hidden ");
Dfop. showscrollnow = false;
}
}
}
//
Function scolling (type, max)
{
// Debugger;
If (! Dfop. autoscroll |! Dfop. showscrollnow)
{
Return;
}
// Debugger;
// Var swidth = stripwrap. attr ("scrollWidth ");
Var sleft = stripwrap. attr ("scrollLeft ");
Var edge = ulwrap. find ("li. x-tab-edge ");
Var eleft = edge. position (). left;
If (type = "left "){
If (scrollerleft. hasClass ("x-tab-scroller-left-disabled "))
{
Return;
}
If (sleft-dfop.scrollwidth-20> 0)
{
Sleft-= dfop. scrollwidth;
}
Else {
Sleft = 0;
Scrollerleft. addClass ("x-tab-scroller-left-disabled ");
}
If (scrollerright. hasClass ("x-tab-scroller-right-disabled "))
{
Scrollerright. removeClass ("x-tab-scroller-right-disabled ");
}
Stripwrap. animate ({"scrollLeft": sleft}, "fast ");
}
Else {
If (scrollerright. hasClass ("x-tab-scroller-right-disabled ")&&! Max)
{
Return;
}
// Left +;
If (max | (eleft> innerwidth & eleft-dfop.scrollwidth-20 <= innerwidth ))
{
// Debugger;
Sleft = sleft + eleft-(innerwidth-38 );
Scrollerright. addClass ("x-tab-scroller-right-disabled ");
// Sleft = eleft-innerwidth;
}
Else
{
Sleft + = dfop. scrollwidth;
}
If (sleft> 0)
{
If (scrollerleft. hasClass ("x-tab-scroller-left-disabled "))
{
Scrollerleft. removeClass ("x-tab-scroller-left-disabled ");
}
}
Stripwrap. animate ({"scrollLeft": sleft}, "fast ");
}
}
Function scollingToli (liitem)
{
Var sleft = stripwrap. attr ("scrollLeft ");
Var lleft = liitem. position (). left;
Var lwidth = liitem. outerWidth ();
Var edge = ulwrap. find ("li. x-tab-edge ");
Var eleft = edge. position (). left;
If (lleft <= 0)
{
Sleft + = (lleft-2 );
If (sleft <0)
{
Sleft = 0;
Scrollerleft. addClass ("x-tab-scroller-left-disabled ");
}
If (scrollerright. hasClass ("x-tab-scroller-right-disabled "))
{
Scrollerright. removeClass ("x-tab-scroller-right-disabled ");
}
Stripwrap. animate ({"scrollLeft": sleft}, "fast ");
}
Else {
If (lleft + lwidth> innerwidth-40)
{
Sleft = sleft + lleft + lwidth +-innerwidth + 40; // 40 = scrollerleft and scrollerrightwidth;
If (scrollerleft. hasClass ("x-tab-scroller-left-disabled "))
{
Scrollerleft. removeClass ("x-tab-scroller-left-disabled ");
}
// If the last one is rolled, disable right;
If (eleft-(lleft + lwidth +-innerwidth + 40) <= innerwidth)
{
Scrollerright. addClass ("x-tab-scroller-right-disabled ");
}
Stripwrap. animate ({"scrollLeft": sleft}, "fast ");
}
}
Liitem. click ();
}
Function liswaphover ()
{
$ (This). hover (function (e ){
If (! $ (This). hasClass ("x-tab-strip-disabled "))
{
$ (This). addClass ("x-tab-strip-over ");
}
}, Function (e ){
If (! $ (This). hasClass ("x-tab-strip-disabled "))
{
$ (This). removeClass ("x-tab-strip-over ");
}
});
}
Function closeitemclick ()
{
If ($ (this). hasClass ("x-tab-strip-closable "))
{
$ (This). find ("a. x-tab-strip-close"). click (function (){
Deleteitembyliid ($ (this). parent (). attr ("id "));
});
}
}
Function liclick ()
{
$ (This). click (function (e ){
Var itemid = this. id. substr (7 );
Var curr = getactiveitem ();
If (curr! = Null & itemid = curr. id)
{
Return;
}
Var clickitem = getitembyid (itemid );
If (clickitem & clickitem. disabled)
{
Return;
}
If (curr)
{
$ ("# Tab_li _" + curr. id). removeClass ("x-tab-strip-active ");
$ ("# Tab_item _" + curr. id). addClass ("x-hide-display ");
Curr. isactive = false;
}
If (clickitem)
{
$ (This). addClass ("x-tab-strip-active ");
$ ("# Tab_item _" + clickitem. id). removeClass ("x-hide-display ");
If (clickitem. url)
{
Var cururl = $ ("# tab_item_frame _" + clickitem. id). attr ("src ");
If (cururl = "about: blank ")
{
$ ("# Tab_item_frame _" + clickitem. id). attr ("src", clickitem. url );
}
}
Else if (clickitem. cuscall &&! Clickitem. cuscalled)
{
Var panel = $ ("# tab_item_content _" + clickitem. id );
Var ret = clickitem. cuscall (this, clickitem, panel );
Clickitem. cuscalled = true;
If (ret) // if a return value exists and is not empty
{
Clickitem. content = ret;
Panel.html (ret );
}
}
Clickitem. isactive = true;
If (clickitem. onactive)
{
Clickitem. onactive. call (this, clickitem );
}
}
});
}
// Obtain the current active item
Function getactiveitem ()
{
For (var I = 0, j = dfop. items. length; I <j; I ++)
{
If (dfop. items [I]. isactive)
{
Return dfop. items [I];
Break;
}
}
Return null;
}
// Obtain Item data by ID
Function getitembyid (id)
{
For (var I = 0, j = dfop. items. length; I <j; I ++)
{
If (dfop. items [I]. id = id)
{
Return dfop. items [I];
Break;
}
}
Return null;
}
Function getIndexbyId (id)
{
For (var I = 0, j = dfop. items. length; I <j; I ++)
{
If (dfop. items [I]. id = id)
{
Return I;
Break;
}
}
Return-1;
}
// Add an item
Function addtabitem (item)
{
Var chkitem = getitembyid (item. id );
If (! Chkitem ){
Var isactive = item. isactive;
Item. isactive = false;
Var lastitem = dfop. items [dfop. items. length-1];
Dfop. items. push (item );
Var lastli = $ ("# tab_li _" + lastitem. id );
Var lastdiv =$ ("# tab_item _" + lastitem. id );
Var litemp = [];
Var bodytemp = [];
Builditemlihtml (item, litemp );
Builditembodyhtml (item, bodytemp );
Var liitem = $ (litemp. join (""));
Var bodyitem = $ (bodytemp. join (""));
Lastli. after (liitem );
Lastdiv. after (bodyitem );
// Event
Var li = $ ("# tab_li _" + item. id );
Inititemevents (li );
If (isactive)
{
Li. click ();
}
Resetscoller ();
Scolling ("right", true );
}
Else {
Alert ("the specified tab item already exists! ");
}
}
Function openitemOrAdd (item, allowAdd)
{
Var checkitem = getitembyid (item. id );
If (! Checkitem & allowAdd)
{
Addtabitem (item );
}
Else {
Var li = $ ("# tab_li _" + item. id );
ScollingToli (li );
}
}
// Remove a tab
Function deleteitembyliid (liid)
{
Var id = liid. substr (7 );
$ ("#" + Liid). remove ();
$ ("# Tab_item _" + id). remove ();
Var index = getIndexbyId (id );
If (index> = 0)
{
Var nextcur;
If (index <dfop. items. length-1)
{
Nextcur = dfop. items [index + 1];
}
Else if (index> 0 ){
Nextcur = dfop. items [index-1];
}
If (nextcur)
{
$ ("# Tab_li _" + nextcur. id). click ();
}
Dfop. items. splice (index, 1 );
Resetscoller ();
Scolling ("right", true );
}
}
Function resize (width, height)
{
If (width = dfop. width & height = dfop. height)
{
Return;
}
If (width) {dfop. width = width };
If (height) {dfop. height = height ;}
Innerwidth = width-2;
Bodyheight = dfop. height-headerheight;
Me.css ("width", dfop. width );
Header.css ("width", innerwidth );
Body.css ({width: innerwidth, height: bodyheight });
For (var I = 0, j = dfop. items. length; I <j; I ++)
{
Var item = dfop. items [I];
$ ("# Tab_item _" incluitem.id).css ({width: innerwidth });
$ ("# Tab_item_content _" incluitem.id).css ({width: innerwidth, height: bodyheight });
}
Resetscoller ();
}
// Set whether the tab item is disabled
Function setdisabletabitem (itemId, disabled)
{
Var chitem = getitembyid (itemId );
If (! Chitem | chitem. disabled = disabled)
{
Return;
}
If (disabled)
{
Chitem. disabled = true;
$ ("# Tab_item _" + item. id). addClass ("x-tab-strip-disabled ");
}
Else {
Chitem. disabled = false;
$ ("# Tab_item _" + item. id). removeClass ("x-tab-strip-disabled ");
}
}
Me [0]. tab = {
Addtabitem: addtabitem,
Opentabitem: openitemOrAdd,
Resize: resize,
Setdisabletabitem: setdisabletabitem
};
};
$. Fn. addtabitem = function (item)
{
If (this [0]. tab)
{
Return this [0]. tab. addtabitem (item );
}
Return false;
}
$. Fn. opentabitem = function (item, orAdd)
{
If (this [0]. tab)
{
Return this [0]. tab. opentabitem (item, orAdd );
}
Return false;
}
$. Fn. resizetabpanel = function (w, h)
{
If (this [0]. tab)
{
Return this [0]. tab. resize (w, h );
}
Return false;
}
$. Fn. setdisabletabitem = function (itemId, disabled)
{
If (this [0]. tab)
{
Return this [0]. tab. setdisabletabitem (itemId, disabled );
}
Return false;
}
}) (JQuery );
Next, let's take a step-by-step analysis of my implementation and start to write the "template" of the jQuery control. For more information about the reason, see this description.Copy codeThe Code is as follows:; (function ($ ){
$. Fn. tabpanel = function (option ){
};
) (JQuery );
Then, write the default parameters.Copy codeThe Code is as follows: var dfop = {
Items: [], // tab data item {id, text, classes, disabled, closeable, content, url, cuscall, onactive}
Width: 500,
Height: 400,
Scrollwidth: 100, // If a scroll bar exists, click the button to scroll each time.
Autoscroll: true // automatically add the scroll button when the tab width is greater than the container
};
The default parameter is still relatively simple. I have added comments, and it is troublesome to use the item array. However, I believe that most of the items are understood by the literal meaning. I 'd like to describe them: id is the identifier. It must be unique, text displayed, and classes-specific styles. For example, in the homepage of the effect, I added an icon, this attribute is used to enable or disable disabled, or disable closeable,
Content, url, and cuscall can be set to either of them. content indicates that the actual content html and url are marked as webpages, and iframe is automatically added to the content, while cuscall indicates custom content, this attribute is used to determine the content display result of cuscall execution.
Onactive refers to the event triggered when the tab item is activated. Is a function that accepts item content. For details, see the demo.
After the parameter settings are complete, update the default parameter through the parameters passed externally:
$. Extend (dfop, option );
The next step is to build the html part, which is long and I will not repeat the code.
After building the html, we need to add events to the html elements, including click events of tabs, left-shift buttons, click events of right-shift buttons, and hover effect events of tabs.
Copy codeThe Code is as follows:
Function initevents ()
{
// Reset scoller
Resetscoller (); // sets whether to scroll out by default.
Scollerclick (); // Click Event of the scroll bar. If so
Ulwrap. find ("li: not (. x-tab-edge)"). each (function (e ){
Inititemevents (this); // Add events to each tab
});
}
Function inititemevents (liitem)
{
Liswaphover. call (liitem); // The mouse hover effect of the tab
Liclick. call (liitem); // Click Event on the tab
Closeitemclick. call (liitem); // click the Close event.
}
As for the implementation of events, it is easy to break through each other. It is cumbersome to handle the appearance and disabling of control scroll buttons. Other click events are relatively simple.
The last step is the public method. To publish these methods to compile some internal methods, the tabpanel is naturally relatively easy to use and scalable. You can make some adjustments based on your actual needs. Of course, the current functions should also meet most of the requirements.
Finally, let's take a look at the public methods:
1: The method of dynamically adding a tab item, that is, adding a tab item dynamically through js. Here it is actually the maintenance of items data, and then re-calling the html method output by tabitem, finally, set the event for it separately. Simple
2: select or add. This is also the method called through js. It is an extension of the previous method. You can activate a tab item through js. If this item does not exist, add this tab through parameters.
3: reset the size of the tabpanel, that is, reset the size of the tabpanel through js. This is called when the size of the window changes. It is very practical.
4: Set an item to disabled, and set the status of a tabitem to disabled using the js method.
Finally, you can use the code to include the previous control instance. I have provided a compressed package, but I recommend that you use SVN to obtain the latest code. Sometimes I will not post any small changes.
Http://code.google.com/p/xjplugin/downloads/list
Http://xiazai.jb51.net/201005/yuanma/xjPlugin_addtabpanel.rar