Gå til innhold

eventhandler sender ikke med event argument i IE


Anbefalte innlegg

Skrevet (endret)

Hei

 

Har laget et javascript (basert på et jeg fant på nett) for å flytte en div. Problemet oppstår når jeg registrerer en eventhandler for onmousemove. I Firefox funker alt glimrende, men når funksjonen/eventhandlern skal kjøres i IE (7) sendes ikke event argumentet med (er null). Er ikke i stand til å finne ut hvorfor det i IE ikke sendes med argument når alt funker i firefox. På alle kilder jeg har funnet står det at IE støtter propertiene i event-argumentet, derfor har jeg også tatt det som gitt at event-argumentet faktisk skal eksistere.

 

HTML dokumentet ligger på: http://www.mediafire.com/?fnxxz2fydkp

 

function mousemove(event)
{
if(over)
{
 if(event == null)	//for debugging
 {
 	alert("event is null for some reason!");
 	over = false;
 	return;
 }
 var ob = document.getElementById("panel");
 ob.style.top = event.pageY - Y;
 ob.style.left = event.pageX - X;
}
}

document.onmousemove = mousemove;

 

Feilen oppstår på linjen hvor det sies event.pageY fordi event ikke er et objekt. alertbeskjeden vil aldri kjøres i firefox, mens den alltid kjøres i IE7.

Endret av invictus
Videoannonse
Annonse
Skrevet (endret)

Jeg vet ikke om det hjelper, men event blir sendt som argument til en eventhandlerfunksjon uansett om du inkluderer event-variabel i argumentlista, så kanskje når du lager din egen event så overskriver du IE sin eller et eller annet...

 

Jeg vet at i Java må man ha med denne og kan kalle den hva man vil, men er litt usikker i JavaScript.

 

Tror jeg hvertfall. (IE er jo alltid litt upålitelig, hvis du skjønner hva jeg mener. :p)

 

Du kan jo prøve noe som under f eks.

 

document.onmousedown = function()
{
if (over)
{
 var ob = document.getElementById("panel");
 X = event.layerX;
 Y = event.layerY;
 return false;
}
}
document.onmousemove = function()
{
//if (ob)

if(over)
{
 if(event == null)	//for debugging
 {
 	alert("event is null for some reason!");
 	over = false;
 	return;
 }
 var ob = document.getElementById("panel");
 ob.style.top = event.pageY - Y;
 ob.style.left = event.pageX - X;
}
}

 

Jeg svært usikker på dette, men hvis jeg ikke tar feil, fungerte dette for meg i IE6.

 

Edit: Prøvde, men fungerer ikke noe bedre er jeg redd. Beklager.

Endret av LostOblivion
Skrevet (endret)

Event i IE må hentes ut i fra window.event. Dette vil vil antageligvis hjelpe deg:

 

function mousemove(event) {
 // Henter ut event egenskaper
 event = event || window.event; // Bruker event hvis finnes, eller window.event 
 var target = event.target || event.srcElement; // Bruker target, eller IEs versjon srcElement
 if ( target.nodeType == 3 ) {
   // Fikser safaribug
   target = target.parentNode;
 }
 
 if(over) {
   [...]

 

Når det er sagt tror jeg nok du vil få litt problemer med pageX/Y. Du kan lese mer om det på http://www.quirksmode.org/js/events_properties.html. På Quirksmode står det ganske mye om forskjeldene på de forskjellige browserene og hvordan man kommer rundt de.

Endret av luxus
Skrevet

Jepp det stemmer. Virker som Mozilla støtter pageX/Y mens IE ikke gjør det. Videre støtter mozilla layerX/Y mens ikke IE. IE derimot støtter offsetX/Y men det gjør ikke mozilla. I tillegg behandler visstnok opera, konquerer, safari osv clientx/y forskjellig.

 

 

 

Av og til er det fristende å gi opp alt som er av webutvikling så lenge ingen browsere støtter noe felles :p

Skrevet

hehe, joda.. Men som det står på Quirksmode, for å få ut riktige mousepos::

function doSomething(e) {
var posx = 0;
var posy = 0;
if (!e) var e = window.event;
if (e.pageX || e.pageY)  {
 posx = e.pageX;
 posy = e.pageY;
}
else if (e.clientX || e.clientY)  {
 posx = e.clientX + document.body.scrollLeft
 	+ document.documentElement.scrollLeft;
 posy = e.clientY + document.body.scrollTop
 	+ document.documentElement.scrollTop;
}
// posx and posy contain the mouse position relative to the document
// Do something with this information
}

 

Det kan jo også være en ide å bruke et bibliotek som YUI, http://developer.yahoo.com/yui/event/. Da kan du la biblioteket ta seg av disse forskjeldene.

Skrevet

Flott. Dette så ut til å funke. Det jeg da må gjøre er å finne ut en nøyaktig metode for å regne ut de lokale x og y kordinatene i forhold til komponenten jeg trykker på. For det bruker jeg for øyeblikket følgende kode:

 

function mousedown(e)
{
if (over)
{
 e = e || window.event;
 ob = document.getElementById("panel");
 ob = ob.style;
 X= e.layerX ? e.layerX : e.offsetX;
 Y= e.layerY ? e.layerY : e.offsetY;
}
}

 

I koder her er det de 2 siste linjene som er viktig. Her sier jeg at X skal være e.layerX hvis den eksisterer og hvis ikke skal den være offsetX. Dessverre er ikke layerX og offsetX det samme, noe som fører til en løsning som ikke er riktig på de forskjellige nettleserne. Noen forslag?

 

mozilla støtter layerX, mens resten tilsynelatende støtter offsetX

Skrevet

Fant en kode som visstnok skulle løse problemet ved å lage en offsetX lignende metode i firefox:

 

var Element = evt.target;
var CalculatedTotalOffsetLeft = CalculatedTotalOffsetTop = 0;
while (Element.offsetParent)
{
CalculatedTotalOffsetLeft += Element.offsetLeft;
CalculatedTotalOffsetTop += Element.offsetTop;
Element = Element.offsetParent;
};
OffsetXForFirefoxOrNetscape = evt.pageX - CalculatedTotalOffsetLeft;
OffsetYForFirefoxOrNetscape = evt.pageY - CalculatedTotalOffsetTop;

 

Når jeg tolket denne koden og skrev noe tilsvarende i min egen kode endte jeg opp med følgende:

 

function mousedown_beta(e)
{
if (over)
{
 var posx = 0;
 var posy = 0;
 e = e || window.event;
 ob = document.getElementById("panel");

 if (e.offsetX || e.offsetY)
 {
 	posx = e.offsetX;
 	posy = e.offsetY;
 }
 else if (e.layerX || e.layerY)
 {
 	var OffsetLeft = 0;
 	var OffsetTop = 0;

 	var Element = ob;
 	while (Element.offsetParent)
 	{
   OffsetLeft += Element.offsetLeft;
   OffsetTop += Element.offsetTop;
   Element = Element.offsetParent;
 	};
 	posx = ob.pageX - OffsetLeft;
 	posy = ob.pageY - OffsetTop;

 	alert("x: " + posx + ", y=" + posy);
 }

 X = posx;
 Y = posy;
}
}

 

Problemet her er bare at den alert()'en jeg har satt inn rapporterer at resultatet er NaH i begge tilfeller. Jeg aner ikke hva NaH betyr og hvordan fikse dette.

Skrevet (endret)

Denne koden skal fungere i både FF, IE og Opera:

Klikk for å se/fjerne innholdet nedenfor
<html>
 <head>
   <style>
     .titlebar {
       width: 100%;
       background-color: #99CCFF;
       border-bottom: 1px solid blue;
       font-size: 14px;
       font-family: verdana;
       color: #000000;
       text-align: center;
       cursor: move;
     }

     .panel {
       width: 150;
       position: absolute;
       border: 1px solid blue;
       left: 350;
       top: 200;
       font-size: 13px;
       font-family: verdana;
     }

     .content {
       width: 100%;
       background-color: yellow;
       font-size: 13px;
       font-family: verdana;
     }
   </style>
<script type="text/javascript">

 /**
  * Funksjonen blir kalt på når musa presses ned
  *
  * @param {Event} e   Event objektet
  */
 function mouseDown(e) {
   e = e || window.event;
   var panel = document.getElementById("panel");
   var mpos = getMousePos(e);
   
   // Finner ut hvor musa er i forhold til top/venstre posisjonen til panelet.
   // Parseint er er fordi top/left er string, og 10 forsikrer at parsinga går etter titallssystemet.
   panel.mouseXOffset = mpos.x - parseInt(panel.style.left, 10);
   panel.mouseYOffset = mpos.y - parseInt(panel.style.top, 10);
   // Gjør slik at mouseMove metoden får lov til å flytte på panalet.
   panel.isDragging = true;
 }

 /**
  * Funksjonen blir kalt på når musetasten slippes
  *
  * @param {Event} e   Event objekte
  */
 function mouseUp(e) {
   // "Resetter panelegenskapene"
   var panel = document.getElementById("panel");
   panel.mouseXOffset = undefined;
   panel.mouseYOffset = undefined;
   panel.isDragging = false; // Dragging skal nå ikke skje mer
 }
 
 /**
  * Funksjonen blir kalt på når musa flyttes over et element
  *
  * @param {Event} e   Event objekte
  */
 function mouseMove(e) {
   var panel = document.getElementById("panel");
   var mpos;

   if (panel.isDragging)  {
     // isDragging er satt til true av mouseDown funksjonen, så da flyter vi på panelet..
     mpos = getMousePos(e);
     panel.style.top   = (mpos.y - panel.mouseYOffset) + "px";
     panel.style.left  = (mpos.x - panel.mouseXOffset) + "px";
   }
 }


/**
* ET PAR GENERELLE FUNKSJONER SOM VI TRENGER KOMMER HER:
*/

 /**
  * Henter ut museposisjonen, fungerer både i IE, FF og Opera
  * Museposisjon er relativ til dokumentet og ikke skjermen.
  *
  * @param {Event}   e   Event objektet
  * @return {Object}     Ett objekt som inneholder x og y, altså museposisjonen
  */
 function getMousePos(e) {
   // Oppretter variable
   var posx = 0;
   var posy = 0;
   // Sjekker om vi har W3C sin måte å gjøre det på (FF og Opera vil gå inn her)
   if (e.pageX || e.pageY)  {
     posx = e.pageX;
     posy = e.pageY;
   }
   else if (e.clientX || e.clientY)  { // IE
     posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
     posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
   }

   // Returnerer et objekt med verdien X og Y i som vi akkurat har funnet..
   return {x: posx, y: posy};
 }

 /**
  * Legger på en eventhandler på node
  *
  * @param {HTMLElement}   node  Noden å sette eventhandleren på
  * @param {String}        type  Hva slags type event skal den reagere på?
  * @param {function}      f     Funksjonen som skal kalles på
  */
 function addEventHandler(node, type, f) {
   if ( node.addEventListener ) { // w3c
     node.addEventListener(type, f, false); // false -> event bubbles up
   } else if ( node.attachEvent ) { // ie
     node.attachEvent("on"+type, f);
   } else { // Dette burde virke på alle, men kan ikke legge på mer enn en event handler pr element
     node["on"+type] = f;
   }
 }

/**
* GENERELLE FUNKSJONER SLUTTER HER
*/

// Legger på eventhandlers når onload blir kalt, altså når siden er lastet inn
window.onload = function() {
 var panel = document.getElementById("panel");
 addEventHandler(panelHead, "mousedown", mouseDown);
 addEventHandler(panelHead, "mouseup",   mouseUp);
 addEventHandler(panelHead, "mousemove", mouseMove);
};
</script>

 </head>
 <body>
   <div style="top: 157px; left: 257px;" id="panel" class="panel">
     <div class="titlebar" id="panelHead">
       <b>title</b>
     </div>
     <div class="content">content</div>
   </div>

   <p>
     </p><center>this is a website</center>
   <p>

   </p>
 </body>
</html>

 

Jeg gjorde et par forandringer. For det første fjerna jeg in-line event-kallene dine. Alså der du hadde

<div style="top: 157px; left: 257px;" id="panel" class="panel" onmousedown="gjør noe">. Det er bedre å la JavaScript selv legge på slike ting, og ikke skrive in-line JavaScript i HTMLen

 

Videre fjernet jeg de globale variablene du hadde, "X", "Y" og "over" variabelene dine. Det er best å ha så lite globale variable som mulig. Disse variablene er nå lagt / blir lagret på selve DIVen med id panel. De heter nå mouseXOffset, mouseYOffset og isDragging.

 

Håper det hjelper. Det virka i allefall her i både Firefox, Opera og IE6 da jeg testa koden jeg skrev.

Endret av luxus
Skrevet (endret)

Denne funket ikke helt optimalt i firefox2. Den virker tilsynelatende, men på spesielle posisjoner så slutter den å dra av seg selv.

 

EDIT: samme problem i opera. virker som det skjer hvis jeg drar for fort

Endret av invictus
Skrevet
Problemet her er bare at den alert()'en jeg har satt inn rapporterer at resultatet er NaH i begge tilfeller. Jeg aner ikke hva NaH betyr og hvordan fikse dette.

8713931[/snapback]

 

Du får feilen NaN vel? Og ikke NaH skulle jeg tro. NaN står for Not a Number, og det kommer av dette:

 

posx = ob.pageX - OffsetLeft;

 

I variabelen pageX ligger det f.eks. "50px".. Altså er dette en tekststreng. I OffsetLeft der i mot ligger det et heltall (integer).. Du må gjøre om (parse) pageX-tekststrengen til et heltall før du kan bruke variabelen i en regneopperasjon. Med andre ord:

 

posx = parseInt(ob.pageX, 10) - OffsetLeft; vil bli riktig. pageX vil bli gjort om til heltall, og 10 indikerer at tallet som skal parses er på formen titallssystemet.

Skrevet
Denne funket ikke helt optimalt i firefox2. Den virker tilsynelatende, men på spesielle posisjoner så slutter den å dra av seg selv.

 

EDIT: samme problem i opera. virker som det skjer hvis jeg drar for fort

8714340[/snapback]

 

Bytt ut addEventHandler(panelHead, "mousemove", mouseMove); med addEventHandler(document, "mousemove", mouseMove); kanskje. Det skjer nok fordi musa kommer utenfor panelet, før panelet rekker å følge med. Derfor så blir det plutselig ikke registrert at den flytter på seg tenker jeg.

Skrevet
Denne funket ikke helt optimalt i firefox2. Den virker tilsynelatende, men på spesielle posisjoner så slutter den å dra av seg selv.

 

EDIT: samme problem i opera. virker som det skjer hvis jeg drar for fort

8714340[/snapback]

 

Bytt ut addEventHandler(panelHead, "mousemove", mouseMove); med addEventHandler(document, "mousemove", mouseMove); kanskje. Det skjer nok fordi musa kommer utenfor panelet, før panelet rekker å følge med. Derfor så blir det plutselig ikke registrert at den flytter på seg tenker jeg.

8714380[/snapback]

 

Ser ut til å funke i mozilla og opera nå ja :)

 

Et annet spørsmål...i Opera og i IE7 så vil tekst bli markert av seg selv når man drar panelet rundt...er det noen måte å hindre dette?

Skrevet
Problemet her er bare at den alert()'en jeg har satt inn rapporterer at resultatet er NaH i begge tilfeller. Jeg aner ikke hva NaH betyr og hvordan fikse dette.

8713931[/snapback]

 

Du får feilen NaN vel? Og ikke NaH skulle jeg tro. NaN står for Not a Number, og det kommer av dette:

 

posx = ob.pageX - OffsetLeft;

 

I variabelen pageX ligger det f.eks. "50px".. Altså er dette en tekststreng. I OffsetLeft der i mot ligger det et heltall (integer).. Du må gjøre om (parse) pageX-tekststrengen til et heltall før du kan bruke variabelen i en regneopperasjon. Med andre ord:

 

posx = parseInt(ob.pageX, 10) - OffsetLeft; vil bli riktig. pageX vil bli gjort om til heltall, og 10 indikerer at tallet som skal parses er på formen titallssystemet.

8714354[/snapback]

 

posx = parseInt(...) fungerte ikke. Får fremdeles NaN på denne. Har jo alltids koden du skrev som jeg kan jobbe videre på, men skulle gjerne likt å visst hvor ting gikk galt i min egen kode også.

Skrevet (endret)

  posx = ob.pageX - OffsetLeft;
 posy = ob.pageY - OffsetTop;

 

Skal selvfølgelig være:

 

  posx = e.pageX - OffsetLeft;
 posy = oe.pageY - OffsetTop;

 

Det funker nå :)

 

Men la meg spørre deg om en annen ting: I koden din skriver du bare

 

panel.mouseXOffset = undefined;
  panel.mouseYOffset = undefined;
  panel.isDragging = false; // Dragging skal nå ikke skje mer

 

Er det lov å bare "opprette" variabler i elementer på den måten?

Endret av invictus
Skrevet

Ja, det er lov, jeg har ikke lest noen som har noe i mot det i allefall. Og vil si det er mye bedre enn å opprette globale variable. Kanskje ikke så viktig å tenke på i små scripts, men når scriptet blir større / du henter inn kode som andre har skrevet er det lurt å passe på å holde sine variabelnavn utenfor det globale skopet.

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...