شنبه, ۴ شهریور ۱۳۸۵
FarsiType ورژن ۱.۲ و حل مشکل تایپ فارسی در فرمهای وب در Opera!
FarsiType ورژن ۱.۲ و حل مشکل تایپ فارسی در فرمهای وب در Opera!
اسکریپتهایی که در حال حاضر برای اضافه کردن امکان تایپ فارسی در فرمهای وب مورد استفاده قرار میگیرند، دارای ۲ مشکل هستند:
اول اینکه بخاطر استفاده از رویدادهای onkeypress یا onclick یا… و اینکه این رویداد/خصوصیتها دیگر در استانداردهای وب جایی ندارند، نمیتوان صفحاتی که امکان تایپ فارسی را در آنها قرار دادهایم، استاندارد کنیم.
مشکل دوم اینکه تنظیم این امکانات با توجه به کارهایی که باید انجام شود، میتواند گیج کننده باشد.
برای اینکه کار را راحتتر کنیم، استاندارد بمانیم و باگ نداشته باشیم(!!!!)، اسکریپت تایپ فارسی را جور دیگری بازنویسی کردم!
اطلاعات بیشتر و جزئیات را میتوانید در صفحهی FarsiType مشاهده کنید.
احتمالا این TextBoxهای فرمها روی وب رو دیدین که امکان تایپ فارسی دارن! (مثلا فرم ارسال کامنت همین وبلاگ یا اکثر وبلاگها و وبسایتها). احتمالا هم میدونین که این فرمها فقط در Internet Explorer درست کار میکنه و در FireFox و… نه! مدتی پیش تلاشهایی برای اینکه این موضوع در FireFox هم کار کنه صورت گرفت اما به نتیجهای نرسید! این روزها روی پروژهای کار میکردم و میخواستم از این امکانات استفاده کنم. از اونجایی که وقت اضافه و بیخودی وسط انجام پروژه هم خیلی زیاد داشتم!!!! تصمیم گرفتم کمی وقت روی این کار بگذارم. مشکل حل شد! این و این!
راهنمای ساده برای تایپ فارسی در فرمها + حل مشکل تایپ فارسی در فایرفاکس.
همانطور که توسعهدهندگان وب که استاندارد سازی صفحات وب را مورد توجه قرار میدهند میدانند، در HTML 4.0 Strict و XHTML 1.0 Strict طبق نظر W3C دیگر شناسه target در تگ <a> معتبر نیست و وجود ندارد. البته ورژنهای Transitional هنوز شامل این شناسه هستند اما این تعاریف خود در حال کنار گذاشته شدن هستند!
استانداردهای وب شاید براساس ایدهالهایی نوشته میشود که به ذهن میآید. این ایدهها گرچه با هدف “انجام کار به بهترین شکل” وضع میشوند اما در عمل ممکن است با واقعیتهای امروز وب سازگاری نداشته باشند. یکی از دلایل اصلی حذف شناسه target این است که معتقدند html باید تنها به اطلاعاتی که در یک پنجره نمایش داده میشود رسیدگی کند.
یکی از مشکلات اصلی در استاندارد کردن صفحات وب اینجاست که استفاده اصلی شناسه target که باز شدن یک لینک در پنجره یا tab جدید با استفاده از target=_blank است، همچنان در صفحات امروزی پر کاربرد است و استانداردها میگوید نباید از آن استفاده کنیم! این نوشته پاسخ به این سوال است که چگونه لینکها را در صفحات جدید باز کنیم و استانداردها را نیز رعایت کنیم…
با استفاده از برنامهنویسی سمت کلاینت و مشخصا JavaScript میتوانیم به این هدف دست یابیم. اولین سوالی که به ذهن میرسد این است: در شرایطی که نمیتوانیم از شناسه target استفاده کنیم، چگونه مشخص کنیم که میخواهیم کدام لینکها در صفحات جدید باز شود؟!
گرچه در استانداردهای جدید شناسه target حذف شده اما بهجای آن شناسهای با عنوان rel (مخفف Relationship) اضافه شده است. این شناسه در واقع قرار است در یک مستند، رابطهی بین صفحه جاری و صفحهای که پیوند به آن زده شده را مشخص کند. مقادیر تعریف شدهای که این شناسه میتواند بگیرد (next, previous, chapter, section و…) این وظیفه را برعهده دارند. کاری که ما میخواهیم انجام دهیم، استفاده از مقداری غیر معتبر برای شناسه rel برای مشخص کردن لینکهاییست که میخواهیم در پنجره جدید باز شود! برای این لینکها شناسه rel را با external مقداردهی میکنیم. در نتیجه لینکهایی که میخواهیم در صفحه جدید باز شود بصورت زیر خواهد بود.
قبلا:
<a href="document.html" target="_blank">external link</a>
از این به بعد:
<a href="document.html" rel="external">external link</a>
پیش از این مرورگرها با دیدن مقدار شناسه target میدانستند چگونه باید رفتار کنند اما اکنون مقدار داده شده به شناسه rel برای آنها بیمفهوم است. فعلا لینکهای مورد نظر را با در نظر گرفتن استانداردها نشانهگذاری کردیم. حالا با استفاده از جاواسکریپت باید آنها را در صفحات جدید باز کنیم!
وظیفهی اسکریپت ما این است که لینکهایی که مقدار شناسهی rel آنها برابر external است را در یک پنجره جدید باز کند! این اسکریپت فقط یکبار و در زمانی که load صفحه تمام شد اجرا خواهد شد.
getElementsByTagName یک متد پرکاربرد DOM 1.0 است که توسط تمام مرورگرهای جدید شناخته میشود.
var anchor = document.getElementsByTagName('a');
متغیر anchor آرایهایست که هر المان آن معرف یک تگ <a> در متن است (در واقع این آرایه به تعداد لینکهای صفحه عنصر خواهد داشت!). اکنون لازم است عناصر آرایه را در جستجوی لینکهایی که باید در صفحهی جدید باز شوند پیمایش کنیم.
for (var i="0"; i<anchor.length; i++) {
برای پیدا کردن این لینکها همانطور که پیش از این نشانهگذاری شده بودند، باید مقدار شناسه rel آنها برابر external باشد. همچنین چک میکنیم که لینک دارای شناسه href (که مسیر لینک را مشخص میکند) نیز باشد چراکه همانطور که میدانید تگ <a> فقط برای لینک کردن استفاده نمیشود و کاربردهای دیگری مانند نشانهگذاری (با شناسه name) نیز دارد که نباید کاری به آنها داشته باشیم!
if (anchor[i].getAttribute("href") && anchor[i].getAttribute("rel") == "external")
در نهایت باید مقدار شناسه target لینکهای مورد نظر را با مقدار blank مقداردهی کنیم:
anchor[i].target = "_blank";
سوالی که اینجا مطرح میشود این است که آیا با توجه به اینکه شناسه target از استانداردها حذف شده – و در نتیجه مرورگرها به تدریج دیگر از آن پشتیبانی نخواهند کرد – میتوان از آن به این شکل سود برد؟ در پاسخ باید بگویم بله! DOM که در واقع آبجکتها و متغیرهای معتبر در جاواسکریپت را مشخص میکند کماکان این متغیر را شامل میشود.
اسکریپت کامل:
بهتر است پیش از اجرای دستورات چک کنیم که آیا مرورگر از getElementsByTagName پشتیبانی میکند یا خیر. اسکریپت کامل به این خواهد بود:
function init() {
if (!document.getElementsByTagName) return;
var anchor = document.getElementsByTagName('a');
for (var i="0"; i<anchor.length; i++) {
if (anchor[i].getAttribute("href") && anchor[i].getAttribute("rel") == "external")
anchor[i].target = "_blank";
}
}
در آخر نیز باید این تابع را یکبار و بعد لود شدن صفحه اجرا کنید:
window.onload = init;
مشکل حل شد!
Happy Programming
پ.ن: یکی از بحثهای داغ که بین توسعهدهندگان وب مطرح است این است که آیا لازم است استانداردهای وب را رعایت کرد یا خیر؟ گرچه دلایلی وجود دارد که توسعهدهندگان وب را به رعایت استانداردها ترغیت میکند اما عدهی زیادی فقط استانداردها را تا جایی رعایت میکنند که صفحه وبشان در مرورگرهای مختلف بدرستی نمایش داده شود. شخصا سعی میکنم تا جایی که بتوانم استانداردها را رعایت کنم اما اصراری ندارم که صفحات کاملا استاندارد باشند. چراکه با توجه به اینکه اکثر صفحات امروزه بصورت دینامیک پیادهسازی میشوند و محتویات آنها عموما توسط کاربرانی که اطلاعات چندانی از این مسائل ندارند به روز میشود، استاندارد بودن همیشگی یک صفحه بیشتر شبیه به یک افسانه است!
-------------------------------------------------
دیگر مقالات کامپیوتری
CSS expression
WeblogPing و XML-RPC!
CSS Layout با استفاده از absolute positioning، مشکلات و راه حلها
کار با Alternate Style Sheets و Style Sheet Switch
در این نوشته با چند مثال به معرفی CSS Expression پرداخته شده و به نیازهایی که این امکان میتواند برای یک طراح رفع کند اشاره شده است.

برای همهی توسعه دهندگان وب حقیقت تلخیست که بزرگ بودن یک تصویر میتواند ساختار صفحه را بر هم بزند! تصویر بالا را ببینید، زیاد بودن عرض تصویر موجب شده ستون سمت راست (یا چپ) از جای اصلی خود خارج شده و کل ساختار صفحه برهم بخورد.
این مشکل بیشتر وقتی خود را نشان میدهد که قرار است مشتری خود تصاویری را همراه با دیگر اطلاعاتش به سیستم وارد کند و خراب شدن ساختار صفحه در این میان اصلا جالب نیست و جلوگیری از چنین اتفاقی واقعا لازم و ضروری است.
برای حل این مشکل البته راههای فراوانی هست. کنترل اندازهی عکس هنگام upload (بالاگذاری!) آن اولین راه حلی است که به ذهن میرسد (در اینجا فرض میکنیم سیستم مدیریت برای سایت در نظر گرفته شده که امکان آپلود کردن فایل را به مشتری میدهد. مثلا یک CMS). اما اعمال چنین محدودیتی برای همهی تصاویر که قرار است توسط سیستم آپلود شود زیاد جالب نیست چرا که مشخص نیست کدام تصویر قرار است در کجا قرار بگیرد و حداکثر اندازه مجاز برایش چقدر خواهد بود و پیاده سازی سیستمی برای مدیریت همهی حالتها مثل یک کابوس خواهد بود. ضمن آنکه اگر مشتری بخواهد طراحی سایت را تغییر بدهد باید برای تنظیم مجدد اندازهها به شما مراجعه کند که خوشایند مشتری نیست هرچند که شما را خوشحال میکند!
مشکلات دیگری هم هست. ممکن است تصویر از راههای دیگری (مثلا با FTP) به سرور فرستاده شده باشد یا اصلا روی سرور دیگری باشد.
راه دیگر اینست که با استفاده از شناسهی width برای تگهای img در CSS همهی تصاویر را با اندازهای متوسط نمایش دهیم!!! به صورت زیر.
.cntnt img { width: 300px; }
<div class="cntnt"><img src="pic.jpg" /></div>اما راه حل بهتر با استفاده از CSS:
در CSS شناسهای وجود دارد که به وسیلهی آن میتوان حداکثر یا حداقل اندازهی طول یا عرض عناصر را مشخص کرد.
max-width, min-width, max-height, min-height.cntnt img { max-width: 300px; }
<div class="cntnt"><img src="pic.jpg" /></div>این دقیقا همان چیزیست که دنبالش بودیم. حالا میتوان مشخص کرد همهی تصاویر تا زمانی که عرض آنها کوچکتر از ۳۰۰px هستند با اندازهی اصلی و تصاویر با عرض برزگتر از ۳۰۰px با اندازهی ۳۰۰px نمایش داده شوند. اما خبر بد اینست که Internet Explorer اصلا این شناسهها را در نظر نمیگیرد و کار خود را میکند! برعکس FireFox بهخوبی با این کدها مشکل را حل میکند.
پیش از آنکه طرفداران FireFox خوشحال شوند از این همه برتری FireFox و حماقت IE، به نکتهای که دلیل اصلی نوشته شدن این نوشته است اشاره میکنم: CSS expression.
CSS expression امکانیست که IE ورژن ۵ به بعد از آن پشتیبانی میکند بهوسیلهی این امکان میتوان در فایلهای CSS از کدهای JavaScript برای داشتن تنظیمات هوشمندتر استفاده کرد البته FireFox از امکان درک و تحلیل این expressionها عاجز است! به صورت زیر:
width: expression( javascript code);برگردیم به مسئلهی اصلی. مشکل را در FireFox حل کردیم. برای حل مشکل در IE با استفاده از expressionهای گفته شده، خط زیر را هم به CSS اضافه میکنیم.
.cntnt img {
max-width: 300px;
width : expression(this.width < 300 ? "auto":"300px");
}
<div class="cntnt"><img src="pic.jpg" /></div>جملهی مشخص شده یک عبارت (اپراتور؟) شرطی است که JavaScript آنرا از زبان C قرض گرفته! A?B:C به این صورت است که اگر A درست باشد B برگردانده میشود در غیر این صورت C. کلمه کلیدی this هم در JavaScript به شی یا المان جاری اشاره میکند. در خط بالا this.width در واقع به شناسهی width از المان img اشاره دارد که اگر از ۳۰۰ کوچکتر باشد مقدار شناسهی width در CSS برابر auto میشود (یعنی هرآنچه هست!) در غیر این صورت برابر ۳۰۰px میشود. و در هیچ حالتی بیشتر از ۳۰۰px نخواهد بود که مقصود ماست.
اگر مرورگرهای دیگر هم CSS expressionها پشنیبانی کامل میکردند میشد با آن معجزات فراوانی کرد که در حالت عادی نیاز به کدنویسی فراوان با DHTML دارد.

مثلا برای متمایز کردن سطرهای یک جدول از یکدیگر (شکل بالا) سمت کلاینت بهجای سمت سرور میتوان از CSS expression استفاده کرد. البته فقط در IE کار میکند. این صفحه را ببینید.
.t1 tbody tr {
background-color: expression(this.sectionRowIndex % 2 == 0 ? "#cccccc" : "#e5e5e5");
}استفادههای سادهی دیگری هم میتوان داشت. مثال پایین به ما کمک میکند که یک المان را نسبت به اندازه مرورگر در صفحه قرار دهیم. بدیهی است که موقعیت این المان وابسته به اندازه مرورگر است. این صفحه را در IE ببینید.
#mybox {
position: absolute;
width: 100px;
height: 100px;
padding: 10px;
left: expression(document.body.offsetWidth - 130 + "px");
top: expression(document.body.offsetHeight - 130 + "px");
background: red;
}
<div id="mybox">my box here</div>البته برای این کار راه حل سادهتر و عمومیتری هم هست! این نکته فقط به عنوان یک نمونه گفته شد.
#mybox {
position: absolute;
width: 100px;
height: 100px;
padding: 10px;
right: 25px;
bottom: 25px;
background: red;
}
<div id="mybox>my" box here</div>با استفاده از همین چند خط میتوان کارهای دیگری نیز کرد که معمولا نیاز طراحان است. اگر مقالهی “CSS Layout با استفاده از absolute positioning، مشکلات و راه حلها” را دیده باشید به مشکلات موجود در قالبهای CSS اشاره کردم و راه حلهای ارائه شده را آوردم که فکر میکنم کسی تمایلی به استفاده از آنها را ندارد!
با همین چند خط کد میتوان این مشکل را تا حدودی حل کرد. به این صفحه نگاه کنید.
min-height:600px;
height:expression(this.scrollHeight > 600 ? "auto":"600px");با در نظر گرفتن حداقل اندازهی ۶۰۰px برای ارتفاع، زیبایی بیشتری به صفحه داده میشود. البته تا زمانی متن از ۶۰۰px در صفحه تجاوز نکند!

در مقالات بعدی شاید به دیگر نیازهایی که با CSS extenssion میتواند آنها را جواب گفت خواهم پرداخت.
پ.ن: برای مشکل اول گفته شده (تصاویر) راه حلهای داینامیک فراوانی وجود دارد مانند استفاده از اسکریپتی برای تعیین اندازه عکس و… که چون اندازهی عکس را سمت سرور مشخص میکند، از لود عکسی بزرگ با حجم بیشتر هم جلوگیری میکند. اما آنچه تجربه ثابت کرده است اینست که مشتری را برای استفاده درست از این اسکریپتها یا حتی رعایت حداکثر اندازه عکس نمیتوان متقاعد کرد.