Archive for the ‘jQuery’ Category

تگهای script اضافی!

دی ۹م, ۱۳۸۷

چندوقت پیش John Resig نویسنده jQuery توی وبلاگش چیز جالبی نوشته بود که منم خودم به این مورد برخورده بودم. برای همین خیلی برام جالب و مفید بود. متن زیر خلاصه ای نوشته های John و کامنت های وبلاگش هست:
اگه دقت کرده باشین هنگامی که ما با استفاده از صفت منبع (source attribute) یک کد جاوا اسکریپت (javascript) رو به صفحه خودمون اضافه میکنیم، قادر نیستیم که کدهای دیگه ای رو در بدنه تگ بنویسیم. منظورم اینه:


<script src="some-lib.js"></script>
<script>
  var foo = use_some_lib();
  foo.do.stuff();
</script>

یعنی واقعا” چرا برای نوشتن ادامه کدها مجبوریم یک تگ دیگه باز کنیم وقتی کد زیر خیلی جذاب تر و تر و تمیز تره؟!


<script src="some-lib.js">
  var foo = use_some_lib();
  foo.do.stuff();
</script>

خب برای اینکه بتونیم این کار رو انجام بدیم، John دست به کار شده و دو خط کد نوشته!
اول اینکه تگ script مربوطه رو انتخاب میکنیم بعد هم محتویات آنها را با استفاده از دستور eval اجرا میکنیم! بهمین سادگی!


var scripts = document.getElementsByTagName("script");
eval( scripts[ scripts.length - 1 ].innerHTML );

خب کافیه که این کد رو به فایل منبع (src) اضافه کنید و حالشو ببرید.
اما خب شاید همین دو خط کافی نباشه. چرا؟ خب فرض کنید مثلا” شما چندتا فایل اسکریپت توی صفحه دارین که حالا یا بطور عادی نوشته شدن یا قراره بارگذاری (load) بشن.
حالا اگه کد شما وابسته به اونها باشه چی؟ بهرحال john پیشنهادهایی داده و کد خودش رو کامل کرده که من تکه کد نهایی رو توضیح میدم.


(function(){
var scripts = document.getElementsByTagName("script");
var curScript = scripts[ scripts.length - 1 ];

if ( curScript.executed )
  return;

// ... jQuery ...

curScript.executed = true;
var script = curScript.innerHTML;
if ( script ) {
  jQuery(document).ready(function(){
    jQuery.globalEval( script );
  });
}
})();

// if you don't use jQuery :
// if ( script )
//    eval ( script );

اولین چیزی که توی این کد به چشم میخوره اینکه که ما چک میکنیم که کد قبلا” اجرا شده یا نه و دومین هم طبق چیزی که گفتم کد رو بعد از اینکه DOM آماده شد کد اجرا میکنیم.
حالا جذابیت نوشته های John یک طرف، کامنت هایی هم که گذاشته میشه حاوی نکات خیلی جالبیه!
مثلا یکی نوشته که چطوره اصلا” همه تک های script رو خلاصه کنیم و منابع اونهارو بصورت آرایه ای مثل مثال زیر بنویسیم !؟


<script src="myScript.js,myNextScript.js,myFinalScript.js">
var hello = "world";
</script>

یا حتی یکی کد زیر رو نوشته و کد خودش رو احمقانه خونده! درصورتی که من فکر نمی کنم نتیجه متفاوتی داشته باشه و احمقانه هم نیست! بالاخره برای خودش یک راهکاره!


<script src="..." onload="eval(innerHTML)"> //code <script>

Tags: , , ,
Posted in jQuery, javascript | Comments (۱)

jQuery History Plugin

آذر ۲۹م, ۱۳۸۷

چند وقت پیش روی پروژه ای کار میکردم که نیاز به یک پلاگین jQuery برای bookmark شدن لینک هایی که بصورت آژاکس (Ajax) باز میشدند داشتم. درواقع میخواستم که History مرورگر رو شبیه سازی کنه. چندتا پلاگین پیدا کردم که خوب هرکدوم یک کار متفاوت انجام میدادند. مثلا” یکی از اونها همون اول با بارگزاری صفحه شروع میکرد تمام لینک ها رو از اول تا آخر پیمایش میکرد و برای هرکدوم href (مسیر) اونها رو ذخیره میکرد و بجای اونها چیزی شبیه “#text-12″ می گذاشت که عدد آخرش شماره لینک پیمایش شده بود (مثلا” اگر شما ۱۲تا لینک توی صفحه جاری داشتین، این میشد href آخریش).

اما خب این کد مشکلش این بود که اگه شما لینک رو Open Link in New Tab میکردین اونوقت دوازهمین لینک اون صفحه رو باز میکرد نه چیزی که شما میخواستین!!!

و نهایتا” اینها یک سری عیب هایی مثل این داشتن که باعث شدند من خودم بر حسب نیازم کدهایی بنویسم که دقیقا” کاری رو که نیاز داشتم انجام بده. چیزی که من نیاز داشتم این بود که اگه کاربر روی یک لینک کلیک کرد (بطور عادی)، اون لینک بصورت آژاکس باز بشه و در ضمن یک پارمتر اضافی هم ارسال بشه به صفحه بعدی. (مثلا” در اینجا ajax_check هست)

در ضمن، ممکن بود کاربر اون لینک رو توی صفحه دیگه باز کنه. در این حالت هم نباید مشکلی پیش میومد. نکته مهم دیگه هم Back و Forward و حتی Refresh مرورگر بود که باید دقیقا” درست عمل میکرد. راستی نباید این حات رو هم فراموش میکردیم که امکان داره جاوا اسکریپت (javascript) کاربر هم غیر فعال باشه! خلاصه بگم چیزی باشه که کاربر اصلا” خطا نبینه و بهترین امکانات رو هم براش فراهم کنه.

کدی که نوشتم سه قسمت داره (دوتا تابع (function) و یک تکه کد). تابع اول به نام history هست که وظیفه تبدیل مسیر لینک کلیک شده به نوعی هش مخصوص هست که این باعث میشه Back و Forward درست عمل کنند. این تابع هش ساخته شده را در url قرار میده. تابع بعدی هم getHash هست که وظیفه تبدیل هش مخصوص موجود در url رو به آدرس کامل و درخواست این آدرس از سرور و بارگذاری اون رو داره. تکه کد هم وظیفه این رو داره که هر لحظه url و Hash رو در اون تست کنه که اگه تغییر کرده باشه، تابع getHash رو فراخوانی کنه و ادامه داستان…!!

فکر کنم کدهایی که نوشتم واضح باشند. اگه کسی سوالی داشت بپرسه یا بگین تا خط به خط توضیحش بدم.

۲ تا نکته مهم:

۱ . این کدها برای صفحاتی نوشته شدند که پسوند PHP دارند. اما میتونین با یه تغییر ساده در متغیر fileExt اون رو به هرچیزی که میخواین تغییر بدین.

۲ . اگه صفحه شما دارای لینکی باشه که href اون “” باشه، بطور پیشفرض index.fileExt رو باز میکنه که شما میتونین با یک تغییر کوچک اون رو حذف کنید.

منتظر اشکالاتی که توی کد پیدا میکنین هستم!! ;)


	var fileExt = 'php';
	var history = function(path){
		//Question Mark Position
		var qmp = (path.indexOf('?') > 0 ) ? path.indexOf('?') + 1 : path.length + 1;
		//End of Path Position (Last Position)
		var lp = path.length;
		var fileNameP1 = path.indexOf('.'+fileExt) + 1;
		var fileNameP2 = (qmp > 1) ? qmp-1 : path.length;
		var params = path.substring(qmp,lp);
		var newPath = '';
		var fileName = path.substring(  path.substring(0,fileNameP2).lastIndexOf('/')+1 , fileNameP2 ).replace('.'+fileExt,'');

		if (params.length > 0 ){
			var a = explodeArray(params,"&");
			for (var i=0, j=a.length; i<j; i++)
				newPath += a[i] + '/';
			newPath = '#' + fileName + ':' + newPath;
		} else {
			newPath = '#' + fileName;
		}
		if ($.browser.msie) {
			var iframe = _historyIframe.contentWindow.document;
            iframe.open();
            iframe.close();
            iframe.location.hash = newPath;
		}
		location.hash = newPath;
		_loadedHash = newPath;
	};

	var getHash = function(myHash){
		h = myHash;
		if ( h.length < 1) h = 'index';
		if ( h.indexOf(':') > 0 ){
			h = h.replace(/^#/,'').replace(':','.'+fileExt+'?');
			while( h.indexOf('/') > 0 )
				h = h.replace('/','&');
		} else {
			h = h.replace(/^#/,''); h += '.'+fileExt;
		}
		$.get(h,{'ajax_check':'true'},function(data){
			$body.html('<center>' + data + '</center>');
		});
		if($.browser.msie)
			_loadedHash = _historyIframe.contentWindow.document.location.hash;
		else
			_loadedHash = myHash;

	};

	if ($.browser.msie) {
		var _historyIframe = $('<iframe style="display: none"></iframe>').appendTo("BODY").get(0);
		var iframe = _historyIframe.contentWindow.document;
		iframe.open();
		iframe.close();
		setInterval(function(){
			checkScrollbarPosition();
			var h = _historyIframe.contentWindow.document.location.hash;
			if ( (_loadedHash != null) &&  ( _loadedHash != h) ) 	getHash(h);

		}, 500);
	} else if ($.browser.mozilla) {
		setInterval(function(){
			checkScrollbarPosition();
			if ( (_loadedHash != null) && ( _loadedHash != location.hash) )	getHash(location.hash);
		}, 500);
	}

	try{
		if(location.hash.length > 0 && !$.browser.msie)
			getHash(location.hash);
	}catch(e){}

//Example for use:
$(document).ready(function(){
	var $body = $("#content");
	$("a").livequery('click',function(){
		var h = $(this).attr("href");
		$.get(h, {'ajax_check':'true'} , function(response){
			$body.html(response);
		});
		history(h);
		return false;
	});
});

Tags: , , , , , , , ,
Posted in jQuery, javascript | Comments (۱)