ghabil
شنبه 02 تیر 1386, 01:52 صبح
میخواستم یک مقاله آموزشی کار با اینتراوب 9 و قابلیتهای جدیدش در پشتیبانی از Ajax رو بزارم اما فکر کردم شاید بد نباشه اول یک مقاله آموزش خیلی مقدماتی برای نوشتن برنامه های تحت وب با استفاده از Ajax بنویسم تا هم دوستای که خیلی با Ajax آشنا نیستند یک آشنایی ابتدایی پیدا کنند و هم بعدا ببینید که چقدر اینتراوب کار رو راحت کرده .
پیشنیاز این مقاله :
بلد بودن مفاهیم ابتدایی برنامه نویسی تحت وب
بلد بودن Html به مقدار کافی
کمی JavaScript
کمی XML
ضمنا اینایی که اینجا میگم فرقی نداره از چه زبان برنامه نویسی استفاده بشه اما برای مثالهام فعلا از دلفی 7 و WebSnap استفاده میکنم .
بسم الله
سناریو :
فرض کنید یک سایت خوشگل طراحی کریدین با کلی عکس و جدول و این حرفها ، یک گوشه سایت هم دوتا TextBox گذاشتین با یک دکمه برای Login . وقتی کاربر کد کاربری و کلمه عبورش رو وارد میکنه و دکمه ورود رو میزنه اطلاعات نوشته شده برای سرور فرستاده میشوند و سرور تصمیم میگیره که اگر اطلاعات درست هست صفحه بعد رو برای کاربر ایجاد کنه و بفرسته ، اما اگر اطلاعات غلط بود باید دوباره همون صفحه قبلی رو بسازه و دوباره کاربر تمام اون صفحه رو لود کنه (حالا بحث کش کردن بماند) با این فرق که این دفعه فقط یک گوشه ای بنویسه مثلا "کد کاربری غلط است". فکرش رو بکنید یکبار تمامی کانتت قیلدهای صفحه برای سرور فرستاده شده ، و یکبار هم کل صفحه دوباره جنریت شده آخر هم یوزر مجبور شده همه صفحه رو دوباره بگیره.
چقدر خوب میشد اگر بدون دست زدن به بقیه صفحه فقط کدکاربری و پسورد برای سرور فرستاده میشد و سرور هم فقط میگفت درسته یا نه !:متفکر:
فکر میکنین میشه ؟
خب معلومه دیگه اگر نمیشد که این قصه رو تعریف نمیکردم . طبیعتا هم با AJAX میشه دیگه ;)
AJAX
آژاکس که مخفف Asynchronous JavaScript And XML هست و شاید اینطوری بشه ترجمش کرد که یعنی استفاده نامتقارن از جاوا اسکریپت و XML ، ذاتا چیزه جدیدی نیست و خیلی وقت هست که تقریبا هر آنچه رو که برای کار کردن باهاش لازم هست فراهم شده اما نامگذاریش و اینکه یکهو اینقدر محبوب بشه شاید 2 سال نیست که باب شده.
به هر حال اصل کار رو آبجکت XMLHttpRequest انجام میده که مایکروسافت نوشتتش و کار این آبجکت اینه که یک اربتاط مجزا با سرور برقرار کنه یکسری اطلاعات رو بفرسته و نتیجه رو از سرور بگیره ، همونطوری که میدونید بهترین روشی که بشر برای تبادل اطلاعاتی که Structorشون از قبل معلوم نیست ، اختراع کرده XML هست پس وقتی این آبجکت بتونه XML بگیره و بفرسته پس میتونه هر اطلاعاتی با هر ساختاری رو بگیره و بفرسته ، اما لزومی هم نداره حالا حتما از XML استفاده کنیم همونطوری که ما فعلا برای اول کار از Text ساده استفاده میکنیم و تازه برای اولین مثال هم بیخیال نامتقارن بودنش میشیم :
مثال اول :
تو مثال اول با استفاده از جاوا اسکریپت یک آبجکت XMLHttpRequest میسازیم، یک درخواست ساده به سرور میفرستیم از طریق این آبجکت ، نتیجه رو از سرور میگیریم و با استفاده از جاوا اسکریپت نشون میدیم ، مثلا میشه توی سرور یکسری اسم و عدد بزاریم و به ازای هر عدد که کاربر وارد میکنه نامش رو بدیم (چقدر لوس)! :
از اینجا ببعد من با دلفی شروع میکنم ، اما مثلا شما هم میتونید با ASP شروع کنید ولی به هر حال هیچ فرقی نداره از چه زبانی استفاده میکنید :
دلفی رو باز کنید ، New>Web Server Application (اون پاییناست) بعد هم Cgi-StandAlone رو انتخاب کنید .
یک وب ماژول براتون ساخته میشه، این اون سرور وب ما هست ; یک جای خوشگل Save بکنیدش ، بعد هم برید توی IIS (بله IIS برنامه تحت وب دارین مینویسین دیگه ) یک VirtualDicrectory رو به نام مثلا AJAXTest بسازید و بهش مربوط کنید .(دسترسی Execute رو هم روش بدین) (لطفا دات نتی ها فکر نکنن که اونا خیلی بهشون خوش میگذره و از این حرفها ندارند، توی دلفی هم ما با اینتراوب وب سرور خودمون رو داریم که خیلی هم از Casini شما بهتره ;) )
خب بریم خدمت جناب دلفی : روی وب ماژول کلیک راست بکنید بعد هم ActionEditor و یک Action جدید ایجاد بکنید ،
اسمش رو مثلا بزارید actStart و PathInfo رو هم به /Start ست بکنید. بعد یکدونه PageProducer از تب اینترنت روی فرم بزارید اسمش رو بزارید ppStart و در اکشن ادیتور دیتا ماژول Producer اکشنی که تعریف کردید رو بزارید همین PageProducer. (معنی این کار این هست که هر موقع این اکشن صدا زده بشه این Producer وظیفه تولید HTML پاسخ رو داره).
این شد اکشنی که قرار صفحه ابتدایی رو تولید کنه ، یک اکشن هم میخواهیم که جواب درخواست آژاکسیمون رو بده ، پس یک اکشن دیگه درست میکنیم اسمش رو میزاریم مثلا GetDay نیازی هم به PageProucer نداره .
حالا بریم توی ppStart کدهای HTML لازم برای تولید صفحه رو بنویسیم :
اول از همه باید یک XMLHttpRequest بسازیم که بتونی اطلاعات رو برامون درخواست کنه ، من ساختن XMLHttpRequest و درخواست اطلاعات رو توی یک تابع مینویسم و بعد توضیحش میدم :
function requestDay()
{
if (window.XMLHttpRequest)
{
var Rqst = new XMLHttpRequest();
}
else
{
var Rqst = new ActiveXObject("Microsoft.XMLHttp");
}
var reqUrl = 'getday?day=' + document.getElementById("txtDay").value;
Rqst.open('GET', reqUrl, false);
Rqst.Send('');
document.getElementById("txtDay").value = Rqst.responseText;
}
توی چند خط اول سعی میکنیم آبجکت XMLHttpRequest رو بسازیم -چه برای اینترنت اکسپلور ، چه فایرفاکس و کلا رفقای موزیلا- بعد هم چون توی این مثال اول میخوایم از متد Get استفاده کنیم ، باید پارامترهامون رو توی URL بفرستیم پس ، یک URL میسازیم که شامل آدرسی که باید بهش مراجه کنیم هست که میشه همون مراجعه به اکشن GetDayی که درست کردیم بعد علامت ؟ که به این معنیه که از اینجا ببعد میخوای پارامتر بفرستیم بعد اسم پارامترمون که من گذاشتم day و بعد هم مقدار پارامتر که از یک TextBox که توی HTMLمون بعدا درست میکنیم و اسمش رو میزاریم txtDay گرفته میشه.
یعنی زمان اجرا مثلا مقدار پارامتر همچین چیزی (اگر کاربر توی TextBox مقدار 5 رو بنویسه) میشه :
getday?day=5
بعد هم میریم سراغ آبجکت XMLHttpRequest که ایجادش کردیم و توی متغیر Rqst داریمش و متد Open رو که صدا میکنیم تا کانکشنش رو با سرور برقرار کنه ، برای متد Open باید 3 تا پارامتر پاس کنیم ، اولی متد ارسال اطلاعات هست که توی این مثال ما از Get استفاده میکنیم ، دومی آدرس سرور هست و سومی اینکه آیا بصورت نامتقارن درخواست صورت بگیره یا خیر (بعدا کاملا توضیحش میدم ) ، ولی فعلا پارامتر سوم را false پاس میکنیم به معنی اینکه متقارن با سرور در ارتباط هستیم .
بعد هم متد Send رو صدا میزنیم با پارامتر خالی تا درخواست صورت بگیره در صورتیکه از متد Post استفاده میکردیم پارامترها رو اینجا پاس میکردیم .(انشاا.. جتما یک متد پست هم مثال میزنم)
در نهایت هم نتیجه برگشته از سرور رو توی همون TextBoxی که کاربر توش عدد رو وارد کرده بر میگردونیم.
تا اینجا هستیم کل HTML لازم برای صفحه اول رو کامل کنیم ، باید در نهایت توی ppStart داخل HTMLDocument این متن رو داشته باشیم :
<html>
<head>
<Script Language="JavaScript">
function requestDay()
{
if (window.XMLHttpRequest)
{
var Rqst = new XMLHttpRequest();
}
else
{
var Rqst = new ActiveXObject("Microsoft.XMLHttp");
}
var reqUrl = 'getday?day=' + document.getElementById("txtDay").value;
Rqst.open('GET', reqUrl, false);
Rqst.Send('');
document.getElementById("txtDay").value = Rqst.responseText;
}
</Script>
</head>
<body>
<Table>
<tr>
<td Align="right"> The Day No: </td>
<td>
<input type="text" id = "txtDay"></td>
<td><input type="Button" onclick= "requestDay();" value = "Get Day" ></td>
</tr>
</Table>
</body>
</html>
در واقع تگهای مورد نیاز HTML و همینطور اون TextBox رو داخل یک Table گذاشتیم ، بعلاوه یک Button که روی OnClickش همون تایعی که نوشتیم رو صدا میزنیم.
خب قسمتهای کلاینت سایدمون تموم شد ، میمونه نوشتن کد دلفی سرور که قرار هست به این درخواستها جواب بده :
اکشن GetDay رو انتخاب کنید و توی ایونت هاش OnAction رو انتخاب کنید ، این رخداد زمانی Fire میشه که یک Request برای این اکشن فرستاده میشه ، یعنی دقیقا وقتی که ما با اون XMLHttpRequest میایم سراغ این اکشن getday ، حالا توی کد دلفی مثلا میتونیم این کد رو بنویسیم :
procedure TwbmdlAjax.wbmdlAjaxactGetDayAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
ADay : Integer;
AResult: String;
begin
ADay := StrToInt(Request.QueryFields.Values['day']);
case ADay of
1: AResult := 'Sat';
2: AResult := 'Sun';
3: AResult := 'Mon';
4: AResult := 'Tue';
5: AResult := 'Wed';
6: AResult := 'Thu';
7: AResult := 'Fri'
else AResult := 'Invalid Day No : ' + IntToStr(ADay);
end;
Response.Content := AResult;
end;
فکر میکنم کدمون واضح هست دیگه ، مقار پارامتر Day رو از Request میگیریم ، بعد هم توی Case معادل روز هفته رو بر میگردونیم و نهایتا هم نتیجه رو در Content جوابمون میزایم.
* در مورد actStart که این کار رو نکردیم و بجاش به یک PageProducer وصلش کردیم ، محتوای PageProducer بعنوان پاسخ فرستاده میشه.
* برای اونایی که زیاد با Websnap آشنایی ندارند : Request آبجکتیه که همه اطلاعات مربوط به درخواست توش هست و Response آبجکتیه که اطلاعات مربوط به پاسخی که قرار فرستاده بشه توش قرار میگیره
دیگه مثالمون آمادست ، حالا یک بروسر باز میکنیم (مثلا IE) و این رو در آدرسش مینویسیم :
(من پروژه رو بنام BasicAjax دخیره کردم)
http://localhost/Ajaxtest/BasicAjax.exe/Start
وقتی که صفحه اولمون اومد توش مثلا عدد 5 رو مینویسیم و دکمه Get Day رو فشار میدیم . دقت کنید که برعکس اکثر صفحاتی که تا بحال در وب دیده اید کل صفحه Refresh نمیشه و اصلا Refreshی در کار نیست ، فقط مقدار جواب در TextBox قرار میگیره.
تو قسمت بعد انشاالله اراسل نامتقارن رو توضیح خواهم داد...
پ ن : لطفا اگر سوالی یا نظری دارین زیر این تاپیک نظر یا سوالتون رو نپرسین یک تاپیک جدا ایجاد کنید تا این تاپیک فقط مخصوص خود مقاله باشه.
پیشنیاز این مقاله :
بلد بودن مفاهیم ابتدایی برنامه نویسی تحت وب
بلد بودن Html به مقدار کافی
کمی JavaScript
کمی XML
ضمنا اینایی که اینجا میگم فرقی نداره از چه زبان برنامه نویسی استفاده بشه اما برای مثالهام فعلا از دلفی 7 و WebSnap استفاده میکنم .
بسم الله
سناریو :
فرض کنید یک سایت خوشگل طراحی کریدین با کلی عکس و جدول و این حرفها ، یک گوشه سایت هم دوتا TextBox گذاشتین با یک دکمه برای Login . وقتی کاربر کد کاربری و کلمه عبورش رو وارد میکنه و دکمه ورود رو میزنه اطلاعات نوشته شده برای سرور فرستاده میشوند و سرور تصمیم میگیره که اگر اطلاعات درست هست صفحه بعد رو برای کاربر ایجاد کنه و بفرسته ، اما اگر اطلاعات غلط بود باید دوباره همون صفحه قبلی رو بسازه و دوباره کاربر تمام اون صفحه رو لود کنه (حالا بحث کش کردن بماند) با این فرق که این دفعه فقط یک گوشه ای بنویسه مثلا "کد کاربری غلط است". فکرش رو بکنید یکبار تمامی کانتت قیلدهای صفحه برای سرور فرستاده شده ، و یکبار هم کل صفحه دوباره جنریت شده آخر هم یوزر مجبور شده همه صفحه رو دوباره بگیره.
چقدر خوب میشد اگر بدون دست زدن به بقیه صفحه فقط کدکاربری و پسورد برای سرور فرستاده میشد و سرور هم فقط میگفت درسته یا نه !:متفکر:
فکر میکنین میشه ؟
خب معلومه دیگه اگر نمیشد که این قصه رو تعریف نمیکردم . طبیعتا هم با AJAX میشه دیگه ;)
AJAX
آژاکس که مخفف Asynchronous JavaScript And XML هست و شاید اینطوری بشه ترجمش کرد که یعنی استفاده نامتقارن از جاوا اسکریپت و XML ، ذاتا چیزه جدیدی نیست و خیلی وقت هست که تقریبا هر آنچه رو که برای کار کردن باهاش لازم هست فراهم شده اما نامگذاریش و اینکه یکهو اینقدر محبوب بشه شاید 2 سال نیست که باب شده.
به هر حال اصل کار رو آبجکت XMLHttpRequest انجام میده که مایکروسافت نوشتتش و کار این آبجکت اینه که یک اربتاط مجزا با سرور برقرار کنه یکسری اطلاعات رو بفرسته و نتیجه رو از سرور بگیره ، همونطوری که میدونید بهترین روشی که بشر برای تبادل اطلاعاتی که Structorشون از قبل معلوم نیست ، اختراع کرده XML هست پس وقتی این آبجکت بتونه XML بگیره و بفرسته پس میتونه هر اطلاعاتی با هر ساختاری رو بگیره و بفرسته ، اما لزومی هم نداره حالا حتما از XML استفاده کنیم همونطوری که ما فعلا برای اول کار از Text ساده استفاده میکنیم و تازه برای اولین مثال هم بیخیال نامتقارن بودنش میشیم :
مثال اول :
تو مثال اول با استفاده از جاوا اسکریپت یک آبجکت XMLHttpRequest میسازیم، یک درخواست ساده به سرور میفرستیم از طریق این آبجکت ، نتیجه رو از سرور میگیریم و با استفاده از جاوا اسکریپت نشون میدیم ، مثلا میشه توی سرور یکسری اسم و عدد بزاریم و به ازای هر عدد که کاربر وارد میکنه نامش رو بدیم (چقدر لوس)! :
از اینجا ببعد من با دلفی شروع میکنم ، اما مثلا شما هم میتونید با ASP شروع کنید ولی به هر حال هیچ فرقی نداره از چه زبانی استفاده میکنید :
دلفی رو باز کنید ، New>Web Server Application (اون پاییناست) بعد هم Cgi-StandAlone رو انتخاب کنید .
یک وب ماژول براتون ساخته میشه، این اون سرور وب ما هست ; یک جای خوشگل Save بکنیدش ، بعد هم برید توی IIS (بله IIS برنامه تحت وب دارین مینویسین دیگه ) یک VirtualDicrectory رو به نام مثلا AJAXTest بسازید و بهش مربوط کنید .(دسترسی Execute رو هم روش بدین) (لطفا دات نتی ها فکر نکنن که اونا خیلی بهشون خوش میگذره و از این حرفها ندارند، توی دلفی هم ما با اینتراوب وب سرور خودمون رو داریم که خیلی هم از Casini شما بهتره ;) )
خب بریم خدمت جناب دلفی : روی وب ماژول کلیک راست بکنید بعد هم ActionEditor و یک Action جدید ایجاد بکنید ،
اسمش رو مثلا بزارید actStart و PathInfo رو هم به /Start ست بکنید. بعد یکدونه PageProducer از تب اینترنت روی فرم بزارید اسمش رو بزارید ppStart و در اکشن ادیتور دیتا ماژول Producer اکشنی که تعریف کردید رو بزارید همین PageProducer. (معنی این کار این هست که هر موقع این اکشن صدا زده بشه این Producer وظیفه تولید HTML پاسخ رو داره).
این شد اکشنی که قرار صفحه ابتدایی رو تولید کنه ، یک اکشن هم میخواهیم که جواب درخواست آژاکسیمون رو بده ، پس یک اکشن دیگه درست میکنیم اسمش رو میزاریم مثلا GetDay نیازی هم به PageProucer نداره .
حالا بریم توی ppStart کدهای HTML لازم برای تولید صفحه رو بنویسیم :
اول از همه باید یک XMLHttpRequest بسازیم که بتونی اطلاعات رو برامون درخواست کنه ، من ساختن XMLHttpRequest و درخواست اطلاعات رو توی یک تابع مینویسم و بعد توضیحش میدم :
function requestDay()
{
if (window.XMLHttpRequest)
{
var Rqst = new XMLHttpRequest();
}
else
{
var Rqst = new ActiveXObject("Microsoft.XMLHttp");
}
var reqUrl = 'getday?day=' + document.getElementById("txtDay").value;
Rqst.open('GET', reqUrl, false);
Rqst.Send('');
document.getElementById("txtDay").value = Rqst.responseText;
}
توی چند خط اول سعی میکنیم آبجکت XMLHttpRequest رو بسازیم -چه برای اینترنت اکسپلور ، چه فایرفاکس و کلا رفقای موزیلا- بعد هم چون توی این مثال اول میخوایم از متد Get استفاده کنیم ، باید پارامترهامون رو توی URL بفرستیم پس ، یک URL میسازیم که شامل آدرسی که باید بهش مراجه کنیم هست که میشه همون مراجعه به اکشن GetDayی که درست کردیم بعد علامت ؟ که به این معنیه که از اینجا ببعد میخوای پارامتر بفرستیم بعد اسم پارامترمون که من گذاشتم day و بعد هم مقدار پارامتر که از یک TextBox که توی HTMLمون بعدا درست میکنیم و اسمش رو میزاریم txtDay گرفته میشه.
یعنی زمان اجرا مثلا مقدار پارامتر همچین چیزی (اگر کاربر توی TextBox مقدار 5 رو بنویسه) میشه :
getday?day=5
بعد هم میریم سراغ آبجکت XMLHttpRequest که ایجادش کردیم و توی متغیر Rqst داریمش و متد Open رو که صدا میکنیم تا کانکشنش رو با سرور برقرار کنه ، برای متد Open باید 3 تا پارامتر پاس کنیم ، اولی متد ارسال اطلاعات هست که توی این مثال ما از Get استفاده میکنیم ، دومی آدرس سرور هست و سومی اینکه آیا بصورت نامتقارن درخواست صورت بگیره یا خیر (بعدا کاملا توضیحش میدم ) ، ولی فعلا پارامتر سوم را false پاس میکنیم به معنی اینکه متقارن با سرور در ارتباط هستیم .
بعد هم متد Send رو صدا میزنیم با پارامتر خالی تا درخواست صورت بگیره در صورتیکه از متد Post استفاده میکردیم پارامترها رو اینجا پاس میکردیم .(انشاا.. جتما یک متد پست هم مثال میزنم)
در نهایت هم نتیجه برگشته از سرور رو توی همون TextBoxی که کاربر توش عدد رو وارد کرده بر میگردونیم.
تا اینجا هستیم کل HTML لازم برای صفحه اول رو کامل کنیم ، باید در نهایت توی ppStart داخل HTMLDocument این متن رو داشته باشیم :
<html>
<head>
<Script Language="JavaScript">
function requestDay()
{
if (window.XMLHttpRequest)
{
var Rqst = new XMLHttpRequest();
}
else
{
var Rqst = new ActiveXObject("Microsoft.XMLHttp");
}
var reqUrl = 'getday?day=' + document.getElementById("txtDay").value;
Rqst.open('GET', reqUrl, false);
Rqst.Send('');
document.getElementById("txtDay").value = Rqst.responseText;
}
</Script>
</head>
<body>
<Table>
<tr>
<td Align="right"> The Day No: </td>
<td>
<input type="text" id = "txtDay"></td>
<td><input type="Button" onclick= "requestDay();" value = "Get Day" ></td>
</tr>
</Table>
</body>
</html>
در واقع تگهای مورد نیاز HTML و همینطور اون TextBox رو داخل یک Table گذاشتیم ، بعلاوه یک Button که روی OnClickش همون تایعی که نوشتیم رو صدا میزنیم.
خب قسمتهای کلاینت سایدمون تموم شد ، میمونه نوشتن کد دلفی سرور که قرار هست به این درخواستها جواب بده :
اکشن GetDay رو انتخاب کنید و توی ایونت هاش OnAction رو انتخاب کنید ، این رخداد زمانی Fire میشه که یک Request برای این اکشن فرستاده میشه ، یعنی دقیقا وقتی که ما با اون XMLHttpRequest میایم سراغ این اکشن getday ، حالا توی کد دلفی مثلا میتونیم این کد رو بنویسیم :
procedure TwbmdlAjax.wbmdlAjaxactGetDayAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
ADay : Integer;
AResult: String;
begin
ADay := StrToInt(Request.QueryFields.Values['day']);
case ADay of
1: AResult := 'Sat';
2: AResult := 'Sun';
3: AResult := 'Mon';
4: AResult := 'Tue';
5: AResult := 'Wed';
6: AResult := 'Thu';
7: AResult := 'Fri'
else AResult := 'Invalid Day No : ' + IntToStr(ADay);
end;
Response.Content := AResult;
end;
فکر میکنم کدمون واضح هست دیگه ، مقار پارامتر Day رو از Request میگیریم ، بعد هم توی Case معادل روز هفته رو بر میگردونیم و نهایتا هم نتیجه رو در Content جوابمون میزایم.
* در مورد actStart که این کار رو نکردیم و بجاش به یک PageProducer وصلش کردیم ، محتوای PageProducer بعنوان پاسخ فرستاده میشه.
* برای اونایی که زیاد با Websnap آشنایی ندارند : Request آبجکتیه که همه اطلاعات مربوط به درخواست توش هست و Response آبجکتیه که اطلاعات مربوط به پاسخی که قرار فرستاده بشه توش قرار میگیره
دیگه مثالمون آمادست ، حالا یک بروسر باز میکنیم (مثلا IE) و این رو در آدرسش مینویسیم :
(من پروژه رو بنام BasicAjax دخیره کردم)
http://localhost/Ajaxtest/BasicAjax.exe/Start
وقتی که صفحه اولمون اومد توش مثلا عدد 5 رو مینویسیم و دکمه Get Day رو فشار میدیم . دقت کنید که برعکس اکثر صفحاتی که تا بحال در وب دیده اید کل صفحه Refresh نمیشه و اصلا Refreshی در کار نیست ، فقط مقدار جواب در TextBox قرار میگیره.
تو قسمت بعد انشاالله اراسل نامتقارن رو توضیح خواهم داد...
پ ن : لطفا اگر سوالی یا نظری دارین زیر این تاپیک نظر یا سوالتون رو نپرسین یک تاپیک جدا ایجاد کنید تا این تاپیک فقط مخصوص خود مقاله باشه.