در این بخش از سری مقالات آموزش HTML به بررسی دقیق کارکرد ویجتهای مختلف فرم میپردازیم و گزینههایی که برای گردآوری انواع دادهها وجود دارند را مورد بررسی قرار میدهیم. این راهنما به نوعی یک راهنمای جامع است و همه ویجت های نیتیو فرم را شامل میشود.
پیشنیاز مطالعه این مقاله داشتن سواد مقدماتی رایانه و درکی ابتدایی از HTML است. هدف از این مقاله نیز آشنایی با انواع ویجتهای نیتیو فرم است که در مرورگرها برای گردآوری دادهها عرضهشدهاند و شیوه پیادهسازی آنها با استفاده از HTML مورد بررسی قرار میگیرد. برای مطالعه بخش قبلی این سری مقالات به لینک زیر مراجعه کنید:
نقطه تمرکز ما در این مقاله روی ویجتهای فرم است که به صورت داخلی در مرورگرها عرضه میشوند، اما از آنجا که فرمهای HTML کاملاً محدود هستند و کیفیت پیادهسازی آنها در هر مرورگر میتواند متفاوت باشد، توسعهدهندههای وب در برخی موارد ویجتهای فرم خاص خود را میسازند. ما این موضوع را در بخشهای آتی این سری مقالات مورد بررسی قرار خواهیم داد.
بسیاری از عناصر مورد استفاده برای تعریف ویجتهای فرم برخی خصوصیتهای خاص خود را دارند. با این حال، مجموعهای از خصوصیتها وجود دارند که در میان همه عناصر فرم مشترک هستند و بدین ترتیب روی این ویجتها کنترل ایجاد میکنند. در ادامه فهرستی از این خصوصیتهای مشترک را میبینید:
نام خصوصیت | مقدار پیشفرض | توضیح |
---|---|---|
autofocus | (false) | این خصوصیت بولی به ما امکان میدهد که تعیین کنیم عنصر باید به صورت خودکار در زمان بارگذاری صفحه، فوکوس بگیرد یا این که این فوکوس بر اثر اقدام کاربر مانند وارد کردن کنترل متفاوت به این عنصر میرسد. تنها یک عنصر مرتبط با فرم در سند میتواند این خصوصیت را فعال داشته باشد. |
disabled | (false) | این خصوصیت بولی نشان میدهد که کاربر نمیتواند با عنصر تعامل پیدا کند. اگر این خصوصیت تعیین نشده باشد، آن عنصر تنظیمات خود را از عنصر شامل خود برای نمونه <fieldset> به ارث میبرد. اگر هیچ عنصر شاملی با خصوصیت disabled تعیینشده، وجود نداشته باشد، در این صورت عنصر به صورت فعال (enabled) خواهد بود. |
form | این همان عنصری است که ویجت با آن مرتبط میشود. مقدار خصوصیت باید خصوصیت id یک عنصر <form> در همان سند باشد. بر اساس تئوری این خصوصیت امکان تعیین ویجت فرم خارج از عنصر <form> را میدهد. با این حال در عمل، هیچ مرورگری وجود ندارد که از این قابلیت پشتیبانی کند. | |
name | نام عنصر است که به همراه دادههای فرم تحویل میشود. | |
value | مقدار اولیه عنصر است. |
فیلدهای <input> متنی ابتداییترین ویجتهای فرم هستند این ویجتها سادهترین روش برای کاربر هستند تا هر نوع دادهای را که میخواهد وارد کند. با این حال برخی فیلدهای متنی برای نیازهای خاصی به صورت تخصصی تنظیم شدهاند. ما در بخش قبلی چند مورد از آنها را مشاهده کردیم.
نکته: فیلدهای متنی HTML کنترلهای ورود متن سادهای هستند. این بدان معنی است که نمیتوان از آنها برای انجام عملیات «ویرایش کامل» (حروف درشت، ایتالیک و غیره) استفاده کرد. همه ویرایشگرهای rich text که در صفحههای وب میبینید، ویجتهای سفارشی هستند که با استفاده از HTML ،CSS و JavaScript ساخته شدهاند.
همه فیلدهای متنی برخی رفتارهای مشترک دارند:
نکته: عنصر <input> یک ویجت خاص است، زیرا میتواند تقریباً هر چیزی باشد. با تعیین خصوصیت Type میتوان در آن تغییرات زیادی ایجاد کرد. از آن برای ایجاد اغلب انواع ویجتها شامل فیلدهای متنی تم خطی، کنترلهای بدون ورود متن، کنترلهای زمان و تاریخ، و دکمهها استفاده میشود. با این وجود، برخی استثناها نیز وجود دارند مثلاً <textarea> برای ورودی متن چندخطی استفاده میشود. در زمان مطالعه این مقاله به این موارد توجه ویژهای داشته باشید.
فیلد متنی تکخطی با استفاده از عنصر <input> ساخته میشود که مقدار خصوصیت Type آن به صورت text تنظیم شده است. البته اگر مقداری نیز برای این خصوصیت تعیین نکرده باشید، مقدار پیشفرض همان text است. مقدار text برای این خصوصیت در مواردی که مقدار تعیینشده این خصوصیت برای مرورگر ناشناس باشد، به عنوان یک مقدار fallback نیز عمل میکند. برای نمونه اگر مقدار “type=”date وارد کرده باشید و مرورگر از ابزارهای انتخاب تاریخ داخلی پشتیبانی نکند به صورت پیشفرض به حالت فوق در میآید.
در ادامه نمونهای از این فیلد متنی تکخطی را مشاهده میکنید:
فیلدهای متنی تکخطی تنها یک محدودیت واقعی دارند و آن این است که اگر متنی با چند خط وارد کنید، مرورگر شکستگی خطوط را پیش از ارسال دادهها حذف میکند:
در HTML5 فیلدهای متنی تکخطی ابتدایی با افزودن مقادیر خاصی برای خصوصیت type بهبود یافتهاند. این مقادیر یک عنصر <input> را همچنان به یک فیلد متنی تکخطی تبدیل میکنند، اما چند قید و قابلیت اضافی نیز به این فیلد اضافه میکنند.
این نوع از فیلد به همراه مقدار email برای خصوصیت type تنظیم میشود:
زمانی که از این type استفاده شود کاربر ملزم میشود که یک آدرس ایمیل معتبر در فیلد وارد کند. هر محتوای دیگری که وارد شود مرورگر در زمان تحویل فرم یک خطا نمایش میدهد. توجه کنید که این یک اعتبارسنجی سمت کاربر است و از سوی مرورگر اجرا میشود:
همچنین با گنجاندن خصوصیت multiple میتوان به کاربر امکان وارد کردن چند نشانی ایمیل (جداشده با کاما) در یک ورودی منفرد را داد. روی برخی دستگاهها (به خصوص موبایل) هنگام تپ کردن روی این ویجت میتوان یک کیبورد مجزا باز کرد که برای وارد کردن ایمیل مناسبتر باشد.
این نوع از فیلد با استفاده از تعیین مقدار password برای خصوصیت type تنظیم میشود:
این فیلد هیچ قید خاصی برای متن وارد شده اضافه نمیکند، اما مقدار وارد شده در فیلد را با استفاده از ستاره یا نقطه مبهم میسازد تا از سوی افراد دیگر قابل خواندن نباشد.
به خاطر داشته باشید که این صرفاً یک قابلیت رابط کاربری است؛ به غیر از این که فرم خود را به طور امنی تحویل دهید، در همه موارد فرم به صورت متن ساده ارسال میشود که از نظر امنیتی رویه بدی محسوب میشود، چون فرد خرابکار میتواند در دادهها دخالت کرده و رمزهای عبور، جزییات کارت اعتباری یا هر داده دیگری که ارسال میشود را به سرقت ببرد. بهترین روش برای حفاظت از کاربران در برابر این رویداد این است که همه صفحهها از جمله فرمها را روی یک اتصال امن یعنی آدرس https عرضه کنیم تا دادهها پیش از ارسال رمزنگاری شوند.
مرورگرهای مدرن تبعات امنیتی ارسال دادههای فرم روی یک اتصال غیر امن را تشخیص میدهند و هشدارهایی ارائه میکند تا کاربران را از استفاده از فرمهای ناامن باز دارند. برای کسب اطلاعات بیشتر در مورد پیادهسازیهای این موارد در فایرفاکس به صفحه «رمزهای عبور ناامن» (+) مراجعه کنید.
این نوع از فیلد با استفاده از مقدار search برای خصوصیت type تنظیم میشود:
تفاوت اصلی بین یک فیلد متنی و یک فیلد جستجو در شیوه استایلبندی آن از سوی مرورگر است. فیلدهای جستجو در اغلب موارد با استفاده از گوشههای گرد رندر میشوند و یا یک کاراکتر × در انتهای آن وجود دارد که با کلیک روی آن میتوان مقدار وارد شده را پاک کرد. با این وجود، قابلیت اضافی دیگری نیز وجود دارد که لازم به ذکر است، در فیلدهای جستجو میتوان مقادیر را به صورت خودکار ذخیره کرد تا روی صفحههای مختلف از یک وبسایت به صورت «تکمیل خودکار» (auto completed) عرضه شوند.
این نوع از فیلد با استفاده از تعیین مقدار tel برای خصوصیت type به دست میآید:
به دلیل طیف گسترده قالبهای شماره تلفن که در دنیا وجود دارد این نوع از قبل هیچ قیدی را روی مقدار وارد شده از سوی کاربر الزام نمیکند. برای مثال میتوان حروف و موارد دیگر را نیز در این فیلد وارد کرد. در واقع تنها تفاوت این فیلد عملاً در بحث معناشناسی است، گرچه برخی دستگاهها (به خصوص روی دستگاههای همراه) در زمان فوکوس گرفتن این فیلد از یک کیپد متفاوت مجازی استفاده میکنند که کار وارد کردن ارقام شماره تلفن را آسانتر میکند.
این نوع از فیلد با استفاده از مقدار url برای خصوصیت type تعیین میشود:
بدین ترتیب قیدهای اعتبارسنجی خاصی روی فیلد اعمال میشود و در صورتی که URL-های نامعتبری وارد شوند، مرورگر خطا گزارش میکند.
نکته: به صرف اینکه یک URL ساختار درستی دارد، به این معنی نیست که حتماً به مکانی که قطعاً وجود دارد اشاره میکند.
نکته: فیلدهایی که قیدهای خاصی دارند، زمانی که خطا داشته باشد از ارسال فرم جلوگیری میکنند، به علاوه میتوانند طوری استایلبندی شوند که خطا را واضحتر نمایش دهند. این مسئله را در ادامه این سری مقالهها و در مقالهای با عنوان «اعتبارسنجی فرم دادهها» بیشتر مورد بررسی قرار میدهیم.
یک فیلد متنی چندخطی فیلدی است که به جای استفاده از عنصر <element> با استفاده از عنصر <textarea> تعیین شده است.
تفاوت اصلی بین یک textarea و یک فیلد متنی تکخطی این است که کاربران میتوانند متنی وارد کنند که در آن متن به چند خط شکسته شده باشد.
نکته: در اغلب موارد فیلدهای متنی چندخطی در مرورگرهای مختلف دارای یک دستگیره کشیدن در گوشه راست-پایین هستند که به کاربر امکان میدهد اندازه آن را تغییر دهد. این توانایی تغییر دادن اندازه را میتوان با تعیین خصوصیت resize به صورت none در CSS غیر فعال کرد.
<textarea> چند خصوصیت دیگر نیز میپذیرد که شیوه رندر شدن آن را در چند خط کنترل میکند:
نام خصوصیت | مقدار پیشفرض | توضیح |
---|---|---|
cols | 20 | عرض قابل مشاهده کنترل متن بر اساس عرض میانگین کاراکترها |
rows | تعداد خطوط متن قابل مشاهده برای کنترل | |
wrap | soft | شیوه کنترل شکستن متن به چند خط را کنترل میکند. مقادیر ممکن hard و soft هستند. |
توجه کنید که عنصر <textarea> کمی متفاوتتر از عنصر <input> نوشته میشود. عنصر <input> یک عنصر خالی است، یعنی نمیتواند شامل هیچ عنصر فرزند باشد و از سوی دیگر عنصر <textarea> یک عنصر معمولی است که میتواند شامل فرزندان با محتوای متنی باشد.
دو نکته کلیدی مرتبط در اینجا وجود دارند که باید مورد اشاره قرار گیرند:
ویجت «بازشدنی» (Drop-down) روشی ساده است که به کاربران امکان میدهد یکی از گزینههای فراوان را بدون اشغال فضای زیاد در رابط کاربری انتخاب کنند. HTML دو شکل از محتوای بازشدنی دارد که یکی «کادر انتخاب» (select box) و دیگری «کادر تکمیل خودکار» (autocomplete box) است. در هر دو حالت شیوه تعامل یکسان است. زمانی که کنترل فعال میشود، مرورگر لیستی از مقادیر را نمایش میدهد که کاربر میتواند از بین آنها انتخاب کند.
کادر انتخاب به وسیله یک عنصر <select> با یک یا دو عنصر <option> به عنوان فرزند ایجاد میشود که هر کدام از آنها یکی از مقادیر ممکن را تعیین میکنند.
اگر مقدار پیشفرض برای یک کادر انتخاب الزامی باشد، میتوان با استفاده از خصوصیت selected روی عنصر <option> مطلوب آن را تعیین کرد. بدین ترتیب در زمان بارگذاری صفحه، این گزینه از قبل انتخاب شده است. عناصر <option> میتوانند درون عناصر <optgroup> نیز به صورت تو در تو تعریف شوند تا به لحاظ بصری گروههایی از مقادیر را تشکیل دهند:
اگر یک عنصر <option> با استفاده از یک خصوصیت value تنظیم شده باشد، این مقدار خصوصیت زمانی که فرم تحویل میشود ارسال خواهد شد. اگر خصوصیت value نادیده گرفته شود، محتوای عنصر <option> به عنوان مقدار کادر انتخاب مورد استفاده قرار میگیرد.
روی عنصر <optgroup>، خصوصیت label پیش از مقادیر نمایش پیدا میکند، اما حتی اگر ظاهر آن تا حدودی شبیه یک گزینه باشد در عمل غیر قابل انتخاب است.
هر کادر انتخاب به صورت پیشفرض امکان انتخاب یک مقدار منفرد را به کاربر میدهد. با افزودن خصوصیت multiple به عنصر <select> میتوان امکان انتخاب چند مقدار را به کاربر داد. در این حالت از سازوکار پیشفرض سیستم عامل استفاده میشود. یعنی کاربر باید کلیدهای cmd (در مک) یا Ctrl (در ویندوز) را برای کلیک و انتخاب چند مورد نگه دارد.
نکته: در صورتی که از کادرهای انتخاب چندگزینهای استفاده میکنید، کادر انتخاب دیگر مقادیر محتوا را به صورت بازشدنی نمایش نمیدهد، بلکه همه آنها به صورت یکباره در یک لیست نمایش مییابند.
نکته: همه مرورگرها از عنصر <select> پشتیبانی میکنند و همچنین همه آنها از خصوصیت multiple نیز روی آن پشتیبانی میکنند.
میتوان مقادیر پیشنهاد شده با تکمیل خودکار را در ویجتهایی که از عنصر <datalist> استفاده میکنند ارائه کرد و مقادیری که قرار است نمایش پیدا کنند نیز با استفاده از عناصر <option> تعیین میشوند.
در این حالت لیست دادهها محدود به فیلد متنی (به طور معمول عنصر <input>) با استفاده از خصوصیت list خواهد بود.
زمانی که لیست دادهها به کمک یک ویجت فرم ارائه شد، از گزینههای آن برای تکمیل خودکار متن وارد شده از سوی کاربر استفاده میشود. در این روش به طور معمول یک کادر بازشدنی به کاربر عرضه میشود که موارد مطابقت ممکن را برای آن چه در کادر وارد میکند نمایش میدهد.
نکته: بر اساس مشخصات HTML (+)، خصوصیت list و عنصر <datalist> را میتوان به همراه هر نوع از ویجت که نیازمند ورودی کاربر است استفاده کرد. با این حال مشخص نیست که طرز کار آن با کنترلهایی به جز متن (برای مثال با رنگ) چگونه میتواند باشد و مرورگرهای مختلف نیز بسته به مورد رفتار متفاوتی نشان میدهند. به همین دلیل در هنگام استفاده از این قابلیت روی هر چیزی به جز فیلدهای متنی هوشیار باشید.
عنصر <datalist> یکی از جدیدترین امکانات فرمهای HTML است، از این رو پشتیبانی مرورگر آن نسبت به آن چه تاکنون بررسی کردیم، تا حدودی محدودتر است. برای مثال IE10 و نسخههای قبل آن و همچنین سافاری در زمان نگارش این مقاله هنوز از آن پشتیبانی نمیکردهاند.
برای رفع این مشکل، ترفند کوچکی را معرفی میکنیم که میتوانید به وسیله آن روی این مرورگرها fallback تعریف کنید:
مرورگرهایی که از عنصر <datalist> پشتیبانی میکنند همه عناصری را که عناصر <option> نیستند نادیده گرفته و مطابق انتظار عمل خواهند کرد. از سوی دیگر، مرورگرهایی که از عنصر پشتیبانی نمیکنند، برچسب و کار انتخاب را نمایش خواهند داد. البته روشهای دیگری نیز برای مدیریت فقدان پشتیبانی برای عنصر <datalist> وجود دارد، اما این سادهترین روش است، چون روشهای دیگر نیازمند استفاده از جاوا اسکریپت هستند.
«آیتمهای قابل بررسی» (Checkable items) ویجتهایی هستند که حالت آنها را میتوان با کلیک کردن رویشان تغییر داد. دو نوع از آیتم قابل بررسی وجود دارند: کادر بررسی و دکمههای رادیویی. هر دو این آیتمها از خصوصیت checked استفاده میکنند تا نشان دهند که ویجت به صورت پیشفرض تیک خورده است یا نه.
لازم به ذکر است که این ویجتها دقیقاً مانند ویجتهای فرم دیگر عمل نمیکنند. در اغلب ویجتهای فرم، زمانی که فرم تحویل میشود، همه ویجتهایی که خصوصیت name دارند ارسال میشوند، حتی اگر هیچ مقداری پر نشده باشد. در مورد آیتمهای قابل بررسی، مقادیر آنها تنها زمانی ارسال میشود که تیک خورده باشند. اگر تیک نخورده باشند، چیزی ارسال نمیشود و این وضعیت حتی شامل نام آنها نیز میشود.
برای این که بالاترین سطح از کاربردپذیری/دسترسپذیری را داشته باشیم، بهتر است هر لیست از آیتمهای مرتبط را در یک <fieldset> قرار دهیم و به همراه آن یک <legend> نیز عرضه کنیم که توضیحی کلی در مورد لیست ارائه میکند. هر جفت منفرد از عناصر <label>/<input> باید در آیتم لیست مخصوص خود قرار گیرد. در ادامه این موضوع را با طرح مثالهایی بیشتر روشن میسازیم.
همچنین در صورتی که میخواهید این کنترلها معنادار باشند، باید مقادیری برای این نوع از ورودیها درون خصوصیت value ارائه کنید. در صورتی که مقداری ارائه نشده باشد، کادرهای بررسی و دکمههای رادیویی مقدار on خواهند داشت.
یک کادر بررسی یا چک باکس با استفاده از عنصر <input> به همراه خصوصیت type آن مقداری برابر با checkbox خواهد داشت.
گنجاندن خصوصیت checked موجب میشود که کادر بررسی در زمان بارگذاری صفحه، به صورت خودکار تیک بخورد.
دکمه رادیویی با استفاده از عنصر <element> به همراه تعیین مقدار radio برای خصوصیت type به دست میآید.
چند دکمه رادیویی را میتوان به همدیگر پیوند زد. اگر این دکمهها مقدار یکسانی برای خصوصیت name داشته باشند، آنها را در گروه یکسانی از دکمهها در نظر میگیریم. تنها یک دکمه در هر گروه مفروض میتواند در آن واحد انتخاب شود. این بدان معنی است که وقتی یکی از آنها تیک میخورد، همه موارد دیگر به صورت خودکار از انتخاب خارج میشوند. زمانی که فرم ارسال میشود تنها مقدار دکمه رادیویی انتخاب شده ارسال میشود. اگر هیچ کدام از دکمهها انتخاب نشده باشند، کل مجموعه دکمههای رادیویی در حالت نامشخص تلقی میشوند و هیچ مقداری در فرم ارسال نمیشود.
درون فرمهای HTML سه نوع دکمه وجود دارد:
هر دکمهای با استفاده از عنصر <button> یا عنصر <input> ایجاد میشود. این مقدار خصوصیت type است که نوع خاص دکمه نمایش یافته را تعیین میکند.
دکمهها همواره رفتار یکسانی دارند، چه از یک عنصر <button> استفاده کنید و چه از عنصر <input> بهره بگیرید. با این حال برخی تفاوتهای قابل توجه وجود دارند:
به بیان فنی تقریباً هیچ تفاوتی بین یک دکمه که با عنصر <button> تعریف شده و دکمهای که با عنصر <input> تعریف شده وجود ندارد. تنها تفاوت قابل توجه در برچسب خود دکمه است. درون یک عنصر <input> برچسب میتواند دادههای کاراکتری باشد، در حالی که در عنصر <button> برچسب میتواند محتوای HTML باشد و از این رو میتواند استایلدهی شود.
در این بخش ویجتهایی را مورد بررسی قرار میدهیم که کاربران به وسیله آنها میتوانند دادههای پیچیده یا غیرمعمول را در فرم وارد کنند. این موارد شامل اعداد دقیق یا تقریبی، تاریخ، زمان و رنگها هستند.
ویجتهایی که برای وارد کردن عدد استفاده میشوند با استفاده از عنصر <input> ایجاد میشوند و خصوصیت type آن نیز روی مقدار number قرار میگیرد. این کنترل ظاهری شبیه به یک فیلد متنی دارد، اما تنها امکان وارد کردن اعداد اعشاری را به کاربر میدهد و دکمههایی برای افزایش یا کاهش مقدار ویجت ارائه میکند.
در این ویجت امکان اجرای کارهای زیر وجود دارد:
بدین ترتیب ویجتی ایجاد میکنیم که مقدار آن محدود به هر مقداری بین 1 و 100 است و دکمههای افزایش و کاهش آن مقدارش را 2 واحد تغییر میدهند.
ورودیهای number در نسخههای 10 و پایینتر از اینترنت اکسپلورر پشتیبانی نمیشوند.
روش دیگری که برای انتخاب عدد وجود دارد، استفاده از یک اسلایدر است. اسلایدرها از نظر بصری نسبت به فیلدهای متنی دقت کمتری دارند و بنابراین برای انتخاب اعدادی استفاده میشوند که در آنها عدد دقیق اهمیت چندانی ندارد.
اسلایدر با استفاده از تعیین مقدار range برای خصوصیت type عنصر <input> به دست میآید. پیکربندی صحیح اسلایدر حائز اهمیت بالایی است. به این منظور قویاً توصیه میشود که خصوصیتهای min، max و step تعیین شوند.
این مثال یک اسلایدر میسازد که مقدار آن میتواند در بازهای بین 0 و 500 تغییر پیدا کند و دکمههای افزایش/کاهش مقدار را به میزان 10+ و 10- تغییر میدهند.
یک مشکل اسلایدرها این است که هیچ نوع بازخورد بصری در مورد این که اسلایدر اکنون روی چه میزانی قرار دارد ارائه نمیکنند. شما باید خودتان با استفاده از جاوا اسکریپت این امکان را فراهم بسازید، اما اجرای آن هم چندان دشوار نیست. در این مثال ما یک عنصر خالی <span> اضافه میکنیم که در آن مقدار کنونی اسلایدر را نمایش داده و به محض تغییر آن را بهروزرسانی میکنیم.
این مثال را میتوان با استفاده از نوعی کد جاوا اسکریپت ساده پیادهسازی کرد:
در این مثال ارجاعی به ورودی بازه و span در دو متغیر ذخیره میکنیم و سپس بیدرنگ textContent این span را روی value کنونی ورودی تنظیم میکنیم. در نهایت یک دستگیره رویداد oninput تنظیم میکنیم به طوری که هر بار اسلایدر جابجا میشود، textContent این span به مقدار ورودی جدید بهروزرسانی شود.
ورودیهای range در اینترنت اکسپلورر نسخههای زیر 10 پشتیبانی نمیشوند.
گردآوری مقادیر تاریخ و زمان به طور سنتی یک کابوس برای توسعهدهندههای وب محسوب میشد. HTML5 برخی بهبودها در این زمینه ارائه کرد و کنترلهای خاصی برای مدیریت این نوع خاص از دادهها عرضه کرده است.
کنترل تاریخ و زمان با استفاده از عنصر input و یک مقدار مناسب برای خصوصیت type آن ایجاد میشود. این مقدار به این بستگی دارد که میخواهید تاریخ یا زمان و یا هر دوی آنها را دریافت کنید.
با استفاده از این مقدار یک ویجت ایجاد میشود که امکان انتخاب تاریخ و زمان را فراهم میسازد، اما این ویجت هیچ منطقه زمانی مشخصی ندارد.
این مقدار ویجتی را نمایش میدهد که میتواند یکی از ماههای سال را انتخاب کند.
این مقدار یک ویجت ایجاد میکند که با استفاده از آن میتوان زمانی را انتخاب کرد.
این مقدار ویجتی را نمایش میدهد که با استفاده از آن میتوان شماره هفته سال را انتخاب کرد.
همه کنترلهای تاریخ و زمان میتوانند با استفاده از خصوصیتهای min و max محدود شوند.
هشدار: ویجتهای تاریخ و زمان پشتیبانی عمیقی ندارند. در زمان نگارش این مقاله کروم، Edge، فایرفاکس و اپرا از آنها به خوبی پشتیبانی میکردند، اما اینترنت اکسپلورر و سافاری پشتیبانی ناقصی از آن داشتند.
مدیریت رنگ در صفحههای وب همواره دشوار بوده است. روشهای مختلفی برای نمایش آنها وجود دارد که شامل مقادیر RGB (دهدهی یا هگزادسیمال)، مقادیر HSL، کلیدواژه و غیره است. ویجت رنگ به کاربر امکان انتخاب رنگ را به روش متنی و همچنین بصری میدهد. ویجت رنگ با استفاده از تعیین مقدار color برای خصوصیت type عنصر <input> به دست میآید.
هشدار: ویجت رنگ در حال حاضر پشتیبانی مناسبی ندارد. اینترنت اکسپلورر اصلاً از آن پشتیبانی نمیکند و سافاری نیز تا زمان نگارش این مقاله از آن پشتیبانی نکرده است. البته مرورگرهای عمده دیگر از آن پشتیبانی میکنند.
چند ویجت دیگر نیز وجود دارند که آنها را نمیتوان به آسانی طبقهبندی کرد، زیرا رفتارهای خاصی دارند اما به هر حال مفید هستند.
فرمهای HTML5 میتوانند فایلها را به یک سرور ارسال کنند. ویجت انتخابگر فایل روش انتخاب یک یا چند فایل برای ارسال را مدیریت میکند.
برای ایجاد ویجت انتخابگر فایل، میتوانید با تعیین مقدار file برای خصوصیت type عنصر <input> استفاده کنید. نوع فایلهایی که قابل قبول هستند را میتوان با استفاده از خصوصیت accept تعیین کرد. به علاوه اگر میخواهید به کاربر امکان انتخاب بیش از یک فایل را نیز بدهید میتوانید این کار را با افزودن خصوصیت multiple انجام دهید.
در این مثال یک انتخابگر فایل ایجاد میشود که نیازمند فایلهای تصویری گرافیکی است. در این حالت کاربر مجاز است که چندین فایل را انتخاب کند.
به دلایل فنی برخی اوقات راحتتر است که برخی بخشهای دادهها در فرم ارسال شوند، اما به کاربر نمایش داده نشوند. به این منظور میتوان عناصر پنهانی در فرم تعبیه کرد. برای انجام این کار باید مقدار hidden در خصوصیت type عنصر <input> مورد استفاده قرار گیرد.
اگر چنین عنصری را ایجاد میکنید، لازم است که خصوصیتهای name و value را تعیین کنید:
کنترل «دکمه تصویر» (image button) کنترلی است که دقیقاً مانند یک عنصر <img> نمایش پیدا میکند به جز این که وقتی کاربر روی آن کلیک بکند، رفتاری مانند دکمه تحویل فرم دارد.
دکمه تصویر با استفاده از تعیین مقدار image برای خصوصیت type عنصر <input> به دست میآید. این عنصر دقیقاً از همان مجموعه خصوصیات عنصر <img> به علاوه همه خصوصیتهای مورد پشتیبانی از سوی دکمههای فرم دیگر پشتیبانی میکند:
اگر دکمه تصویر برای تحویل فرم استفاده شود، این ویجت مقدار خودش را ارائه نمیکند، بلکه به جای آن مختصات X و Y نقطه کلیک روی تصویر ارائه میشود. توجه کنید که مختصات بر اساس تصویر، نسبی هستند، یعنی گوشه بالا-چپ تصویر مختصات 0 و 0 را دارد. این مختصات به صورت جفت کلید/مقدر ارسال میشود:
بنابراین برای نمونه زمانی که روی تصویر این ویجت کلیک میکنید، یک URL مانند زیر ارسال میشود:
این یک روش کاملاً آسان برای ساخت یک hot map است.
مترها و نوارهای پیشروی بازنماییهای بصری از مقادیر عددی محسوب میشوند.
نوار پیشروی مقداری است که در طی زمان تا رسیدن به یک حد بیشینه تعیین شده در خصوصیت max تغییر پیدا میکند. چنین نواری با استفاده از عنصر <progress> ایجاد میشود.
از این نوار برای پیادهسازی هر چیزی که نیازمند گزارش پیشروی است، مانند درصد کل فایلهای دانلود شده یا تعداد سؤالهایی که در یک پرسشنامه پاسخ داده شدهاند، استفاده میشود.
محتوای درون عنصر <progress> یک fallback برای مرورگرهایی است که از این عنصر پشتیبانی نمیکنند و از فناوریهای حمایتی برای بیان صوتی آن استفاده میشود.
«نوار متر» (Meter Bar) نماینده یک مقدار ثابت دریک بازه است که به وسیله مقدار min و max نمایش پیدا میکند. این مقدار از نظر بصری به صورت یک نوار نمایش پیدا میکند و برای این که بدانید این نوار چگونه به نظر میرسد، مقدار آن را با برخی مقادیر تعیین شده دیگر مقایسه میکنیم:
همه مرورگرهایی که عنصر <meter> را پیادهسازی کردهاند، از مقادیر زیر برای تغییر رنگ نوار متر استفاده میکنند:
چنین نواری با استفاده از عنصر <meter> ساخته میشود. این عنصر میتواند برای پیادهسازی هر نوع متر مورد استفاده قرار گیرد. برای نمونه میتوان نواری ساخت که فضای کل مصرف شده دیسک را نمایش میدهد و زمانی که نزدیک پر شدن دیسک است قرمز میشود.
محتوای درون عنصر <meter> یک fallback برای مرورگرهایی است که از این عنصر پشتیبانی نمیکنند و به فناوریهای حمایتی برای بیان صوتی آن کمک میکند.
پشتیبانی از عناصر پیشروی و متر نسبتاً مناسب است، هر چند اینترنت اکسپلورر از آن پشتیبانی نمیکند اما مرورگرهای دیگر از آن به طور کامل پشتیبانی میکنند.
چنان که در این مقاله دیدیم، انواع بسیار متفاوتی از عناصر فرم وجود دارند و لازم نیست که همه این جزییات را یکباره به خاطر بسپارید. شما میتوانید هر زمان در آینده مجدداً به این مقاله مراجعه کنید و جزییات مورد نظر خود را مورد بررسی قرار دهید.
کار با پایتون در اغلب موارد به تنهایی خود یک نعمت محسوب میشود. افرادی که مدت زمان زیادی با پایتون کار کردهاند، غالباً اظهار میکنند که در کار با آن هیچ مشکلی ندارد، اما شاید آنها مجبور به کار با «صفحههای گسترده» (اسپردشیت) و فایل های اکسل در پایتون نشدهاند. پایتون ساختار آسانی برای نوشتن دارد و سبک دینامیک آن موجب شده که به گزینهای عالی برای مبتدیان تبدیل شود. اما مزیتهای آن به اینجا ختم نمیشود. پایتون میتواند در بسیاری از محصولات بزرگ مانند فریمورک Django استفاده شود و استفاده هم میشود.
جنگو قدرت برخی اپلیکیشنهای رسانهای مانند اینستاگرام را تأمین میکند. نمونههای دیگر شامل BitTorrent ،Google App Engine و Ubuntu Software Center هستند. حتی کارکردهای مرکزی یوتیوب نیز در پایتون نوشته شدهاند. همه این مثالها پایداری و مفید بودن پایتون را نشان میدهند.
پایتون یک زبان اسکریپتنویسی عالی است و توسعهدهندگان ترجیح میدهند از آن در مواردی استفاده کنند که قرار است با داده سروکار داشته باشند و آنها را دستکاری کنند. به طور خاص پایتون در مواردی مفید است که قرار است در یک پروژه دادههایی از محصولات گردآوری شده و به مشتریان گزارشدهی شود.
این کار نیازمند واکشی دادهها از پایگاه داده و دستکاری آنها به صورت یک فرم قابل ارائه است که به صورت کلی قالب «صفحه گسترده» است. در این نوشته به بررسی روش انجام این کار میپردازیم.
نکاتی که در این نوشته مطرح میشوند مختص افرادی هستند که با دادههای زیادی سروکار دارند و میخواهند آنها را در قالب صفحه گسترده یا اسپردشیت ارائه کنند. در مسیر انجام این کار چند مشکل وجود دارد که برخی از آنها را در اینجا مطرح میکنیم و روشهای رفع آنها را نیز توضیح میدهیم.
پکیجهای شخص ثالث زیادی برای کار با اسپردشیتها در پایتون وجود دارند. برخی از آنها شامل فهرست زیر هستند:
شاید اطلاع داشته باشید که اکسل دو پسوند فایل برای صفحههای گسترده ارائه کرده است که یکی xls. و دیگری xlsx. است. اولی برای فایلهایی با قالب مایکروسافت اکسل 2003 و قبلتر است و دومی برای نسخههای جدیدتر استفاده میشود.
نخستین مشکلی که در زمان کار کردن با صفحههای گسترده در پایتون پیش میآید این است که دو پسوند فایل مختلف وجود دارند. پکیج xlwt از پسوند xls. برای فایلهای اکسل پشتیبانی میکند و openpyxl نیز از پسوند xlsx. برای فایلهای اکسل پشتیبانی میکند.
در ادامه شیوه استفاده از پکیج xlwt را برای کار کردن با صفحههای گسترده توضیح میدهیم. شما میتوانید این پکیج را با اجرای دستور زیر روی ترمینال یا اعلان فرمان، نصب کنید:
pip install xlwt
توجه کنید که باید pip روی سیستم شما نصب باشد. برای نصب pip از دستورالعملهای این مطلب استفاده کنید:
در این مطلب از xlwt نسخه 1.3.0 استفاده شده است. پس از این که کار نصب پکیج کامل شد یک ویرایشگر متنی باز کنید و یک فایل جدید ایجاد کرده و نامی که دوست دارید را به آن بدهید. ما نام فایل خود را excelScript.py گذاردهایم.
درون این اسکریپت کد زیر را بنویسید:
کد فوق یک فایل اکسل خالی با نام Sample.xls ایجاد میکند که شامل یک برگه منفرد با عنوان Sheet 1 است. این برگه نمونهای از ایجاد فایل ساده xls. است. اسکریپت فوق را میتوانید به صورت زیر در خط فرمان اجرا کنید:
python excelScript.py
برای نوشتن دادهها در برگه اکسل، کد را به صورت زیر تغییر دهید:
بدین ترتیب عبارت sample در ردیف صفر و ستون صفر نوشته میشود. به خاطر بسپارید که پکیج xlwt اندیسهای ردیفها و ستونها را از صفر آغاز میکند. بدین ترتیب میتوانیم هر تعداد برگه که میخواهید در فایلهای اکسل بنویسید. این اسکریپت را با استفاده از دستور زیر در خط فرمان اجرا کنید:
python excelScript.py
این یک روش رایج برای نوشتن اکسل با استفاده از پکیج xlwt است که در آن میتوانید ستونها و ردیفها را ادغام کنید. شما میتوانید استایل نیز تعیین کنید. کد زیر روش انجام این کار را نشان میدهد:
بدین ترتیب ستونهای (0,1) و ردیفهای (0,1) ادغام میشوند تا یک ستون منفرد تشکیل دهند و sample 1 در آن نوشته میشود که در جهات افقی و عمودی به صوت مرکزی همراستا شده است. xlwt.easyxf کار استایل دادن را برای شما انجام میدهد. اگر فایل xls را باز کنید، نمونه قبلاً نوشته شده را میبینید. برای کسب اطلاعات بیشتر در مورد متدهای ارائه شده از سوی پکیج xlwt میتوانید به صفحه مستندات آن (+) مراجعه کنید.
توجه داشته باشید که اگر از xlwt استفاده کنید و فایلی با همان نام وجود داشته باشد در این صورت فایل جایگزین خواهد شد. رویه فوق محدودیتهایی نیز دارد، زیرا میتوانید تنها 65536 ردیف و 256 ستون در نسخههای قدیمی اکسل ایجاد کنید. به طور مشابه در زمان استفاده از این پکیج نیز تنها میتوانید این تعداد ردیف و ستون ایجاد کنید. اگر میخواهید دادههای بیشتر از این مقدار بنویسید، در این صورت متأسفانه این پکیج نمیتواند به شما کمک کند و باید از پکیج پایتون دیگری به نام openpyxl (+) استفاده کنید.
در زمان کار با پکیج xlwt متوجه شدیم که ایجاد فایلهای xls. بسیار آسان است، اما اگر از قبل یک فایل xls. داشته باشیم و بخواهیم دادههای جدیدی به فایل موجود الحاق کنیم چطور؟ در چنین حالتی پکیج xlwt مناسب نخواهد بود و باید این مشکل را رفع کنیم. توجه داشته باشید که اگر یک فایل xls. داشته باشید در این صورت نمیتوانید از openpyxl استفاده کنید که از الحاق دادهها به فایلهای موجود پشتیبانی میکند، زیرا این پکیج با نسخههای قدیمی فایلهای اکسل ناسازگار است.
برای حل این مشکل به دو پکیج دیگر پایتون نیاز داریم. برای نمونه پکیج xlrd برای خواندن فایل اکسل و پکیج xlutils برای ایجاد یک کپی از شیء اکسل درون شیء xlwt است به طوری که بتوان درون آن چیزی نوشت. برای نصب این پکیجها دستورهای زیر را اجرا کنید:
pip install xlrd pip install xlutils
برای الحاق دادهها به یک فایل موجود xls. با استفاده از xlwt، رویه زیر میتواند مورد استفاده قرار گیرد. در فایل excelScript.py، کد را به صورت زیر تغییر دهید:
زمانی که این اسکریپت را با استفاده از دستور زیر اجرا کنید:
python excelScript.py
و فایل اکسل ایجاد شده را باز کنید، متوجه خواهید شد که sample 1 در فایل xls. موجود قبلی نوشته شده است و sample 2 و sample 3 نیز به آن فایل اضافه شده است. این همان کارکردی است که به آن نیاز داریم. در ادامه روش اجرای آن را توضیح میدهیم.
سیر وقایعی که اتفاق میافتند به صورت زیر است. ابتدا فایل با استفاده از پکیج xlrd خوانده میشود و در یک متغیر به نام rb در قالب یک شیء ذخیره میشود. سپس این شیء با استفاده از متد copy در پکیج xlutils درون یک متغیر wb کپی میشود. این بدان معنی است که در بازهای از زمان هر دو متغیر rb و wb حاوی دادههای شیء یکسانی خواهند بود. اکنون با استفاده از اندیس صفر به برگه نخست اکسل دسترسی داریم و دادههای شیء آن را درون متغیر sheet ذخیره میکنیم. همچنین در این زمان میتوانیم از همه ظرفیتهای کارکردی پکیج xlwt برای ذخیره نهایی برگه اکسل با همان نام قبلی یعنی sample.xls استفاده کنیم.
اگر مطالب فوق را به دقت پیگیری کرده باشید، در این صورت احتمالاً متوجه شدهاید که دادهها در عمل واقعاً به فایل موجود الحاق نشدهاند. در واقع کاری که ما انجام دادیم این است که دادههای فایل موجود را با استفاده از xlrd درون حافظه کپی کردهایم، پس آنها را با استفاده از متد copy از پکیج xlutiles درون فایل اکسل جدیدی نوشتهایم و در نهایت دادههای جدید را در فایل جدید اکسل نوشتهایم و آن را با همان نام قبلی ذخیره کردهایم تا روی فایل قبلی بازنویسی شود.
در صورتی که با فایلهای قدیمی xls. کار میکنید، شاید این روش چندان مناسب نباشد و قضیه به همین جا ختم نمیشود. همه این موارد که طرح شد به کار با فایلهای xls. مربوط میشوند، اما گر بخواهیم همین کار را روی فایلهای xlsx. انجام دهیم باید از پکیج openpyxl استفاده کنیم.
در ادامه به بررسی استفاده از پکیج پایتون openpyxl برای ایجاد صفحههای گسترده در قالب xlsx. میپردازیم. چنان که پیشتر گفتیم، اگر دادههای زیادی در فایل خود داشته باشید و مشتریهای زیادی وجود داشته باشند که قرار باشد به همه آنها گزارش دهیم در این صورت دانستن روش کار با قالبهای xls. و xlsx. به عنوان قالبهای قدیمی و جدید ذخیره فایل اکسل مهارت مناسبی است که در اغلب موارد به کار شما میآید.
پکیج openpyxl (+) یک کتابخانه پایتون برای خواندن و نوشتن فایلهای xlsx/xlsm/xltx/xltm است.
بدین ترتیب تنها با استفاده از یک پکیج میتوان دادهها را خواند، نوشت و الحاق کرد. این پکیج را میتوان با استفاده از دستور زیر در ترمینال یا اعلان فرمان نصب کرد:
pip install openpyxl
توجه کنید که pip باید روی سیستم نصب باشد. پس از این که نصب پکیج پایان یافت، ویرایشگر متنی را باز کنید تا یک فایل جدید ایجاد کنید و نامی که دوست دارید را روی آن بگذارید. ما فایل خود را excelScript.py نامیدیم. درون اسکریپت کد زیر را بنویسید:
کد فوق یک فایل اکسل خالی به نام Sample.xlsx ایجاد میکند که شامل یک برگه منفرد به نام sheet 1 است. این برگه نمونهای از فرایند ایجاد یک فایل xslx. است. اسکریپت زیر را با وارد کردن دستور زیر در خط فرمان اجرا کنید:
python excelScript.py
زمانی که این فایل xlsx. را باز کنید، میبینید که به جای یک برگه، دو برگه در فایل ایجاد شده است. دلیل رخ دادن این وضعیت آن است که در زمان ایجاد یک شیء با متد ()Workbook در پکیج openpyxl، این متد به طور پیشفرض به محض فراخوانی یک برگه به نام sheet ایجاد میکند.
اگر نامهای برگهای که روی آن کار میکنید، برایتان مهم نیست میتوانید مستقیماً روی همین برگه کار کنید و نیازی به ایجاد برگه دیگر وجود ندارد. اگر کارتان طوری است که باید حتماً از یک برگه استفاده کنید، میتوانید مستقیماً شروع به نوشتن در این برگه بکنید. در ادامه شیوه حذف برگه پیشفرض Sheet از فایل xlsx. را آموزش خواهیم داد. برای نوشتن دادهها در اکسل کد را به صورت زیر تغییر دهید:
کد فوق عبارت sample را در ردیف اول و ستون اول وارد میکند. به خاطر داشته باشید که پکیج openpyxl اندیسهای ردیف و ستون را با شروع از یک میخواند. بدین ترتیب میتوانید در فایل اکسل بنویسید و هر تعداد برگه که دوست دارید ایجاد کنید. اسکریپت فوق را با وارد کردن دستور زیر در خط فرمان اجرا کنید:
python excelScript.py
همچنین میتوانید به آن استایل نیز بدهید. کد زیر روش انجام این کار را به شما نشان میدهد:
بدین ترتیب عبارت sample در ردیف اول و ستون اول درج میشود. این سلول از جهات افقی و عمودی به صورت مرکرگزا همراستا شده است. برای کسب اطلاعات بیشتر در مورد متدهای ارائه شده از سوی پکیج openpyxl به مستندات آن (+) مراجعه کنید.
همچنین همانند کاری که با استفاده از xlwt انجام دادیم، میتوانید با استفاده از openpyxl نیز سلولها را در هم ادغام کنید. کد زیر روش ادغام سلولها را با استفاده از openpyxl نشان میدهد:
کد فوق شیوه ادغام سلولها را هنگامی نشان میدهد که نام سلولهایی که باید ادغام شوند را به طور کامل میدانید. مثلاً در کد فوق میدانستیم که نام سلول ستون اول و ردیف اول A1 و نام سلول ستون سوم و ردیف اول C1 است. در این حالت آنها را مستقیماً با استفاده از متد merge_cells در پکیج openpyxl ادغام میکنیم. این یکی از دو متدی است که در openpyxl برای ادغام سلولها استفاده میشود. متد دوم نیز به صورت زیر عمل میکند:
این متد زمانی به کار میآید که دادهها به صورت دینامیک در فایل اکسل نوشته شده باشند. اگر مطمئن نیستید که نام دقیق سلولهایی که قرار است ادغام شوند چه هستند، در این صورت میتوانید از این متد استفاده کنید. این متد سه ستون اول از سه ردیف اول را در یک سلول منفرد ادغام میکند.
زمانی که سلولها را ادغام میکنید، همواره به خاطر داشته باشید که باید مقدار را درون ستون اول سلول ادغام شده وارد کنید، چون در غیر این صورت مقدار مورد نظر از فایل اکسل حذف میشود. شما میتوانید استایل سلول ادغام شده را به طرز مشابهی که قبلاً نشان دادیم اعمال کنید. اکنون نوبت به بررسی روش حذف برگه اضافی میرسد که به طور پیشفرض با فراخوانی متد ()Workbook کتابخانه openpyxl ایجاد شده است. روش انجام کار به صورت زیر است:
در این کد ما برگهای با نام Sheet را با استفاده از متد ()get_sheet_by_name در یک شیء قرار میدهیم و سپس آن را در متغیر extraSheet ذخیره کرده و در نهایت برگه را با استفاده از فراخوانی متد ()remove_sheet روی متغیر extraSheet حذف میکنیم. بدین ترتیب با مراحل ایجاد یک فایل جدید xlxs.، نوشتن آن، ادغام سلولها و استایلدهی آن آشنا شدیم. اکنون به بررسی روش خواندن و الحاق دادهها در فایل xlsx. با استفاده از پکیج openpyxl میپردازیم.
قبل از هر چیز روش خواندن فایل xlsx. را با استفاده از openpyxl بررسی میکنیم. همانند روش نوشتن میتوان از ()openpyxl.load_workbook برای باز کردن یک ورکبوک موجود استفاده کرد:
کد فوق همه سلولهای نوشته شده در فایل اکسل را نمایش میدهد. حلقه for به جای 0 از 1 آغاز میشود چون openpyxl اندیسگذاری را از 1 آغاز میکند. همچنین میتوان سلولها را با استفاده از نام سلولها نیز خواند:
ما [cells[0 را انتخاب کردیم، زیرا [‘sheet[‘A1:C1 یک چندتایی از چندتاییها ایجاد میکند و همه اشیای سلول در اندیس 0-ام چندتایی ذخیره شدهاند، لذا [cells[0 را میخوانیم. در نهایت با روش الحاق دادهها به فایل xlsx. آشنا میشویم. کد زیر فرایند این کار را نشان میدهد:
در واقع فرایند کار بسیار آسان است. کافی است فایل xlsx. موجود را درون یک شیء بارگذاری کنید و آن را با فراخوانی متد روی فایل Sample.xlsx در متغیر book ذخیره کنید. سپس برگه sample را با فراخوانی متد ()get_sheet_by_name روی شیء book به دست میآوریم.
اکنون میتوانیم همانند روش ایجاد یک فایل جدید، به سادگی شروع به الحاق دادهها روی برگه بکنیم. همه آن متدهایی که در زمان ایجاد فایل در اختیار ما بودند، هم اینک نیز موجود هستند. در نهایت زمانی که کار نوشتن دادهها در فایل را انجام دادیم، نباید فراموش کنیم که فایل را با فراخوانی متد ()save ذخیره کنیم.
به علاوه فراموش نکنید که در زمان کدنویسی از کدهای زیباتری استفاده کنید و استانداردهای PEP8 را رعایت کنید تا کد شما خواناتر باشد. پیش از عرضه کد خود از PyLint استفاده کنید. بدین ترتیب میتوانید یک استاندارد کدنویسی در پروژه خود نگهداری کنید.
در این نوشته به معرفی روشهای مختلف کار با فایلهای صفحه گسترده در پایتون پرداختیم، اما کار به همین جا ختم نمیشود. اینها تنها مبانی مقدماتی روش خواندن، نوشتن و الحاق دادهها در فایلهای xls. و xlsx. بودند. شما باید این پکیجها را مورد بررسی بیشتر قرار دهید و بر اساس الزامات خود بسته به حالتی که دادهها را در فایلهای اکسل نمایش میدهید، الگوریتمهای خاص خود را بنویسید.
این بخش هجدهم و پایانی سری مقالات آموزش زبان سوئیفت مجله فرادرس محسوب میشود. شما با مطالعه هفده بخش قبلی این سری مقالات آموزش زبان برنامهنویسی سوئیفت با مبانی این زبان آشنا شدید. اینک و با مطالعه این بخش با موضوع معماری MVC میتوانید شروع به نوشتن عملی اپلیکیشنهای خود بکنید. در بخش قبلی این سری مقالات در مورد نوشتن تست صحبت کردیم. برای مطالعه آن به لینک زیر مراجعه کنید:
آموزش سوئیفت (Swift): نوشتن تست — بخش هفدهم
اینک باید چند سؤال از خود بپرسید.
ما در این مقاله به دو سؤال نخست پاسخ میدهیم. این مقاله به این منظور نوشته شده است که شیوه استفاده مؤثر از معماری MVC را به شما آموزش دهد. MVC اختصاری برای عبارت «مدل، نما، کنترلر» (Model-View-Controller) است.
در مورد سؤال سوم باید گفت که این موضوع به تجربه شما در زمینه برنامهنویسی وابسته است. اگر شما قبلاً زبان دیگری را بلد بودهاید، احتمالاً اینک پاسخ این سؤال را میدانید، اما به عنوان سطح مقدماتی پیشنهاد میشود، دست کم 20 برنامه یا دست کم یک برنامه با قابلیتهای کامل در سوئیفت نوشته باشید.
اگر به تازگی وارد دنیای برنامهنویسی شدهاید و این نخستین راهنمایی است که مطالعه کردهاید شما نباید برای این جایگاه شغلی اقدام کنید. حتی اگر این شغل را به دست بیاورید هم، آنها از شما چیزهایی خواهند خواست که هنوز نیاموختهاید و این فرایند دشواری خواهد بود. مثلاً ممکن است از شما خواسته شود «دادههایی را از یک URL دانلود کنید، پاسخ JSON را تحلیل کنید، سپس آن را در فایل plist ذخیره کرده و در قالب مورد نظر عرضه کنید.» بنابراین بهتر است اقدام به درخواست این شغل نکنید.
نکته دیگری که باید اشاره کنیم این است که گرچه وبسایتهایی مانند HackerRank و CodeWars وجود دارند که به ارتقای مهارتهای برنامهنویسی کمک میکنند، اما تمرکز اولیه آنها پیرامون الگوریتمها است. البته هیچ اشکالی در کار این وبسایتها نیست، اما فکر کنید آخرین باری که نیازمند استفاده از الگوریتم اقلیدسی برای انجام تکالیف خود بودید چه زمانی بوده است، همچنین خواندن فایل، تحلیل نتایج یک پاسخ وب و کارهای دیگر نیز به همین منوال است.
در این وبسایتها میتوان چیزهای مفیدی مانند لیستهای پیوندی، صفها، پشتهها، درختهای دودویی، درختها و غیره را آموخت و همه این موارد کمک میکنند که در مورد روش حل مسائل به روشهای کارآمدتری فکر کنید. این وبسایتها به طور کلی مفید و جالب هستند و روشهای خوبی برای ارتقای دانش شما در زمانی که مشغول کار روی پروژهای نیستید ارائه میکنند. همچنین میتوانید کار با زبانهای دیگر را نیز امتحان کنید.
MVC جایی است که تقریباً همه افراد در زمان نوشتن نخستین اپلیکیشن خود از آنجا شروع میکنند. استفاده از آن آسان و درکش ساده است و موجب میشود که کد شما زیبا و منسجم بماند و همچنین سرنخهایی در مورد روش تجزیه کد و تمیز نگهداشتن آن به دست میدهد.
بنابراین در این بخش در مورد این معماری صحبت میکنیم. زمانی که کلمه معماری را میشنوید به احتمال زیاد به یاد ساختمانها و پلها میافتید که البته آن معنایی نیست که در دنیای برنامهنویسی دارد.
معماری یک اپلیکیشن تنها ساختار پوشه پروژه را تعریف نمیکند، بلکه شیوه تعامل هر کلاس با کلاسها و ماژولهای دیگر را نیز تعریف میکند. برای نمونه ممکن است لازم باشد که به یک کلاس بازیابی فایل اجازه دهیم با کلاسهایی کار کند که دادههای درون فایلها را دستکاری میکنند. اما این وضعیت شاید برای کلاس دستکاری دادهها که با کلاسهایی کار میکند که مسئول طراحی رابط کاربری (UI) هستند مناسب نباشد، چون میزان جدایی آنها زیاد است.
ایده نهفته در پس این معماری این است که نهادهای مختلف باید تنها در معرض دید چند عنصر معدود پیرامون خود باشند. نماها باید تنها مسئول کار با UI باشند، مدلها باید تنها مسئول ذخیرهسازی، قالببندی و بازیابی دادهها باشند و کنترلرها نیز صرفاً باید مسئول مسیریابی دادهها از مدل به نما باشند.
اغلب افراد به این بخش از توضیح معماری MVC که میرسند به ارائه یک تصویر متوسل میشوند اما ما چنین قصدی نداریم. ما قصد داریم هر بخش را با ارائه یک مثال توضیح دهیم و سپس تصویر را در انتها نمایش دهیم.
مدلها اساس کلاسها و سازههایی پر از مشخصه و متد هستند که برای ذخیره، قالببندی و بازیابی دادههای برنامه استفاده میشوند. زمانی که به یک مدل فکر میکنید، باید آن را به صورت یک رکورد منفرد در پایگاه داده تصور کنید. در ادامه مثالی از یک مدل را میبینید:
این تنها یک مثال است و به صورت معمول شما میخواهید کاری بیش از این مانند دریافت به دست آوردن حالت صحیح نام اختصاری یک ایالت یا قالببندی کد پستی را انجام دهید.
شما میتوانید این مدخل را بردارید، آن را به یک آرایه از مدخل در کلاس دیگر PhoneBook در یک فایل دیگر اضافه کنید. جای نگرانی نیست چون تا زمانی که خصوصیت دسترسی مناسبی تنظیم کرده باشید، میتوانید از این کلاس در فایلهای دیگر استفاده کنید به طوری که گویی در همان فایل قرار دارد.
«نماها» (Views) برای نگهداری منطقی که دادهها روی صفحه نمایش میدهند مورد استفاده قرار میگیرند. این منطق میتواند یک شکل رسم شده خاص، یک سلول نمای جدولی سفارشی یا یک ظاهر دکمه سفارشی باشد. این همان کدی است که منطق رسم و خروجی (IBOutlet) مورد استفاده از سوی نما را نگهداری میکند. به طور معمول، نماها زیرکلاسهایی از IView ،UITableViewCell یا UIButton هستند، اما میتوانند هر چیزی باشند که صرفاً برای نمایش اشیا روی صفحه استفاده میشوند.
iOS شهرت بدی در مورد داشتن کنترلرهای سنگین دارد و واقعاً هم میتوانند گسترده باشند. کنترلرها جایی هستند که منطق در اپلیکیشن شما اتفاق میافتد و دادهها را از مدلهای شما گرفته و آنها را در نماها مقداردهی میکند. زمانی که این معماری به درستی اجرا شود، نماها هیچ ایدهای در مورد مدل و حتی وجود آن نخواهند داشت و مدل نیز نمیداند که دادهها چگونه مقداردهی میشوند.
کنترلرها در iOS به وسیله پسوند ViewController مشخص میشوند. بدین ترتیب SearchViewController یک کنترلر و SearchView یک نما و Items میتواند یک مدل باشد.
اگر به مثال دفترچه تلفن بازگردیم، میبینیم که دفترچه تلفنی به عنوان مدل خود داریم. این دفترچه تلفن شامل آرایهای از مدخلها است. کنترل ما میتواند مسئول اعلان کردن وهلهسازی از دفترچه تلفن و واکشی دادهها از مدخل دفترچه تلفن باشد که نما به آن نیاز دارد. پس از این که دادهها بازیابی شدند، میتوانیم خروجیها را درون نما مقداردهی کرده و نما را عرضه کنیم. اگر کاربر شماره تلفن فردی را تغییر دهد، نما به کنترل اطلاع میدهد و کنترلر اقدام به مدیریت ارسال دادهها به مدل از طریق فراخوانی یکی از متدهای بهروزرسانی و ارسال دادههای تغییریافته به آن میکند.
متد بهروزرسانی درون کلاس مدل، مسئول قالببندی دادهها است تا بتواند آنها را ذخیره کرده و در ادامه بازیابی کند. این بدان معنی است که اگر شماره تلفن کاربر در قالب 123.456.7890 باشد، باید نقطهها را از آن جدا کنیم تا بتوانی آن را در ادامه در قالبی که در همه جا به صورت یکنواخت استفاده میشود بازیابی کنیم.
تنها مقصود نما، نمایش اطلاعات به کاربر است و از این رو نماهای iOS کاملاً ساده هستند. این نماها از چیزی خارج از حوزه نمایش UI و اطلاعرسانی به کنترلر بیاطلاع هستند.
کارکرد مدل تا حدود زیادی شبیه به منشی است و صرفاً دادهها را منظم حفظ میکند. مدل وظیفه مهم نگهداری دادهها را بر عهده دارد. مدلها الزاماً به ذخیرهسازی دادهها نمیپردازند، بلکه ارجاعی برای ارائه قالببندی دادهها ارائه میکند که در پایگاه داده ذخیره میشوند.
وظیفه کنترلر ارسال دادهها بین مدل و نما است. این کار ساده به نظر میرسد، اما گاهی اوقات منطق زیادی وجود دارد که باید به این منظور اتفاق بیفتد. برای نمونه کنترلر باید یک ارجاع به هر مدلی که نما کنترل میکند نگهداری کند و از همه متدهای کلاس برای اجرای بهروزرسانی و بازیابیها استفاده کند. در ادامه میتوانید تصویری که وعدهاش را داده بودیم ببینید:
شما نباید اجازه بدهید مدلها با نماها صحبت کنند. از نماها صرفاً جهت نمایش محتوا برای کاربر استفاده کنید، از مدلها برای ذخیرهسازی دادهها استفاده کنید و از کنترلرها برای مدیریت منطق بین این دو بهره بگیرید.
MVC یک نقطه شروع خوب برای هر اپلیکیشنی که میخواهید بنویسید محسوب میشود. البته الگوهای معماری دیگری نیز وجود دارند که میتوان استفاده کرد، اما این سادهترین معماری است که میتوان در آغاز مورد استفاده قرار داد. ممکن است وسوسه شوید که از معماری متفاوتی استفاده کنید، اما باور کنید معماریهای دیگر بسیار دشوارتر هستند.
شما باید معماری را بر مبنای نوع اپلیکیشن انتخاب کنید. نباید بگویید من میخواهیم این اپلیکیشن را با معماری فلان بنویسم. زمانی که افراد چنین چیزی را میگویند خود را به زحمت میاندازند، چون در اغلب موارد اپلیکیشن آنها به چیزی بیش از MVC نیاز ندارد. ای بدان معنی نیست که باید گزینههای دیگر را کلاً کنار بگذاریم، بلکه منظور ما این است که در آغاز از MVC برای بررسی طرز کار اپلیکیشن خود استفاده کنید و سپس اگر دیدید نمیتوانید پاسخ مناسبی دریافت کنید و حجم بیشتر کار به مزیتهایی که ارائه میکرد میارزید، از معماریهای پیچیدهتر استفاده کنید.
بدین ترتیب به پایان این سری مقالات آموزش سوئیفت میرسیم. اما شما فرایند یادگیری خود را متوقف نکنید، و تلاش کنید از منابع دیگر برای آموزش موارد بیشتر کمک بگیرید.
منبع: فرادرس
پیش از آنکه پشتیبانی از عبارتهای لامبدا در نسخه JDK8 به جاوا اضافه شود، ما تنها در زبانهایی مانند #C و ++C از آنها استفاده کرده بودیم. اینک که این قابلیت به جاوا اضافه شده است باید نگاهی دقیقتر به آنها بیندازیم. اضافه شدن عبارت های لامبدا در جاوا موجب اضافه شدن عناصر ساختاری دیگری به این زبان شده است که توان بیان عبارتها را در جاوا بالا برده است. در این مقاله میخواهیم روی مبانی مقدماتی که برای آغاز کار با عبارتهای لامبدا در کدهای مدرن نیاز دارید تمرکز کنیم.
عبارتهای لامبدا از مزیت ظرفیتهای پردازش موازی محیطهای چند نخی چنان که در پشتیبانی از عملیات pipeline روی دادهها در API Stream دیدهایم استفاده میکنند. برخی متدهای بینام وجود دارند که برای پیادهسازی متد تعریف شده از سوی یک اینترفیس تابعی استفاده میشوند. پیش از آشنا شدن با عبارتهای لامبدا باید با مفهوم اینترفیس تابعی آشنا شوید.
اینترفیس تابعی اینترفیسی است که شامل یک و تنها یک متد مجرد است. اگر نگاهی به تعریف اینترفیس Runnable استاندارد جاوا بکنید، متوجه خواهید شد که در تعریف اینترفیس تابعی قرار میگیرد، زیرا تنها یک متد یعنی ()run را تعریف میکند. در قطعه کد نمونه زیر متد computeName به صراحت مجرد است و تنها متد تعریف شده است که موجب میشود MyName یک اینترفیس تابعی باشد.
عبارتهای لامبدا عملگر جدید arrow را به صورت (<-) در جاوا معرفی کردهاند. و این عملگر عبارت لامبدا را به دو بخش تقسیم میکند:
(n) -> n*n
سمت چپ پارامترهای مورد نیاز عبارت را تعیین میکند که در صورت عدم نیاز به پارامتر میتواند خالی هم باشد. سمت راست بدنه لامبدا است که اقدامات عبارت لامبدا را تعیین میکند. این عملگر را میتوان به صورت «تبدیل میشود» ترجمه کرد. برای نمونه در مثال فوق «n تبدیل میشود به n*n» یا «n تبدیل میشود به جذر n.» با استفاده از اینترفیس تابعی و عملگر arrow میتوانید یک عبارت لامبدای ساده را کنار هم قرار دهید:
متغیرهای morningGreeting و eveningGreeting در خطوط 6 و 7 فوق ارجاعی به اینترفیس MyGreeting دارند و عبارتهای خوشامدگویی مختلفی را تعریف میکنند. زمانی که یک عبارت لامبدا مینویسیم امکان تعیین صریح نوع پارامتر در عبارت به صورت زیر نیز وجود دارد:
تا به اینجا، نمونههایی از لامبداهای عبارت منفرد را مورد بررسی قرار دادیم. نوع دیگری از عبارت نیز وجود دارد که هنگامی استفاده میشود که کد سمت راست عملگر arrow شامل بیش از یک گزاره باشد که به نام «لامبدای بلوکی» (block lambdas) شناخته میشود:
عبارت لامبدا نمیتواند ژنریک باشد. اما اینترفیس تابعی مرتبط با عبارت لامبدا میتواند چنین باشد. امکان نوشتن یک اینترفیس تابعی و مدیریت انواع بازگشتی مختلف به صورت زیر وجود دارد:
یکی از استفادههای رایج از لامبداها برای ارسال آنها به صورت آرگومان است. میتوان از آنها در هر قطعه کدی که یک نوع هدف ارائه میکند استفاده کرد. این وضعیت کاربردهای جالبی دارد، زیرا امکان ارسال کد قابل اجرا را به عنوان آرگومان به متدها فراهم میکند. برای ارسال عبارت لامبدا به صورت پارامتر، باید مطمئن شوید که نوع اینترفیس تابعی با پارامتر مورد نیاز مطابقت دارد:
مفاهیمی که در این مقاله بررسی کردیم، یک نقطه شروع مناسب برای یادگیری عبارتهای لامبدای جاوا در اختیار شما قرار میدهند. بدین ترتیب، میتوانید کدهای خود را بررسی کنید تا ببیند کجا قادر هستید توان کدنویسی جاوا را افزایش دهید.