parsgreen.com
article

ساخت منوی آکاردئونی با جاوا اسکریپت و CSS

javascript-accordion-box

ساخت منوها و باکس های آکاردئونی (accordion) یا به اصطلاح جمع شونده، یکی از قابلیت هایی است که جاوا اسکریپت (JavaScript) و کتابخانه های زیرمجموعه آن مانند جی کئوری (jQuery) در اختیار برنامه نویسان و طراحان وب قرار می دهند، قابلیت تعاملی و زیبایی که این نوع منوها به رابط کاربری (Interface) سایت یا وبلاگ می دهد باعث می شود که خیلی از مدیران وب گرایش به سمت استفاده از آن داشته باشند، البته در این مورد باید همیشه به مقوله سازگاری، سرعت و سبکی صفحات دقت نمود، چرا که هرچند می توانیم جلوه های خیلی خاصی در صفحات وب ایجاد کنیم، اما باید توجه داشت که این جلوه ها سرعت بارگذاری و قابلیت سازگاری سایت یا وبلاگمان را در مرورگرها و سیستم های مختلف تحت تاثیر قرار ندهند، از این رو است که همیشه استفاده از کدهای کم حجم با بیشترین سازگاری توصیه می شود.

منظور از منوی آکاردئون چیست؟


منوی آکاردئونی در واقع برگرفته از نام واژه آکاردئون (accordion) و به معنی یک نوع ساز بادی معروف است، قسمتی از این ساز دارای یک مجاری عبور هوای فنر مانند و پله پله ای است که نوازنده برای نواختن آهنگ باید آن را با دست خود به طور متناوب حرکت دهد، این ساز قدمت زیادی داشته و در خیلی از فیلم ها و سریال ها معمولا به عنوان ساز بینوایان استفاده می شود! به خاطر شباهت این نوع منو با این ساز به آن آکاردئونی می گوییم.

کد جاوا اسکریپت برای ساخت باکس آکاردئونی


همان طور که گفتیم برای ساختن منوها و باکس های آکاردئونی یا به اصلاح جمع شونده، می توان از جاوا اسکریپت استفاده کرد، از این رو در زیر یکی از سبک ترین و در عین حال سازگارترین توابعی که بدین منظور نوشته شده را با هم بررسی می کنیم.
<script type="text/javascript">
//<![CDATA[
var contentHeight = 34;
var TimeToSlide = 300.0;
var openprobox = '';
function runprobox(index){
    var divID = "probox" + index + "content";
    if(openprobox == divID){
        divID = '';
    }
    setTimeout("animate(" + new Date().getTime() + "," + TimeToSlide + ",'" + openprobox + "','" + divID + "')", 33);
    openprobox = divID;
}
function animate(lastTick, timeLeft, closingId, openingId){
    var curTick = new Date().getTime();
    var elapsedTicks = curTick - lastTick;
    var opening = (openingId == '') ? null : document.getElementById(openingId);
    var closing = (closingId == '') ? null : document.getElementById(closingId);
    
    if(timeLeft <= elapsedTicks){
        if(opening != null){
            opening.style.height = contentHeight + 'px';
        }
        if(closing != null){
            closing.style.display = 'none';
            closing.style.height = '0px';
        }
    return;
    }
    timeLeft -= elapsedTicks;
  var newClosedHeight = Math.round((timeLeft/TimeToSlide) * contentHeight);
  if(opening != null){
      if(opening.style.display != 'block'){
          opening.style.display = 'block';
      }
      opening.style.height = (contentHeight - newClosedHeight) + 'px';
  }
  if(closing != null){
      closing.style.height = newClosedHeight + 'px';
  }
  setTimeout("animate(" + curTick + "," + timeLeft +",'" + closingId + "','" + openingId + "')", 33);
}
//]]>
</script>
اگرچه درک صحیح عملکرد این کد نیازمند تجربه نسبی و کار با جاوا اسکریپت است، اما بد نیست برای آگاهی بیشتر هم که شده، نگاهی اجمالی به کد بالا داشته باشیم.
توضیح:
- در قسمت متغیر contentHeight در ابتدای کد، ارتفاع بلاک محتوا را به پیکسل مشخص می کنیم، این همان بلاکی است که محتویات هر منو را در خود نمایش می دهد.
- در متغیر TimeToSlide میزان زمان (به میلی ثانیه) را برای شروع و پایان انیمیشن تعیین می کنیم، هر چه این زمان بیشتر باشد، سرعت انمیشن کندتر و میزان فرم های بیشتری ایجاد می شود (توصیه می شود مقادیر پیش فرض را تغییر ندهید).
- تابع runprobox در کد بالا، یک عدد به عنوان آرگومان می پذیرد، این عدد در واقع در هنگام فراخوانی تابع (که در ادامه خواهیم دید) برای هر بلاک متفاوت خواهد بود، به این ترتیب تابع قادر خواهد بود تا بلاک هدف را از سایر موارد شناسایی کند.
- setTimeout در توابع بالا نقش یک وقفه را بازی می کند، به این ترتیب که با فراخوانی تابع animate در زمان های متوالی، بین فرم ها وقفه های خیلی کوتاهی ایجاد می شود تا در نهایت حاصل کار به شکل یک انیمیشن به نمایش درآید.
- تابع animate نیز به عنوان موتور کد عمل کرده و با دریافت چهار آرگومان و بررسی آنها، در نهایت انیمیشن را خلق می کند، در این تابع متغیر curTick زمان فعلی، elapsedTicks میزان اختلاف بین آخرین اجرای تابع animate و زمان فعلی و متغیر opening و closing نیز مقادیر id بلاک هدف را در خود دارند.
- همان طور که ملاحظه می کنید تابع animate برای کنترل استایل و ویژگی های css بلاک ها از متد style و object استفاده می کند، به طور مثال opening.style.height ارتفاع بلاک opening را تعیین می کند یا closing.style.display نوع display بلاک closing را مشخص می کند.
نکته: این کد با وجود حجم بسیار کم، تقریبا با تمام مرورگرها سازگار است، از جمله اینترنت اکسپلورر 6 و مابعد، فایرفاکس، گوگل کروم، اپرا، سافاری و...

کد css منوی آکاردئونی


برای اینکه منوهای ما به درستی کار کنند، علاوه بر کد جاوا اسکریپت، به استایل css و کلاس های آن نیازمندیم، بدین منظور استایل زیر را نیز باید در صفحه خود وارد کنیم (به صورت یک فایل خارجی و یا به صورت درون صفحه ای).
<style type="text/css">
.proboxtitle, .proboxcontent, .proboxmain{
    position:relative;
}
.proboxtitle{
    width:200px;    
    height:25px;
    overflow:hidden;
    text-align:right;
    display:block;
    cursor:pointer;
    background-color:#666;
    color:#FFF;
    direction:rtl;
    padding:4px;
    text-align:center;
    border-bottom:1px dashed #CCC;    
}
.proboxcontent{
    width:200px;    
    height:auto;
    overflow:hidden;
    display:none;
    background-color:#F8F8F8;
    padding:4px;
    direction:rtl;
}
.proboxmain{
    border:1px solid #F0F0F0;
    width:208px;    
}
</style>
همان طور که ملاحظه می کنید، کد css بالا سه کلاس دارد که با آن، ویژگی ها و خواص ظاهری سه بلاک را در صفحه کنترل می کنیم، همچنین برخی موارد در استایل بالا قابل تغییر و برخی نیز به نحوه عملکرد برنامه مربوط بوده و غیر قابل تغییر هستند.

نحوه استفاده از منوی آکاردئونی


برای استفاده از کدهای بالا، در نهایت باید منو و باکس ها را در بلاک های div تعریف کنیم، برای نمونه مثال زیر می تواند راهنمای ما باشد.
<div id="proboxmain" class="proboxmain">
<!-- منوی شماره 1 -->
  <div class="proboxtitle" onclick="runprobox(1);">
  تیتر باکس 1
  </div>
  <div id="probox1content" class="proboxcontent">
  محتوای باکس آکاردئونی 1
  </div>
<!-- منوی شماره 2 -->  
  <div class="proboxtitle" onclick="runprobox(2);">
  تیتر باکس 2
  </div>
  <div id="probox2content" class="proboxcontent">
  محتوای باکس آکاردئونی 2
  </div>
<!-- منوی شماره 3 -->  
  <div class="proboxtitle" onclick="runprobox(3);">
  تیتر باکس 3
  </div>
  <div id="probox3content" class="proboxcontent">
  محتوای باکس آکاردئونی 3
  </div>
<!-- منوی شماره 4 -->  
  <div class="proboxtitle" onclick="runprobox(4);">
  تیتر باکس 4
  </div>
  <div id="probox4content" class="proboxcontent">
  محتوای باکس آکاردئونی 4
  </div>
</div>
توضیح:
- در مثال بالا، ابتدا یک بلاک اصلی با کلاس و آی دی proboxmain تعریف می کنیم، این بلاک تمام محتوای منوهای ما را در برمی گیرد.
- سپس برای هر منو، یک بلاک با کلاس proboxtitle و به همراه رویداد onclick تعریف می کنیم که تیتر منوها را در خود جای می دهد، این بلاک وظیفه فراخوانی تابع runprobox را دارد و یک عدد به عنوان آرگومان به تابع مذکور ارسال می کند، این عدد باید بین منوهای مختلف متفاوت و یکتا باشد تا برنامه بتواند بلاک مورد نظر را شناسایی کند.
- سپس در بلاک دیگری با آی دی و کلاس proboxcontent محتوای باکس خود را قرار می دهیم، در اینجا باید دقت کنید که برای آی دی،  بعد از عبارت probox عدد آرگومان را قرار داده و سپس عبارت content را اضافه کنید، به فرض اگر آرگومان تابع runprobox عدد 3 باشد، آی دی بلاک محتوا باید به صورت probox3content تنظیم شود.

مثال و پیش نمایش آنلاین


برای بررسی و تست برنامه، می توانید از مثال و پیش نمایش آنلاین زیر استفاده کنید.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>وبگو | باکس آکاردئونی با جاوا اسکریپت</title>
<!-- http://webgoo.ir -->
<style type="text/css">
body{
    font-family:Tahoma, Geneva, sans-serif;
    font-size:12px;
    direction:rtl;
}
.proboxtitle, .proboxcontent, .proboxmain{
    position:relative;
}
.proboxtitle{
    width:200px;    
    height:25px;
    overflow:hidden;
    text-align:right;
    display:block;
    cursor:pointer;
    background-color:#666;
    color:#FFF;
    direction:rtl;
    padding:4px;
    text-align:center;
    border-bottom:1px dashed #CCC;    
}
.proboxcontent{
    width:200px;    
    height:auto;
    overflow:hidden;
    display:none;
    background-color:#F8F8F8;
    padding:4px;
    direction:rtl;
}
.proboxmain{
    border:1px solid #F0F0F0;
    width:208px;    
}
</style>
<script type="text/javascript">
//<![CDATA[
var contentHeight = 34;
var TimeToSlide = 300.0;
var openprobox = '';
function runprobox(index){
    var divID = "probox" + index + "content";
    if(openprobox == divID){
        divID = '';
    }
    setTimeout("animate(" + new Date().getTime() + "," + TimeToSlide + ",'" + openprobox + "','" + divID + "')", 33);
    openprobox = divID;
}
function animate(lastTick, timeLeft, closingId, openingId){
    var curTick = new Date().getTime();
    var elapsedTicks = curTick - lastTick;
    var opening = (openingId == '') ? null : document.getElementById(openingId);
    var closing = (closingId == '') ? null : document.getElementById(closingId);
    
    if(timeLeft <= elapsedTicks){
        if(opening != null){
            opening.style.height = contentHeight + 'px';
        }
        if(closing != null){
            closing.style.display = 'none';
            closing.style.height = '0px';
        }
    return;
    }
    timeLeft -= elapsedTicks;
  var newClosedHeight = Math.round((timeLeft/TimeToSlide) * contentHeight);
  if(opening != null){
      if(opening.style.display != 'block'){
          opening.style.display = 'block';
      }
      opening.style.height = (contentHeight - newClosedHeight) + 'px';
  }
  if(closing != null){
      closing.style.height = newClosedHeight + 'px';
  }
  setTimeout("animate(" + curTick + "," + timeLeft +",'" + closingId + "','" + openingId + "')", 33);
}
//]]>
</script>
</head>
<body>
<noscript>
جاوا اسکریپت در مرورگر شما غیرفعال است یا پشتیبانی نمی شود!<br />
</noscript>
<div id="proboxmain" class="proboxmain">
<!-- منوی شماره 1 -->
  <div class="proboxtitle" onclick="runprobox(1);">
  تیتر باکس 1
  </div>
  <div id="probox1content" class="proboxcontent">
  محتوای باکس آکاردئونی 1
  </div>
<!-- منوی شماره 2 -->  
  <div class="proboxtitle" onclick="runprobox(2);">
  تیتر باکس 2
  </div>
  <div id="probox2content" class="proboxcontent">
  محتوای باکس آکاردئونی 2
  </div>
<!-- منوی شماره 3 -->  
  <div class="proboxtitle" onclick="runprobox(3);">
  تیتر باکس 3
  </div>
  <div id="probox3content" class="proboxcontent">
  محتوای باکس آکاردئونی 3
  </div>
<!-- منوی شماره 4 -->  
  <div class="proboxtitle" onclick="runprobox(4);">
  تیتر باکس 4
  </div>
  <div id="probox4content" class="proboxcontent">
  محتوای باکس آکاردئونی 4
  </div>
</div>
<hr />
برای بررسی ویژگی های منو، بر روی یکی از آیتم ها کلیک کنید.
</body>
</html>
پیش نمایش
sectionدسته بندی: آموزش کاربردی » JavaScript
related مطالب بیشتر:
» ساخت افکت رنگی با جاوا اسکریپت (Javascript)
» ایجاد باکس جمع شونده با جاوا اسکریپت و دریم ویور
» نمایش پیام صفحه در حال بارگذاری با جاوا اسکریپت
» استفاده ترکیبی از جاوا اسکریپت (JavaScript) و PHP
» اعتبار سنجی فرم های وب با جاوا اسکریپت
commentنظرات (۳۱ یادداشت برای این مطلب ارسال شده است)
نویسنده: hosin
زمان: ۱۳:۴۵:۰۰ - تاریخ: ۱۳۹۱/۰۸/۰۵
ممنون از آموزش هاتون
نویسنده: reza
زمان: ۰۹:۳۹:۳۶ - تاریخ: ۱۳۹۱/۰۸/۱۵
سلام ، خسته نباشید
چطور میشه محتویات منوی auto کرد یعنی به اندازه محتویات باز بشه ؟
پاسخ: 
سلام
این مورد را بررسی نکرده ایم، ولی به نظر می رسد برای انجام این کار باید تغییراتی اساسی در نحوه عملکرد کد ایجاد کنید، چرا که برنامه از مقادیر عددی برای محاسبه تعداد فرم های انیمیشن در متغیر contentHeight استفاده می کند و عملیات ریاضی مانند ضرب نیز در ادامه آن وجود دارد، از طرفی این نوع منوها معمولا برای موارد استاتیک استفاده می شوند.
نویسنده: نگین
زمان: ۲۳:۴۰:۱۰ - تاریخ: ۱۳۹۱/۱۱/۱۶
ببخشید چه طوری میشه کاری کرد که حهت باز شدن منو برعکس بشه؟
پاسخ: 
سلام
برای این کار کافی است بلاک های div مربوط به محتوا را پیش از بلاک های مربوط به تیتر قرار دهید.
نویسنده: فرناز
زمان: ۱۲:۲۷:۳۷ - تاریخ: ۱۳۹۱/۱۲/۲۲
سلام خسته نباشید
واقعا ممنون از آموزش هاتون
من که خیلی استفاده کردم
من چند مشکل دارم ممنون میشم راهنماییم کنین...
1 - چطور طول منو را زیاد کنم ؟ چون با این طولی که داره بیشتر از 5 منو رو نشون نمیده
2 - چطور در زیرمنوها چند گزینه قرار بدم چون با اینکه من چند تا زیر منو گذاشتم ولی یکی بیشتر نشون نمیده
3 - چطور به زیر منوها لینک بدم که به دسته مشخص خودشون ارجاع داده بشن ....
ممنون از همکاریتون .....
پاسخ: 
سلام
در مورد سوال اول، اگر منظور از طول، ارتفاع باکس است، این کار با افزودن باکس های بیشتر به صورت خودکار انجام می شود و نیاز به تغییر مورد خاصی نیست، اگر منو نمایش داده نمی شود، ممکن است به دلیل ارتفاع محدود بلاک های دیگری باشد که باکس منو را داخل آنها استفاده کرده اید.
در مورد سوال دوم و اینکه چند گزینه در زیرمنوها قرار دهید، البته این نوع منو محدودیت هایی از این لحاظ دارد، اما با افزایش مقدار var contentHeight و درج و تنظیم بلاک های div بیشتر داخل بلاک های proboxcontent می توان موارد مورد نظر را ایجاد کرد (نیاز به آشنایی و تسلط نسبی با html و طراحی وب دارد).
برای مورد آخر نیز محدودیتی وجود ندارد، می توانید از تگ a و href در محتوای داخل زیرمنوها برای ایجاد لینک استفاده کنید.
نویسنده: فرناز
زمان: ۱۱:۴۶:۰۵ - تاریخ: ۱۳۹۱/۱۲/۲۳
1 - ارتفاع باکس تغییر نمی کنه با اینکه وقتی چند دسته قرار میدم خیلی بیشتر از این ارتفاع داره و اونو کامل نشون میده
2 - من زیر منو ها رو اینطور اضافه کردم
<div id="proboxmain" class="proboxmain">
<!-- منوي شماره 1 -->
<div class="proboxtitle" onclick="runprobox(1);">
درباره ما
</div>
<div id="probox1content" class="proboxcontent">
سيماي استان
</div>
<div id="probox1content" class="proboxcontent">
اساسنامه
</div>
ولی فقط سیمای استان نمایش داده میشه ....
پاسخ: 
نحوه استفاده از کد اشتباه است!
اگر به مثال توجه کنید، هر منو یک شماره متناظر دارد که در دو قسمت runprobox و آی دی بلاک محتوا استفاده می شود تا منوهای متفاوت از هم تفکیک شوند.
برای نمایش محتوای بیشتر مقادیر متغیر contentHeight را افزایش داده و داخل هر بلاک محتوا به صورت نمونه زیر از بلاک های زیر مجموعه استفاده کنید:
<!-- منوی شماره 1 -->
<div class="proboxtitle" onclick="runprobox(1);">
تیتر باکس 1
</div>
<div id="probox1content" class="proboxcontent">
<div class="sub_1">
محتوای باکس آکاردئونی 1-1
</div>
<div class="sub_2">
محتوای باکس آکاردئونی 1-2
</div>
<div class="sub_3">
محتوای باکس آکاردئونی 1-3
</div>
</div>
نویسنده: الهه
زمان: ۱۶:۰۴:۱۵ - تاریخ: ۱۳۹۲/۰۴/۰۶
سلام و ممنون از سایت خوبتون.
الان با رفرش صفحه محتویات هر چهار منو نمایش داده نمیشه و باید روشون کلیک کرد. چطور میشه کاری کرد که با رفرش صفحه محتویات یک منوی خاص به صورت پیش فرض نمایش داده بشه؟
ممنون!
پاسخ: 
سلام
برای این کار کافی است در انتهای کدهای منو، کد زیر را قرار دهید:
<script type="text/javascript">
runprobox(1);
</script>
نویسنده: الهه
زمان: ۱۴:۳۰:۴۶ - تاریخ: ۱۳۹۲/۰۴/۰۹
ممنون از وقتی که برای من گذاشتین و پاسخ دادین.
نویسنده: ابوالفضل
زمان: ۰۳:۵۹:۴۸ - تاریخ: ۱۳۹۲/۰۴/۱۹
با سلام
آیا می شه کاری کرد زمانی که بر روی منو باز شده کلیک شد بسته نشود و فقط با انتخاب گزینه های دیگه بسته شود منو. به طور کلی نمی خوام زمانی که روی یک منو کلیک کردیم و باز شد با کلیک مجدد بسته شود؟!
ممنون میشم راهنمایی بفرمایید ...
پاسخ: 
سلام
بله، قسمت زیر را در کد پیدا کنید:
	if(openprobox == divID){
divID = '';
}
در تابع runprobox مشخص است، سپس آن را به صورت زیر تغییر دهید:
	if(openprobox == divID){
divID = '';
return false;
}
نویسنده: irtouring
زمان: ۱۶:۱۹:۲۴ - تاریخ: ۱۳۹۲/۰۵/۰۳
بسیار ساده و مفید بود ، ممنونم
نویسنده: آیدا
زمان: ۲۰:۲۲:۳۲ - تاریخ: ۱۳۹۲/۰۹/۰۸
واقعا از سایتتون ممنونم کارم رو تو بد شرایطی راه انداخت
نویسنده: سحر
زمان: ۱۰:۴۵:۵۲ - تاریخ: ۱۳۹۲/۰۹/۱۸
با تشکر فراوان به خاطر آموزش.چطور می توانیم منوی اول را پیش فرض باز نمایش دهیم؟
پاسخ: 
سلام
برای این کار کافی است در انتهای کدهای منو، کد زیر را قرار دهید:
<script type="text/javascript">
runprobox(1);
</script>
نویسنده: محمد حسین
زمان: ۲۰:۲۴:۵۸ - تاریخ: ۱۳۹۲/۰۹/۲۴
سلام! ممنون از زحماتتون و اینکه وقت میزارید و به سوالات کاربران پاسخ میدید...
میخواستم بدونم چطوری میشه تعداد باکس ها رو از 4 تا افزایش داد ممنون
پاسخ: 
سلام
به صورت نمونه زیر می توانید هر تعداد بخواهید باکس اضافه کنید:
<!-- منوی شماره 4 -->  
<div class="proboxtitle" onclick="runprobox(4);">
تیتر باکس 4
</div>
<div id="probox4content" class="proboxcontent">
محتوای باکس آکاردئونی 4
</div>
<!-- منوی شماره 5 -->
<div class="proboxtitle" onclick="runprobox(5);">
تیتر باکس 5
</div>
<div id="probox5content" class="proboxcontent">
محتوای باکس آکاردئونی 5
</div>
نویسنده: علی
زمان: ۲۳:۰۲:۴۹ - تاریخ: ۱۳۹۲/۱۱/۰۲
با سلام ممنون از آموزش هایتان وقتی کد پیام بلاگ را به بلاگفا می ریزم ارور (امکان درج عبارت payamblog.js در قالب وبلاگ وجود ندارد) را می دهد و وقتی این آدرس را پاک می کنم جدول بندی وبلاگم بهم می خورد چکار کنم لطفا راهنمائی کنید.
پاسخ: 
سلام
این مشکل تنها با تغییر نام فایل (یا فایل ها) و آپلود آن در یک سرویس دیگر (و ایجاد کد جدید) قابل حل است.
نویسنده: SINA
زمان: ۱۹:۰۹:۲۰ - تاریخ: ۱۳۹۲/۱۱/۲۳
چطوری میتونم باکس ها را افقی کنم
پاسخ: 
به نظر با CSS قابل حل است، باید مسلط باشید!
نویسنده: SINA
زمان: ۱۰:۲۵:۳۲ - تاریخ: ۱۳۹۲/۱۱/۲۴
نمیشه شما بگید کجا رو عوض کنم تا افقی بشه چون من خیلی CSS بلد نیستم
پاسخ: 
متاسفانه خیر، این کار نیاز به تغییر استایل CSS از مبنا و آزمایش و خطا دارد که کاری وقتگیر است.
paged صفحه 1 از 3




more لطفا دقت کنید که یادداشت های زیر منتشر نشده و حذف خواهند شد:
- یادداشت های خارج از موضوع این مطلب.
- سوالات کلی، غیر ضروری و مشکلاتی که هیچ تلاشی برای رفع آن نکرده باشید.
- نظرات حاوی کدها و اسکریپت های خیلی طولانی (به طور مثال کد کامل قالب وبلاگ).

5 × 1
 refresh
آگهی
seonab.com
طراحی نرم افزار اندروید
رنگین کمان عکس
Ranginkamaan.com

آرشیو عکس های باکیفیت با موضوعات متنوع...