webForumDet fria alternativet
Logga in / Bli medlem

Problem med Javascript klass och Ajax

JavaScript

8 svar · 681 visningar · startad av andreaswebb

Medlem sedan apr. 2003101 inlägg
Frågan#1

Hej på er!

Håller på med en javascript-class som ska skapa "fönster" i form av div:ar i olika layer. Till detta hade jag tänkt att använda ajax för att hämta innehåller i dessa "fönster".

Klassen http://andreas.famstromgren.se/js/window.class.js
Ajax http://andreas.famstromgren.se/js/ajax.js

Koden i ajax.js är bara för att skapa ajax-objektet. Funktionen för att hämta datan ligger sedan i klassen. Grejjer är den att hur jag än gör så blir this.content == undefined. Jag har felsökt ajax-funktionen och den fungerar som den ska, det är kommunikationen mellan ajax-funktionen och draw-funktionen som inte fungerar. Har testat med att byta namn på variabeln som ska innehålla return-värdet från ajax-funktionen men det hjälper inte heller. Också testat att sätta variabeln direkt i ajax-funktionen men det hjälper inte.

Någon som vet vad som jag gjort fel?

Tackar på förhand!

Medlem sedan dec. 20025 483 inlägg
#2

Ett exempel:

function iWindow(id,header) {
	
	this.id = id;
	this.header = header;
	
	this.draw = function() {
		
		if(!document.getElementById(this.id)) {
		
			if(this.width == undefined) this.width = 100;
			if(this.height == undefined) this.height = 100;
			if(this.top == undefined) this.top = 0;
			if(this.left == undefined) this.left = 0;

			this.id = this.id
			
			this.wrapper = document.createElement('div');

			this.wrapper.id = this.id;

			this.wrapper.style.width = this.width;
			this.wrapper.style.height = this.height;
			this.wrapper.style.backgroundColor = this.backgroundColor;
			this.wrapper.style.position = 'absolute';
			this.wrapper.style.top = this.top;
			this.wrapper.style.left = this.left;

			if(this.getContentMethod == undefined) this.getContentMethod = 'GET';
			if(this.ajaxContent != undefined) {}
      
      this.getContent(/*this.content*/"http://www.webforum.nu/",this.getContentMethod);
		
		} else this.show();
		
	}
  
  this._draw = function() {
			this.wrapper.innerHTML = iWindow._response;

			document.getElementById('body').appendChild(this.wrapper);
  }
	
	this.getContent = function(addr,method) {

		ajax = createAjaxObj();
    iWindow._currObject = this;

		ajax.onreadystatechange = function(obj) {
			
			if(ajax.readyState == 4 && ajax.status == 200) {
				
        iWindow._response = ajax.responseText;
        iWindow._helper_();

			}
		
		}
		
		ajax.open(method,addr,true);
		ajax.send(null);
		
	}
	
	this.hide = function() {
		
		document.getElementById(this.id).style.display = 'none';
		
	}
	
	this.show = function() {
		
		document.getElementById(this.id).style.display = '';
		
	}

}

iWindow._response = iWindow._currObject = null;
iWindow._helper_ = function() {
  iWindow._currObject._draw();
}

Kanske ett fulhack, men det fungerar. :)

Medlem sedan apr. 2003101 inlägg
#3

Man tackar :) Men nyfiken som man är så funderar jag på varför mitt inte fungerar?

Medlem sedan dec. 20025 483 inlägg
#4

Du har någonting i stil med detta:

this.content = this.getContent(...);

I getContent()-metoden har du

obj.onreadystatechange = function(){
  return <ajaxContent>;
}

Problemet är att onreadystatechange är en händelsehanterare, varför tiden för dess exekvering inte är omedelbar. Vad du gör i getContent() är att registrera den här händelsen för ett specifikt objekt, men du kan inte i den hanteraren returnera ett värde för den funktion i vilken onreadystatechange() definierats. I draw() kommer getContent() att köras, uppifrån och ned, avsluta och sedan återvända till draw(), utan att ha returnerat någonting. Därför blir this.content undefined.

Medlem sedan apr. 2003101 inlägg
#5

Okej, man lär sig nått nytt varje dag ;). Om man nu skulle lösa detta på ett icke "fulhackat" sätt, hur ska det då se ut? Känns som att exemplet ovan blir onödigt krångligt, eller är det så det måste bli?

Medlem sedan dec. 20025 483 inlägg
#6

Du kan wrappa AJAX-objektet i en egen klass:

ajax.js

function createAjaxObj() {
	var httprequest=false
	if (window.XMLHttpRequest){ // if Mozilla, Safari etc
		httprequest=new XMLHttpRequest()
	if (httprequest.overrideMimeType)
		httprequest.overrideMimeType('text/html')
	} else if (window.ActiveXObject){ // if IE
		try {
			httprequest=new ActiveXObject("Msxml2.XMLHTTP");
		} 
		catch (e){
		try{
			httprequest=new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e){}
		}
	}
	return httprequest;
}

window.class.js

function iWindow(id,header,name) {
		

	this.id = id;
	this.header = header;
	this.name = name
	
	zIndex = 0;	//Global variabel för att hålla reda på Z-index
	
	this.draw = function() {
		
		if(!document.getElementById(this.id)) {
		
			if(this.width == undefined) this.width = 100;
			if(this.height == undefined) this.height = 100;
			if(this.top == undefined) this.top = 0;
			if(this.left == undefined) this.left = 0;
			if(this.template == undefined) this.template = 'standard';
			if(this.html == undefined) this.html = '';			

			this.id = this.id
			
			this.wrapper = document.createElement('div');

			this.wrapper.id = this.id;
			
			//Storlek
			this.wrapper.style.width = (this.width+6)+'px';
			this.wrapper.style.height = (this.height+6)+'px';
			
			//Dropshadow
			this.wrapper.className = 'dropshadow';
						
			//Lagerhantering
			this.wrapper.style.position = 'absolute';
			this.wrapper.style.top = (this.top+4)+'px';
			this.wrapper.style.left = (this.left+4)+'px';
			
			this.wrapper.setAttribute('onclick',this.name +'.setFocus()');
			this.wrapper.setAttribute('onmousedown',this.name +'.drag');			
		
			document.getElementById('body').appendChild(this.wrapper);
			
			//Innehållet i wrapper
			this.content = document.createElement('div');
			
			this.content.id = this.id +'_content' 
			this.content.className = this.template;
			this.content.style.padding = '3px';
			this.content.style.width = (this.width-6)+'px';
			this.content.style.height = (this.height-6)+'px';

			document.getElementById(this.id).appendChild(this.content);
			
			//Skapar rubrik
			this.rubrik = document.createElement('h1');
			this.rubrik.className = 'drag_area';
			this.rubrik.innerHTML = this.header;

			document.getElementById(this.id +'_content').appendChild(this.rubrik);
			
			//Skapar container för användardefinierat innehåll
			this.container = document.createElement('div');
			this.container.id = this.id +'_container';
			
      this.ajaxContent = true;
      
			if(this.ajaxContent == true) this.getContent("http://www.webforum.nu/","GET",this);
			else {
        this.container.innerHTML = this.html;
        document.getElementById(this.id +'_content').appendChild(this.container);
        this.setFocus();			
      }
	
		} else {

			if(this.wrapper.style.display == 'none') this.show();
			else this.setFocus();

		}
		
	}
	
	this.setFocus = function() {
		
		this.wrapper.style.zIndex = zIndex++;
		
	}
	
	this.getContent = function(addr,method,iwin) {
		
		var ajax = new ajaxobj(iwin);

		ajax.initorsc();
		
		ajax.open(method,addr,true);
		ajax.send(null);
		
	}
	
	this.hide = function() {
		
		document.getElementById(this.id).style.display = 'none';
		
	}
	
	this.show = function() {
		
		document.getElementById(this.id).style.display = '';
		
	}

}

function ajaxobj(iwin)
{
  this.xmlreq = createAjaxObj();
  this.iwin = iwin;
  this.initorsc = function()
  {
    this.xmlreq.onreadystatechange = function()
    {
      if (this.readyState == 4 && this.status == 200){
        iwin.container.innerHTML = this.responseText;
        document.getElementById(iwin.id +'_content').appendChild(iwin.container);
        iwin.setFocus();	
      }
    }
  }
  this.open = function(method,addr,async)
  {
    this.xmlreq.open(method,addr,async);
  }
  this.send = function(str)
  {
    this.xmlreq.send(str);
  }
}
Medlem sedan apr. 2003101 inlägg
#7

Nu har jag äntligen fått tummen ur och testat detta. Fungerar utmärkt i IE, men i FF så går det inte. Efter lite felsökning så ser jag att this.readyState och this.status blir undefined i FF. Har testat att lägga till xmlreq mellan this och egenskapen, men det hjälper inte.

Medlem sedan dec. 20025 483 inlägg
#8

Testa följande:

function ajaxobj(iwin)
{
  this.iwin = iwin;
  this.initorsc = function()
  {
    this.xmlreq = createAjaxObj();
    var _this = this;
    this.xmlreq.onreadystatechange = function()
    {
      if (_this.xmlreq.readyState == 4 && _this.xmlreq.status == 200){
        _this.iwin.container.innerHTML = _this.xmlreq.responseText;
        document.getElementById(_this.iwin.id +'_content').appendChild(_this.iwin.container);
        _this.iwin.setFocus();
      }
    }
  }
  this.open = function(method,addr,async)
  {
    try {
      netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
    } catch (e){}
    this.xmlreq.open(method,addr,async);
  }
  this.send = function(str)
  {
    this.xmlreq.send(str);
  }
}
Medlem sedan apr. 2003101 inlägg
#9

Nu fungerar det klockrent i både IE och FF. Tackar tackar :)

276 ms totalt · 4 externa anrop · v20260731065814-full.0583408b
129 ms — deklarationer (db)
0 ms — hämta statistik (cache)
144 ms — hämta tråd, inlägg och bilagor (db)
127 ms — ändringar (db)