بازگشت به دوره

کار با انواع کنترل ها

در بخش قبل با مقدمات و مفاهیم اولیه‌ی مربوط به فرم‌ها آشنا شدیم. در این بخش قصد داریم کمی با جزئیات بیشتر در رابطه با انواع کنترل‌ها و روش‌های تعامل با آنها صحبت کنیم.

 

کنترل‌ها متنی

در HTML انواع مختلفی از کنترل‌های متنی وجود دارد که نحوه‌ی تعامل با آنها در جاوا اسکریپت کاملاً یکسان است. به غیر از فیلدهای متنی چند خطی که با تگ <textarea> ایجاد می‌شوند، سایر فیلدهای متنی با تگ <input> ایجاد می‌شوند و نوع آنها با مقدار صفت type مشخص می‌شود. از این دست کنترل‌ها می‌توان به نوع text، نوع password، نوع email، نوع search و ... اشاره کرد.

مقدار اولیه‌ی کنترل‌های متنی را می‌توان در HTML مشخص کرد. این کار در فیلدهای متنی چند خطی با قرار دادن رشته‌ی مورد نظر بین تگ‌های شروع و پایان <textarea> انجام می‌شود. و در سایر فیلدهای متنی نیز با صفت value می‌توان مقدار اولیه را مشخص کرد.

برای به دست آوردن مقدار یک فیلد متنی از خاصیت value استفاده می‌شود. این خاصیت خواندنی و نوشتنی است. یعنی می‌توان با تغییر مقدار این خاصیت، رشته‌ی موجود در فیلدهای متنی را تغییر داد. به عنوان مثال فرم زیر را در نظر بگیرید که از یک فیلد متنی از نوع text و یک دکمه از نوع button تشکیل شده است. توجه کنید که دکمه‌های از نوع button هیچ رفتار پیش‌فرضی برای رویداد click ندارند. بنابراین با کلیک کردن بر روی این نوع دکمه‌ها هیچ اتفاق خاصی رخ نمی‌دهد، مگر اینکه در جاوا اسکریپت یک Event Handler برای این رویداد تعریف کرده باشیم.


<form>
	<input type="text" value="OTedia" /><br /> 
	<button type="button">Duplicate</button>
</form>

برنامه‌ی زیر یک Event Handler برای رویداد click از عنصر <button> تعریف می‌کند تا در صورت کلیک کردن بر روی این دکمه، متن موجود در فیلد متنی Duplicate یا دو برابر شود. یعنی مقدار جدید فیلد متنی، با الحاق مقدار قبلی به خودش به وجود می‌آید. ضمناً مقدار اولیه‌ی فیلد متنی با استفاده از صفت value برابر با "OTedia" قرار داده شده است.


const button = document.querySelector('button');

button.addEventListener('click' , duplicate);

function duplicate(){
	const input = document.querySelector('input');
	input.value = input.value + input.value;
}

این برنامه را می‌توانید اینجا در CodePen اجرا کنید. با وارد کردن هر مقدار دلخواهی در فیلد متنی و سپس کلیک کردن بر روی دکمه، متن موجود در فیلد متنی دو برابر خواهد شد.

 

کنترل‌های نوع Checkbox

Checkbox ها از فیلدهای پر کاربرد در فرم‌های HTML هستند. این نوع فیلدها نیز دارای خاصیتی به نام value هستند که دقیقاً مانند فیلدهای متنی می‌توان آن را مقداردهی کرد و یا مقدار آن را خواند. اما مقدار خاصیت value در چک باکس‌ها معمولاً توسط جاوا اسکریپت تغییر نمی‌کند. در واقع اهمیت مقدار خاصیت value در این نوع فیلدها در سمت سرور است. یعنی در زمان Submit شدن فرم‌ها، مقدار خاصیت value این فیلدها به سرور ارسال می‌شود.

چک باکس‌ها دارای خاصیتی به نام checked هستند که اهمیت زیادی در جاوا اسکریپت دارد. این خاصیت از نوع boolean است. یعنی فقط می‌تواند یکی از دو مقدار true و false را داشته باشد. مقدار true به معنی تیک خوردن، و مقدار false به معنی تیک نخوردن چک باکس است. مقدار پیش‌فرض این خاصیت false است. به همین دلیل چک باکس‌ها به صورت پیش‌فرض در حالت انتخاب نشده هستند. اما با استفاده از صفت checked در HTML می‌توان حالت پیش‌فرض یک چک باکس را به وضعیت انتخاب شده تغییر داد.

به عنوان یک مثال از کاربرد چک باکس‌ها فرم زیر را در نظر بگیرید. این فرم یک منوی بسیار ساده است و کاربر می‌تواند موارد مورد نیاز خود را با استفاده از چک باکس‌ها انتخاب کند. سپس با کلیک کردن بر روی دکمه‌ی "سفارش" یک فاکتور ساده در قسمت زیر فرم بر اساس انتخاب‌های کاربر نمایش داده می‌شود.


<h1>منوی سفارش</h1>
<form>
	<input type="checkbox" value="کوبیده" checked /><label>کوبیده</label> <br />
	<input type="checkbox" value="جوجه کباب" /><label>جوجه کباب</label><br />
	<input type="checkbox" value="نوشابه" /><label>نوشابه</label><br />
	<input type="checkbox" value="دوغ" /><label>دوغ</label><br />
	<button type="button">سفارش</button>
</form>
<h2>سفارش فعلی شما</h2>
<div id="result"></div>

const button = document.querySelector('button');
button.addEventListener('click' , handler);

function handler(){
	const inputs = document.querySelectorAll('input');
	let html = '<table border="1" width="200">';
	for(let input of inputs){
		if(input.checked){
			html += `<tr><td>${input.value}</td></tr>`;						
		}
	}
	html += '</table>';
	const div = document.getElementById('result');
	div.innerHTML = html;
}

این برنامه را می‌توانید اینجا اجرا کنید. در این برنامه پس از کلیک کردن بر روی دکمه‌ی "سفارش"، ابتدا با استفاده از متد querySelectorAll تمام تگ‌های <input> انتخاب می‌شوند. سپس در یک حلقه‌ی for..of مقدار خاصیت checked برای هر یک از چک باکس‌ها بررسی می‌شود. و در صورت true بودن مقدار این خاصیت، مقدار خاصیت value از چک باکس مورد نظر در یک سلول جدید از یک جدول قرار می‌گیرد. در انتها نیز جدولی که به صورت یک رشته‌ی HTML ایجاد شده است، در خاصیت innerHTML عنصر <div> قرار داده می‌شود. ضمناً توجه کنید که گزینه‌ی اول این منو به صورت پیش‌فرض انتخاب شده است. زیرا در کدهای HTML از صفت checked برای این عنصر استفاده شده است.

 

کنترل‌های نوع Radio Button

دکمه‌های رادیویی یا Radio Button ها، شباهت بسیار زیادی به چک باکس‌ها دارند. این کنترل‌ها نیز با استفاده از تگ <input> ایجاد می‌شوند و مقدار صفت type برای آنها برابر با radio است. تفاوت اصلی دکمه‌های رادیویی با چک باکس‌ها در این است که دکمه‌های رادیویی معمولاً به صورت گروه‌بندی شده به کار می‌روند و در هر لحظه فقط یکی از گزینه‌ها در هر گروه می‌تواند انتخاب شود. اما چک باکس‌ها به صورت کاملاً مستقل از هم عمل می‌کنند و انتخاب هر گزینه، کاملاً مستقل از گزینه‌های دیگر است. برای قرار دادن دکمه‌های رادیویی در یک گروه لازم است که مقدار صفت name آنها یکسان باشد.

دکمه‌های رادیویی نیز خاصیتی به نام checked دارند که وضعیت انتخاب شدن یا نشدن آنها را مشخص می‌کند. مانند چک باکس‌ها، دکمه‌های رادیویی نیز به صورت پیش‌فرض در وضعیت انتخاب نشده هستند. اما می‌توان با استفاده از صفت checked این وضعیت را تغییر داد.

به عنوان مثال در فرم زیر دو گروه مختلف از دکمه‌های رادیویی وجود دارد. گروه اول دارای دو گزینه برای انتخاب وضعیت تاهل، و گروه دوم دارای ۴ گزینه برای انتخاب مدرک تحصیلی است. همانطور که مشاهده می‌کنید مقدار صفت name در گزینه‌هایی که متعلق به یک گروه هستند یکسان است.


<h1>انتخاب وضعیت</h1>
<form>
	<input type="radio" name="marriage" value="مجرد" checked /><label>مجرد</label>
	<input type="radio" name="marriage" value="متاهل" /><label>متاهل</label>
	<hr />
	<input type="radio" name="education" value="دیپلم" /><label>دیپلم</label>
	<input type="radio" name="education" value="لیسانس" checked /><label>لیسانس</label>
	<input type="radio" name="education" value="فوق لیسانس" /><label>فوق لیسانس</label>
	<input type="radio" name="education" value="دکتری" /><label>دکتری</label>
	<hr />
	<button type="button">مشاهده‌ی وضعیت</button>
</form>
<h2>وضعیت فعلی شما</h2>
<div id="result"></div>

برای مدیریت این فرم از برنامه‌ی زیر استفاده می‌کنیم.


const button = document.querySelector('button');
button.addEventListener('click' , handler);

function handler(){
	const marriageInputs = document.querySelectorAll('input[name="marriage"]');
	const educationInputs = document.querySelectorAll('input[name="education"]');
	let marriage , education;
	for(let input of marriageInputs){
		if(input.checked){
			marriage = input.value;
			break;
		}
	}
	for(let input of educationInputs){
		if(input.checked){
			education = input.value;
			break;
		}
	}
	const div = document.getElementById('result');
	div.innerHTML = `<p>شما ${marriage} هستید و دارای مدرک ${education} هستید.</p>`;
}

این برنامه را می‌توانید اینجا اجرا کنید. با اجرای این مثال مشاهده خواهید کرد که در هر لحظه فقط یکی از گزینه‌ها را در هر گروه می‌توان انتخاب کرد. با کلیک کردن بر روی دکمه‌ی "مشاهده‌ی وضعیت"، با توجه به گزینه‌های انتخاب شده، پیام مناسب در زیر این دکمه و داخل عنصر <div> نمایش داده می‌شود.

در این مثال نیز برای بررسی وضعیت گزینه‌های مختلف از حلقه‌های for..of استفاده شده است. اما در این مثال در صورت انتخاب شدن یک گزینه، از بررسی گزینه‌های دیگر صرف نظر می‌شود. زیرا مطمئن هستیم که از هر گروه فقط یک گزینه انتخاب شده است. به همین دلیل در خطوط ۱۱ و ۱۷ از دستور break استفاده شده است تا پس از مشخص شدن گزینه‌ی انتخاب شده، از بررسی وضعیت سایر گزینه‌ها صرف نظر شود.

 

کنترل‌های Drop-down List

این نوع کنترل‌ها با یک عنصر <select> و تعدادی عنصر <option> در داخل آن ایجاد می‌شوند. این کنترل‌ها دارای دو حالت تک انتخابی و چند انتخابی هستند. حالت پیش‌فرض حالت تک انتخابی است. برای تغییر وضعیت این کنترل به حالت چند انتخابی می‌توان از صفت multiple برای عنصر <select> استفاده کرد.

لیست‌های تک انتخابی معمولاً جایگزین مناسبی برای دکمه‌های رادیویی هستند و با استفاده از آنها می‌توان تا حد زیادی حجم کدها را کاهش داد. به عنوان مثال می‌توان فرم موجود در مثال قبلی را به صورت زیر با لیست‌های تک انتخابی جایگزین کرد.


<h1>انتخاب وضعیت</h1>
<form>
	<select name="marriage">
		<option value="مجرد" selected>مجرد</option>
		<option value="متاهل">متاهل</option>
	</select>
	<hr />
	<select name="education">
		<option value="دیپلم">دیپلم</option>
		<option value="لیسانس" selected>لیسانس</option>
		<option value="فوق لیسانس">فوق لیسانس</option>
		<option value="دکتری">دکتری</option>
	</select>
	<hr />
	<button type="button">مشاهده‌ی وضعیت</button>
</form>
<h2>وضعیت فعلی شما</h2>
<div id="result"></div>

هرچند در این فرم جدید تعداد خطوط کدهای HTML کمی بیشتر شده است. اما تعداد خطوط برنامه‌ی جاوا اسکریپت برای مدیریت این فرم به شکل چشمگیری کاهش پیدا می‌کند.


const button = document.querySelector('button');
button.addEventListener('click' , handler);

function handler(){
	const marriageMenu = document.querySelector('select[name="marriage"]');
	const educationMenu = document.querySelector('select[name="education"]');
	const div = document.getElementById('result');
	div.innerHTML = `<p>شما ${marriageMenu.value} هستید و دارای مدرک ${educationMenu.value} هستید.</p>`;
}

این برنامه را می‌توانید اینجا اجرا کنید. رفتار این مثال کاملاً مشابه مثال قبلی است. اما همانطور که مشاهده می‌کنید حجم کدهای جاوا اسکریپت کمتر از نصف مثال قبلی است.

نکته‌ی مهمی که در زمان استفاده از لیست‌ها باید به آن توجه شود، تفاوت‌های موجود در خاصیت value این کنترل با سایر کنترل‌ها است. زمانی که مقدار خاصیت value از یک عنصر <select> خوانده می‌شود. در واقع مقدار صفت value از عنصر <option> انتخاب شده بازگردانده می‌شود. اما ممکن است گزینه‌ی انتخاب شده صفت value را نداشته باشد. در این صورت متن موجود در گزینه‌ی انتخاب شده به عنوان value بازگردانده می‌شود.

همچنین باید توجه کنید که در صورت انتساب یک مقدار جدید به خاصیت value از عنصر <select>، این مقدار باید به عنوان مقدار صفت value در یکی از عناصر <option> تعریف شده باشد. در غیر این صورت هیچ یک از گزینه‌های داخل لیست انتخاب نخواهند شد. مثلاً در مثال قبلی اجرای دستور زیر باعث انتخاب آخرین گزینه می‌شود.


educationMenu.value = 'دکتری';

اما اجرای دستور زیر هیچ یک از گزینه‌ها را انتخاب نمی‌کند. همچنین گزینه‌ی انتخاب شده‌ی قبلی را نیز از حالت انتخاب خارج می‌کند.


educationMenu.value = 'فوق دیپلم';

عناصر <select> خاصیتی به نام selectedIndex نیز دارند که اندیس گزینه‌ی انتخاب شده را مشخص می‌کند. این خاصیت خواندنی و نوشتنی است. پس می‌توان با تغییر مقدار این خاصیت، گزینه‌ی انتخاب شده را نیز تغییر داد. توجه کنید که اندیس گزینه‌ی اول صفر است و مقدار 1- به معنی عدم انتخاب تمام گزینه‌ها است. به عنوان مثال دستور زیر موجب انتخاب گزینه‌ی دوم می‌شود.


educationMenu.selectedIndex = 1;