たとえば、大量の情報を表示する場合、Web ページでマルチウィンドウ フレームワークを使用するときに使用されます。現在、インターネット上には、idtabs が非常に多くあります。私が以前に使用したものは比較的シンプルで実用的で、より柔軟でもありますが、複雑な状況ではより多くのコーディングが必要になり、単純すぎます。 jquery UI のタブ コントロールもあります (使ったことはありません。jquery ui にはあまり興味がありません)。最近少し人気のある easyui のタブ コントロールは、javaeye で初めて見られました。 、インターフェイスは非常に美しいです。これまでオープンソース化されていなかったため、フォローしていませんでした(最近オープンソース化されたようです。数日前にダウンロードして見ました。コーディングスタイルはプロトタイプに少し似ていて、jquery の影が見えません。なぜ jquery easyui と呼ばれているのかわかりません (笑)。詳しくは勉強していないので、他の評価を行うのは簡単ではありません。)そうは言っても、本題に戻りましょう。さまざまな理由から、自分たちで開発することを考えなければなりません。この記事では、まずその効果を見てみましょう。
下の図は、単一の Web ページのマルチウィンドウ フレームのレンダリングです
下の写真は、記事の最後に記載されている呼び出し例のスクリーンショットです。
ExtJ を使用した効果がわかります。実際、CSS は基本的に CSS の直接コピーです。もちろん、実際に使ってみると、それぞれの見方ができると思います
。
まずは HTML から始めましょう
注: 最初に制御するという私の考えは、常に最初に HTML 構造を決定し、次にスタイルを決定し、最後に js によって実装されるイベント メソッドを決定することです。
実際、この図を見ると、タブ コントロールには主に HTML の 2 つの部分があることがわかります。1 つはタブを配置するために使用されるヘッダー、もう 1 つはコンテナーであるボディです。内容的には。次に、2 つの Div コンテナーがあり、タブ コントロールはヘッダーとボディの 2 つの部分に分かれています。
ヘッダー部分には複数のタブが含まれており、ul liの連携が考えられやすいです。ヘッダー内の実際の HTML 構造を見てみましょう
li をタブとして渡すことにより、最初の a は閉じるボタン、2 番目の a は実際のコンテンツとなり、左右の背景画像設定はネストされたタグによって実現されます (このアプローチがより一般的です)。もちろん、良い結果を得るには CSS サポートが必要です。 CSS に関するある程度の知識が必要です。
Body の構造はより単純で、div 内に div がネストされているだけです。
2 番目の CSS スタイルシート
CSSはEXTJSからコピーしたものなので詳しくは紹介しません。コードのダウンロードで実際のコードを確認できます。ご質問がある場合は、
までお問い合わせください。
3 番目: JS の作成を開始します
古いルールでは、約 500 行のコードである完全な JS コードから始めることになっています。実際、私はより熱心に行を変更しており、実際のコードの量は比較的少ないです。
; (function ($) {
$.fn.tabpanel =function(option){
var dfop ={
items:[], //选项卡数据项 {id,text,classes,disabled,closeable,content,url,cuscall,onactive}
width:500,
height:400,
scrollwidth:100,//如果存在滚动条,点击按钮次每次滚动的距离
autoscroll:true //当选项卡宽度大于容器时自动添加滚动按钮
};
var headerheight=28;
$.extend(dfop, option);
var me =$(this).addClass("x-tab-panel").width(dfop.width);
innerwidth = dfop.width-2;
//构建Tab的Html
var tcs= dfop.autoscroll?"x-tab-scrolling-top":"";
var header = $("");
var stripwrap = $("
");
var scrollerright = $("
");
var scrollerleft = $("
");
var ulwrap = $("
");
var stripspacer = $("
");
var litemp =[];
for(var i=0,l=dfop.items.length; i
{
var item =dfop.items[i];
builditemlihtml(item,litemp);
}
litemp.push("");
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 = $("");
var body = $("").css({width:innerwidth,height:bodyheight});
var bodytemp=[];
for(var i=0,l=dfop.items.length; ivar 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("");
parray.push("");
parray.push("");
parray.push("",item.text,"");
parray.push("");
}
function builditembodyhtml(item,parray)
{
parray.push("");
parray.push("
");
parray.push("
");
if(item.url){
parray.push("
");
}
else if(item.cuscall){
parray.push("
");
}
else{
parray.push(item.content);
}
parray.push("
");
}
function initevents()
{
//scoller をリセット
resetscoller();
scollerclick();
ulwrap.find("li: not(.x-tab-edge)").each(function(e){
inititemevents(this);
});
}
function inititemevents(liitem)
{
liswaphover.call(liitem);
liclick.call(liitem);
}
関数 scollerclick()
{
if(dfop) .autoscroll)
{
scrollerleft.click(function(e){scolling("left")});
scrollerright.click(function(e){scolling("right")}); 🎜>}
}
関数 restartscoller()
{
if(dfop.autoscroll)
{
varedge = ulwrap.find("li.x-tab-edge" );
var eleft =edge.position().left;
var sleft =tripwrap.attr("scrollLeft");
if( sleft eleft>innerwidth )
{
ヘッダー。 addClass("x-tab-scrolling");
scrollerleft.css("visibility","visible");
scrollerright.css("visibility","visible"); 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("可視性","非表示");
scrollerright.css("可視性","非表示");
dfop.showscrollnow =false;
}
}
}
//
関数 scolling(type,max)
{
//デバッガー;
if(!dfop.autoscroll || !dfop.showscrollnow)
{
return;
}
//デバッガー;
//var swidth =tripwrap.attr("scrollWidth");
var sleft =tripwrap.attr("scrollLeft");
varedge = 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;
}
//左 ;
if(max || (eleft>innerwidth && eleft-dfop.scrollwidth-20{
//デバッガ;
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");
}
}
関数 scollingToli(liitem)
{
var sleft =tripwrap.attr("scrollLeft");
var lleft = liitem.position().left;
var lwidth = liitem.outerWidth();
varedge = ulwrap.find("li.x-tab-edge");
var eleft =edge.position().left ;
if(lleft{
sleft =(lleft-2) ;
if(sleft{
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 = スクロール左とスクロール右幅;
if(scrollerleft.hasClass("x-tab-scroller-left-disabled"))
{
scrollerleft.removeClass("x-tab-scroller-left-disabled");
}
//滚到最終一个了,那么要禁使用権;
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-無効"))
{
$(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.cuscall)
{
var パネル = $("#tab_item_content_" clickitem.id);
var ret = clickitem.cuscall(this,clickitem,panel);
clickitem.cuscall =true;
if(ret) //如果存在返值、空でない
{
clickitem.content = ret;
パネル.html(ret);
}
}
clickitem.isactive =true;
if(clickitem.onactive)
{
clickitem.onactive.call(this,clickitem);
}
}
});
}
//获取当前活跃项
function getactiveitem()
{
for(var i=0,j=dfop.items.length;i{
if(dfop.items[i].isactive)
{
return dfop.items[i];
休憩;
}
}
null を返します。
}
//ベースID获取Itemデータベース
function getitembyid(id)
{
for(var i=0,j=dfop.items.length;i{
if(dfop.items[i].id == id)
{
return dfop.items[i];
休憩;
}
}
null を返します。
}
function getIndexbyId(id)
{
for(var i=0,j=dfop.items.length;i{
if(dfop .items[i].id == id)
{
return i;
休憩;
}
}
return -1;
}
//追加项
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(アイテム);
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);
// イベント
var li = $("#tab_li_" item.id);
inititemevents(li);
if(isactive)
{
li.click();
}
resetscoller();
scolling("right",true);
}
else{
alert("指定されたタブ项已存在!");
}
}
function openitemOrAdd(item,allowAdd)
{
var checkitem = getitembyid(item.id);
if(!checkitem &&allowAdd )
{
addtabitem(item);
}
else{
var li = $("#tab_li_" item.id);
叱責トリ(li);
}
}
//移除一タブ项
function deleteitembyliid(liid)
{
var id= liid.substr(7);
$("#" liid).remove();
$("#tab_item_" id).remove();
var インデックス = 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);
}
}
関数リサイズ(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({幅:内側幅,高さ:本体高さ});
for(var i=0,j=dfop.items.length;i{
var item =dfop.items[i];
$("#tab_item_" item.id).css({width:innerwidth});
$("#tab_item_content_" item.id).css({幅:内側幅,高さ:本体高さ});
}
resetscoller();
}
//設置場所が無効かどうか
function setdisabletabitem(itemId,disabled)
{
var chiitem= getitembyid(itemId);
if(!chitem || chitem.disabled ==disabled)
{
return;
}
if(無効)
{
chiitem.disabled =true;
$("#tab_item_" item.id).addClass("x-tab-strip-disabled");
}
else{
chiitem.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);
}
false を返します。
}
$.fn.opentabitem =function(item,orAdd)
{
if(this[0].tab)
{
return this[0].tab. opentabitem(項目、または追加);
}
false を返します。
}
$.fn.resizetabpanel =function(w,h)
{
if(this[0].tab)
{
return this[0].tab.サイズ変更(w,h);
}
false を返します。
}
$.fn.setdisabletabitem =function(itemId,disabled)
{
if(this[0].tab)
{
return this[0].tab.setdisabletabitem(itemId, disabled);
}
return false;
}
})(jQuery);
Then let’s analyze my implementation step by step. Let’s start by writing jQuery The "template" of the control. Regarding why it is written like this, please refer to the instructions in this article
; (function ($) {
$.fn.tabpanel =function(option){
};
)(jQuery);
Continue Just write the default parameters
var dfop ={
items:[] , //Tab data item {id, text, classes, disabled, closeable, content, url, cuscall, onactive}
width:500,
height:400,
scrollwidth:100,//if There is a scroll bar, and the distance of scrolling each time the button is clicked
autoscroll:true //Automatically add a scroll button when the tab width is larger than the container
};
The default parameters are still relatively simple , I have added comments, among which the items of the item array are more troublesome, but I believe you already know most of them through the literal meaning. Let me describe it: id is the label, which must be unique, text displays the text, and classes For a specific style, such as the home page in the effect, I added an icon and implemented it through this attribute, whether disabled is disabled, whether closeable can be closed,
content, url and cuscall. Just set one of them. Yes, content is the actual content html, and url marks the content as a web page, and iframe is automatically added to the content. Cuscall is customized, that is, the content displayed is determined by the result of cuscall execution. This attribute can be used to implement asynchronous content.
onactive refers to the event triggered when the tab item is activated. It is a function that accepts item content. See demo for details.
After the parameters are set, update the default parameters through externally passed parameters:
$.extend(dfop, option);
The next step is to build the html. This part is quite long, so I won’t post the code again.
After we complete the html construction, we need to add events to the html elements, including click events of the tab, click events of the left move button, right move button, mouse hover effect events of the tab, etc.
function initevents()
{
//reset scoller
resetscoller(); //Set whether scrolling will appear by default
scollerclick(); //Click event of the scroll bar, if it exists
ulwrap.find(" li:not(.x-tab-edge)").each(function(e){
initemevents(this); //Add events to each tab
});
}
function inititemevents(liitem)
{
liswaphover.call(liitem); //The mouse hover effect of the tab
liclick.call(liitem); //The click event of the tab
closeitemclick. call(liitem); // Click the close button event
}
As for the implementation of the event, it is actually done one by one, and it is simple to defeat each one. The main tediousness is in controlling the appearance and disabling of scroll buttons. Other click events are relatively simple.
The last is the public methods, and to write some internal methods in order to expose these methods, this tabpanel is naturally relatively simple and easy to use, and at the same time scalable. You can make adjustments according to actual needs. Of course, the current functions should meet most requirements.
Finally, let’s take a look at the disclosed methods:
1: The method of dynamically adding tab items, that is, dynamically adding tab items through js. This is actually the maintenance of items data, and then Recall tabitem's output html method, and finally set an event for it separately. Simple
2: Select or add. This is also a method called through js. It is an extension of the previous method. You can activate a certain tab item through js. If the item does not exist, add the tab through parameters
3: Re- Set the size of the tabpanel, that is, reset the size of the tabpanel through js. This is called when the window size changes, which is very practical.
4: Set an item to be disabled, and set the tabitem status of a certain item to be disabled through the js method.
Finally, you can use the code to include examples of previous controls. I have provided a compressed package, but I recommend you to use SVN to get the latest code. Because sometimes I won’t post any notifications about small changes.
http://code.google.com/p/xjplugin/downloads/list http://xiazai.jb51.net/201005/ yuanma/xjPlugin_addtabpanel.rar