webForumDet fria alternativet

Problem med Javascript klass och Ajax

8 svar · 681 visningar · startad av andreaswebb

andreaswebbMedlem sedan apr. 2003111 inlägg
#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!

Peter SMedlem sedan dec. 20025 484 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. :)

andreaswebbMedlem sedan apr. 2003111 inlägg
#3

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

Peter SMedlem sedan dec. 20025 484 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.

andreaswebbMedlem sedan apr. 2003111 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?

Peter SMedlem sedan dec. 20025 484 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);
  }
}
andreaswebbMedlem sedan apr. 2003111 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.

Peter SMedlem sedan dec. 20025 484 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);
  }
}
andreaswebbMedlem sedan apr. 2003111 inlägg
#9

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

Genererad på 381 ms · cache AV · v20260730165559-full.f96bc7eb