مشکل با رویداد onload برای تگ link

neopersia

Member
سلام

من میخوام بتونم اسکرپتهای js و css خارجی رو بعد از لود شدن صفحه به صورت اختیاری لود کنم. برای همشون یک آبجکت ایجاد کردم که توی لود کردن فایلها مشکلی نداره. فقط میخوام یک پارامتر callback هم داشته باشه که بعد از لود شدن فایل اجرا بشه. در مورد فایلهای js مشکلی نیست و توی همه مرورگرها اجرا میشه اما onload برای تگ <link> فقط توی IE اجرا میشه که جای تعجب داره (از IE بعیده مگر اینکه این رویداد برای link غیر استاندارد باشه ;))

در کل میخوام وقتی که این دستور فراخوانده میشه تابع کال بک رو اجرا کنه:
کد:
dynamicLoad.css('/new_style.css', function() {
    alert('callBack')
});

اینم کد کامل آبجکت و متعلقاتش هست. اگر بتونید کمک کنید ممنون میشم :)
کد:
/**
 * @param mixed $needle
 * @param array $haystack
 * @param bool $strict
 * @return bool
 */
var in_array = function($needle, $haystack, $strict) {
	for(x in $haystack) {
		if((!$strict && $haystack[x] == $needle) || ($strict && $haystack[x] == $needle && typeof($haystack[x]) == typeof($needle))) {
			return true;
		}
	}
	return false;
};


/**
 * Load external files (scripts and styles) after loading the page
 */
var dynamicLoad = {
	_loadedFiles: [],
	
	/**
	 * Loads external js file
	 * @param string $src: path to the file
	 * @param function callBack: optional callback function
	 */
	js: function($src, callBack) {
		var callCallBack = function() {
			if(callBack) {
				setTimeout(callBack, 1000);
			}
		}
		
		if(!in_array($src, this._loadedFiles)) {
			var fired = false;
			
			var o = document.createElement('script');
			o.type = 'text/javascript';
			o.src = $src;
			
			o.onload = function() {
				if(!fired) {
					fired = true;
					callCallBack();
				}
			};
			
			o.onreadystatechange = function() {
				if(this.readyState == 'complete' && !fired) {
					fired = true;
					callCallBack();
				}
			};
			
			document.getElementsByTagName('head')[0].appendChild(o);
			this._loadedFiles[this._loadedFiles.length] = $src;
		} else {
			callCallBack();
		}
	},
	
	/**
	 * Loads external css file
	 * @param string $href: path to the file
	 * @param function callBack: optional callback function
	 */
	css: function($href, callBack) {
		var callCallBack = function() {
			if(callBack) {
				setTimeout(callBack, 1000)
			}
		}
		
		if(!in_array($href, this._loadedFiles)) {
			var fired = false;
			
			var o = document.createElement('link');
			o.rel = 'stylesheet';
			o.type = 'text/css';
			o.href = $href;
			
			o.onload = function() {
				if(!fired) {
					fired = true;
					callCallBack();
				}
			};
			
			o.onreadystatechange = function() {
				if(this.readyState == 'complete' && !fired) {
					fired = true;
					callCallBack();
				}
			};
			
			document.getElementsByTagName('head')[0].appendChild(o);
			this._loadedFiles[this._loadedFiles.length] = $href;
		} else {
			callCallBack();
		}
	}
};
 

eAmin

Well-Known Member
سلام

خیلی خوشحالم می یای اینورا:green:
بریم سر اصل مطلب.

خب متاسفانه فعلا راهی برای اینکه بدونی واقعا فایل css ی در مرورگرهای safari,chrome, firefox لود شده یا نه، وجود نداره! چون بادرخواستی که می فرستی، ارور Bad request یا همون 400 رو مرورگر دریافت می کنه.

تنها راهی که می تونی انجام بدی اینه که، توی فایرفاکس بدون در نظر گرفتن اینکه آیا واقعا لود شده یا نه، callback رو صدا بزنی و در اون دوتای دیگه ( مرورگرها )، باید چک کنی که آیا صفت خاصی ست شده یا نه.
درضمن درخواست crossdomain هم نمی تونی داشته باشی.

مثلا این روش پیاده شده در xLazyloader هست:
کد:
(function(){
	try {
		link.sheet.cssRules;
	} catch (e) {
		cssTimeout = setTimeout(arguments.callee, 20);
		return;
	};
	callback();
})();

راستی یه چیزی، اگر درخواستهات crossdomain نیست، از Ajax استفاده کن ببین جواب می ده یا نه؟
یه راه دیگه هم هست، بنظرم بشه از طریق JSONP هم اینکار رو انجام داد! ولی خب این هم دردسرهای خودش رو داره، ولی مطمئنا جواب می ده. اینهایی که گفتم مستلزم به امتحان کردنه، اگر همه این روشها رو امتحان کردی(!) منم با خبر کن:cool:

موفقیت.
 
آخرین ویرایش:

neopersia

Member
ممنون امین جون.
دلم برا جوابهات تنگ شده بود همیشه یه چیز تازه ازش یاد میگیرم :rose:

درخواستها که کراس دومین نیست همش از یک دامنه اجرا میشه. ولی در مورد اجرا کردنش با ای جکس فکر نکردم شاید بشه با کمک ای جکس هم لودش کرد. JSONP رو که دفعه اول بود میشنیدم باید در موردش مطالعه کنم ببینم چی هست :D

اینو بر اساس همون کد که از xLazyloader گذاشتی نوشتم. تو لوکال تست کردم جواب میده هنوز آنلاین چک نکردم:

کد:
var browser = (new function(){
	new RegExp(/(MSIE|Firefox|Opera|Safari)\/?[ ]?([0-9\.]+)/i).exec(navigator.userAgent)
	this.name = RegExp.$1;
	this.version = RegExp.$2;
});

var dynamicLoad = {
	_loadedFiles: [],
	
	css: function($href, callBack) {
		if(!in_array($href, this._loadedFiles)) {
			var o = document.createElement('link');
			o.rel = 'stylesheet';
			o.type = 'text/css';
			o.href = $href;
			
			document.getElementsByTagName('head')[0].appendChild(o);
			this._loadedFiles[this._loadedFiles.length] = $href;
			
			if(!callBack) {
				return;
			}
			
			if(browser.name == 'MSIE') {
				o.onreadystatechange = function() {
					if(this.readyState == 'complete') {
						callBack();
					}
				};
			} else {
				(function callCallBack(c, callBack) {
					var maxRetry = 10, timeout = 500;
					c = c || 0;
					
					if(c >= maxRetry) {
						callBack();
						console.log('Unable to get response for css file "' + $href + '" after ' + maxRetry + ' tries!');
						return false;
					}
					
					try {
						var f = o.sheet.cssRules;
						
						if(f.length) {
							callBack();
							return true;
						} else {
							console.log('Invalid CSS file!');
						}
					} catch (e) {
						setTimeout(function() {
							callCallBack(c++, callBack);
						}, timeout);
					}
				})(0, callBack);
			}
		} else {
			if(callBack) callBack();
		}
	}
};

به نظرت جواب میده؟
 

eAmin

Well-Known Member
سلام

نظر لطفته، هندونه نذار زیر بغلمون، پررو می شم:wink:

من مشکلی توش ندیدم، فقط برای اپرا می تونی از onload استفاده کنی مشکلی نیست، همونطور که گفتم مشکل فقط توی همون 3 مرورگر بود.

JSONP همون JSON هست، با این تفاوت که crossdomain ه، چطور اسکریپتها خارجی روی بصورت داینامیک با استفاده از همین کدت لود می کنی؟( توی تگ script محدودیت لود کردن اسکریپت از دامینهای خارجی وجود نداره ) خب توی JSONP بجای لود کردن کدهای JS داده های JSON رو لود می کنیم. JSON هم که همون روش Literal توی جاوااسکریپت هست، چیزه زیادی نداره.

خوش باشی.
 
آخرین ویرایش:

جدیدترین ارسال ها

بالا