پرش به محتوا

قسمت اول:اعتبار سنجی سمت کلاینت با استفاده از dijit.form.ValidationTextBox

قسمت دوم:اعتبارسنجی فرم ها در دوجو

یکی از بدیهی ترین امکانی که از فریم ورک های جاوا اسکریپت انتظار داریم فراهم آوردن ابزاری برای اعتبار سنجی فرم ها ،سمت کلاینت (client side validation) است.این کار با دوجو در حالت declarative به راحت ترین شکل ممکن انجام میشود.

فرم ها در دوجو dijit.form.Form

برای اینکه یک فرم html به ویجت دوجو(dijit دیجیت) تبدیل شود فقط کافیست dojoType را به عنوان attribute به تگ فرم اضافه کنیم:

<form method="POST" dojoType="dijit.form.Form" ></form>

و با استفاده از تگ script رفتار فرم موقع submit شدن را تغییر دهیم.

<form method="POST" dojoType="dijit.form.Form"  >
	<script type="dojo/method" event="onSubmit" >
		if(this.validate()){ //or this.isValid()
			alert('submit');
		}
		return false;
	</script>
</form>

پارسر دوجو همه ی تگ های script-ی که بعد از هر dijit را به عنوان event به آن attach می کند.دقیقا ما از همین روش استفاده میکنیم تا رفتار پیش فرض فرم در onSubmit ، event تغییر دهیم.

()this.validate و ()this.isValid

متد ()isValid چک می کند که فرم به صورت درست و کامل پر شده است یا نه ، متد ()validate هم دقیقا همین کار را انجام می دهد به علاوه اینکه فیلد های اشتباه را به صورت گرافیکی مشخص و به اولین فیلد اشتباه focus میکند و اسکرول  را جابجا می کند تا فیلد نمایان شود.پس استفاده از متد ()validate به خاطر کاربر پسندتر بودن آن بهتر است.

با فراخوانی متد ()validate یا ()isValid در فرم ، این متد همه ی متدهای یکسان در child-ها را فراخوانی میکند و احتیاج به بررسی درستی هر یک از فیلدهای فرم وجود ندارد.

dijit.form.Button

همه میدانیم برای submit کردن یک فرم html باید یک button تعریف کنیم type=”submit”. همین کار هم برای submit کردن یک فرم dijit-ی کافیست ولی اگر بخواهیم از تم های دوجو استفاده کنیم dojoType attribute را به المان اضافه کنیم.

<button  dojoType="dijit.form.Button" type="submit" >ارسال</button>

حتما به خاطر داریم که اگر از <button type=”submit” > به جای <input type=”submit” /> استفاده کنیم می توانیم داخل تگ button کدهای html قرار دهیم و از هر عکس یا آیکنی استفاده کنیمو

<button type="submit" >ارسال<img src="http://s.wordpress.org/style/images/wp3-logo.png" /></button>

البته در dojo با اضافه کردن و مقدار دهی به iconClass ،آیکون مورد نظر به dijit.form.Button اضافه می شود.

<button dojoType="dijit.form.Button" type="submit" iconClass="dijitEditorIcon dijitEditorIconCut" ></button>


اجرای مثال های بالا
 
مشاهده مثال در dojotoolkit
 

قبلا در مورد dijit.form.ValidationTextbox و dijit.form.FilteringSelect نوشته بودم،حالا با استفاده از ویجت form یک فرم ساده طراحی میکنیم:

<form method="POST" dojoType="dijit.form.Form"  >
	<script type="dojo/method" event="onSubmit" >
		if(this.validate()){
			alert('submit');
		}else{
			console.log('invalid');
		}
		return false;
	</script>
	<select dojoType="dijit.form.FilteringSelect" >
		<option>dojo</option>
		<option>dijit</option>
	</select>
	<br/>
	<input
		value="milad"
		id="test"
		type="text"
		tooltipPosition="after-centered"
		regExp="\d{1,5}"
		promptMessage="prompt message"
		missingMessage="missing message"
		invalidMessage="invalid message"
		dojoType="dijit.form.ValidationTextBox" />
	<br/>
	<button dojoType="dijit.form.Button" type="submit" >ارسال</button>
</form>

قسمت اول:اعتبار سنجی سمت کلاینت با استفاده از dijit.form.ValidationTextBox

قسمت دوم:اعتبارسنجی فرم ها در دوجو

ValidationTextBox یک المان <input> است که با استفاده از امکانات خود طراح را مطمئن می کند که مقادیر وارد شده کاملا معتبر است. در مواردی که مقدار غیر معتبر وارد شود با تغییر رنگ ، نمایش آیکون و نشان دادن tooltip این ارور به کاربر اطلاع داده می شود.

یکی از تغییرات بزرگ ورژن ۱٫۷ دوجو ،پشتیبانی کامل از AMD هست،و تغییر بزرگ دیگر ،استاندارد سازی همه ی تگ ها و attribute -هاست.به این معنی که همه ی attribute -های سفارشی(custom) ، به attribute استاندارد data-dojo-* HTML5 تبدیل شده است.

همه ی attribute-های سفارشی تا ورژن ۲ و data-dojo-* attribute از ورژن ۱٫۷ قابل استفاده است.

required

مشخص کردن این attribute که از جنس  boolean است مشخص می کند که این فیلد باید حتما پر شود یا نه،به صورت پیش فرض مقدار false دارد.

dojo < 2<br/>
<input type="text" name="name" required="true" dojoType="dijit.form.ValidationTextBox"/>
<br/>
dojo >= 1.7<br/>
<input type="text" name="name" required="true" data-dojo-type="dijit.form.ValidationTextBox"/>

trim

برای حذف کردن همه ی فاصله ها در اول و آخر یک فیلد از این attribute استفاده میکنیم.به صورت پیش فرض این attribute مقدار false را دارد و به معنی عدم حذف فاصله ها در حالت پیش فرض است.

dojo < 2<br/>
<input type="text" name="name" trim="true" dojoType="dijit.form.ValidationTextBox"/>
<br/>
dojo >= 1.7<br/>
<input type="text" name="name" trim="true" data-dojo-type="dijit.form.ValidationTextBox"/>

promptMessage

اگر بخواهیم توضیح یا راهنمایی برای فیلد خاصی بنویسیم تا در موقع پر کردن فیلد نمایش داده شود از promptMessage attribute استفاده می کنیم.این attribute در حالت پیش فرض مقداری ندارد.

dojo < 2<br/>
<input type="text" name="name" required="true" promptMessage="نوشته برای نمایش" dojoType="dijit.form.ValidationTextBox"/>
<br/>
dojo >= 1.7<br/>
<input type="text" name="name" required="true" data-dojo-props="promptMessage:'نوشته برای نمایش'" data-dojo-type="dijit.form.ValidationTextBox"/>

missingMessage

اگر مقدار required=”true” تنظیم شود،و در موقع سابمیت فرم هیچ مقداری در آن فیلد وارد نگردد بعد از focus دوباره در آن ، این پیغام نمایش داده می شود.

dojo < 2<br/>
<input type="text" name="name" required="true" missingMessage="نوشته در زمان فراموشی پر کردن" dojoType="dijit.form.ValidationTextBox"/>
<br/>
dojo >= 1.7<br/>
<input type="text" name="name" required="true" data-dojo-props="missingMessage:'نوشته در زمان فراموشی پر کردن'" data-dojo-type="dijit.form.ValidationTextBox"/>

invalidMessage

در پاراگراف های بعدی این نوشته نحوه اعتبار سنجی یک فیلد را توضیح خواهم داد ولی اگر مقدار وارد شده برای یک فیلد صحیح نباشد این پیغام نمایش داده می شود.

dojo < 2<br/>
<input type="text" name="name" required="true" invalidMessage="نوشته در زمان invalid" dojoType="dijit.form.ValidationTextBox"/>
<br/>
dojo >= 1.7<br/>
<input type="text" name="name" required="true" data-dojo-props="invalidMessage:'نوشته در زمان invalid'" data-dojo-type="dijit.form.ValidationTextBox"/>

regExp

استفاده از عبارات منظم(regular expression) یکی از روش هایی است که برای اعتبار سنجی استفاده می شود،قوانین (نحو – syntax) عبارات منظم در دوجو، مستقیما از قوانین عبارات منظم در جاوا اسکریپت تبعیت می کند،
در regular expression برای مشخص کردن ابتدا از ^ و انتها از $ استفاده می کنیم،که این دو قانون به صورت پیش فرض در regExp دوجو رعایت می شود و لازم به ذکر آنها نیست.

کد زیر یک مثال ساده از استفاده از regExp برای اعتبارسنجی کد پستی ۱۰ رقمی می باشد.

dojo < 2<br/>
<input type="text" name="name" required="true" regExp="\d{10,10}" dojoType="dijit.form.ValidationTextBox"/>
<br/>
dojo >= 1.7<br/>
<input type="text" name="name" required="true" data-dojo-props="regExp:'\\d{10,10}'" data-dojo-type="dijit.form.ValidationTextBox"/>

regExpGen

ValidationTextBox همچنین قابلیت پشتیبانی از عبارات منظم(regular expression) دینامیک را دارد،البته به همراه regExpGen می توان از dojo.regexp.*(که در نوشته های بعدی توضیح می دهم) نیز استفاده کنیم.
بعد از اجرای کد زیر فیلدهای ما قابلیت قبول دو نوع مقدار را دارد،برای مثال اگر کاراکتر اول وارد شده برابر ۰ باشد حدس میزنیم که کاربر قصد وارد کردن شماره تلفن و در غیر اینصورت قصد وارد کردن کدپستی ۱۰ رقمی را دارد .

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js" djConfig="parseOnLoad:true"></script>
        <script type="text/javascript">
            //dojo.require("dijit.form.ValidationTextBox"); //dojo < 2 or use below line
			require(["dojo/parser", "dijit/form/ValidationTextBox","dijit/form/Form"]); // dojo >= 1.7
			var regExpFunc = function(constraints){
				if(this.displayedValue.substr(0,1)=='0'){
					return "\\d{11}";
				}else{
					return "\\d{10}";
				}
			}
        </script>
        <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dijit/themes/claro/claro.css" />
    </head>
    <body class="claro" dir="rtl">
		dojo < 2<br/>
		<input type="text" name="name" required="true" regExpGen="regExpFunc" dojoType="dijit.form.ValidationTextBox"/>
		<br/>
		dojo >= 1.7<br/>
		<input type="text" name="name" required="true" data-dojo-props="regExpGen:regExpFunc" data-dojo-type="dijit.form.ValidationTextBox"/>
    </body>
</html>

validator

اگر قابلیت های بالا امکان اعتبارسنجی را به طور کامل به شما نمی دهد می توانید از validator attribute استفاده کنید تا از تابعی خاص برای اعتبار سنجی بهره ببرید،برای یک مثال واقعی در مورد استفاده از این قابلیت می توان به اعتبارسنجی کدملی اشاره کرد که باید مقدار وارد شده برای تابعی ارسال و بعد پاسخ معتبر بودن یا نبودن مقدار مشخص شود.
کد زیر مثال ساده از امکان validator در ValidationTextBox را نشان می دهد،اگر طول مقدار وارد شده برابر ۳ بود آن مقدار معتبر در غیر اینصورت نامعتبر است:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js" djConfig="parseOnLoad:true"></script>
        <script type="text/javascript">
            //dojo.require("dijit.form.ValidationTextBox"); //dojo < 2 or use below line
			require(["dojo/parser", "dijit/form/ValidationTextBox","dijit/form/Form"]); // dojo >= 1.7
			var someFunction = function(node){
				if(node.get('value').length==3){
					return true;
				}else{
					return false;
				}
			}
        </script>
        <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dijit/themes/claro/claro.css" />
    </head>
    <body class="claro" dir="rtl">
		dojo < 2<br/>
		<input type="text" name="name" required="true" validator="return someFunction(this)" dojoType="dijit.form.ValidationTextBox"/>
		<br/>
		dojo >= 1.7<br/>
		<input type="text" name="name" required="true" data-dojo-props="" data-dojo-type="dijit.form.ValidationTextBox"/>
    </body>
</html>

تقریبا امکان استفاده از همه ی قابلیت های بالا در ویجت های دیگر دوجو مانند NumberTextBox NumberSpinner CurrencyTextBox DateTextBox TimeTextBox وجود دارد.

در مطلب بعدی در مورد dijit.form.Form و استفاده از آن به همراه dijit.form.ValidationTextBox خواهم نوشت.

Zend_Mail یکی از کامپوننت های فریم ورک زند هست که قابلیت ارسال ایمیل برای شما فراهم می کند.با استفاده از این کامپوننت می توانید به راحتی از ایمیل های جی میل پیغام ارسال کنید.

config

$config=array( 'auth' => 'login',
 'username' => 'smtp_username@gmail.com',
 'password' => 'pass',
 'ssl' => 'tls',
 'port' => 25, //if closed,use port 587
 );
 $tr_smtp = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config );
 Zend_Mail::setDefaultTransport($tr_smtp);

username : نام کاربری شمادر smtp سرور، که در این حالت از آدرس ایمیل در gmail استفاده می کنیم.

password : کلمه عبور اختصاص داده شده،.

اگر ۲-step verification اکانت گوگل خود را فعال کرده باشید،باید پسورد جدید genterate و استفاده کنید

افزودن گیرنده

()addTo : برای اضافه کردن گیرنده جدید به هدر ایمیل

()addCc : اضافه کردن دریافت کننده به عنوان “cc” به هدر ایمیل

()addBcc : اضافه کردن دریافت کننده به عنوان “bcc” به هدر ایمیل

پارامترهای دوم ()addTo و ()addCc و ()addBcc که اختیاری هستند برای اضافه کردن نامی که قابل خوانده شدن توسط انسان باشد به کار می رود.

عنوان ایمیل

متد ()setSubject برای set کردن عنوان ایمیل کاربرد دارد

ارسال ایمیل متنی

با استفاده از متد ()setBodyText متن دلخواهی را قرار داده و ارسال کنید.

ارسال ایمیل HTML

تقریبا همه ایمیل هایی که به دست ما میرسد فقط حاوی متن ساده نیست و به متن ها استایل داده یا داخل ایمیل از لینک یا عکس استفاده شده است. برای این منظور از متد ()setBodyHtml برای قرار دادن کدهای HTML داخل ایمیل استفاده می کنیم.

قبل از ارسال ایمیل حتما درستی property کدهای HTML-ی که از Attribute استایل داخل تگ ها استفاده کرده اید را در اینترفیس های مختلف گوگل ، یاهو و … چک کنید

ارسال ایمیل به همراه فایل attache

ضمیمه کردن فایل به وسیله متد ()createAttachment انجام میشود.پارامتر اول این متد یک (application/octet-stream)Binary Object را قبول میکند و خروجی ، آبجکتی از Zend_Mime_Part است. با تغییر property filename خروجی متد ()createAttachment امکان تغییر نام فایل پیوست شده وجود دارد.

در انتها با استفاده از متد ()send ایمیل را ارسال میکنیم.

انکودینگ Zend_Mail به صورت پیش فرض iso-8859-1 تنظیم شده و برای ارسال ایمیل فارسی باید در __construct() به UTF-8 تغییر داده شود.

<?php
try{
	$config=array( 'auth' => 'login',
					'username' => 'smtp_username@gmail.com',
					'password' => 'pass',
					'ssl' => 'tls',
					'port' => 25, //if closed,use port 587
				);
	$tr_smtp = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config );
	Zend_Mail::setDefaultTransport($tr_smtp);
	$mail = new Zend_Mail('UTF-8');
	$mail->setBodyHtml('body html code here');
	$mail->addTo('to@any.com','to name');
	$mail->setSubject('mail subject');
	$mail->setFrom('from@gmail.com','from name');
	$attachment = $mail->createAttachment(file_get_contents('LogoSmall.gif'));
	$attachment ->filename = 'LogoSmall.gif';
	$mail->send();
}catch(Exception $e){
	echo $e->getMessage();
}
?>

در تولکیت دوجو ، به فریم ورکی که برای ساخت UI استفاده می شود dijit می گویند.

از دید برنامه نویس ها یکی از برتری های دیجیت اینست که میتوان از دو راه ویجت ها را ساخت: Programmatically یا Declaratively

dojo.require : لود کردن کلاس های لازم

اگر هر یک از دو راه Programmatically یا Declaratively را برای ساخت ویجت ها ترجیح بدهید لازم است که کلاس های مربوط به آن را از قبل لود کنید:

dojo.require('dijit.form.Select');
dojo.require('dijit.layout.TabContainer');
dojo.require('dijit.layout.ContentPane');

راه اول:ساخت ویجت به صورت Declaratively

ساخت ویجت ها به صورت Declaratively به این معنی هست که برای ساختن ویجت ها از تگ ها و attribute-های html استفاده کنید تا یک المان ، ویجت گردد.اولین قسمت ساخت ویجت به صورت Declaratively اینست که دوجو را راهنمائی کنید که صفحه را parse کند و دنبال ویجت های دوجو بگردد،باز هم ۲ راه برای این کار وجود دارد.اولین راه مقدار دهی property parseOnLoad در djConfig به صورت زیر است:

<script src="/js/dojo.js" djConfig="parseOnLoad:true;"></script>

parseOnLoad:true دقیقا به دوجو میگوید:بعد از اینکه همه Resource-ها(فایل های جاوا اسکریپت و CSS و …) و المان های DOM لود شد، صفحه را parse کن.
راه دیگر اینست که به صراحت به دوجو بگید که صفحه را parse کن:

//load the parser
dojo.require('dojo.parser');

//parse the page
dojo.ready(function() {
 dojo.parser.parse()
});

همانطور که گفتم در ساخت ویجت ها در روش Declaratively شما با استفاده از تگ ها و attribute-های html ویجت های خود را می سازید.dojoType امکان این را فراهم آورده که مشخص کنید ، المان باید به چه نوع ویجتی از Dijit تبدیل گردد.

<select dojoType="dijit.form.Select">
 <option value="value1">Key 1</option>
 <option value="value2">Key 2</option>
</select>

<!-- layout widget -->
<div dojoType="dijit.layout.TabContainer">
 <div dojoType="dijit.layout.ContentPane"><!-- content --></div>
 <div dojoType="dijit.layout.ContentPane"><!-- content --></div>
 <div dojoType="dijit.layout.ContentPane"><!-- content --></div>
</div>

BOOM! به محض اینکه DOM آماده شد و فایل های خارجی لود شدند، تمام المان ها با attribute (صفت) dojoType تبدیل به ویجت های دوجو می شوند. خصیصه های اختیاری(option-ها) به صورت attribute-های اضافه مقدار دهی می گردند.

<!-- turn a DIV into a "Select"; options will come from data store -->
<div dojoType="dijit.form.Select" store="optionsStore" searchAttr="val">
 <!-- options come from a data store -->
</div>

<!-- create a layout widget; contentpane has custom attributes for JS -->
<div dojoType="dijit.layout.TabContainer">
 <div dojoType="dijit.layout.ContentPane" closable="true" href="somepage.php" preload="true">
 <!-- content 1 here -->
 </div>
</div>

بامزست نه؟به این فکر کنید که با قرار دادن نوع و خصیصه های انتخابی(option-ها) ویجت ها درون خودشان (و عدم کدنویسی در جاوا اسکریپت) چقدر در وقت صرفه جوئی میکنید.

راه دوم:ساخت ویجت به صورت Programmatically

برای ساخت ویجت ها به صورت Programmatically شما باید node-ها را به عنوان placeholder-ی برای ساخت ویجت در آینده در نظر بگیرید.

<button id="makeMeAWidget">Click Me</button>

به محض اینکه DOM آماده شد و همه ی وابستگان (dojo.require) لود شدند،شما باید کدهای جاوا اسکریپتی برای تبدیل المان های HTML به ویجت ها بنویسید.

//when dependencies are loaded...
dojo.ready(function() {
 //...make elements into widgets
 var widget = new dijit.form.Button({},'makeMeAWidget'); //options,elementID
});

عوض اینکه به صورت اختصاصی(تکی) ویجت هر المان را مشخص کنید میتوانید از dojo.behavior و css selector-ها برای انتخاب المان ها و ویجتی کردن آنها استفاده کنید.

dojo.behavior.add({
 'button': {
 found: function(button) {
 new dijit.form.Button({},button); //options,elementID
 }
 }
})

دوجو همه ی المانهایی که هماهنگ هستند را پیدا و آنها را تبدیل به ویجت می کند.

کدام بهتر است؟

وقتی میخواین تصمیم بگیرید که از کدام روش در پروژه خو استفاده کنید باید چند نکته را مد نظر داشته باشید:

  • ساخت ویجت ها به صورت programmatic سریعتر است چون لازم نیست که DOM توسط دوجو parse شود تا المان ها تبدیل به ویجت گردند.
  • ساخت ویجت ها به صورت declarative به شما اجازه میدهد سریعتر کد بنویسید.اگر صفحه ی شما زیاد بزرگ نیست،اختلاف سرعت بین دو روش خیلی کم است.

برای اینکه ببینید Dijit چه قابلیت هایی دارد به این آدرس نگاه کنید

ترجمه ای آزاد از این لینک

تابع stat در php برای گرفتن اطلاعات یک فایل استفاده می شود.که این تابع آرایه ای را به عنوان خروجی میدهد که حاوی اطلاعات آن فایل است.

خروجی این تابع در هر سرور متفاوت است و کلیدهای آرایه ی خروجی به صورت عددی یا حروفی یا هر دو نوع میباشد.

نتایج این تابع در cache ذخیره میشود،از تابع clearstatcache برای پاک کردن cache استفاده کنید

نحوه استفاده :

<?php
$fileData = stat('dga.zip');
print_r($fileData);
?>

نتایج :

Array
(
    [0] => 3
    [1] => 0
    [2] => 33206
    [3] => 1
    [4] => 0
    [5] => 0
    [6] => 3
    [7] => 22362131
    [8] => 1304863503
    [9] => 1304863545
    [10] => 1304863503
    [11] => -1
    [12] => -1
    [dev] => 3
    [ino] => 0
    [mode] => 33206
    [nlink] => 1
    [uid] => 0
    [gid] => 0
    [rdev] => 3
    [size] => 22362131
    [atime] => 1304863503
    [mtime] => 1304863545
    [ctime] => 1304863503
    [blksize] => -1
    [blocks] => -1
)

توضیح نتایج خروجی :

ایندکس ۴ و ایندکس uid : در سیستم های یونیکسی userid of owner

ایندکس ۵ و ایندکس gid : در سیستم های یونیکسی groupid of owner

ایندکس ۷ و ایندکس size : حجم فایل مورد نظر به بایت

ایندکس ۹ و ایندکس mtime : تاریخ آخرین تغییر فایل(Unix timestamp)

تعدادی از کدنویس ها برای تغییر رفتار event-ها در element-های خاص، از کدی شبیه کد زیر استفاده میکنند:

$("a").click(function () {
    console.log('do something');
    return false;
});

فرض کنیم به یکی از node-ها در event کلیک ،دو تابع مختلف attach کرده باشیم و در انتهای تابع اول مقدار false را بازگشت داده ایم.

$("a").click(function () {
    console.log('do something');
    return false;
});
$("a").click(function () {
    console.log('do something else');
    return false;
});

انتظار ما اینست که بعد از کلیک روی <a> ،مقدار false بازگشت داده شده باعث جلوگیری از تغییر مسیر صفحه شود،ولی عملا handler اول اجرا شده و از اجرای handler دوم هم جلوگیری کرده ایم.

preventDefault

برای حل این مشکل در جی کوئری باید از متد preventDefault استفاده کنیم،این متد بعد از فراخوانی باعث میگردد که رفتاری اصلی event اتفاق نیفتد(trigger نشود). کد بالا را به صورت زیر تغییر میدهیم:

$("a").click(function (event) {
    console.log('do something');
    event.preventDefault();
});
$("a").click(function (event) {
    console.log('do something else');
    event.preventDefault(); //یکبار فراخوانی متد preventDefault در هر event-ی کافیست و عملا این خط اضافه است
});

با اجرای کد بالا، بعد از کلیک روی <a> هر دو متد فراخوانی شده و در عین حال از تغییر مسیر صفحه نیز جلوگیری کرده ایم.

stopPropagation

باعث جلوگیری از اجرای متدهای attach شده به parent-های یک node میگردد.

فرض کنیم یکی از المان های <a> صفحه ی ما داخل <div> قرار دارد و به event کلیک <a> ، دو متد و به <div> یک متد attach شده.

<html>

    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
        <script>
            $(document).ready(

            function () {
                $('a').on("click", function (event) {
                    console.log('do something');
                    event.preventDefault();
                    //event.stopPropagation(); //uncomment this line
                });
                $('a').on("click", function (event) {
                    console.log('do something else')
                });
                $('div').on("click", function () {
                    console.log('clicked the div')
                });
            });
        </script>
    </head>

    <body>
        <div style="width:150px;border:1px solid black;padding:10px 10px 10px 10px; ">
            <a href="http://www.google.com">click me and see console</a>
        </div>
    </body>

</html>

حالا با کلیک بر روی <a> (در حالتی که از preventDefault استفاده کرده ایم) ۳ متد فراخوانی میشود.و اگر از stopPropagation استفاده کنیم فقط دو متد attach شده به <a> فراخوانی میشود.

stopImmediatePropagation

فراخوانی این متد باعث میگردد که از اجرای بقیه ی متدهای attach شده به node جلوگیری کند.

<html>

    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
        <script>
            $(document).ready(

            function () {
                $('a').on("click", function (event) {
                    console.log('do something');
                    event.preventDefault();
                    event.stopImmediatePropagation();
                });
                $('a').on("click", function (event) {
                    console.log('do something else')
                });
            });
        </script>
    </head>

    <body>
        <div style="width:150px;border:1px solid black;padding:10px 10px 10px 10px; ">
            <a href="http://www.google.com">click me and see console</a>
        </div>
    </body>

</html>

برای تست هر سه متد:try it

<html>

    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
        <script>
            function handler2(event) {
                $('#result').append('<div>handler2 on a</div>');
            }

            function handler1(event) {
                $('#result').empty();
                $('#result').append('<div>handler1 on a</div>');
                if ($('#preventDefault').attr('checked')) {
                    event.preventDefault();
                }
                if ($('#stopPropagation').attr('checked')) {
                    event.stopPropagation();
                }
                if ($('#stopImmediatePropagation').attr('checked')) {
                    event.stopImmediatePropagation();
                }
            }
            $(document).ready(

            function () {
                $('a').on("click", handler1);
                $('a').on("click", handler2);
                $('div').on("click", function (event) {
                    $('#result').append('<div>clicked the div</div>');
                });
            });
        </script>
    </head>

    <body>
        <div style="width:150px;border:1px solid black;padding:10px 10px 10px 10px; ">
            <a target="_blank" href="http://www.google.com">click me</a>
        </div>
        <br/>
        <label>
            <input type="checkbox" id="preventDefault" />preventDefault</label>
        <label>
            <input type="checkbox" id="stopPropagation" />stopPropagation</label>
        <label>
            <input type="checkbox" id="stopImmediatePropagation" />stopImmediatePropagation</label>
        <br/>
        <p id="result" style="width:150px;border:1px solid black;padding:10px 10px 10px 10px; "></p>
    </body>

</html>

بسیاری از برنامه نویس های php از تابع opendir برای گرفتن لیست فایل ها در یک پوشه استفاده می کنند،خوشبختانه php تابعی با نام glob دارد که بسیار سریعتر و باهوشتر عمل میکنه.

$dir = "/wwwroot/";
// This must be known directory

if (is_dir($dir))
{
 if ($p_dir = opendir($dir))
 {
 while (($file = readdir($p_dir)) !== false)
 {
 echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
 }
 closedir($p_dir);
 }
}

کد بالا برای همه آشناست چون تقریبا همه ی برای انجام این کار از این کد استفاده میکنیم،ولی اگر همین کار با ۳ یا ۴ خط انجام بدیم خیلی بهتر میشه.

کد زیر ببینید:

$dir = "/wwwroot/*";
// Open a known directory, and proceed to read its contents
foreach(glob($dir) as $file)
{
    echo "filename: $file : filetype: " . filetype($file) . "<br />";
}

این روش بسیار آسانتر است.

تابع glob دو آرگومان را به عنوان ورودی می گیرد،آرگومان اول آدرس پوشه ی مورد نظر،و آرگومان دوم فلگ هایی برای کنترل بهتر رفتار این تابع که اختیاری است .

آرگومان اول:

آرگومان اول آدرس پوشه مورد نظر را تعیین می نماید،این آرگومان از الگوها پشتیبانی میکند.یعنی میتوانید کنترل کنید که لیست چه نوع فایلهایی را دریافت کنید یا از * استفاده کنید تا لیست همه فایلها بگیرید.

با یک مثال توضیح بیشتری میدهم:

فرض کنید شما وب سایتی دارید که کاربران ثبت نام شده میتوانند فایلهای خود را آپلود کنند و شما آنها را در پوشه های جداگانه با الگوی زیر ذخیره میکنید:

wwwroot/files/hd/username/image
wwwroot/files/small/username/image

در اینجا ‘hd’ محل ذخیره تصاویر با وضوح بالا(High-definition) و ‘small’ محل ذخیره thumbnail می باشد.

در این وضعیت glob کار شما رو خیلی آسانتر میکند:

foreach(glob('wwwroot/files/hd/*/image/*') as $image)
{
    echo "Filename: " . $image . "<br />";
}

با تکه کد بالا به فایل ها و فولدرها در پوشه ی hd همه ی یوزرها دسترسی خواهیم داشت.

ما با قرار دادن * در آخر آدرس باعث شدیم  تمام فایل ها و فولدرها لیست شوند،,ولی اگر بخواهیم فایلهایی با پسوند خاص لیست شود باید کد را به صورت زیر تغییر دهیم.

foreach(glob('wwwroot/files/hd/*/image/*.jpg') as $image)
{
echo "Filename: " . $image . "<br />";
}

کد بالا تمام فقط فایهای jpg را لیست میکند.

آرگومان دوم:

همانطور که قبلا اشاره شد آرگومان دوم که اختیاری است فلگ هایی هستند که رفتار تابع glob را تغییر می دهند.

GLOB_MARK: یک / به دایرکتوری ها اضافه میکند
GLOB_NOSORT: فایل ها را همانطور که در دایرکتوری وجود دارند لیست می کند(نه به صورت sort شده )
GLOB_NOCHECK: اگر فایل یا دایرکتوری یافت نشد الگویی که ما به عنوان آرگومان اول فرستاده بودیم برگشت داده خواهد شد
Backslashes do not quote metacharacters GLOB_NOESCAPE 
GLOB_BRACE: باعث می شود الگویی مانند {a,b,c} با ‘a’ یا ‘b’ یا  ‘c’ منطبق گردد
GLOB_ONLYDIR: فقط دایرکتوری ها را لیست میکند که با الگو هماهنگی داشته باشد
GLOB_ERR: توقف در زمانی که ارور اتفاق می افتد(مثل وقتیکه به پوشه ی unreadable می رسد) به صورت پیش فرض ارور-ها ندید گرفته می شود.

در کد قبلی ما همه ی فایلهای *.jpg را لیست کردیم ولی برای گرفتن فایل هایی با پسوند های متفاوت به این صورت عمل میکنیم:

foreach(glob('wwwroot/files/hd/*/image/{*.jpg,*.gif}',GLOB_BRACE) as $image)
{
echo "Filename: " . $image . "<br />";
}

برای مشاهده نام فولدرهای موجود در یک فولدر خاص باید از فلگ GLOB_ONLYDIR استفاده کنیم.

foreach(glob('wwwroot/*',GLOB_ONLYDIR) as $folder)
{
echo "FolderName: " . $folder . "<br />";
}

نصب pear

فروردین ۵

pear یک فریم ورک php است که قابلیت نصب و استفاده از کامپوننت های(پکیج های) مختلف را میدهد.

ابتدا مطمئن شوید php نصب شده است(در خط فرمان دستور زیر را اجرا کنید):

php -v

در جواب باید چیزی شبیه این در خروجی ببینید:

PHP 5.3.6 (cli) (built: Mar 17 2011 10:37:07)
Copyright (c) 1997-2011 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend Technologies

در ویندوز:

در مسیری که php را نصب کرده اید فایل go-pear.bat را پیدا کنید و در خط فرمان اجرا نمائید.بعد از جواب دادن به چند پرسش ساده package manager نصب خواهد شد.

در سیستم عامل های دیگر یا اگر فایل go-pear.bat را در ویندوز پیدا نکردید:

فایل http://pear.php.net/go-pear.phar را دانلود کرده و با php اجرا کنید.

$ wget http://pear.php.net/go-pear.phar
$ php go-pear.phar

اگر در اجرای مراحل بالا مشکلی نباشد pear به درستی نصب خواهد شد.با اجرای دستور زیر مشخصات package manager را خواهید دید:

pear version

خروجی:

PEAR Version: 1.9.4
PHP Version: 5.3.6
Zend Engine Version: 2.3.0
Running on: Windows NT WIN-RRSVEEQCTOS 6.1 build 7601 (Unknow Windows version Enterprise Edition Ser
vice Pack 1) i586

حالا برای نصب هر یک از پکیج ها دستور زیر را در خط فرمان اجرا میکنیم:

pear install package

پکیج های pear تشکیل شده از چند فایل php که بعد از Install کردن در پوشه ای دانلود میشود.برای پیدا کردن این پوشه دستور زیر را اجرا کنید:

pear config-get php_dir

یکی از همکارامون تو دانشگاه شریف درس خونده (و میخونه) امروز با هم صحبت میکردیم ، شخصی به نام آیدین نصیری‌شرق معرفی کرد که از دانشجوهای دانشگاه شریف بوده (یا هست) که TA  (Teacher Assistant) بوده.

ایشون چند تا پروژه ی شخصی هم نوشته که Phormer یکی از اونهاست. Phormer یک گالری عکس با PHP که بدون استفاده از دیتابیس نوشته شده و همه ی اطلاعات تو فایلهای XML ذخیره میکنه(FlatPress که یادتون هست).اینارو گفتم که بگم بعد از مدتها یک کد PHP خوب دیدم که تقریبا همه ی قسمتهاش توسط یک ایرانی نوشته شده (خسته شدم اینقدر فریم ورک های پیچیده و  سیستم های مدیریت محتوا دیدم).

چون آخرین ورژن این گالری سال ۲۰۰۷ منتشر شده و تو اون تاریخ  OOP تو PHP شاید کاربرد کمی داشته، ولی تقریبا ریزترین موارد تو این پروژه رعایت شده. جدای از اینکه نوشتن یه پروژه ی مجزا به این شکل تو دوره ای که همه سعی می کنند پروژه های کوچیک به CMS های بزرگ لینک کنند درست هست یا نه ولی شدیدا به همه ی دوستانی که تجربه ی کمی تو کد نویسی دارند توصیه میکنم به کدهای این پروژه دقت کنند.

کد قبلی که دیده بودم و خیلی ساده و تمیز نوشته شده بود و نمونه ای پایه ای! برای آموزش OOP بود پروژه ی CMS Detector که حامد افشار زحمت کشیدند و کدهای جاوا اسکریپت اکستنشن Chrome Sniffer گوگل کروم به PHP تبدیل کردند.

اگه شما هم پروژه ای میشناسید که قسمت زیادیش توسط یک ایرانی نوشته شده و Open Source هم هست، خوشحال میشم اسمشو بدونم.

تولکیت دوجو برای تگ<select> معادلهای گوناگونی  داره که تفاوتشون توی مقادیر option-ها و نحوه ورود اطلاعات از سمت یوزر هست:

مشاهده مثال

dijit.form.Select

API

این ویجت مثل تگ <Select> عمل می کنه یعنی لیبل option-ها با value آنها تفاوت داره.
width:
در حالت پیش فرض عرض ویجت برابر با عرض option-ی هست که انتخاب شده ولی برای فیکس کردن عرض باید از style استفاده کنیم.مثلا:
<select style="width: 150px;">
maxHeight:
یکی از مهمترین attribute این ویجت  maxHeight هست که ارتفاع لیست حاوی option-ها رو مشخص می کنه برحسب پیکسل ولی نباید لفظ px را نوشت.
اگر  ارتفاع لیست حاوی option-ها بلندتر از مقدار مشخص شده در maxHeight  بود  ، scroll کنار لایه ظاهر میشه.
forceWidth:
این attribute پهنای  لیست option-هارو مشخص می کنه .یعنی  اگه می خواین پهنای لیست option-ها دقیقا برابر با پهنای ویجت باشه این attr را true می کنید و اگه می خواین پهنای لیست option-ها در حالت حداکثری باشه و همه option-ها به طور کامل دیده شوند،false (به صورت پیش فرض هم false هست)
emptyLabel:
اگر emptyLabel را ست کرده و ویجت select-ی بدون هیچ option-ی بسازیم، emptyLabel نمایش داده می شود.
separator:
برای افزودن جداکننده بین option-ها (خطی شبیه <hr>)از این کد استفاده می کنیم:
Styled options:
در این ویجت برعکس <select> می تونیم option-هایی با رنگ یا فونت متفاوت بسازیم یعنی داخل <option> می تونیم از <li> <strong> <font> یا ... استفاده کنیم و option-هایی با استایل متفاوت داشته باشیم.
addOption:
برای اضافه کردن یک یا چند option ، می تونیم از این متد استفاده کنیم
dijit.byId('myId').addOption({value: 'myValue',label: 'Displayed'});
:get
مقدار انتخاب شده توسط کاربر بوسیله دستور
dijit.byId('myId').get('value')
و لیبل گزینه انتخاب شده توسط کاربر
dijit.byId('myId').get('displayedValue')
:set
برای تنظیم attribute های این ویدجت از این تابع استفاده میشه.
متدهای closeDropDown و openDropDown و toggleDropDown برای باز و بسته کردن لیست option-ها توسط جاوا اسکریپت و چند متد دیگه مثل toString و watch و onBlur و onChange و onClick و onClose و onDblClick و onFetch و onFocus و onHide و onKeyDown و onKeyPress و onKeyUp و onMouseDown و onMouseEnter و onMouseLeave و onMouseMove و onMouseOut و onMouseOver و onMouseUp بسیار مفید هستند.

dijit.form.FilteringSelect

api

این ویجت مثل تگ <Select> عمل می کنه یعنی لیبل option-ها با value آنها تفاوت داره و فرق اصلی اون با تگ <select> و ویدجت Select در نحوه انتخاب مقادیر توسط کاربر هست که می تونه از لیست option-ها هم با موس و هم با کیبورد مقداری انتخاب کنه.

همه ی attribute-های قبلا گفته شده برای این ویجت به درستی عمل می کنه و چند attribute مفید دیگه:

hasDownArrow:

این attribute که پیش فرض مقدار true دارد برای نمایش "فلش رو به پایین" هست،در صورتی که مقدار  false وارد شود این ویدجت مثل یک textbox ساده به نظر میاد که خاصیت autoComplete دارد.

highlightMatch:

برای هایلایت کردن مقادیر وارد شده ی کاربر در لیبل option-های موجود،که به صورت پیش فرض first تنظیم شده (و تقریبا شبیه field like string% در mysql عمل می کند)

اگر مقدار all ست شود و queryExpr="*${0}*" نیز اضافه گردد شبیه field like %string% در mysql عمل می کند.

intermediateChanges:

فرض کنید به  onChange این ویدجت تابعی connect شده باشد،اگر intermediateChanges برابر true باشد با هر بار تغییر مکان در لیست option-ها تابع connect شده اجرا می شود.مقدار پیش فرض این false ، attribute  است.

searchDelay:

تاخیر بر حسب میلی ثانیه بین زمانیکه کاربر چیزی تایپ می کنه و دوجو شروع به جستجو در option-ها می کند.

attribute-های مفید دیگری مثل trim و selectOnClick و scrollOnFocus و ignoreCase وجود دارد.


dijit.form.ComboBox

api

این ویجت مخلوطی از تگ Select و input هست،یعنی option-های این ویجت value ندارد

این سه ویدجت تقریبا همه ی نیازهای یک برنامه نویس تامین میکنه ولی من شخصا ویدجتی می خوام که option-هاش value داشته باشند و در عین حال یوزر بتونه مقدار جدید اضافه کنه.که تو نوشته بعدی این کار انجام میدیم.